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