Fortran · 4168 bytes Raw Blame History
1 module yank_stack_module
2 use iso_fortran_env, only: int32
3 implicit none
4 private
5
6 public :: yank_stack_t, init_yank_stack, cleanup_yank_stack
7 public :: push_yank, pop_yank, peek_yank, clear_yank_stack
8
9 integer, parameter :: MAX_YANK_SIZE = 1024 * 1024 ! 1MB max per entry
10 integer, parameter :: MAX_YANK_ENTRIES = 100
11
12 type :: yank_entry_t
13 character(len=:), allocatable :: text
14 end type yank_entry_t
15
16 type :: yank_stack_t
17 type(yank_entry_t), allocatable :: entries(:)
18 integer :: top = 0
19 integer :: capacity = MAX_YANK_ENTRIES
20 end type yank_stack_t
21
22 contains
23
24 subroutine init_yank_stack(stack)
25 type(yank_stack_t), intent(out) :: stack
26
27 allocate(stack%entries(stack%capacity))
28 stack%top = 0
29 end subroutine init_yank_stack
30
31 subroutine cleanup_yank_stack(stack)
32 type(yank_stack_t), intent(inout) :: stack
33 integer :: i
34
35 if (allocated(stack%entries)) then
36 do i = 1, stack%top
37 if (allocated(stack%entries(i)%text)) then
38 deallocate(stack%entries(i)%text)
39 end if
40 end do
41 deallocate(stack%entries)
42 end if
43 stack%top = 0
44 end subroutine cleanup_yank_stack
45
46 subroutine push_yank(stack, text)
47 type(yank_stack_t), intent(inout) :: stack
48 character(len=*), intent(in) :: text
49 integer :: i
50
51 ! Check if we need to grow the stack
52 if (stack%top >= stack%capacity) then
53 ! Shift entries down, losing the oldest
54 do i = 1, stack%capacity - 1
55 if (allocated(stack%entries(i)%text)) then
56 deallocate(stack%entries(i)%text)
57 end if
58 if (allocated(stack%entries(i+1)%text)) then
59 allocate(character(len=len(stack%entries(i+1)%text)) :: stack%entries(i)%text)
60 stack%entries(i)%text = stack%entries(i+1)%text
61 end if
62 end do
63 stack%top = stack%capacity - 1
64 end if
65
66 ! Add new entry
67 stack%top = stack%top + 1
68 if (allocated(stack%entries(stack%top)%text)) then
69 deallocate(stack%entries(stack%top)%text)
70 end if
71
72 ! Limit text size
73 if (len(text) > MAX_YANK_SIZE) then
74 allocate(character(len=MAX_YANK_SIZE) :: stack%entries(stack%top)%text)
75 stack%entries(stack%top)%text = text(1:MAX_YANK_SIZE)
76 else
77 allocate(character(len=len(text)) :: stack%entries(stack%top)%text)
78 stack%entries(stack%top)%text = text
79 end if
80 end subroutine push_yank
81
82 function pop_yank(stack) result(text)
83 type(yank_stack_t), intent(inout) :: stack
84 character(len=:), allocatable :: text
85
86 if (stack%top > 0) then
87 if (allocated(stack%entries(stack%top)%text)) then
88 allocate(character(len=len(stack%entries(stack%top)%text)) :: text)
89 text = stack%entries(stack%top)%text
90 deallocate(stack%entries(stack%top)%text)
91 else
92 text = ''
93 end if
94 stack%top = stack%top - 1
95 else
96 text = ''
97 end if
98 end function pop_yank
99
100 function peek_yank(stack) result(text)
101 type(yank_stack_t), intent(in) :: stack
102 character(len=:), allocatable :: text
103
104 if (stack%top > 0) then
105 if (allocated(stack%entries(stack%top)%text)) then
106 allocate(character(len=len(stack%entries(stack%top)%text)) :: text)
107 text = stack%entries(stack%top)%text
108 else
109 text = ''
110 end if
111 else
112 text = ''
113 end if
114 end function peek_yank
115
116 subroutine clear_yank_stack(stack)
117 type(yank_stack_t), intent(inout) :: stack
118 integer :: i
119
120 do i = 1, stack%top
121 if (allocated(stack%entries(i)%text)) then
122 deallocate(stack%entries(i)%text)
123 end if
124 end do
125 stack%top = 0
126 end subroutine clear_yank_stack
127
128 end module yank_stack_module