Annotation of libelwix/src/array.c, revision 1.8.4.1
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.4.1 ! misho 6: * $Id: array.c,v 1.8 2019/01/22 16:18:47 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
1.8.4.1 ! misho 71: memset(arr->arr_data, 0, array_Size(arr) * sizeof(intptr_t));
1.1 misho 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
1.8.4.1 ! misho 99: memset(arr->arr_data, 0, array_Size(arr) * sizeof(intptr_t));
1.8 misho 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++)
1.8.4.1 ! misho 178: if (arr->arr_data[i])
1.1 misho 179: e_free(arr->arr_data[i]);
180:
1.8.4.1 ! misho 181: array_Zero(arr);
1.1 misho 182: }
183:
184: /*
185: * array_Destroy() - Free and destroy dynamic array
186: *
187: * @parr = Array
188: * return: none
189: */
1.2 misho 190: void
1.1 misho 191: array_Destroy(array_t ** __restrict parr)
192: {
193: if (!parr || !*parr)
194: return;
195:
196: if ((*parr)->arr_data)
197: e_free((*parr)->arr_data);
198: e_free(*parr);
199: *parr = NULL;
1.6 misho 200: }
201:
202: /*
203: * array_Reset() - Reset array to initial state
204: *
205: * @parr = Array
206: * @purge = Purge data, if <>0 then will be free entire data memory
207: * return: none
208: */
209: void
210: array_Reset(array_t * __restrict arr, int purge)
211: {
212: if (!arr)
213: return;
214:
215: if (purge && arr->arr_data) {
216: e_free(arr->arr_data);
1.7 misho 217: arr->arr_num = 0;
1.6 misho 218: arr->arr_data = e_calloc(array_Size(arr), sizeof(intptr_t));
219: }
220:
221: array_Zero(arr);
1.1 misho 222: }
223:
224: /*
225: * array_Len() - Get last used element in dynamic array (array Length)
226: *
227: * @arr = Array
228: * return: -1 empty or >-1 position of last used element
229: */
1.2 misho 230: int
1.1 misho 231: array_Len(array_t * __restrict arr)
232: {
233: register int i;
234:
235: if (!arr)
236: return -1;
237:
238: for (i = array_Size(arr); i && !arr->arr_data[i - 1]; i--);
239:
240: return --i;
241: }
242:
243: /*
244: * array_Grow() - Grow/Shrink dynamic array, Use with care when it shrink!!!
245: *
246: * @arr = Array
247: * @newNumItems = Number of Items
248: * @freeShrink = Free elements before shrink array
249: * return: -1 error, 0 ok
250: */
251: int
252: array_Grow(array_t * __restrict arr, int newNumItems, int freeShrink)
253: {
254: void **data;
255: int n = 0;
256: register int i;
257:
258: if (!arr)
259: return -1;
260:
261: if (arr->arr_num == newNumItems)
262: return 0;
263: if (array_Size(arr) < newNumItems) {
264: n = newNumItems - array_Size(arr);
265: } else if (freeShrink)
266: for (i = newNumItems; i < arr->arr_num; i++)
267: if (arr->arr_data[i])
268: e_free(arr->arr_data[i]);
269:
270: arr->arr_num = newNumItems;
271: if (array_Size(arr)) {
272: data = e_realloc(arr->arr_data, array_Size(arr) * sizeof(intptr_t));
273: if (!data)
274: return -1;
275: else
276: arr->arr_data = data;
277:
278: memset(arr->arr_data + (array_Size(arr) - n), 0, n * sizeof(intptr_t));
279: arr->arr_last = array_Len(arr);
280: } else {
281: if (arr->arr_data)
282: e_free(arr->arr_data);
283: arr->arr_data = NULL;
284: arr->arr_last = -1;
285: }
286:
287: return 0;
288: }
289:
290: /*
291: * array_Vacuum() - Vacuum dynamic array, empty elements will be deleted
292: *
293: * @arr = Array
294: * @fromWhere = 1 begin, 2 ALL empty elements
295: * return: -1 error, 0 ok
296: */
297: int
298: array_Vacuum(array_t * __restrict arr, int fromWhere)
299: {
300: register int i, j, num;
301: int cx = 0;
302:
303: if (!arr)
304: return -1;
305: else
306: fromWhere &= 0x7;
307:
308: num = array_Size(arr);
309: #ifdef VACUUM_RIGHT
310: if (fromWhere & VACUUM_RIGHT) {
311: for (cx = 0, i = num - 1; i && !arr->arr_data[i]; i--, cx++);
312: num -= cx;
313: }
314: #endif
315: if (fromWhere & VACUUM_LEFT) {
316: for (i = 0; i < num && !arr->arr_data[i]; i++);
317: if (i) {
318: memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(intptr_t));
319: memset(arr->arr_data + (num - i), 0, i * sizeof(intptr_t));
320:
321: num -= i;
322: cx += i;
323: }
324: }
325: if (fromWhere & VACUUM_BETWEEN) {
326: for (i = 0; i < num; i++) {
327: if (arr->arr_data[i])
328: continue;
329:
330: for (j = i; j < num && !arr->arr_data[j]; j++);
331:
332: memmove(arr->arr_data + i, arr->arr_data + j, (num - j) * sizeof(intptr_t));
333: memset(arr->arr_data + i + (num - j), 0, (j - i) * sizeof(intptr_t));
334:
335: num -= j - i;
336: cx += j - i;
337: }
338: }
339:
340: arr->arr_last = array_Len(arr);
341: return cx;
342: }
343:
344: /*
345: * array_Concat() Concat source array to destination array
346: *
347: * @dest = Destination array
348: * @src = Source array
349: * return: -1 error; >0 new count of destination array
350: */
351: int
352: array_Concat(array_t * __restrict dest, array_t * __restrict src)
353: {
354: int n;
355:
356: if (!dest || !src)
357: return -1;
358:
359: n = array_Size(dest);
360: if (array_Grow(dest, n + array_Size(src), 0))
361: return -1;
362: memcpy(dest->arr_data + n, src->arr_data, array_Size(src) * sizeof(intptr_t));
363:
364: dest->arr_last = array_Len(dest);
365: return array_Size(dest);
366: }
367:
368: /*
369: * array_Copy() Copy source array to destination array
370: *
1.3 misho 371: * @dest = Destination array, after use free with array_Destroy()
1.1 misho 372: * @src = Source array
373: * return: -1 error; >0 count of destination array
374: */
375: int
376: array_Copy(array_t ** __restrict dest, array_t * __restrict src)
377: {
378: if (!dest || !src)
379: return -1;
380:
381: *dest = array_Init(array_Size(src));
382: if (!*dest)
383: return -1;
384: else
385: (*dest)->arr_last = src->arr_last;
386:
387: memcpy((*dest)->arr_data, src->arr_data, array_Size(*dest) * sizeof(intptr_t));
388: return array_Size(*dest);
389: }
390:
391: /*
392: * array_Elem() - Always GET/PUT element into dynamic array, if not enough elements grow array
393: *
394: * @arr = Array
395: * @n = Position
396: * @data = Element, if set NULL GET element at position or !=NULL PUT element at position
397: * return: -1 error or !=-1 return element at position
398: */
1.2 misho 399: void *
1.1 misho 400: array_Elem(array_t * __restrict arr, int n, void *data)
401: {
402: void *dat = NULL;
403:
404: if (!arr)
405: return (void*) -1;
406:
407: if (n >= array_Size(arr) && array_Grow(arr, n + 1, 0))
408: return (void*) -1;
409:
410: dat = array_Get(arr, n);
411: if (data)
412: array_Set(arr, n, data);
413:
414: return dat;
415: }
416:
417: /*
418: * array_Push() - Push element into dynamic array like stack manner, place at first empty position
419: *
420: * @arr = Array
421: * @data = Element, if set NULL return only first empty position
422: * @nogrow = Don't grow array if not enough space
423: * return: -1 not found empty position, array is full!, >-1 return position of stored element into array
424: */
1.2 misho 425: int
426: array_Push(array_t * __restrict arr, void *data, int nogrow)
1.1 misho 427: {
428: int ret = -1;
429:
430: if (!arr)
431: return -1;
432: else
433: ret = array_Last(arr) + 1;
434: if (nogrow && ret >= array_Size(arr))
435: return -1;
436: if (!nogrow && ret >= array_Size(arr) && array_Grow(arr, ret + 1, 0))
437: return -1;
438:
1.2 misho 439: ret = ++arr->arr_last;
440: arr->arr_data[arr->arr_last] = data;
1.1 misho 441:
442: return ret;
443: }
444:
445: /*
446: * array_Pop() - Pop element from dynamic array like stack manner, last used position
447: *
448: * @arr = Array
449: * @data = Element, if set NULL return only last used position
450: * @nodel = Don't delete after Pop element
451: * return: -1 not found used position, array is empty!, >-1 return element position
452: */
1.2 misho 453: int
1.1 misho 454: array_Pop(array_t * __restrict arr, void ** __restrict data, int nodel)
455: {
456: int ret = -1;
457:
458: if (!arr)
459: return -1;
460:
1.2 misho 461: if ((ret = array_Last(arr)) != -1) {
462: if (data)
463: *data = arr->arr_data[arr->arr_last];
464: if (!nodel)
465: arr->arr_data[arr->arr_last] = NULL;
466: arr->arr_last--;
467: }
1.1 misho 468:
469: return ret;
470: }
471:
472: /*
473: * array_Args() Parse and make array from arguments ... (input string will be modified!!!
1.3 misho 474: * and output array must be free with array_Destroy() after use!)
1.1 misho 475: *
476: * @psArgs = Input arguments line, after execute string is modified!!!
477: * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs
478: * @csDelim = Delimiter(s) for separate
479: * @parr = Output array of arguments ... (must be free with array_Destroy() after use!)
480: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
481: */
482: int
483: array_Args(char * __restrict psArgs, int nargs, const char *csDelim, array_t ** __restrict parr)
484: {
485: char **app;
486: register int i;
487:
488: if (!psArgs || !csDelim || !parr)
489: return -1;
490:
491: if (nargs)
492: i = nargs;
493: else
494: i = str_ArgsNum(psArgs, csDelim);
495:
496: *parr = array_Init(i);
497: if (!*parr)
498: return -1;
499:
500: for (i = 0, app = (char**) (*parr)->arr_data;
501: app < (char**) (*parr)->arr_data + (*parr)->arr_num &&
502: (*app = strsep((char **) &psArgs, csDelim));
503: **app ? i++ : i, **app ? app++ : app);
504:
505: (*parr)->arr_last = i - 1;
506: return i;
507: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>