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