1 
2 #include "stdlib.h"
3 #include "string.h"
4 #include "list_struct.h"
5 
6 
7 /*----------------------------------------------------------------------
8  *
9  * list_struct.c            - for creating and destroying list structures
10  *
11  * each list structure contains:
12  *
13  *   num   - the number of elements used       (the user may alter this number)
14  *   nall  - the number of elements allocated
15  *   list  - the 'list', the list of elements (the user may alter these values)
16  *
17  * each pointer list structure also contains:
18  *
19  *   elen  - the length of each list in the main array
20  *
21  * Rick Reynolds - December 6, 2004
22  *----------------------------------------------------------------------*/
23 
24 
25 /*----------------------------------------------------------------------
26  * sample struct and prototypes:
27  *
28  *   I will use float for examples, noting that float may be replaced
29  *   with any of int, short and void, also.
30  *
31  *   typedef struct { int num,nall;  float *  list; } float_list;
32  *
33  *   int init_float_list ( float_list  * d_list, int nel );
34  *   int init_floatp_list( floatp_list * d_list, int nel );
35  *   int free_float_list ( float_list  * d_list );
36  *   int free_floatp_list( floatp_list * d_list );
37  *
38  * brief sample function descriptions:
39  *
40  *   Note that all of these functions set d_list->num to 0.  That
41  *   variable is for the user to apply, if they wish.
42  *
43  *   int init_float_list( float_list * d_list, int nel );
44  *
45  *       The user should pass a (useless) float_list structure.
46  *       This function will set num to 0, nall to the input nel
47  *       and allocate an array of length nel.
48  *
49  *       This will return nel (>= 0) on success, and < 0 on failure.
50  *
51  *   int init_floatp_list( floatp_list * d_list, int nel, int len );
52  *
53  *       Like above, but now d_list->list will be an array of
54  *       (float *).
55  *
56  *   int free_float_list( float_list * d_list );
57  *
58  *       This function will free d_list->list, and set num and nall to 0.
59  *
60  *----------------------------------------------------------------------*/
61 
62 
63 /*----------------------------------------------------------------------
64  * init_XXXX_list:
65  *
66  *   input: structure pointer and number of elements
67  *
68  *   if nel <= 0, set all fields to zero (or NULL)
69  *   if nel >  0, attempt to malloc the requested number of elements
70  *
71  *   return:
72  *       success: nel (>= 0)
73  *       failure: < 0
74  *----------------------------------------------------------------------*/
init_float_list(float_list * d_list,int nel)75 int init_float_list( float_list * d_list, int nel )
76 {
77     if ( !d_list ) return -1;
78 
79     if ( nel <= 0 ) {
80         d_list->num = 0;  d_list->nall = 0;  d_list->list = NULL;
81         return 0;
82     }
83 
84     d_list->list = (float *)malloc(nel * sizeof(float));   /* allocate memory */
85 
86     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
87 
88     d_list->num = 0;
89     d_list->nall = nel;
90 
91     return nel;
92 }
93 
init_int_list(int_list * d_list,int nel)94 int init_int_list( int_list * d_list, int nel )
95 {
96     if ( !d_list ) return -1;
97 
98     if ( nel <= 0 ) {
99         d_list->num = 0;  d_list->nall = 0;  d_list->list = NULL;
100         return 0;
101     }
102 
103     d_list->list = (int *)malloc(nel * sizeof(int));       /* allocate memory */
104 
105     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
106 
107     d_list->num = 0;
108     d_list->nall = nel;
109 
110     return nel;
111 }
112 
init_short_list(short_list * d_list,int nel)113 int init_short_list( short_list * d_list, int nel )
114 {
115     if ( !d_list ) return -1;
116 
117     if ( nel <= 0 ) {
118         d_list->num = 0;  d_list->nall = 0;  d_list->list = NULL;
119         return 0;
120     }
121 
122     d_list->list = (short *)malloc(nel * sizeof(short));   /* allocate memory */
123 
124     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
125 
126     d_list->num = 0;
127     d_list->nall = nel;
128 
129     return nel;
130 }
131 
132 /* string_list: memory allocation is optional        30 Jun 2014 [rickr] */
133 /* alloc: flag to allocate string memory, does not affect init           */
init_string_list(string_list * d_list,int nel,int alloc)134 int init_string_list( string_list * d_list, int nel, int alloc )
135 {
136     int ind;
137 
138     if ( !d_list ) return -1;
139 
140     if ( nel <= 0 ) {
141         d_list->num = 0;  d_list->nall = 0;  d_list->list = NULL;
142         return 0;
143     }
144 
145     d_list->list = (char **)malloc(nel * sizeof(char *));  /* allocate memory */
146     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
147 
148     /* init to NULL, just to be safe */
149     for( ind = 0; ind < nel; ind++ ) d_list->list[ind] = NULL;
150 
151     d_list->num  = 0;
152     d_list->nall = nel;
153     d_list->alloc  = alloc;
154 
155     return nel;
156 }
157 
158 
159 /*----------------------------------------------------------------------
160  * pointer lists:
161  *----------------------------------------------------------------------*/
init_floatp_list(floatp_list * d_list,int nel)162 int init_floatp_list( floatp_list * d_list, int nel )
163 {
164     if ( !d_list ) return -1;
165 
166     /* an 'empty' structure will contain 0 and NULL field entries */
167     if ( nel <= 0 ) {
168         d_list->num = d_list->nall = 0;
169         d_list->list  = NULL;
170         return 0;
171     }
172 
173     d_list->list = (float **)malloc(nel * sizeof(float *));/* allocate memory */
174 
175     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
176 
177     d_list->num = 0;                                     /* none used yet   */
178     d_list->nall = nel;                     /* number of pointers allocated */
179 
180     return nel;
181 }
182 
init_intp_list(intp_list * d_list,int nel)183 int init_intp_list( intp_list * d_list, int nel )
184 {
185     if ( !d_list ) return -1;
186 
187     /* an 'empty' structure will contain 0 and NULL field entries */
188     if ( nel <= 0 ) {
189         d_list->num = d_list->nall = 0;
190         d_list->list  = NULL;
191         return 0;
192     }
193 
194     d_list->list = (int **)malloc(nel * sizeof(int *));    /* allocate memory */
195 
196     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
197 
198     d_list->num = 0;                                       /* none used yet */
199     d_list->nall = nel;                     /* number of pointers allocated */
200 
201     return nel;
202 }
203 
init_shortp_list(shortp_list * d_list,int nel)204 int init_shortp_list( shortp_list * d_list, int nel )
205 {
206     if ( !d_list ) return -1;
207 
208     /* an 'empty' structure will contain 0 and NULL field entries */
209     if ( nel <= 0 ) {
210         d_list->num = d_list->nall = 0;
211         d_list->list  = NULL;
212         return 0;
213     }
214 
215     d_list->list = (short **)malloc(nel * sizeof(short *));/* allocate memory */
216 
217     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
218 
219     d_list->num = 0;                                       /* none used yet */
220     d_list->nall = nel;                     /* number of pointers allocated */
221 
222     return nel;
223 }
224 
init_voidp_list(voidp_list * d_list,int nel)225 int init_voidp_list( voidp_list * d_list, int nel )
226 {
227     if ( !d_list ) return -1;
228 
229     /* an 'empty' structure will contain 0 and NULL field entries */
230     if ( nel <= 0 ) {
231         d_list->num = d_list->nall = 0;
232         d_list->list  = NULL;
233         return 0;
234     }
235 
236     d_list->list = (void **)malloc(nel * sizeof(void *));  /* allocate memory */
237 
238     if ( d_list->list == NULL ) return -1;                 /* malloc failure  */
239 
240     d_list->num = 0;                                       /* none used yet */
241     d_list->nall = nel;                     /* number of pointers allocated */
242 
243     return nel;
244 }
245 
246 /*----------------------------------------------------------------------
247  * add_to_XXXX_list:                                 4 Nov, 2011 [rickr]
248  *
249  *   input: structure pointer, value, list increment size
250  *
251  *   return:
252  *       success: nel (>= 1)
253  *----------------------------------------------------------------------*/
add_to_float_list(float_list * d_list,float val,int inc_size)254 int add_to_float_list( float_list * d_list, float val, int inc_size )
255 {
256     int llen;
257 
258     if ( !d_list ) return -1;
259 
260     /* maybe we need more space */
261     if ( d_list->num >= d_list->nall ) {
262         if (inc_size <= 0) llen = d_list->nall + 1;
263         else               llen = d_list->nall + inc_size;
264         d_list->nall = llen;
265         d_list->list = (float *)realloc(d_list->list, llen*sizeof(float));
266         if( !d_list->list ) return -1;
267     }
268 
269     d_list->list[d_list->num++] = val;
270 
271     return d_list->num;
272 }
273 
add_to_int_list(int_list * d_list,int val,int inc_size)274 int add_to_int_list( int_list * d_list, int val, int inc_size )
275 {
276     int llen;
277 
278     if ( !d_list ) return -1;
279 
280     /* maybe we need more space */
281     if ( d_list->num >= d_list->nall ) {
282         if (inc_size <= 0) llen = d_list->nall + 1;
283         else               llen = d_list->nall + inc_size;
284         d_list->nall = llen;
285         d_list->list = (int *)realloc(d_list->list, llen*sizeof(int));
286         if( !d_list->list ) return -1;
287     }
288 
289     d_list->list[d_list->num++] = val;
290 
291     return d_list->num;
292 }
293 
294 /* must also allocate for passed string */
add_to_string_list(string_list * d_list,char * val,int inc_size)295 int add_to_string_list( string_list * d_list, char * val, int inc_size )
296 {
297     int llen, nadd, ind;
298 
299     if ( !d_list ) return -1;
300 
301     /* maybe we need more space */
302     if ( d_list->num >= d_list->nall ) {
303         /* note new size for NULL init */
304         if (inc_size <= 0) nadd = 1;
305         else               nadd = inc_size;
306         llen = d_list->nall + nadd;
307         d_list->list = (char **)realloc(d_list->list, llen*sizeof(char *));
308         if( !d_list->list ) return -1;
309         /* init to NULL */
310         for( ind = 0; ind < nadd; ind++ ) d_list->list[ind+d_list->nall] = NULL;
311         d_list->nall = llen;
312     }
313 
314     /* allocate memory or just copy pointer (copy includes NULL case) */
315     if( val && d_list->alloc ) d_list->list[d_list->num++] = strdup(val);
316     else                       d_list->list[d_list->num++] = val;
317 
318     return d_list->num;
319 }
320 
321 
322 /*----------------------------------------------------------------------
323  * resize_XXXX_list:                                         20 Aug 2014
324  *
325  * reset nalloc to the given length, return new length
326  *----------------------------------------------------------------------*/
resize_int_list(int_list * L,int len)327 int resize_int_list(int_list * L, int len)
328 {
329     int oldlen;
330 
331     if( !L || len < 0 )  return -1;
332     if( len == 0 )       return free_int_list(L);   /* nuke */
333     if( len == L->nall ) return len;                /* already done */
334 
335     L->list = (int *)realloc(L->list, len*sizeof(int));
336     if( !L->list ) return -1;
337 
338     /* either clear new memory or reset used length */
339     if(len > L->nall) memset(L->list+L->nall, '\0', (len-L->nall)* sizeof(int));
340     else              L->num = len;
341 
342     L->nall = len;
343 
344     return len;
345 }
346 
347 
348 
349 /*----------------------------------------------------------------------
350  * extend_XXXX_list:                                         26 Apr 2012
351  *
352  * extend first list by another, returning the new length (or -1 on error)
353  *----------------------------------------------------------------------*/
extend_int_list(int_list * Ldest,int_list * Lsrc)354 int extend_int_list( int_list * Ldest, int_list * Lsrc )
355 {
356     int newlen;
357 
358     if ( !Ldest || !Lsrc ) return -1;
359 
360     newlen = Ldest->num + Lsrc->num;
361 
362     /* maybe we need more space */
363     if ( newlen >= Ldest->nall ) {
364         Ldest->nall = newlen;
365         Ldest->list = (int *)realloc(Ldest->list, newlen*sizeof(int));
366         if( !Ldest->list ) return -1;
367     }
368 
369     /* now append Lsrc to Ldest */
370     memcpy(Ldest->list+Ldest->num, Lsrc->list, Lsrc->num * sizeof(int));
371     Ldest->num = newlen;
372 
373     return Ldest->num;
374 }
375 
376 
extend_string_list(string_list * Ldest,string_list * Lsrc)377 int extend_string_list( string_list * Ldest, string_list * Lsrc )
378 {
379     int newlen, ind;
380 
381     if ( !Ldest || !Lsrc ) return -1;
382 
383     newlen = Ldest->num + Lsrc->num;
384 
385     /* maybe we need more space */
386     if ( newlen >= Ldest->nall ) {
387         Ldest->nall = newlen;
388         Ldest->list = (char **)realloc(Ldest->list, newlen*sizeof(char *));
389         if( !Ldest->list ) return -1;
390     }
391 
392     /* now append Lsrc to Ldest (need to dupe strings) */
393     for( ind = 0; ind < Lsrc->num; ind++ )
394        if( add_to_string_list(Ldest, Lsrc->list[ind], 0) < 0 ) return -1;
395     Ldest->num = newlen;
396 
397     return Ldest->num;
398 }
399 
400 
401 /*----------------------------------------------------------------------
402  * free_XXXX_list:
403  *
404  * free all lists
405  *
406  * return 0 on success, -1 on error
407  *----------------------------------------------------------------------*/
free_float_list(float_list * d_list)408 int free_float_list( float_list * d_list )
409 {
410     if ( !d_list ) return -1;
411 
412     if ( d_list->list ) { free(d_list->list);  d_list->list = NULL; }
413     d_list->num = d_list->nall = 0;
414 
415     return 0;
416 }
417 
free_int_list(int_list * d_list)418 int free_int_list( int_list * d_list )
419 {
420     if ( !d_list ) return -1;
421 
422     if ( d_list->list ) { free(d_list->list);  d_list->list = NULL; }
423     d_list->num = d_list->nall = 0;
424 
425     return 0;
426 }
427 
428 /* keep list intact, but clear values */
clear_float_list(float_list * d_list)429 int clear_float_list( float_list * d_list )
430 {
431     int ind;
432 
433     if ( ! d_list ) return -1;
434     if ( d_list->nall <= 0 || ! d_list->list ) return 0;
435 
436     memset(d_list->list, '\0', d_list->nall*sizeof(float));
437     d_list->num = 0;
438 
439     return 0;
440 }
441 
442 /* keep list intact, but clear values */
clear_int_list(int_list * d_list)443 int clear_int_list( int_list * d_list )
444 {
445     int ind;
446 
447     if ( ! d_list ) return -1;
448     if ( d_list->nall <= 0 || ! d_list->list ) return 0;
449 
450     memset(d_list->list, '\0', d_list->nall*sizeof(int));
451     d_list->num = 0;
452 
453     return 0;
454 }
455 
free_short_list(short_list * d_list)456 int free_short_list( short_list * d_list )
457 {
458     if ( !d_list ) return -1;
459 
460     if ( d_list->list ) { free(d_list->list);  d_list->list = NULL; }
461     d_list->num = d_list->nall = 0;
462 
463     return 0;
464 }
465 
466 /* keep list intact, but free/clear any strings */
clear_string_list(string_list * d_list)467 int clear_string_list( string_list * d_list )
468 {
469     int ind;
470 
471     if ( ! d_list ) return -1;
472 
473     if ( d_list->list ) {
474        for( ind = 0; ind < d_list->num; ind++ ) {
475           if( d_list->list[ind] ) {
476              if( d_list->alloc ) free(d_list->list[ind]);
477              d_list->list[ind] = NULL;
478           }
479        }
480     }
481 
482     d_list->num = 0;
483 
484     return 0;
485 }
486 
free_string_list(string_list * d_list)487 int free_string_list( string_list * d_list )
488 {
489     int ind;
490 
491     if ( ! d_list ) return -1;
492 
493     if ( d_list->list ) {
494        if( d_list->alloc ) { /* then try to free */
495           for( ind = 0; ind < d_list->num; ind++ )
496              if( d_list->list[ind] ) free(d_list->list[ind]);
497        }
498        free(d_list->list);  d_list->list = NULL;
499     }
500 
501     d_list->num = d_list->nall = 0;
502 
503     return 0;
504 }
505 
506 
507 /*----------------------------------------------------------------------
508  * free_XXXXp_list:
509  *
510  * free all sub-lists and lists
511  *
512  * return 0 on success, -1 on error
513  *----------------------------------------------------------------------*/
free_floatp_list(floatp_list * d_list)514 int free_floatp_list( floatp_list * d_list )
515 {
516     if ( !d_list ) return -1;
517 
518     /* this is bad, but nothing to do */
519     if ( d_list->list ) free(d_list->list);
520 
521     d_list->list = NULL;
522     d_list->num = d_list->nall = 0;
523 
524     return 0;
525 }
526 
free_intp_list(intp_list * d_list)527 int free_intp_list( intp_list * d_list )
528 {
529     if ( !d_list ) return -1;
530 
531     if ( d_list->list ) free(d_list->list);
532 
533     d_list->list = NULL;
534     d_list->num = d_list->nall = 0;
535 
536     return 0;
537 }
538 
free_shortp_list(shortp_list * d_list)539 int free_shortp_list( shortp_list * d_list )
540 {
541     if ( !d_list ) return -1;
542 
543     if ( d_list->list ) free(d_list->list);
544 
545     d_list->list = NULL;
546     d_list->num = d_list->nall = 0;
547 
548     return 0;
549 }
550 
free_voidp_list(voidp_list * d_list)551 int free_voidp_list( voidp_list * d_list )
552 {
553     if ( !d_list ) return -1;
554 
555     if ( d_list->list ) free(d_list->list);
556 
557     d_list->list = NULL;
558     d_list->num = d_list->nall = 0;
559 
560     return 0;
561 }
562 
563