Annotation of libelwix/src/array.c, revision 1.8
1.1 misho 1: /*************************************************************************
2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.8 ! misho 6: * $Id: array.c,v 1.7.2.1 2019/01/22 16:16:45 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.6 misho 15: Copyright 2004 - 2019
1.1 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
49: /*
50: * array_Init() - Create and initialize dynamic array
51: *
52: * @numItems = Number of Items
53: * return: NULL error, != NULL allocated memory for array
54: */
1.2 misho 55: array_t *
1.1 misho 56: array_Init(int numItems)
57: {
58: array_t *arr = NULL;
59:
60: arr = e_malloc(sizeof(array_t));
61: if (!arr)
62: return NULL;
63:
64: arr->arr_last = -1;
65: arr->arr_num = numItems;
66: arr->arr_data = e_calloc(array_Size(arr), sizeof(intptr_t));
67: if (!arr->arr_data) {
68: e_free(arr);
69: return NULL;
70: } else
71: array_Zero(arr);
72:
73: return arr;
74: }
1.8 ! misho 75:
! 76: /*
! 77: * array_Init2() - Initialize dynamic array
! 78: *
! 79: * @arr = Allocated array variable
! 80: * @numItems = Number of Items
! 81: * return: NULL error, != NULL allocated memory for array
! 82: */
! 83: array_t *
! 84: array_Init2(array_t * __restrict arr, int numItems)
! 85: {
! 86: if (!arr)
! 87: return array_Init(numItems);
! 88:
! 89: if (array_Size(arr))
! 90: return NULL; /* already allocated array! */
! 91:
! 92: arr->arr_last = -1;
! 93: arr->arr_num = numItems;
! 94: arr->arr_data = e_calloc(array_Size(arr), sizeof(intptr_t));
! 95: if (!arr->arr_data) {
! 96: e_free(arr);
! 97: return NULL;
! 98: } else
! 99: array_Zero(arr);
! 100:
! 101: return arr;
! 102: }
! 103:
1.1 misho 104:
105: /*
106: * array_From() - Create and fill array from array with pointers
107: *
108: * @pargv = Array with pointers
109: * @argc = Number of Items, if 0 walk through argv and stop when reach NULL item
110: * return: NULL error, != NULL allocated new array
111: */
112: array_t *
113: array_From(const char *** __restrict pargv, int argc)
114: {
115: array_t *arr = NULL;
116: const char **a = NULL;
117: register int num = 0;
118:
119: if (!pargv || !*pargv || argc < 0)
120: return NULL;
121:
122: if (argc)
123: num = argc;
124: else
125: for (a = *pargv; *a; a++, num++);
126:
127: arr = array_Init(num);
128: if (!arr)
129: return NULL;
130: else {
131: memcpy(arr->arr_data, *pargv, array_Size(arr) * sizeof(intptr_t));
132: arr->arr_last = array_Size(arr) - 1;
133: }
134:
135: return arr;
136: }
137:
138: /*
139: * array_To() - Create and fill array with pointers from dynamic array
140: *
141: * @arr = Array
142: * return: NULL error, != NULL allocated memory for array, NULL terminated
143: */
144: char **
145: array_To(array_t * __restrict arr)
146: {
147: char **args = NULL;
148:
149: if (!arr || !array_Size(arr))
150: return NULL;
151:
152: args = (char **) e_calloc(array_Size(arr) + 1, sizeof(char*));
153: if (!args)
154: return NULL;
155: else
156: memcpy(args, arr->arr_data, array_Size(arr) * sizeof(char*));
157: args[array_Size(arr)] = NULL;
158:
159: return args;
160: }
161:
162: /*
163: * array_Free() - Free all data in dynamic array items
164: * (WARNING! If assign static array dont use this!!!)
165: *
166: * @arr = Array
167: * return: none
168: */
1.2 misho 169: void
1.1 misho 170: array_Free(array_t * __restrict arr)
171: {
172: register int i;
173:
174: if (!arr)
175: return;
176:
177: for (i = 0; i < array_Size(arr); i++)
178: if (arr->arr_data[i]) {
179: e_free(arr->arr_data[i]);
180: arr->arr_data[i] = NULL;
181: }
182:
183: arr->arr_last = -1;
184: }
185:
186: /*
187: * array_Destroy() - Free and destroy dynamic array
188: *
189: * @parr = Array
190: * return: none
191: */
1.2 misho 192: void
1.1 misho 193: array_Destroy(array_t ** __restrict parr)
194: {
195: if (!parr || !*parr)
196: return;
197:
198: if ((*parr)->arr_data)
199: e_free((*parr)->arr_data);
200: e_free(*parr);
201: *parr = NULL;
1.6 misho 202: }
203:
204: /*
205: * array_Reset() - Reset array to initial state
206: *
207: * @parr = Array
208: * @purge = Purge data, if <>0 then will be free entire data memory
209: * return: none
210: */
211: void
212: array_Reset(array_t * __restrict arr, int purge)
213: {
214: if (!arr)
215: return;
216:
217: if (purge && arr->arr_data) {
218: e_free(arr->arr_data);
1.7 misho 219: arr->arr_num = 0;
1.6 misho 220: arr->arr_data = e_calloc(array_Size(arr), sizeof(intptr_t));
221: }
222:
223: array_Zero(arr);
1.7 misho 224: arr->arr_last = -1;
1.1 misho 225: }
226:
227: /*
228: * array_Len() - Get last used element in dynamic array (array Length)
229: *
230: * @arr = Array
231: * return: -1 empty or >-1 position of last used element
232: */
1.2 misho 233: int
1.1 misho 234: array_Len(array_t * __restrict arr)
235: {
236: register int i;
237:
238: if (!arr)
239: return -1;
240:
241: for (i = array_Size(arr); i && !arr->arr_data[i - 1]; i--);
242:
243: return --i;
244: }
245:
246: /*
247: * array_Grow() - Grow/Shrink dynamic array, Use with care when it shrink!!!
248: *
249: * @arr = Array
250: * @newNumItems = Number of Items
251: * @freeShrink = Free elements before shrink array
252: * return: -1 error, 0 ok
253: */
254: int
255: array_Grow(array_t * __restrict arr, int newNumItems, int freeShrink)
256: {
257: void **data;
258: int n = 0;
259: register int i;
260:
261: if (!arr)
262: return -1;
263:
264: if (arr->arr_num == newNumItems)
265: return 0;
266: if (array_Size(arr) < newNumItems) {
267: n = newNumItems - array_Size(arr);
268: } else if (freeShrink)
269: for (i = newNumItems; i < arr->arr_num; i++)
270: if (arr->arr_data[i])
271: e_free(arr->arr_data[i]);
272:
273: arr->arr_num = newNumItems;
274: if (array_Size(arr)) {
275: data = e_realloc(arr->arr_data, array_Size(arr) * sizeof(intptr_t));
276: if (!data)
277: return -1;
278: else
279: arr->arr_data = data;
280:
281: memset(arr->arr_data + (array_Size(arr) - n), 0, n * sizeof(intptr_t));
282: arr->arr_last = array_Len(arr);
283: } else {
284: if (arr->arr_data)
285: e_free(arr->arr_data);
286: arr->arr_data = NULL;
287: arr->arr_last = -1;
288: }
289:
290: return 0;
291: }
292:
293: /*
294: * array_Vacuum() - Vacuum dynamic array, empty elements will be deleted
295: *
296: * @arr = Array
297: * @fromWhere = 1 begin, 2 ALL empty elements
298: * return: -1 error, 0 ok
299: */
300: int
301: array_Vacuum(array_t * __restrict arr, int fromWhere)
302: {
303: register int i, j, num;
304: int cx = 0;
305:
306: if (!arr)
307: return -1;
308: else
309: fromWhere &= 0x7;
310:
311: num = array_Size(arr);
312: #ifdef VACUUM_RIGHT
313: if (fromWhere & VACUUM_RIGHT) {
314: for (cx = 0, i = num - 1; i && !arr->arr_data[i]; i--, cx++);
315: num -= cx;
316: }
317: #endif
318: if (fromWhere & VACUUM_LEFT) {
319: for (i = 0; i < num && !arr->arr_data[i]; i++);
320: if (i) {
321: memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(intptr_t));
322: memset(arr->arr_data + (num - i), 0, i * sizeof(intptr_t));
323:
324: num -= i;
325: cx += i;
326: }
327: }
328: if (fromWhere & VACUUM_BETWEEN) {
329: for (i = 0; i < num; i++) {
330: if (arr->arr_data[i])
331: continue;
332:
333: for (j = i; j < num && !arr->arr_data[j]; j++);
334:
335: memmove(arr->arr_data + i, arr->arr_data + j, (num - j) * sizeof(intptr_t));
336: memset(arr->arr_data + i + (num - j), 0, (j - i) * sizeof(intptr_t));
337:
338: num -= j - i;
339: cx += j - i;
340: }
341: }
342:
343: arr->arr_last = array_Len(arr);
344: return cx;
345: }
346:
347: /*
348: * array_Concat() Concat source array to destination array
349: *
350: * @dest = Destination array
351: * @src = Source array
352: * return: -1 error; >0 new count of destination array
353: */
354: int
355: array_Concat(array_t * __restrict dest, array_t * __restrict src)
356: {
357: int n;
358:
359: if (!dest || !src)
360: return -1;
361:
362: n = array_Size(dest);
363: if (array_Grow(dest, n + array_Size(src), 0))
364: return -1;
365: memcpy(dest->arr_data + n, src->arr_data, array_Size(src) * sizeof(intptr_t));
366:
367: dest->arr_last = array_Len(dest);
368: return array_Size(dest);
369: }
370:
371: /*
372: * array_Copy() Copy source array to destination array
373: *
1.3 misho 374: * @dest = Destination array, after use free with array_Destroy()
1.1 misho 375: * @src = Source array
376: * return: -1 error; >0 count of destination array
377: */
378: int
379: array_Copy(array_t ** __restrict dest, array_t * __restrict src)
380: {
381: if (!dest || !src)
382: return -1;
383:
384: *dest = array_Init(array_Size(src));
385: if (!*dest)
386: return -1;
387: else
388: (*dest)->arr_last = src->arr_last;
389:
390: memcpy((*dest)->arr_data, src->arr_data, array_Size(*dest) * sizeof(intptr_t));
391: return array_Size(*dest);
392: }
393:
394: /*
395: * array_Elem() - Always GET/PUT element into dynamic array, if not enough elements grow array
396: *
397: * @arr = Array
398: * @n = Position
399: * @data = Element, if set NULL GET element at position or !=NULL PUT element at position
400: * return: -1 error or !=-1 return element at position
401: */
1.2 misho 402: void *
1.1 misho 403: array_Elem(array_t * __restrict arr, int n, void *data)
404: {
405: void *dat = NULL;
406:
407: if (!arr)
408: return (void*) -1;
409:
410: if (n >= array_Size(arr) && array_Grow(arr, n + 1, 0))
411: return (void*) -1;
412:
413: dat = array_Get(arr, n);
414: if (data)
415: array_Set(arr, n, data);
416:
417: return dat;
418: }
419:
420: /*
421: * array_Push() - Push element into dynamic array like stack manner, place at first empty position
422: *
423: * @arr = Array
424: * @data = Element, if set NULL return only first empty position
425: * @nogrow = Don't grow array if not enough space
426: * return: -1 not found empty position, array is full!, >-1 return position of stored element into array
427: */
1.2 misho 428: int
429: array_Push(array_t * __restrict arr, void *data, int nogrow)
1.1 misho 430: {
431: int ret = -1;
432:
433: if (!arr)
434: return -1;
435: else
436: ret = array_Last(arr) + 1;
437: if (nogrow && ret >= array_Size(arr))
438: return -1;
439: if (!nogrow && ret >= array_Size(arr) && array_Grow(arr, ret + 1, 0))
440: return -1;
441:
1.2 misho 442: ret = ++arr->arr_last;
443: arr->arr_data[arr->arr_last] = data;
1.1 misho 444:
445: return ret;
446: }
447:
448: /*
449: * array_Pop() - Pop element from dynamic array like stack manner, last used position
450: *
451: * @arr = Array
452: * @data = Element, if set NULL return only last used position
453: * @nodel = Don't delete after Pop element
454: * return: -1 not found used position, array is empty!, >-1 return element position
455: */
1.2 misho 456: int
1.1 misho 457: array_Pop(array_t * __restrict arr, void ** __restrict data, int nodel)
458: {
459: int ret = -1;
460:
461: if (!arr)
462: return -1;
463:
1.2 misho 464: if ((ret = array_Last(arr)) != -1) {
465: if (data)
466: *data = arr->arr_data[arr->arr_last];
467: if (!nodel)
468: arr->arr_data[arr->arr_last] = NULL;
469: arr->arr_last--;
470: }
1.1 misho 471:
472: return ret;
473: }
474:
475: /*
476: * array_Args() Parse and make array from arguments ... (input string will be modified!!!
1.3 misho 477: * and output array must be free with array_Destroy() after use!)
1.1 misho 478: *
479: * @psArgs = Input arguments line, after execute string is modified!!!
480: * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs
481: * @csDelim = Delimiter(s) for separate
482: * @parr = Output array of arguments ... (must be free with array_Destroy() after use!)
483: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
484: */
485: int
486: array_Args(char * __restrict psArgs, int nargs, const char *csDelim, array_t ** __restrict parr)
487: {
488: char **app;
489: register int i;
490:
491: if (!psArgs || !csDelim || !parr)
492: return -1;
493:
494: if (nargs)
495: i = nargs;
496: else
497: i = str_ArgsNum(psArgs, csDelim);
498:
499: *parr = array_Init(i);
500: if (!*parr)
501: return -1;
502:
503: for (i = 0, app = (char**) (*parr)->arr_data;
504: app < (char**) (*parr)->arr_data + (*parr)->arr_num &&
505: (*app = strsep((char **) &psArgs, csDelim));
506: **app ? i++ : i, **app ? app++ : app);
507:
508: (*parr)->arr_last = i - 1;
509: return i;
510: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>