FreeBASIC  0.91.0
list.bas
Go to the documentation of this file.
1 '' generic double-linked list
2 ''
3 '' chng: jan/2005 written [v1ctor]
4 ''
5 
6 #include once "list.bi"
7 
9  '' Abort right now, the rtlib will show the error
10  error(4)
11 end sub
12 
13 function xallocate(byval size as long) as any ptr
14  dim as any ptr p = allocate(size)
15  if (p = NULL) then
17  end if
18  return p
19 end function
20 
21 function xcallocate(byval size as long) as any ptr
22  dim as any ptr p = callocate(size)
23  if (p = NULL) then
25  end if
26  return p
27 end function
28 
29 function xreallocate(byval old as any ptr, byval size as long) as any ptr
30  dim as any ptr p = reallocate(old, size)
31  if (p = NULL) then
33  end if
34  return p
35 end function
36 
37 sub listInit _
38  ( _
39  byval list as TLIST ptr, _
40  byval nodes as integer, _
41  byval nodelen as integer, _
42  byval flags as LIST_FLAGS _
43  )
44 
45  '' fill ctrl struct
46  list->tbhead = NULL
47  list->tbtail = NULL
48  list->nodes = 0
49  list->nodelen = nodelen + len( TLISTNODE )
50  list->head = NULL
51  list->tail = NULL
52  list->flags = flags
53 
54  '' allocate the initial pool
55  listAllocTB( list, nodes )
56 
57 end sub
58 
59 sub listEnd(byval list as TLIST ptr)
60  dim as TLISTTB ptr tb = any, nxt = any
61 
62  '' for each pool, free the mem block and the pool ctrl struct
63  tb = list->tbhead
64  do while( tb <> NULL )
65  nxt = tb->next
66  deallocate( tb->nodetb )
67  deallocate( tb )
68  tb = nxt
69  loop
70 
71  list->tbhead = NULL
72  list->tbtail = NULL
73  list->nodes = 0
74 end sub
75 
76 sub listAllocTB _
77  ( _
78  byval list as TLIST ptr, _
79  byval nodes as integer _
80  )
81 
82  dim as TLISTNODE ptr nodetb = any, node = any, prv = any
83  dim as TLISTTB ptr tb = any
84  dim as integer i = any
85 
86  assert(nodes >= 1)
87 
88  '' allocate the pool
89  if( (list->flags and LIST_FLAGS_CLEARNODES) <> 0 ) then
90  nodetb = xcallocate( nodes * list->nodelen )
91  else
92  nodetb = xallocate( nodes * list->nodelen )
93  end if
94 
95  '' and the pool ctrl struct
96  tb = xallocate( len( TLISTTB ) )
97 
98  '' add the ctrl struct to pool list
99  if( list->tbhead = NULL ) then
100  list->tbhead = tb
101  end if
102  if( list->tbtail <> NULL ) then
103  list->tbtail->next = tb
104  end if
105  list->tbtail = tb
106 
107  tb->next = NULL
108  tb->nodetb = nodetb
109  tb->nodes = nodes
110 
111  '' add new nodes to the free list
112  list->fhead = nodetb
113  list->nodes += nodes
114 
115  ''
116  if( (list->flags and LIST_FLAGS_LINKFREENODES) <> 0 ) then
117  prv = NULL
118  node = list->fhead
119 
120  for i = 1 to nodes-1
121  node->prev = prv
122  node->next = cast( TLISTNODE ptr, cast( byte ptr, node ) + list->nodelen )
123 
124  prv = node
125  node = node->next
126  next
127 
128  node->prev = prv
129  node->next = NULL
130  end if
131 
132 end sub
133 
134 '':::::
135 function listNewNode _
136  ( _
137  byval list as TLIST ptr _
138  ) as any ptr
139 
140  dim as TLISTNODE ptr node = any, tail = any
141 
142  '' alloc new node list if there are no free nodes
143  if( list->fhead = NULL ) Then
144  listAllocTB( list, cunsg(list->nodes) \ 4 )
145  end if
146 
147  '' take from free list
148  node = list->fhead
149  list->fhead = node->next
150 
151  if( (list->flags and LIST_FLAGS_LINKUSEDNODES) <> 0 ) then
152  '' add to used list
153  tail = list->tail
154  list->tail = node
155  if( tail <> NULL ) then
156  tail->next = node
157  else
158  list->head = node
159  end If
160 
161  node->prev = tail
162  node->next = NULL
163 
164  function = cast( byte ptr, node ) + len( TLISTNODE )
165 
166  else
167  function = node
168  end if
169 
170 end function
171 
172 '':::::
173 sub listDelNode _
174  ( _
175  byval list as TLIST ptr, _
176  byval node_ as any ptr _
177  )
178 
179  dim as TLISTNODE ptr node = any, prv = any, nxt = any
180 
181  if( node_ = NULL ) then
182  exit sub
183  end if
184 
185  if( (list->flags and LIST_FLAGS_LINKUSEDNODES) <> 0 ) then
186  node = cast( TLISTNODE ptr, cast( byte ptr, node_ ) - len( TLISTNODE ) )
187 
188  '' remove from used list
189  prv = node->prev
190  nxt = node->next
191  if( prv <> NULL ) then
192  prv->next = nxt
193  else
194  list->head = nxt
195  end If
196 
197  if( nxt <> NULL ) then
198  nxt->prev = prv
199  else
200  list->tail = prv
201  end If
202 
203  else
204  node = cast( TLISTNODE ptr, node_ )
205  end if
206 
207  '' add to free list
208  node->next = list->fhead
209  list->fhead = node
210 
211  '' node can contain strings descriptors, so, erase it..
212  if( (list->flags and LIST_FLAGS_CLEARNODES) <> 0 ) then
213  clear( byval node_, 0, list->nodelen - len( TLISTNODE ) )
214  end if
215 
216 end sub
217 
218 '':::::
219 function listGetHead _
220  ( _
221  byval list as TLIST ptr _
222  ) as any ptr
223 
224  assert( (list->flags and LIST_FLAGS_LINKUSEDNODES) <> 0 )
225 
226  if( list->head = NULL ) then
227  function = NULL
228  else
229  function = cast( byte ptr, list->head ) + len( TLISTNODE )
230  end if
231 
232 end function
233 
234 '':::::
235 function listGetTail _
236  ( _
237  byval list as TLIST ptr _
238  ) as any ptr
239 
240  assert( (list->flags and LIST_FLAGS_LINKUSEDNODES) <> 0 )
241 
242  if( list->tail = NULL ) then
243  function = NULL
244  else
245  function = cast( byte ptr, list->tail ) + len( TLISTNODE )
246  end if
247 
248 end function
249 
250 '':::::
251 function listGetPrev _
252  ( _
253  byval node as any ptr _
254  ) as any ptr
255 
256  dim as TLISTNODE ptr prev = any
257 
258  assert( node <> NULL )
259 
260  prev = cast( TLISTNODE ptr, _
261  cast( byte ptr, node ) - len( TLISTNODE ) )->prev
262 
263  if( prev = NULL ) then
264  function = NULL
265  else
266  function = cast( byte ptr, prev ) + len( TLISTNODE )
267  end if
268 
269 end function
270 
271 '':::::
272 function listGetNext _
273  ( _
274  byval node as any ptr _
275  ) as any ptr
276 
277  dim as TLISTNODE ptr nxt = any
278 
279  assert( node <> NULL )
280 
281  nxt = cast( TLISTNODE ptr, _
282  cast( byte ptr, node ) - len( TLISTNODE ) )->next
283 
284  if( nxt = NULL ) then
285  function = NULL
286  else
287  function = cast( byte ptr, nxt ) + len( TLISTNODE )
288  end if
289 
290 end function
291 
292 sub strlistAppend(byval list as TLIST ptr, byref s as string)
293  dim as string ptr p = listNewNode(list)
294  *p = s
295 end sub
296 
297 sub strlistInit(byval list as TLIST ptr, byval nodes as integer)
298  listInit(list, nodes, sizeof(string))
299 end sub
300