Annotation of libaitio/src/array.c, revision 1.10.6.4
1.2 misho 1: /*************************************************************************
2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.10.6.4! misho 6: * $Id: array.c,v 1.10.6.3 2012/07/30 11:11:39 misho Exp $
1.2 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.8 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.2 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: * io_arrayInit() - Create and initialize dynamic array
1.8 misho 51: *
1.2 misho 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:
1.10 misho 60: arr = io_malloc(sizeof(array_t));
1.2 misho 61: if (!arr) {
62: LOGERR;
63: return NULL;
64: }
65:
1.9 misho 66: arr->arr_last = -1;
1.2 misho 67: arr->arr_num = numItems;
1.10 misho 68: arr->arr_data = io_calloc(io_arraySize(arr), sizeof(void*));
1.2 misho 69: if (!arr->arr_data) {
70: LOGERR;
1.10 misho 71: io_free(arr);
1.2 misho 72: return NULL;
73: } else
1.5 misho 74: io_arrayZero(arr);
1.2 misho 75:
76: return arr;
77: }
78:
79: /*
1.3 misho 80: * io_arrayFrom() - Create and fill array from array with pointers
1.8 misho 81: *
1.4 misho 82: * @pargv = Array with pointers
1.3 misho 83: * @argc = Number of Items, if 0 walk through argv and stop when reach NULL item
1.4 misho 84: * return: NULL error, != NULL allocated new array
1.3 misho 85: */
86: inline array_t *
1.4 misho 87: io_arrayFrom(const char *** __restrict pargv, int argc)
1.3 misho 88: {
89: array_t *arr = NULL;
90: const char **a = NULL;
91: register int num = 0;
92:
1.4 misho 93: assert(pargv);
94: if (!pargv || !*pargv || argc < 0)
1.3 misho 95: return NULL;
96:
97: if (argc)
98: num = argc;
99: else
1.4 misho 100: for (a = *pargv; *a; a++, num++);
1.3 misho 101:
1.10 misho 102: arr = io_malloc(sizeof(array_t));
1.3 misho 103: if (!arr) {
104: LOGERR;
105: return NULL;
106: }
107:
108: arr->arr_num = num;
1.10 misho 109: arr->arr_data = io_calloc(io_arraySize(arr), sizeof(void*));
1.3 misho 110: if (!arr->arr_data) {
111: LOGERR;
1.10 misho 112: io_free(arr);
1.3 misho 113: return NULL;
1.9 misho 114: } else {
1.4 misho 115: memcpy(arr->arr_data, *pargv, io_arraySize(arr) * sizeof(void*));
1.9 misho 116: arr->arr_last = io_arraySize(arr) - 1;
117: }
1.3 misho 118:
119: return arr;
120: }
121:
122: /*
123: * io_arrayTo() - Create and fill array with pointers from dynamic array
1.8 misho 124: *
1.3 misho 125: * @arr = Array
1.4 misho 126: * return: NULL error, != NULL allocated memory for array, NULL terminated
1.3 misho 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:
1.10 misho 137: args = (char **) io_calloc(io_arraySize(arr) + 1, sizeof(char*));
1.3 misho 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
1.2 misho 150: * (WARNING! If assign static array dont use this!!!)
1.8 misho 151: *
1.2 misho 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:
1.3 misho 163: for (i = 0; i < io_arraySize(arr); i++)
1.2 misho 164: if (arr->arr_data[i]) {
1.10 misho 165: io_free(arr->arr_data[i]);
1.2 misho 166: arr->arr_data[i] = NULL;
167: }
1.9 misho 168:
169: arr->arr_last = -1;
1.2 misho 170: }
171:
172: /*
1.3 misho 173: * io_arrayDestroy() - Free and destroy dynamic array
1.8 misho 174: *
1.2 misho 175: * @parr = Array
176: * return: none
177: */
178: inline void
179: io_arrayDestroy(array_t ** __restrict parr)
180: {
1.4 misho 181: if (!parr || !*parr)
1.2 misho 182: return;
183:
184: if ((*parr)->arr_data)
1.10 misho 185: io_free((*parr)->arr_data);
186: io_free(*parr);
1.2 misho 187: *parr = NULL;
188: }
189:
190: /*
191: * io_arrayLen() - Get last used element in dynamic array (array Length)
1.8 misho 192: *
1.2 misho 193: * @arr = Array
1.9 misho 194: * return: -1 empty or >-1 position of last used element
1.2 misho 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:
1.3 misho 205: for (i = io_arraySize(arr); i && !arr->arr_data[i - 1]; i--);
1.2 misho 206:
1.9 misho 207: return --i;
1.2 misho 208: }
209:
210: /*
211: * io_arrayGrow() - Grow/Shrink dynamic array, Use with care when it shrink!!!
1.8 misho 212: *
1.2 misho 213: * @arr = Array
214: * @newNumItems = Number of Items
1.5 misho 215: * @freeShrink = Free elements before shrink array
1.2 misho 216: * return: -1 error, 0 ok
217: */
218: int
1.5 misho 219: io_arrayGrow(array_t * __restrict arr, int newNumItems, int freeShrink)
1.2 misho 220: {
221: void **data;
222: int n = 0;
1.5 misho 223: register int i;
1.2 misho 224:
225: if (!arr)
226: return -1;
227:
228: if (arr->arr_num == newNumItems)
229: return 0;
1.3 misho 230: if (io_arraySize(arr) < newNumItems) {
231: n = newNumItems - io_arraySize(arr);
1.5 misho 232: } else if (freeShrink)
1.2 misho 233: for (i = newNumItems; i < arr->arr_num; i++)
234: if (arr->arr_data[i])
1.10 misho 235: io_free(arr->arr_data[i]);
1.2 misho 236:
237: arr->arr_num = newNumItems;
1.3 misho 238: if (io_arraySize(arr)) {
1.10 misho 239: data = io_realloc(arr->arr_data, io_arraySize(arr) * sizeof(void*));
1.3 misho 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*));
1.9 misho 247: arr->arr_last = io_arrayLen(arr);
1.3 misho 248: } else {
249: if (arr->arr_data)
1.10 misho 250: io_free(arr->arr_data);
1.3 misho 251: arr->arr_data = NULL;
1.9 misho 252: arr->arr_last = -1;
1.3 misho 253: }
1.2 misho 254:
255: return 0;
256: }
257:
258: /*
259: * io_arrayVacuum() - Vacuum dynamic array, empty elements will be deleted
1.8 misho 260: *
1.2 misho 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:
1.3 misho 276: num = io_arraySize(arr);
1.2 misho 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++);
1.4 misho 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*));
1.2 misho 288:
1.4 misho 289: num -= i;
290: cx += i;
291: }
1.2 misho 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:
1.9 misho 308: arr->arr_last = io_arrayLen(arr);
1.2 misho 309: return cx;
310: }
311:
312: /*
1.6 misho 313: * io_arrayElem() - Always GET/PUT element into dynamic array, if not enough elements grow array
1.8 misho 314: *
1.6 misho 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 *
1.7 misho 321: io_arrayElem(array_t * __restrict arr, int n, void *data)
1.6 misho 322: {
323: void *dat = NULL;
324:
325: if (!arr)
326: return (void*) -1;
327:
1.9 misho 328: if (n >= io_arraySize(arr) && io_arrayGrow(arr, n + 1, 0))
1.6 misho 329: return (void*) -1;
330:
331: dat = io_arrayGet(arr, n);
332: if (data)
1.7 misho 333: io_arraySet(arr, n, data);
1.6 misho 334:
335: return dat;
336: }
337:
338: /*
1.2 misho 339: * io_arrayPush() - Push element into dynamic array like stack manner, place at first empty position
1.8 misho 340: *
1.2 misho 341: * @arr = Array
342: * @data = Element, if set NULL return only first empty position
1.9 misho 343: * @mayGrow = Array may to grow, if not enough room for new element
1.2 misho 344: * return: -1 not found empty position, array is full!, >-1 return position of stored element into array
345: */
346: inline int
1.9 misho 347: io_arrayPush(array_t * __restrict arr, void **data, int mayGrow)
1.2 misho 348: {
1.9 misho 349: #if 0
1.2 misho 350: register int i;
1.9 misho 351: #endif
1.2 misho 352: int ret = -1;
353:
1.6 misho 354: if (!arr)
355: return -1;
1.9 misho 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;
1.6 misho 363:
1.9 misho 364: #if 0
1.3 misho 365: for (i = 0; i < io_arraySize(arr); i++)
1.2 misho 366: if (!arr->arr_data[i]) {
367: if (data)
368: arr->arr_data[i] = *data;
369: ret = i;
370: break;
371: }
1.9 misho 372: #endif
373: arr->arr_data[++arr->arr_last] = *data;
1.2 misho 374:
375: return ret;
376: }
377:
378: /*
379: * io_arrayPop() - Pop element from dynamic array like stack manner, last used position
1.8 misho 380: *
1.2 misho 381: * @arr = Array
1.4 misho 382: * @data = Element, if set NULL return only last used position
1.2 misho 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: {
1.9 misho 389: #if 0
1.2 misho 390: register int i;
1.9 misho 391: #endif
1.2 misho 392: int ret = -1;
393:
1.6 misho 394: if (!arr)
395: return -1;
396:
1.9 misho 397: #if 0
1.3 misho 398: for (i = io_arraySize(arr) - 1; i >= 0; i--)
1.2 misho 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: }
1.9 misho 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;
1.2 misho 414:
415: return ret;
416: }
417:
418: /*
1.3 misho 419: * io_arrayConcat() Concat source array to destination array
1.8 misho 420: *
1.3 misho 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);
1.5 misho 436: if (io_arrayGrow(dest, n + io_arraySize(src), 0))
1.3 misho 437: return -1;
438: memcpy(dest->arr_data + n, src->arr_data, io_arraySize(src) * sizeof(void*));
439:
1.9 misho 440: dest->arr_last = io_arrayLen(dest);
1.3 misho 441: return io_arraySize(dest);
442: }
443:
444: /*
1.5 misho 445: * io_arrayCopy() Copy source array to destination array
1.8 misho 446: *
1.5 misho 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;
1.9 misho 462: else
463: (*dest)->arr_last = src->arr_last;
1.5 misho 464:
465: memcpy((*dest)->arr_data, src->arr_data, io_arraySize(*dest) * sizeof(void*));
466: return io_arraySize(*dest);
467: }
468:
469: /*
1.2 misho 470: * io_argsNum() Parse and calculate number of arguments
1.8 misho 471: *
1.2 misho 472: * @csArgs = Input arguments line
473: * @csDelim = Delimiter(s) for separate
474: * return: 0 error format; -1 error:: can`t read; >0 ok, number of items
475: */
476: inline int
477: io_argsNum(const char *csArgs, const char *csDelim)
478: {
479: register int res;
480: char *pos;
481:
482: assert(csArgs);
483: assert(csDelim);
484: if (!csArgs || !csDelim)
485: return -1;
486:
487: for (res = 1, pos = (char*) csArgs; (pos = strpbrk(pos, csDelim)); res++, pos++);
488: return res;
489: }
490:
491: /*
492: * io_arrayMake() Parse and make array from arguments ... (input string will be modified!!!
493: * and output array must be free with io_arrayDestroy() after use!)
1.8 misho 494: *
1.2 misho 495: * @psArgs = Input arguments line, after execute string is modified!!!
496: * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs
497: * @csDelim = Delimiter(s) for separate
498: * @parr = Output array of arguments ... (must be free with io_arrayDestroy() after use!)
499: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
500: */
501: int
502: io_arrayMake(char * __restrict psArgs, int nargs, const char *csDelim, array_t ** __restrict parr)
503: {
504: char **app;
505: register int i;
506:
507: assert(psArgs);
508: assert(csDelim);
509: assert(parr);
510: if (!psArgs || !csDelim || !parr)
511: return -1;
512:
513: if (nargs)
514: i = nargs;
515: else
516: i = io_argsNum(psArgs, csDelim);
517: *parr = io_arrayInit(i);
518: if (!*parr)
519: return -1;
520:
521: for (i = 0, app = (char**) (*parr)->arr_data;
522: app < (char**) (*parr)->arr_data + (*parr)->arr_num &&
523: (*app = strsep((char **) &psArgs, csDelim));
524: **app ? i++ : i, **app ? app++ : app);
525: return i;
526: }
527:
528: /*
529: * io_MakeAV() Parse and make attribute/value pair
1.8 misho 530: *
1.2 misho 531: * @csArgs = Input argument line
532: * @csDelim = Delimiter for separate
533: * @psAttr = Output Attribute
534: * @attrLen = Size of attribute array
535: * @psValue = Output Value, if ==NULL this element not present value or not wanted for return
536: * @valLen = Size of value array
537: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
538: */
539: int
540: io_MakeAV(const char * __restrict csArgs, const char *csDelim,
541: char * __restrict psAttr, int attrLen, char * __restrict psValue, int valLen)
542: {
543: register int ret = 0;
544: char *pos, *psBuf;
545:
546: if (!csArgs || !csDelim || !psAttr || !attrLen)
547: return -1;
548: if (psValue && !valLen)
549: return -1;
550: else
551: memset(psValue, 0, valLen);
1.10 misho 552: psBuf = io_strdup(csArgs);
1.2 misho 553: if (!psBuf) {
554: LOGERR;
555: return -1;
556: }
557:
558: pos = strpbrk(psBuf, csDelim);
559: if (pos)
560: *pos++ = 0;
561: ret++;
562: strlcpy(psAttr, psBuf, attrLen);
563:
564: if (pos && *pos) {
565: ret++;
566: if (psValue)
567: strlcpy(psValue, pos, valLen);
568: }
569:
1.10 misho 570: io_free(psBuf);
1.2 misho 571: return ret;
572: }
573:
1.10.6.1 misho 574: /*
575: * io_MakeAV2() Parse and make attribute/value pair over input string
576: *
577: * @csArgs = Input argument line, will be modified!
578: * @csDelim = Delimiter for separate
579: * @psAttr = Output Attribute
580: * @psValue = Output Value, if ==NULL this element not present value or not wanted for return
581: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
582: */
583: int
1.10.6.2 misho 584: io_MakeAV2(char * __restrict psArgs, const char *csDelim,
1.10.6.4! misho 585: char ** __restrict psAttr, char ** __restrict psValue)
1.10.6.1 misho 586: {
587: register int ret = 0;
588: char *pos;
589:
1.10.6.2 misho 590: if (!psArgs || !csDelim)
1.10.6.1 misho 591: return -1;
592:
1.10.6.2 misho 593: pos = strpbrk(psArgs, csDelim);
1.10.6.3 misho 594: if (pos) {
1.10.6.1 misho 595: *pos++ = 0;
1.10.6.3 misho 596: ret++;
597: if (psAttr)
1.10.6.4! misho 598: *psAttr = psArgs;
1.10.6.3 misho 599: } else
600: return 0;
1.10.6.1 misho 601:
602: if (psValue) {
603: if (pos && *pos) {
604: ret++;
1.10.6.4! misho 605: *psValue = pos;
1.10.6.1 misho 606: } else
1.10.6.4! misho 607: *psValue = NULL;
1.10.6.1 misho 608: }
609:
610: return ret;
611: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>