File:
[ELWIX - Embedded LightWeight unIX -] /
libaitio /
src /
Attic /
array.c
Revision
1.11:
download - view:
text,
annotated -
select for diffs -
revision graph
Wed Aug 1 00:37:08 2012 UTC (12 years, 1 month ago) by
misho
Branches:
MAIN
CVS tags:
io5_0,
io4_1,
io4_0,
io3_9,
io3_8,
io3_7,
io3_6,
io3_5,
IO4_1,
IO4_0,
IO3_9,
IO3_8,
IO3_7,
IO3_6,
IO3_5,
IO3_4,
HEAD
version 3.4
1: /*************************************************************************
2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
6: * $Id: array.c,v 1.11 2012/08/01 00:37:08 misho Exp $
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
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: * io_arrayInit() - Create and initialize dynamic array
51: *
52: * @numItems = Number of Items
53: * return: NULL error, != NULL allocated memory for array
54: */
55: inline array_t *
56: io_arrayInit(int numItems)
57: {
58: array_t *arr = NULL;
59:
60: arr = io_malloc(sizeof(array_t));
61: if (!arr) {
62: LOGERR;
63: return NULL;
64: }
65:
66: arr->arr_last = -1;
67: arr->arr_num = numItems;
68: arr->arr_data = io_calloc(io_arraySize(arr), sizeof(void*));
69: if (!arr->arr_data) {
70: LOGERR;
71: io_free(arr);
72: return NULL;
73: } else
74: io_arrayZero(arr);
75:
76: return arr;
77: }
78:
79: /*
80: * io_arrayFrom() - Create and fill array from array with pointers
81: *
82: * @pargv = Array with pointers
83: * @argc = Number of Items, if 0 walk through argv and stop when reach NULL item
84: * return: NULL error, != NULL allocated new array
85: */
86: inline array_t *
87: io_arrayFrom(const char *** __restrict pargv, int argc)
88: {
89: array_t *arr = NULL;
90: const char **a = NULL;
91: register int num = 0;
92:
93: assert(pargv);
94: if (!pargv || !*pargv || argc < 0)
95: return NULL;
96:
97: if (argc)
98: num = argc;
99: else
100: for (a = *pargv; *a; a++, num++);
101:
102: arr = io_malloc(sizeof(array_t));
103: if (!arr) {
104: LOGERR;
105: return NULL;
106: }
107:
108: arr->arr_num = num;
109: arr->arr_data = io_calloc(io_arraySize(arr), sizeof(void*));
110: if (!arr->arr_data) {
111: LOGERR;
112: io_free(arr);
113: return NULL;
114: } else {
115: memcpy(arr->arr_data, *pargv, io_arraySize(arr) * sizeof(void*));
116: arr->arr_last = io_arraySize(arr) - 1;
117: }
118:
119: return arr;
120: }
121:
122: /*
123: * io_arrayTo() - Create and fill array with pointers from dynamic array
124: *
125: * @arr = Array
126: * return: NULL error, != NULL allocated memory for array, NULL terminated
127: */
128: inline char **
129: io_arrayTo(array_t * __restrict arr)
130: {
131: char **args = NULL;
132:
133: assert(arr);
134: if (!arr || !io_arraySize(arr))
135: return NULL;
136:
137: args = (char **) io_calloc(io_arraySize(arr) + 1, sizeof(char*));
138: if (!args) {
139: LOGERR;
140: return NULL;
141: } else
142: memcpy(args, arr->arr_data, io_arraySize(arr) * sizeof(char*));
143: args[io_arraySize(arr)] = NULL;
144:
145: return args;
146: }
147:
148: /*
149: * io_arrayFree() - Free all data in dynamic array items
150: * (WARNING! If assign static array dont use this!!!)
151: *
152: * @arr = Array
153: * return: none
154: */
155: inline void
156: io_arrayFree(array_t * __restrict arr)
157: {
158: register int i;
159:
160: if (!arr)
161: return;
162:
163: for (i = 0; i < io_arraySize(arr); i++)
164: if (arr->arr_data[i]) {
165: io_free(arr->arr_data[i]);
166: arr->arr_data[i] = NULL;
167: }
168:
169: arr->arr_last = -1;
170: }
171:
172: /*
173: * io_arrayDestroy() - Free and destroy dynamic array
174: *
175: * @parr = Array
176: * return: none
177: */
178: inline void
179: io_arrayDestroy(array_t ** __restrict parr)
180: {
181: if (!parr || !*parr)
182: return;
183:
184: if ((*parr)->arr_data)
185: io_free((*parr)->arr_data);
186: io_free(*parr);
187: *parr = NULL;
188: }
189:
190: /*
191: * io_arrayLen() - Get last used element in dynamic array (array Length)
192: *
193: * @arr = Array
194: * return: -1 empty or >-1 position of last used element
195: */
196: inline int
197: io_arrayLen(array_t * __restrict arr)
198: {
199: register int i;
200:
201: assert(arr);
202: if (!arr)
203: return -1;
204:
205: for (i = io_arraySize(arr); i && !arr->arr_data[i - 1]; i--);
206:
207: return --i;
208: }
209:
210: /*
211: * io_arrayGrow() - Grow/Shrink dynamic array, Use with care when it shrink!!!
212: *
213: * @arr = Array
214: * @newNumItems = Number of Items
215: * @freeShrink = Free elements before shrink array
216: * return: -1 error, 0 ok
217: */
218: int
219: io_arrayGrow(array_t * __restrict arr, int newNumItems, int freeShrink)
220: {
221: void **data;
222: int n = 0;
223: register int i;
224:
225: if (!arr)
226: return -1;
227:
228: if (arr->arr_num == newNumItems)
229: return 0;
230: if (io_arraySize(arr) < newNumItems) {
231: n = newNumItems - io_arraySize(arr);
232: } else if (freeShrink)
233: for (i = newNumItems; i < arr->arr_num; i++)
234: if (arr->arr_data[i])
235: io_free(arr->arr_data[i]);
236:
237: arr->arr_num = newNumItems;
238: if (io_arraySize(arr)) {
239: data = io_realloc(arr->arr_data, io_arraySize(arr) * sizeof(void*));
240: if (!data) {
241: LOGERR;
242: return -1;
243: } else
244: arr->arr_data = data;
245:
246: memset(arr->arr_data + (io_arraySize(arr) - n), 0, n * sizeof(void*));
247: arr->arr_last = io_arrayLen(arr);
248: } else {
249: if (arr->arr_data)
250: io_free(arr->arr_data);
251: arr->arr_data = NULL;
252: arr->arr_last = -1;
253: }
254:
255: return 0;
256: }
257:
258: /*
259: * io_arrayVacuum() - Vacuum dynamic array, empty elements will be deleted
260: *
261: * @arr = Array
262: * @fromWhere = 1 begin, 2 ALL empty elements
263: * return: -1 error, 0 ok
264: */
265: int
266: io_arrayVacuum(array_t * __restrict arr, int fromWhere)
267: {
268: register int i, j, num;
269: int cx = 0;
270:
271: if (!arr)
272: return -1;
273: else
274: fromWhere &= 0x7;
275:
276: num = io_arraySize(arr);
277: /*
278: if (fromWhere & VACUUM_RIGHT) {
279: for (cx = 0, i = num - 1; i && !arr->arr_data[i]; i--, cx++);
280: num -= cx;
281: }
282: */
283: if (fromWhere & VACUUM_LEFT) {
284: for (i = 0; i < num && !arr->arr_data[i]; i++);
285: if (i) {
286: memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(void*));
287: memset(arr->arr_data + (num - i), 0, i * sizeof(void*));
288:
289: num -= i;
290: cx += i;
291: }
292: }
293: if (fromWhere & VACUUM_BETWEEN) {
294: for (i = 0; i < num; i++) {
295: if (arr->arr_data[i])
296: continue;
297:
298: for (j = i; j < num && !arr->arr_data[j]; j++);
299:
300: memmove(arr->arr_data + i, arr->arr_data + j, (num - j) * sizeof(void*));
301: memset(arr->arr_data + i + (num - j), 0, (j - i) * sizeof(void*));
302:
303: num -= j - i;
304: cx += j - i;
305: }
306: }
307:
308: arr->arr_last = io_arrayLen(arr);
309: return cx;
310: }
311:
312: /*
313: * io_arrayElem() - Always GET/PUT element into dynamic array, if not enough elements grow array
314: *
315: * @arr = Array
316: * @n = Position
317: * @data = Element, if set NULL GET element at position or !=NULL PUT element at position
318: * return: -1 error or !=-1 return element at position
319: */
320: inline void *
321: io_arrayElem(array_t * __restrict arr, int n, void *data)
322: {
323: void *dat = NULL;
324:
325: if (!arr)
326: return (void*) -1;
327:
328: if (n >= io_arraySize(arr) && io_arrayGrow(arr, n + 1, 0))
329: return (void*) -1;
330:
331: dat = io_arrayGet(arr, n);
332: if (data)
333: io_arraySet(arr, n, data);
334:
335: return dat;
336: }
337:
338: /*
339: * io_arrayPush() - Push element into dynamic array like stack manner, place at first empty position
340: *
341: * @arr = Array
342: * @data = Element, if set NULL return only first empty position
343: * @mayGrow = Array may to grow, if not enough room for new element
344: * return: -1 not found empty position, array is full!, >-1 return position of stored element into array
345: */
346: inline int
347: io_arrayPush(array_t * __restrict arr, void **data, int mayGrow)
348: {
349: #if 0
350: register int i;
351: #endif
352: int ret = -1;
353:
354: if (!arr)
355: return -1;
356: else
357: ret = io_arrayLast(arr) + 1;
358: if (!mayGrow && ret >= io_arraySize(arr))
359: return -1;
360: if (mayGrow && ret >= io_arraySize(arr) &&
361: io_arrayGrow(arr, ret + 1, 0))
362: return -1;
363:
364: #if 0
365: for (i = 0; i < io_arraySize(arr); i++)
366: if (!arr->arr_data[i]) {
367: if (data)
368: arr->arr_data[i] = *data;
369: ret = i;
370: break;
371: }
372: #endif
373: arr->arr_data[++arr->arr_last] = *data;
374:
375: return ret;
376: }
377:
378: /*
379: * io_arrayPop() - Pop element from dynamic array like stack manner, last used position
380: *
381: * @arr = Array
382: * @data = Element, if set NULL return only last used position
383: * @delAfter = Delete after Pop element, !=0 delete element from array after return data
384: * return: -1 not found used position, array is empty!, >-1 return element position
385: */
386: inline int
387: io_arrayPop(array_t * __restrict arr, void ** __restrict data, int delAfter)
388: {
389: #if 0
390: register int i;
391: #endif
392: int ret = -1;
393:
394: if (!arr)
395: return -1;
396:
397: #if 0
398: for (i = io_arraySize(arr) - 1; i >= 0; i--)
399: if (arr->arr_data[i]) {
400: if (data)
401: *data = arr->arr_data[i];
402: if (delAfter)
403: arr->arr_data[i] = NULL;
404: ret = i;
405: break;
406: }
407: #endif
408: ret = io_arrayLast(arr);
409:
410: if (data)
411: *data = arr->arr_data[ret];
412: if (delAfter)
413: arr->arr_data[arr->arr_last--] = NULL;
414:
415: return ret;
416: }
417:
418: /*
419: * io_arrayConcat() Concat source array to destination array
420: *
421: * @dest = Destination array
422: * @src = Source array
423: * return: -1 error; >0 new count of destination array
424: */
425: int
426: io_arrayConcat(array_t * __restrict dest, array_t * __restrict src)
427: {
428: int n;
429:
430: assert(dest);
431: assert(src);
432: if (!dest || !src)
433: return -1;
434:
435: n = io_arraySize(dest);
436: if (io_arrayGrow(dest, n + io_arraySize(src), 0))
437: return -1;
438: memcpy(dest->arr_data + n, src->arr_data, io_arraySize(src) * sizeof(void*));
439:
440: dest->arr_last = io_arrayLen(dest);
441: return io_arraySize(dest);
442: }
443:
444: /*
445: * io_arrayCopy() Copy source array to destination array
446: *
447: * @dest = Destination array, after use free with io_arrayDestroy()
448: * @src = Source array
449: * return: -1 error; >0 count of destination array
450: */
451: int
452: io_arrayCopy(array_t ** __restrict dest, array_t * __restrict src)
453: {
454: assert(dest);
455: assert(src);
456: if (!dest || !src)
457: return -1;
458:
459: *dest = io_arrayInit(io_arraySize(src));
460: if (!*dest)
461: return -1;
462: else
463: (*dest)->arr_last = src->arr_last;
464:
465: memcpy((*dest)->arr_data, src->arr_data, io_arraySize(*dest) * sizeof(void*));
466: return io_arraySize(*dest);
467: }
468:
469: /*
470: * io_arrayMake() Parse and make array from arguments ... (input string will be modified!!!
471: * and output array must be free with io_arrayDestroy() after use!)
472: *
473: * @psArgs = Input arguments line, after execute string is modified!!!
474: * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs
475: * @csDelim = Delimiter(s) for separate
476: * @parr = Output array of arguments ... (must be free with io_arrayDestroy() after use!)
477: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
478: */
479: int
480: io_arrayMake(char * __restrict psArgs, int nargs, const char *csDelim, array_t ** __restrict parr)
481: {
482: char **app;
483: register int i;
484:
485: assert(psArgs);
486: assert(csDelim);
487: assert(parr);
488: if (!psArgs || !csDelim || !parr)
489: return -1;
490:
491: if (nargs)
492: i = nargs;
493: else
494: i = io_argsNum(psArgs, csDelim);
495: *parr = io_arrayInit(i);
496: if (!*parr)
497: return -1;
498:
499: for (i = 0, app = (char**) (*parr)->arr_data;
500: app < (char**) (*parr)->arr_data + (*parr)->arr_num &&
501: (*app = strsep((char **) &psArgs, csDelim));
502: **app ? i++ : i, **app ? app++ : app);
503: return i;
504: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>