Annotation of libelwix/src/array.c, revision 1.5.36.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.5.36.1! misho 6: * $Id: array.c,v 1.5 2015/06/25 17:53:50 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.5.36.1! 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: }
75:
76: /*
77: * array_From() - Create and fill array from array with pointers
78: *
79: * @pargv = Array with pointers
80: * @argc = Number of Items, if 0 walk through argv and stop when reach NULL item
81: * return: NULL error, != NULL allocated new array
82: */
83: array_t *
84: array_From(const char *** __restrict pargv, int argc)
85: {
86: array_t *arr = NULL;
87: const char **a = NULL;
88: register int num = 0;
89:
90: if (!pargv || !*pargv || argc < 0)
91: return NULL;
92:
93: if (argc)
94: num = argc;
95: else
96: for (a = *pargv; *a; a++, num++);
97:
98: arr = array_Init(num);
99: if (!arr)
100: return NULL;
101: else {
102: memcpy(arr->arr_data, *pargv, array_Size(arr) * sizeof(intptr_t));
103: arr->arr_last = array_Size(arr) - 1;
104: }
105:
106: return arr;
107: }
108:
109: /*
110: * array_To() - Create and fill array with pointers from dynamic array
111: *
112: * @arr = Array
113: * return: NULL error, != NULL allocated memory for array, NULL terminated
114: */
115: char **
116: array_To(array_t * __restrict arr)
117: {
118: char **args = NULL;
119:
120: if (!arr || !array_Size(arr))
121: return NULL;
122:
123: args = (char **) e_calloc(array_Size(arr) + 1, sizeof(char*));
124: if (!args)
125: return NULL;
126: else
127: memcpy(args, arr->arr_data, array_Size(arr) * sizeof(char*));
128: args[array_Size(arr)] = NULL;
129:
130: return args;
131: }
132:
133: /*
134: * array_Free() - Free all data in dynamic array items
135: * (WARNING! If assign static array dont use this!!!)
136: *
137: * @arr = Array
138: * return: none
139: */
1.2 misho 140: void
1.1 misho 141: array_Free(array_t * __restrict arr)
142: {
143: register int i;
144:
145: if (!arr)
146: return;
147:
148: for (i = 0; i < array_Size(arr); i++)
149: if (arr->arr_data[i]) {
150: e_free(arr->arr_data[i]);
151: arr->arr_data[i] = NULL;
152: }
153:
154: arr->arr_last = -1;
155: }
156:
157: /*
158: * array_Destroy() - Free and destroy dynamic array
159: *
160: * @parr = Array
161: * return: none
162: */
1.2 misho 163: void
1.1 misho 164: array_Destroy(array_t ** __restrict parr)
165: {
166: if (!parr || !*parr)
167: return;
168:
169: if ((*parr)->arr_data)
170: e_free((*parr)->arr_data);
171: e_free(*parr);
172: *parr = NULL;
1.5.36.1! misho 173: }
! 174:
! 175: /*
! 176: * array_Reset() - Reset array to initial state
! 177: *
! 178: * @parr = Array
! 179: * @purge = Purge data, if <>0 then will be free entire data memory
! 180: * return: none
! 181: */
! 182: void
! 183: array_Reset(array_t * __restrict arr, int purge)
! 184: {
! 185: if (!arr)
! 186: return;
! 187:
! 188: arr->arr_last = -1;
! 189: arr->arr_num = 0;
! 190:
! 191: if (purge && arr->arr_data) {
! 192: e_free(arr->arr_data);
! 193: arr->arr_data = e_calloc(array_Size(arr), sizeof(intptr_t));
! 194: }
! 195:
! 196: array_Zero(arr);
1.1 misho 197: }
198:
199: /*
200: * array_Len() - Get last used element in dynamic array (array Length)
201: *
202: * @arr = Array
203: * return: -1 empty or >-1 position of last used element
204: */
1.2 misho 205: int
1.1 misho 206: array_Len(array_t * __restrict arr)
207: {
208: register int i;
209:
210: if (!arr)
211: return -1;
212:
213: for (i = array_Size(arr); i && !arr->arr_data[i - 1]; i--);
214:
215: return --i;
216: }
217:
218: /*
219: * array_Grow() - Grow/Shrink dynamic array, Use with care when it shrink!!!
220: *
221: * @arr = Array
222: * @newNumItems = Number of Items
223: * @freeShrink = Free elements before shrink array
224: * return: -1 error, 0 ok
225: */
226: int
227: array_Grow(array_t * __restrict arr, int newNumItems, int freeShrink)
228: {
229: void **data;
230: int n = 0;
231: register int i;
232:
233: if (!arr)
234: return -1;
235:
236: if (arr->arr_num == newNumItems)
237: return 0;
238: if (array_Size(arr) < newNumItems) {
239: n = newNumItems - array_Size(arr);
240: } else if (freeShrink)
241: for (i = newNumItems; i < arr->arr_num; i++)
242: if (arr->arr_data[i])
243: e_free(arr->arr_data[i]);
244:
245: arr->arr_num = newNumItems;
246: if (array_Size(arr)) {
247: data = e_realloc(arr->arr_data, array_Size(arr) * sizeof(intptr_t));
248: if (!data)
249: return -1;
250: else
251: arr->arr_data = data;
252:
253: memset(arr->arr_data + (array_Size(arr) - n), 0, n * sizeof(intptr_t));
254: arr->arr_last = array_Len(arr);
255: } else {
256: if (arr->arr_data)
257: e_free(arr->arr_data);
258: arr->arr_data = NULL;
259: arr->arr_last = -1;
260: }
261:
262: return 0;
263: }
264:
265: /*
266: * array_Vacuum() - Vacuum dynamic array, empty elements will be deleted
267: *
268: * @arr = Array
269: * @fromWhere = 1 begin, 2 ALL empty elements
270: * return: -1 error, 0 ok
271: */
272: int
273: array_Vacuum(array_t * __restrict arr, int fromWhere)
274: {
275: register int i, j, num;
276: int cx = 0;
277:
278: if (!arr)
279: return -1;
280: else
281: fromWhere &= 0x7;
282:
283: num = array_Size(arr);
284: #ifdef VACUUM_RIGHT
285: if (fromWhere & VACUUM_RIGHT) {
286: for (cx = 0, i = num - 1; i && !arr->arr_data[i]; i--, cx++);
287: num -= cx;
288: }
289: #endif
290: if (fromWhere & VACUUM_LEFT) {
291: for (i = 0; i < num && !arr->arr_data[i]; i++);
292: if (i) {
293: memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(intptr_t));
294: memset(arr->arr_data + (num - i), 0, i * sizeof(intptr_t));
295:
296: num -= i;
297: cx += i;
298: }
299: }
300: if (fromWhere & VACUUM_BETWEEN) {
301: for (i = 0; i < num; i++) {
302: if (arr->arr_data[i])
303: continue;
304:
305: for (j = i; j < num && !arr->arr_data[j]; j++);
306:
307: memmove(arr->arr_data + i, arr->arr_data + j, (num - j) * sizeof(intptr_t));
308: memset(arr->arr_data + i + (num - j), 0, (j - i) * sizeof(intptr_t));
309:
310: num -= j - i;
311: cx += j - i;
312: }
313: }
314:
315: arr->arr_last = array_Len(arr);
316: return cx;
317: }
318:
319: /*
320: * array_Concat() Concat source array to destination array
321: *
322: * @dest = Destination array
323: * @src = Source array
324: * return: -1 error; >0 new count of destination array
325: */
326: int
327: array_Concat(array_t * __restrict dest, array_t * __restrict src)
328: {
329: int n;
330:
331: if (!dest || !src)
332: return -1;
333:
334: n = array_Size(dest);
335: if (array_Grow(dest, n + array_Size(src), 0))
336: return -1;
337: memcpy(dest->arr_data + n, src->arr_data, array_Size(src) * sizeof(intptr_t));
338:
339: dest->arr_last = array_Len(dest);
340: return array_Size(dest);
341: }
342:
343: /*
344: * array_Copy() Copy source array to destination array
345: *
1.3 misho 346: * @dest = Destination array, after use free with array_Destroy()
1.1 misho 347: * @src = Source array
348: * return: -1 error; >0 count of destination array
349: */
350: int
351: array_Copy(array_t ** __restrict dest, array_t * __restrict src)
352: {
353: if (!dest || !src)
354: return -1;
355:
356: *dest = array_Init(array_Size(src));
357: if (!*dest)
358: return -1;
359: else
360: (*dest)->arr_last = src->arr_last;
361:
362: memcpy((*dest)->arr_data, src->arr_data, array_Size(*dest) * sizeof(intptr_t));
363: return array_Size(*dest);
364: }
365:
366: /*
367: * array_Elem() - Always GET/PUT element into dynamic array, if not enough elements grow array
368: *
369: * @arr = Array
370: * @n = Position
371: * @data = Element, if set NULL GET element at position or !=NULL PUT element at position
372: * return: -1 error or !=-1 return element at position
373: */
1.2 misho 374: void *
1.1 misho 375: array_Elem(array_t * __restrict arr, int n, void *data)
376: {
377: void *dat = NULL;
378:
379: if (!arr)
380: return (void*) -1;
381:
382: if (n >= array_Size(arr) && array_Grow(arr, n + 1, 0))
383: return (void*) -1;
384:
385: dat = array_Get(arr, n);
386: if (data)
387: array_Set(arr, n, data);
388:
389: return dat;
390: }
391:
392: /*
393: * array_Push() - Push element into dynamic array like stack manner, place at first empty position
394: *
395: * @arr = Array
396: * @data = Element, if set NULL return only first empty position
397: * @nogrow = Don't grow array if not enough space
398: * return: -1 not found empty position, array is full!, >-1 return position of stored element into array
399: */
1.2 misho 400: int
401: array_Push(array_t * __restrict arr, void *data, int nogrow)
1.1 misho 402: {
403: int ret = -1;
404:
405: if (!arr)
406: return -1;
407: else
408: ret = array_Last(arr) + 1;
409: if (nogrow && ret >= array_Size(arr))
410: return -1;
411: if (!nogrow && ret >= array_Size(arr) && array_Grow(arr, ret + 1, 0))
412: return -1;
413:
1.2 misho 414: ret = ++arr->arr_last;
415: arr->arr_data[arr->arr_last] = data;
1.1 misho 416:
417: return ret;
418: }
419:
420: /*
421: * array_Pop() - Pop element from dynamic array like stack manner, last used position
422: *
423: * @arr = Array
424: * @data = Element, if set NULL return only last used position
425: * @nodel = Don't delete after Pop element
426: * return: -1 not found used position, array is empty!, >-1 return element position
427: */
1.2 misho 428: int
1.1 misho 429: array_Pop(array_t * __restrict arr, void ** __restrict data, int nodel)
430: {
431: int ret = -1;
432:
433: if (!arr)
434: return -1;
435:
1.2 misho 436: if ((ret = array_Last(arr)) != -1) {
437: if (data)
438: *data = arr->arr_data[arr->arr_last];
439: if (!nodel)
440: arr->arr_data[arr->arr_last] = NULL;
441: arr->arr_last--;
442: }
1.1 misho 443:
444: return ret;
445: }
446:
447: /*
448: * array_Args() Parse and make array from arguments ... (input string will be modified!!!
1.3 misho 449: * and output array must be free with array_Destroy() after use!)
1.1 misho 450: *
451: * @psArgs = Input arguments line, after execute string is modified!!!
452: * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs
453: * @csDelim = Delimiter(s) for separate
454: * @parr = Output array of arguments ... (must be free with array_Destroy() after use!)
455: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
456: */
457: int
458: array_Args(char * __restrict psArgs, int nargs, const char *csDelim, array_t ** __restrict parr)
459: {
460: char **app;
461: register int i;
462:
463: if (!psArgs || !csDelim || !parr)
464: return -1;
465:
466: if (nargs)
467: i = nargs;
468: else
469: i = str_ArgsNum(psArgs, csDelim);
470:
471: *parr = array_Init(i);
472: if (!*parr)
473: return -1;
474:
475: for (i = 0, app = (char**) (*parr)->arr_data;
476: app < (char**) (*parr)->arr_data + (*parr)->arr_num &&
477: (*app = strsep((char **) &psArgs, csDelim));
478: **app ? i++ : i, **app ? app++ : app);
479:
480: (*parr)->arr_last = i - 1;
481: return i;
482: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>