Annotation of libaitio/src/array.c, revision 1.2.4.3
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.2.4.3 ! misho 6: * $Id: array.c,v 1.2.4.2 2011/05/19 03:01:20 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:
15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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: * @numItems = Number of Items
52: * return: NULL error, != NULL allocated memory for array
53: */
54: inline array_t *
55: io_arrayInit(int numItems)
56: {
57: array_t *arr = NULL;
58:
59: arr = malloc(sizeof(array_t));
60: if (!arr) {
61: LOGERR;
62: return NULL;
63: }
64:
65: arr->arr_num = numItems;
1.2.4.2 misho 66: arr->arr_data = calloc(io_arraySize(arr), sizeof(void*));
1.2 misho 67: if (!arr->arr_data) {
68: LOGERR;
69: free(arr);
70: return NULL;
71: } else
1.2.4.2 misho 72: memset(arr->arr_data, 0, io_arraySize(arr) * sizeof(void*));
1.2 misho 73:
74: return arr;
75: }
76:
77: /*
1.2.4.2 misho 78: * io_arrayFrom() - Create and fill array from array with pointers
79: * @argv = 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 memory for array
82: */
83: inline array_t *
84: io_arrayFrom(const char **argv, int argc)
85: {
86: array_t *arr = NULL;
87: const char **a = NULL;
88: register int num = 0;
89:
90: assert(argv);
91: if (!argv || !*argv || argc < 0)
92: return NULL;
93:
94: if (argc)
95: num = argc;
96: else
97: for (a = argv; *a; a++, num++);
98:
99: arr = malloc(sizeof(array_t));
100: if (!arr) {
101: LOGERR;
102: return NULL;
103: }
104:
105: arr->arr_num = num;
106: arr->arr_data = calloc(io_arraySize(arr), sizeof(void*));
107: if (!arr->arr_data) {
108: LOGERR;
109: free(arr);
110: return NULL;
111: } else
112: memcpy(arr->arr_data, argv, io_arraySize(arr) * sizeof(void*));
113:
114: return arr;
115: }
116:
117: /*
118: * io_arrayTo() - Create and fill array with pointers from dynamic array
119: * @arr = Array
120: * return: NULL error, != NULL allocated memory for array
121: */
122: inline char **
123: io_arrayTo(array_t * __restrict arr)
124: {
125: char **args = NULL;
126:
127: assert(arr);
128: if (!arr || !io_arraySize(arr))
129: return NULL;
130:
1.2.4.3 ! misho 131: args = (char **) calloc(io_arraySize(arr) + 1, sizeof(char*));
1.2.4.2 misho 132: if (!args) {
133: LOGERR;
134: return NULL;
135: } else
136: memcpy(args, arr->arr_data, io_arraySize(arr) * sizeof(char*));
1.2.4.3 ! misho 137: args[io_arraySize(arr)] = NULL;
1.2.4.2 misho 138:
139: return args;
140: }
141:
142: /*
1.2.4.1 misho 143: * io_arrayFree() - Free all data in dynamic array items
1.2 misho 144: * (WARNING! If assign static array dont use this!!!)
145: * @arr = Array
146: * return: none
147: */
148: inline void
149: io_arrayFree(array_t * __restrict arr)
150: {
151: register int i;
152:
153: assert(arr);
154: if (!arr)
155: return;
156:
1.2.4.2 misho 157: for (i = 0; i < io_arraySize(arr); i++)
1.2 misho 158: if (arr->arr_data[i]) {
159: free(arr->arr_data[i]);
160: arr->arr_data[i] = NULL;
161: }
162: }
163:
164: /*
1.2.4.1 misho 165: * io_arrayDestroy() - Free and destroy dynamic array
1.2 misho 166: * @parr = Array
167: * return: none
168: */
169: inline void
170: io_arrayDestroy(array_t ** __restrict parr)
171: {
172: assert(parr);
173: if (!parr)
174: return;
175:
176: if ((*parr)->arr_data)
177: free((*parr)->arr_data);
178: free(*parr);
179: *parr = NULL;
180: }
181:
182: /*
183: * io_arrayLen() - Get last used element in dynamic array (array Length)
184: * @arr = Array
185: * return: -1 error, 0 empty or >0 position of last used element
186: */
187: inline int
188: io_arrayLen(array_t * __restrict arr)
189: {
190: register int i;
191:
192: assert(arr);
193: if (!arr)
194: return -1;
195:
1.2.4.2 misho 196: for (i = io_arraySize(arr); i && !arr->arr_data[i - 1]; i--);
1.2 misho 197:
198: return i;
199: }
200:
201: /*
202: * io_arrayGrow() - Grow/Shrink dynamic array, Use with care when it shrink!!!
203: * @arr = Array
204: * @newNumItems = Number of Items
205: * return: -1 error, 0 ok
206: */
207: int
208: io_arrayGrow(array_t * __restrict arr, int newNumItems)
209: {
210: void **data;
211: int n = 0;
212: /* register int i; */
213:
214: assert(arr);
215: if (!arr)
216: return -1;
217:
218: if (arr->arr_num == newNumItems)
219: return 0;
1.2.4.2 misho 220: if (io_arraySize(arr) < newNumItems) {
221: n = newNumItems - io_arraySize(arr);
1.2 misho 222: } /* else
223: for (i = newNumItems; i < arr->arr_num; i++)
224: if (arr->arr_data[i])
225: free(arr->arr_data[i]);
226: */
227:
228: arr->arr_num = newNumItems;
1.2.4.2 misho 229: data = realloc(arr->arr_data, io_arraySize(arr) * sizeof(void*));
1.2 misho 230: if (!data) {
231: LOGERR;
232: return -1;
233: } else
234: arr->arr_data = data;
1.2.4.2 misho 235: memset(arr->arr_data + (io_arraySize(arr) - n), 0, n * sizeof(void*));
1.2 misho 236:
237: return 0;
238: }
239:
240: /*
241: * io_arrayVacuum() - Vacuum dynamic array, empty elements will be deleted
242: * @arr = Array
243: * @fromWhere = 1 begin, 2 ALL empty elements
244: * return: -1 error, 0 ok
245: */
246: int
247: io_arrayVacuum(array_t * __restrict arr, int fromWhere)
248: {
249: register int i, j, num;
250: int cx = 0;
251:
252: assert(arr);
253: if (!arr)
254: return -1;
255: else
256: fromWhere &= 0x7;
257:
1.2.4.2 misho 258: num = io_arraySize(arr);
1.2 misho 259: /*
260: if (fromWhere & VACUUM_RIGHT) {
261: for (cx = 0, i = num - 1; i && !arr->arr_data[i]; i--, cx++);
262: num -= cx;
263: }
264: */
265: if (fromWhere & VACUUM_LEFT) {
266: for (i = 0; i < num && !arr->arr_data[i]; i++);
267:
268: memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(void*));
269: memset(arr->arr_data + (num - i), 0, i * sizeof(void*));
270:
271: num -= i;
272: cx += i;
273: }
274: if (fromWhere & VACUUM_BETWEEN) {
275: for (i = 0; i < num; i++) {
276: if (arr->arr_data[i])
277: continue;
278:
279: for (j = i; j < num && !arr->arr_data[j]; j++);
280:
281: memmove(arr->arr_data + i, arr->arr_data + j, (num - j) * sizeof(void*));
282: memset(arr->arr_data + i + (num - j), 0, (j - i) * sizeof(void*));
283:
284: num -= j - i;
285: cx += j - i;
286: }
287: }
288:
289: return cx;
290: }
291:
292: /*
293: * io_arrayPush() - Push element into dynamic array like stack manner, place at first empty position
294: * @arr = Array
295: * @data = Element, if set NULL return only first empty position
296: * return: -1 not found empty position, array is full!, >-1 return position of stored element into array
297: */
298: inline int
299: io_arrayPush(array_t * __restrict arr, void **data)
300: {
301: register int i;
302: int ret = -1;
303:
304: assert(arr);
305:
1.2.4.2 misho 306: for (i = 0; i < io_arraySize(arr); i++)
1.2 misho 307: if (!arr->arr_data[i]) {
308: if (data)
309: arr->arr_data[i] = *data;
310: ret = i;
311: break;
312: }
313:
314: return ret;
315: }
316:
317: /*
318: * io_arrayPop() - Pop element from dynamic array like stack manner, last used position
319: * @arr = Array
320: * @data = Element, if set NULL return only first empty position
321: * @delAfter = Delete after Pop element, !=0 delete element from array after return data
322: * return: -1 not found used position, array is empty!, >-1 return element position
323: */
324: inline int
325: io_arrayPop(array_t * __restrict arr, void ** __restrict data, int delAfter)
326: {
327: register int i;
328: int ret = -1;
329:
330: assert(arr);
331:
1.2.4.2 misho 332: for (i = io_arraySize(arr) - 1; i >= 0; i--)
1.2 misho 333: if (arr->arr_data[i]) {
334: if (data)
335: *data = arr->arr_data[i];
336: if (delAfter)
337: arr->arr_data[i] = NULL;
338: ret = i;
339: break;
340: }
341:
342: return ret;
343: }
344:
345: /*
1.2.4.1 misho 346: * io_arrayConcat() Concat source array to destination array
347: * @dest = Destination array
348: * @src = Source array
349: * return: -1 error; >0 new count of destination array
350: */
351: int
352: io_arrayConcat(array_t * __restrict dest, array_t * __restrict src)
353: {
354: int n;
355:
356: assert(dest);
357: assert(src);
358: if (!dest || !src)
359: return -1;
360:
1.2.4.2 misho 361: n = io_arraySize(dest);
362: if (io_arrayGrow(dest, n + io_arraySize(src)))
1.2.4.1 misho 363: return -1;
1.2.4.2 misho 364: memcpy(dest->arr_data + n, src->arr_data, io_arraySize(src) * sizeof(void*));
1.2.4.1 misho 365:
366: return io_arraySize(dest);
367: }
368:
369: /*
1.2 misho 370: * io_argsNum() Parse and calculate number of arguments
371: * @csArgs = Input arguments line
372: * @csDelim = Delimiter(s) for separate
373: * return: 0 error format; -1 error:: can`t read; >0 ok, number of items
374: */
375: inline int
376: io_argsNum(const char *csArgs, const char *csDelim)
377: {
378: register int res;
379: char *pos;
380:
381: assert(csArgs);
382: assert(csDelim);
383: if (!csArgs || !csDelim)
384: return -1;
385:
386: for (res = 1, pos = (char*) csArgs; (pos = strpbrk(pos, csDelim)); res++, pos++);
387: return res;
388: }
389:
390: /*
391: * io_arrayMake() Parse and make array from arguments ... (input string will be modified!!!
392: * and output array must be free with io_arrayDestroy() after use!)
393: * @psArgs = Input arguments line, after execute string is modified!!!
394: * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs
395: * @csDelim = Delimiter(s) for separate
396: * @parr = Output array of arguments ... (must be free with io_arrayDestroy() after use!)
397: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
398: */
399: int
400: io_arrayMake(char * __restrict psArgs, int nargs, const char *csDelim, array_t ** __restrict parr)
401: {
402: char **app;
403: register int i;
404:
405: assert(psArgs);
406: assert(csDelim);
407: assert(parr);
408: if (!psArgs || !csDelim || !parr)
409: return -1;
410:
411: if (nargs)
412: i = nargs;
413: else
414: i = io_argsNum(psArgs, csDelim);
415: *parr = io_arrayInit(i);
416: if (!*parr)
417: return -1;
418:
419: for (i = 0, app = (char**) (*parr)->arr_data;
420: app < (char**) (*parr)->arr_data + (*parr)->arr_num &&
421: (*app = strsep((char **) &psArgs, csDelim));
422: **app ? i++ : i, **app ? app++ : app);
423: return i;
424: }
425:
426: /*
427: * io_MakeAV() Parse and make attribute/value pair
428: * @csArgs = Input argument line
429: * @csDelim = Delimiter for separate
430: * @psAttr = Output Attribute
431: * @attrLen = Size of attribute array
432: * @psValue = Output Value, if ==NULL this element not present value or not wanted for return
433: * @valLen = Size of value array
434: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
435: */
436: int
437: io_MakeAV(const char * __restrict csArgs, const char *csDelim,
438: char * __restrict psAttr, int attrLen, char * __restrict psValue, int valLen)
439: {
440: register int ret = 0;
441: char *pos, *psBuf;
442:
443: if (!csArgs || !csDelim || !psAttr || !attrLen)
444: return -1;
445: if (psValue && !valLen)
446: return -1;
447: else
448: memset(psValue, 0, valLen);
449: psBuf = strdup(csArgs);
450: if (!psBuf) {
451: LOGERR;
452: return -1;
453: }
454:
455: pos = strpbrk(psBuf, csDelim);
456: if (pos)
457: *pos++ = 0;
458: ret++;
459: strlcpy(psAttr, psBuf, attrLen);
460:
461: if (pos && *pos) {
462: ret++;
463: if (psValue)
464: strlcpy(psValue, pos, valLen);
465: }
466:
467: free(psBuf);
468: return ret;
469: }
470:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>