1 /****************************************************************************
2 *
3 * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 * Copyright (C) 2003-2013 Sourcefire, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License Version 2 as
8 * published by the Free Software Foundation. You may not use, modify or
9 * distribute this program under any other version of the GNU General
10 * Public License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 ****************************************************************************/
22
23 /*
24 * sflsq.c
25 *
26 * Simple list, stack, queue, and dictionary implementations
27 * ( most of these implementations are list based - not performance monsters,
28 * and they all use alloc via s_alloc/s_free )
29 * Stack based Ineteger and Pointer Stacks, these are for performance.(inline would be better)
30 *
31 * 11/05/2005 - man - Added sflist_firstx() and sflist_nextx() with user
32 * provided SF_NODE inputs for tracking the list position. This allows
33 * multiple readers to traverse a list. The built in 'cur' field does not
34 * wrok for multiple readers.
35 *
36 *
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include "sflsq.h"
48
49 /*
50 * private alloc
51 */
s_alloc(size_t n)52 static void * s_alloc (size_t n)
53 {
54 void *p = (void*) calloc( 1,n );
55 return p;
56 }
57
58 /*
59 * private free
60 */
s_free(void * p)61 static void s_free (void *p)
62 {
63 if( p ) free( p );
64 }
65
66 /*
67 * INIT - called by the NEW functions
68 */
sflist_init(SF_LIST * s)69 void sflist_init ( SF_LIST * s)
70 {
71 s->count=0;
72 s->head = s->tail = s->cur = 0;
73 }
74
75 /*
76 * NEW
77 */
sflist_new(void)78 SF_LIST * sflist_new(void)
79 {
80 SF_LIST * s;
81 s = (SF_LIST*)s_alloc( sizeof(SF_LIST) );
82 if( s )sflist_init( s );
83 return s;
84 }
85
sfstack_new(void)86 SF_STACK * sfstack_new(void)
87 {
88 return (SF_STACK*)sflist_new();
89 }
90
sfqueue_new(void)91 SF_QUEUE * sfqueue_new(void)
92 {
93 return (SF_QUEUE*)sflist_new();
94 }
95 /*
96 * Add-before Item
97 */
sflist_add_before(SF_LIST * s,SF_LNODE * lnode,NODE_DATA ndata)98 int sflist_add_before ( SF_LIST* s, SF_LNODE * lnode, NODE_DATA ndata )
99 {
100 SF_LNODE * q;
101
102 if( !lnode )
103 return 0;
104
105 /* Add to head of list */
106 if( s->head == lnode )
107 {
108 return sflist_add_head ( s, ndata );
109 }
110 else
111 {
112 q = (SF_LNODE *) s_alloc ( sizeof (SF_LNODE) );
113 if( !q )
114 {
115 return -1;
116 }
117 q->ndata = (NODE_DATA)ndata;
118
119 q->next = lnode;
120 q->prev = lnode->prev;
121 lnode->prev->next = q;
122 lnode->prev = q;
123 }
124 s->count++;
125
126 return 0;
127 }
128
129 /*
130 * ADD to List/Stack/Queue/Dictionary
131 */
132 /*
133 * Add-Head Item
134 */
135 int
sflist_add_head(SF_LIST * s,NODE_DATA ndata)136 sflist_add_head ( SF_LIST* s, NODE_DATA ndata )
137 {
138 SF_LNODE * q;
139 if (!s->head)
140 {
141 q = s->tail = s->head = (SF_LNODE *) s_alloc (sizeof (SF_LNODE));
142 if(!q)return -1;
143 q->ndata = (NODE_DATA)ndata;
144 q->next = 0;
145 q->prev = 0;
146 }
147 else
148 {
149 q = (SF_LNODE *) s_alloc (sizeof (SF_LNODE));
150 if(!q)return -1;
151 q->ndata = ndata;
152 q->next = s->head;
153 q->prev = 0;
154 s->head->prev = q;
155 s->head = q;
156
157 }
158 s->count++;
159
160 return 0;
161 }
162
163 /*
164 * Add-Tail Item
165 */
166 int
sflist_add_tail(SF_LIST * s,NODE_DATA ndata)167 sflist_add_tail ( SF_LIST* s, NODE_DATA ndata )
168 {
169 SF_LNODE * q;
170 if (!s->head)
171 {
172 q = s->tail = s->head = (SF_LNODE *) s_alloc (sizeof (SF_LNODE));
173 if(!q)return -1;
174 q->ndata = (NODE_DATA)ndata;
175 q->next = 0;
176 q->prev = 0;
177 }
178 else
179 {
180 q = (SF_LNODE *) s_alloc (sizeof (SF_LNODE));
181 if(!q)return -1;
182 q->ndata = ndata;
183 q->next = 0;
184 q->prev = s->tail;
185 s->tail->next = q;
186 s->tail = q;
187 }
188 s->count++;
189
190 return 0;
191 }
192
sfqueue_add(SF_QUEUE * s,NODE_DATA ndata)193 int sfqueue_add(SF_QUEUE * s, NODE_DATA ndata )
194 {
195 return sflist_add_tail ( s, ndata );
196 }
197
sfstack_add(SF_STACK * s,NODE_DATA ndata)198 int sfstack_add( SF_STACK* s, NODE_DATA ndata )
199 {
200 return sflist_add_tail ( s, ndata );
201 }
202
203 /*
204 * List walk - First/Next - return the node data or NULL
205 */
sflist_first(SF_LIST * s)206 NODE_DATA sflist_first( SF_LIST * s )
207 {
208 if(!s)
209 return 0;
210
211 s->cur = s->head;
212 if( s->cur )
213 return s->cur->ndata;
214 return 0;
215 }
sflist_next(SF_LIST * s)216 NODE_DATA sflist_next( SF_LIST * s )
217 {
218 if(!s)
219 return 0;
220
221 if( s->cur )
222 {
223 s->cur = s->cur->next;
224 if( s->cur )
225 return s->cur->ndata;
226 }
227 return 0;
228 }
sflist_firstpos(SF_LIST * s,SF_LNODE ** v)229 NODE_DATA sflist_firstpos( SF_LIST * s, SF_LNODE ** v )
230 {
231 if(!s)
232 return 0;
233
234 *v = s->head;
235
236 if( *v )
237 return (*v)->ndata;
238
239 return 0;
240 }
sflist_nextpos(SF_LIST * s,SF_LNODE ** v)241 NODE_DATA sflist_nextpos( SF_LIST * s, SF_LNODE ** v )
242 {
243 if(!s)
244 return 0;
245
246 if(v)
247 {
248 if(*v)
249 {
250 *v = (*v)->next;
251 if( *v )
252 return (*v)->ndata;
253 }
254 }
255 return 0;
256 }
257 /*
258 * List walk - First/Next - return the node data or NULL
259 */
sflist_first_node(SF_LIST * s)260 SF_LNODE * sflist_first_node( SF_LIST * s )
261 {
262 if(!s)
263 return 0;
264
265 s->cur = s->head;
266 return s->cur;
267 }
sflist_next_node(SF_LIST * s)268 SF_LNODE * sflist_next_node( SF_LIST * s )
269 {
270 if(!s)
271 return 0;
272 if( s->cur )
273 {
274 s->cur = s->cur->next;
275 if( s->cur )
276 return s->cur;
277 }
278 return 0;
279 }
280
281 /*
282 * Remove Head Item from list
283 */
sflist_remove_head(SF_LIST * s)284 NODE_DATA sflist_remove_head (SF_LIST * s)
285 {
286 NODE_DATA ndata = 0;
287 SF_QNODE * q;
288 if ( s && s->head )
289 {
290 q = s->head;
291 ndata = q->ndata;
292 s->head = s->head->next;
293 s->count--;
294 if( !s->head )
295 {
296 s->tail = 0;
297 }
298 else
299 {
300 s->head->prev = NULL;
301 }
302 s_free( q );
303 }
304 return (NODE_DATA)ndata;
305 }
306
307 /*
308 * Remove tail Item from list
309 */
sflist_remove_tail(SF_LIST * s)310 NODE_DATA sflist_remove_tail (SF_LIST * s)
311 {
312 NODE_DATA ndata = 0;
313 SF_QNODE * q;
314 if (s && s->tail)
315 {
316 q = s->tail;
317
318 ndata = q->ndata;
319 s->count--;
320 s->tail = q->prev;
321 if (!s->tail)
322 {
323 s->head = NULL;
324 }
325 else
326 {
327 s->tail->next = NULL;
328 }
329 s_free (q);
330 }
331 return (NODE_DATA)ndata;
332 }
333
sflist_remove_node(SF_LIST * s,SF_LNODE * n)334 void sflist_remove_node (SF_LIST * s, SF_LNODE * n)
335 {
336 // NODE_DATA ndata = 0;
337 SF_LNODE * cur;
338
339 if( n == s->head )
340 {
341 s->head = s->head->next;
342 s->count--;
343 if (!s->head)
344 {
345 s->tail = 0;
346 }
347 else
348 {
349 s->head->prev = NULL;
350 }
351 s_free( n );
352 return ;
353 }
354 else if( n == s->tail )
355 {
356 s->tail = s->tail->prev;
357 s->count--;
358 if (!s->tail )
359 {
360 s->head = 0;
361 }
362 else
363 {
364 s->tail->next = NULL;
365 }
366 s_free( n );
367 return ;
368 }
369
370 for(cur = s->head;
371 cur!= NULL;
372 cur = cur->next )
373 {
374 if( n == cur )
375 {
376 /* unlink a middle node */
377 n->next->prev = n->prev;
378 n->prev->next = n->next;
379 s->count--;
380 s_free(n);
381 return ;
382 }
383 }
384 }
385
386 /*
387 * Remove Head Item from queue
388 */
sfqueue_remove(SF_QUEUE * s)389 NODE_DATA sfqueue_remove (SF_QUEUE * s)
390 {
391 return (NODE_DATA)sflist_remove_head( s );
392 }
393
394 /*
395 * Remove Tail Item from stack
396 */
sfstack_remove(SF_QUEUE * s)397 NODE_DATA sfstack_remove (SF_QUEUE * s)
398 {
399 return (NODE_DATA)sflist_remove_tail( s );
400 }
401
402 /*
403 * COUNT
404 */
sfqueue_count(SF_QUEUE * s)405 int sfqueue_count (SF_QUEUE * s)
406 {
407 if(!s)return 0;
408 return s->count;
409 }
sflist_count(SF_LIST * s)410 int sflist_count ( SF_LIST* s)
411 {
412 if(!s)return 0;
413 return s->count;
414 }
sfstack_count(SF_STACK * s)415 int sfstack_count ( SF_STACK * s)
416 {
417 if(!s)return 0;
418 return s->count;
419 }
420
421
422 /*
423 * Free List + Free it's data nodes using 'nfree'
424 */
sflist_free_all(SF_LIST * s,void (* nfree)(void *))425 void sflist_free_all( SF_LIST * s, void (*nfree)(void*) )
426 {
427 void * p;
428
429 if(!s)
430 return;
431
432 while( s->count > 0 )
433 {
434 p = sflist_remove_head (s);
435
436 if( p && nfree )
437 nfree( p );
438 }
439 s_free(s);
440 }
441
sfqueue_free_all(SF_QUEUE * s,void (* nfree)(void *))442 void sfqueue_free_all(SF_QUEUE * s,void (*nfree)(void*) )
443 {
444 sflist_free_all( s, nfree );
445 }
446
sfstack_free_all(SF_STACK * s,void (* nfree)(void *))447 void sfstack_free_all(SF_STACK * s,void (*nfree)(void*) )
448 {
449 sflist_free_all( s, nfree );
450 }
451
sflist_static_free_all(SF_LIST * s,void (* nfree)(void *))452 void sflist_static_free_all( SF_LIST * s, void (*nfree)(void*) )
453 {
454 void * p;
455
456 if(!s)
457 return;
458
459 while( s->count > 0 )
460 {
461 p = sflist_remove_head (s);
462
463 if( p && nfree )
464 nfree( p );
465 }
466 }
467
sfqueue_static_free_all(SF_QUEUE * s,void (* nfree)(void *))468 void sfqueue_static_free_all(SF_QUEUE * s,void (*nfree)(void*) )
469 {
470 sflist_static_free_all( s, nfree );
471 }
472
sfstack_static_free_all(SF_STACK * s,void (* nfree)(void *))473 void sfstack_static_free_all(SF_STACK * s,void (*nfree)(void*) )
474 {
475 sflist_static_free_all( s, nfree );
476 }
477
478
479 /*
480 * FREE List/Queue/Stack/Dictionary
481 *
482 * This does not free a nodes data
483 */
sflist_free(SF_LIST * s)484 void sflist_free (SF_LIST * s)
485 {
486 while( sflist_count(s) )
487 {
488 sflist_remove_head(s);
489 }
490 s_free(s);
491 }
sfqueue_free(SF_QUEUE * s)492 void sfqueue_free (SF_QUEUE * s)
493 {
494 sflist_free ( s );
495 }
sfstack_free(SF_STACK * s)496 void sfstack_free (SF_STACK * s)
497 {
498 sflist_free ( s );
499 }
500
501 /* Use these if the SF_LIST was not dynamically allocated via
502 * sflist_new() */
sflist_static_free(SF_LIST * s)503 void sflist_static_free(SF_LIST *s)
504 {
505 while (sflist_count(s))
506 sflist_remove_head(s);
507 }
508
sfqueue_static_free(SF_QUEUE * s)509 void sfqueue_static_free(SF_QUEUE *s)
510 {
511 sflist_static_free(s);
512 }
513
sfstack_static_free(SF_STACK * s)514 void sfstack_static_free(SF_STACK *s)
515 {
516 sflist_static_free(s);
517 }
518
519 /*
520 * Integer stack functions - for performance scenarios
521 */
sfistack_init(SF_ISTACK * s,unsigned * a,unsigned n)522 int sfistack_init( SF_ISTACK * s, unsigned * a, unsigned n )
523 {
524 if( a ) s->stack = a;
525 else
526 {
527 s->stack = (unsigned*) calloc( n, sizeof(unsigned) );
528 }
529 if( !s->stack ) return -1;
530 s->nstack= n;
531 s->n =0;
532 return 0;
533 }
sfistack_push(SF_ISTACK * s,unsigned value)534 int sfistack_push( SF_ISTACK *s, unsigned value)
535 {
536 if( s->n < s->nstack )
537 {
538 s->stack[s->n++] = value;
539 return 0;
540 }
541 return -1;
542 }
sfistack_pop(SF_ISTACK * s,unsigned * value)543 int sfistack_pop( SF_ISTACK *s, unsigned * value)
544 {
545 if( s->n > 0 )
546 {
547 s->n--;
548 *value = s->stack[s->n];
549 return 0;
550 }
551 return -1;
552 }
553 /*
554 * Pointer Stack Functions - for performance scenarios
555 */
sfpstack_init(SF_PSTACK * s,void ** a,unsigned n)556 int sfpstack_init( SF_PSTACK * s, void ** a, unsigned n )
557 {
558 if( a ) s->stack = a;
559 else
560 {
561 s->stack = (void**) calloc( n , sizeof(void*) );
562 }
563
564 if( !s->stack ) return -1;
565 s->nstack= n;
566 s->n =0;
567 return 0;
568 }
sfpstack_push(SF_PSTACK * s,void * value)569 int sfpstack_push( SF_PSTACK *s, void * value)
570 {
571 if( s->n < s->nstack )
572 {
573 s->stack[s->n++] = value;
574 return 0;
575 }
576 return -1;
577 }
sfpstack_pop(SF_PSTACK * s,void ** value)578 int sfpstack_pop( SF_PSTACK *s, void ** value)
579 {
580 if( s->n > 0 )
581 {
582 s->n--;
583 *value = s->stack[s->n];
584 return 0;
585 }
586 return -1;
587 }
588