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