--- libaitio/src/Attic/array.c 2011/04/19 22:00:44 1.1.2.2 +++ libaitio/src/Attic/array.c 2012/07/30 11:11:39 1.10.6.3 @@ -1,16 +1,54 @@ /************************************************************************* -* (C) 2011 AITNET ltd - Sofia/Bulgaria - -* by Michael Pounov +* (C) 2011 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov * * $Author: misho $ -* $Id: array.c,v 1.1.2.2 2011/04/19 22:00:44 misho Exp $ +* $Id: array.c,v 1.10.6.3 2012/07/30 11:11:39 misho Exp $ * -*************************************************************************/ +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + by Michael Pounov . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ #include "global.h" /* * io_arrayInit() - Create and initialize dynamic array + * * @numItems = Number of Items * return: NULL error, != NULL allocated memory for array */ @@ -19,27 +57,98 @@ io_arrayInit(int numItems) { array_t *arr = NULL; - arr = malloc(sizeof(array_t)); + arr = io_malloc(sizeof(array_t)); if (!arr) { LOGERR; return NULL; } + arr->arr_last = -1; arr->arr_num = numItems; - arr->arr_data = calloc(arr->arr_num, sizeof(void*)); + arr->arr_data = io_calloc(io_arraySize(arr), sizeof(void*)); if (!arr->arr_data) { LOGERR; - free(arr); + io_free(arr); return NULL; } else - memset(arr->arr_data, 0, arr->arr_num * sizeof(void*)); + io_arrayZero(arr); return arr; } /* - * io_arrayFree() - Free all data in dynamic array + * io_arrayFrom() - Create and fill array from array with pointers + * + * @pargv = Array with pointers + * @argc = Number of Items, if 0 walk through argv and stop when reach NULL item + * return: NULL error, != NULL allocated new array + */ +inline array_t * +io_arrayFrom(const char *** __restrict pargv, int argc) +{ + array_t *arr = NULL; + const char **a = NULL; + register int num = 0; + + assert(pargv); + if (!pargv || !*pargv || argc < 0) + return NULL; + + if (argc) + num = argc; + else + for (a = *pargv; *a; a++, num++); + + arr = io_malloc(sizeof(array_t)); + if (!arr) { + LOGERR; + return NULL; + } + + arr->arr_num = num; + arr->arr_data = io_calloc(io_arraySize(arr), sizeof(void*)); + if (!arr->arr_data) { + LOGERR; + io_free(arr); + return NULL; + } else { + memcpy(arr->arr_data, *pargv, io_arraySize(arr) * sizeof(void*)); + arr->arr_last = io_arraySize(arr) - 1; + } + + return arr; +} + +/* + * io_arrayTo() - Create and fill array with pointers from dynamic array + * + * @arr = Array + * return: NULL error, != NULL allocated memory for array, NULL terminated + */ +inline char ** +io_arrayTo(array_t * __restrict arr) +{ + char **args = NULL; + + assert(arr); + if (!arr || !io_arraySize(arr)) + return NULL; + + args = (char **) io_calloc(io_arraySize(arr) + 1, sizeof(char*)); + if (!args) { + LOGERR; + return NULL; + } else + memcpy(args, arr->arr_data, io_arraySize(arr) * sizeof(char*)); + args[io_arraySize(arr)] = NULL; + + return args; +} + +/* + * io_arrayFree() - Free all data in dynamic array items * (WARNING! If assign static array dont use this!!!) + * * @arr = Array * return: none */ @@ -48,39 +157,41 @@ io_arrayFree(array_t * __restrict arr) { register int i; - assert(arr); if (!arr) return; - for (i = 0; i < arr->arr_num; i++) + for (i = 0; i < io_arraySize(arr); i++) if (arr->arr_data[i]) { - free(arr->arr_data[i]); + io_free(arr->arr_data[i]); arr->arr_data[i] = NULL; } + + arr->arr_last = -1; } /* - * io_arrayDestroy() - Free all data in dynamic array and Destroy dynamic array + * io_arrayDestroy() - Free and destroy dynamic array + * * @parr = Array * return: none */ inline void io_arrayDestroy(array_t ** __restrict parr) { - assert(parr); - if (!parr) + if (!parr || !*parr) return; if ((*parr)->arr_data) - free((*parr)->arr_data); - free(*parr); + io_free((*parr)->arr_data); + io_free(*parr); *parr = NULL; } /* * io_arrayLen() - Get last used element in dynamic array (array Length) + * * @arr = Array - * return: -1 error, 0 empty or >0 position of last used element + * return: -1 empty or >-1 position of last used element */ inline int io_arrayLen(array_t * __restrict arr) @@ -91,52 +202,62 @@ io_arrayLen(array_t * __restrict arr) if (!arr) return -1; - for (i = arr->arr_num; i && !arr->arr_data[i - 1]; i--); + for (i = io_arraySize(arr); i && !arr->arr_data[i - 1]; i--); - return i; + return --i; } /* * io_arrayGrow() - Grow/Shrink dynamic array, Use with care when it shrink!!! + * * @arr = Array * @newNumItems = Number of Items + * @freeShrink = Free elements before shrink array * return: -1 error, 0 ok */ int -io_arrayGrow(array_t * __restrict arr, int newNumItems) +io_arrayGrow(array_t * __restrict arr, int newNumItems, int freeShrink) { void **data; int n = 0; -/* register int i; */ + register int i; - assert(arr); if (!arr) return -1; if (arr->arr_num == newNumItems) return 0; - if (arr->arr_num < newNumItems) { - n = newNumItems - arr->arr_num; - } /* else + if (io_arraySize(arr) < newNumItems) { + n = newNumItems - io_arraySize(arr); + } else if (freeShrink) for (i = newNumItems; i < arr->arr_num; i++) if (arr->arr_data[i]) - free(arr->arr_data[i]); - */ + io_free(arr->arr_data[i]); arr->arr_num = newNumItems; - data = realloc(arr->arr_data, arr->arr_num * sizeof(void*)); - if (!data) { - LOGERR; - return -1; - } else - arr->arr_data = data; - memset(arr->arr_data + (arr->arr_num - n), 0, n * sizeof(void*)); + if (io_arraySize(arr)) { + data = io_realloc(arr->arr_data, io_arraySize(arr) * sizeof(void*)); + if (!data) { + LOGERR; + return -1; + } else + arr->arr_data = data; + memset(arr->arr_data + (io_arraySize(arr) - n), 0, n * sizeof(void*)); + arr->arr_last = io_arrayLen(arr); + } else { + if (arr->arr_data) + io_free(arr->arr_data); + arr->arr_data = NULL; + arr->arr_last = -1; + } + return 0; } /* * io_arrayVacuum() - Vacuum dynamic array, empty elements will be deleted + * * @arr = Array * @fromWhere = 1 begin, 2 ALL empty elements * return: -1 error, 0 ok @@ -147,13 +268,12 @@ io_arrayVacuum(array_t * __restrict arr, int fromWhere register int i, j, num; int cx = 0; - assert(arr); if (!arr) return -1; else fromWhere &= 0x7; - num = arr->arr_num; + num = io_arraySize(arr); /* if (fromWhere & VACUUM_RIGHT) { for (cx = 0, i = num - 1; i && !arr->arr_data[i]; i--, cx++); @@ -162,12 +282,13 @@ io_arrayVacuum(array_t * __restrict arr, int fromWhere */ if (fromWhere & VACUUM_LEFT) { for (i = 0; i < num && !arr->arr_data[i]; i++); + if (i) { + memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(void*)); + memset(arr->arr_data + (num - i), 0, i * sizeof(void*)); - memmove(arr->arr_data, arr->arr_data + i, (num - i) * sizeof(void*)); - memset(arr->arr_data + (num - i), 0, i * sizeof(void*)); - - num -= i; - cx += i; + num -= i; + cx += i; + } } if (fromWhere & VACUUM_BETWEEN) { for (i = 0; i < num; i++) { @@ -184,11 +305,170 @@ io_arrayVacuum(array_t * __restrict arr, int fromWhere } } + arr->arr_last = io_arrayLen(arr); return cx; } /* + * io_arrayElem() - Always GET/PUT element into dynamic array, if not enough elements grow array + * + * @arr = Array + * @n = Position + * @data = Element, if set NULL GET element at position or !=NULL PUT element at position + * return: -1 error or !=-1 return element at position + */ +inline void * +io_arrayElem(array_t * __restrict arr, int n, void *data) +{ + void *dat = NULL; + + if (!arr) + return (void*) -1; + + if (n >= io_arraySize(arr) && io_arrayGrow(arr, n + 1, 0)) + return (void*) -1; + + dat = io_arrayGet(arr, n); + if (data) + io_arraySet(arr, n, data); + + return dat; +} + +/* + * io_arrayPush() - Push element into dynamic array like stack manner, place at first empty position + * + * @arr = Array + * @data = Element, if set NULL return only first empty position + * @mayGrow = Array may to grow, if not enough room for new element + * return: -1 not found empty position, array is full!, >-1 return position of stored element into array + */ +inline int +io_arrayPush(array_t * __restrict arr, void **data, int mayGrow) +{ +#if 0 + register int i; +#endif + int ret = -1; + + if (!arr) + return -1; + else + ret = io_arrayLast(arr) + 1; + if (!mayGrow && ret >= io_arraySize(arr)) + return -1; + if (mayGrow && ret >= io_arraySize(arr) && + io_arrayGrow(arr, ret + 1, 0)) + return -1; + +#if 0 + for (i = 0; i < io_arraySize(arr); i++) + if (!arr->arr_data[i]) { + if (data) + arr->arr_data[i] = *data; + ret = i; + break; + } +#endif + arr->arr_data[++arr->arr_last] = *data; + + return ret; +} + +/* + * io_arrayPop() - Pop element from dynamic array like stack manner, last used position + * + * @arr = Array + * @data = Element, if set NULL return only last used position + * @delAfter = Delete after Pop element, !=0 delete element from array after return data + * return: -1 not found used position, array is empty!, >-1 return element position + */ +inline int +io_arrayPop(array_t * __restrict arr, void ** __restrict data, int delAfter) +{ +#if 0 + register int i; +#endif + int ret = -1; + + if (!arr) + return -1; + +#if 0 + for (i = io_arraySize(arr) - 1; i >= 0; i--) + if (arr->arr_data[i]) { + if (data) + *data = arr->arr_data[i]; + if (delAfter) + arr->arr_data[i] = NULL; + ret = i; + break; + } +#endif + ret = io_arrayLast(arr); + + if (data) + *data = arr->arr_data[ret]; + if (delAfter) + arr->arr_data[arr->arr_last--] = NULL; + + return ret; +} + +/* + * io_arrayConcat() Concat source array to destination array + * + * @dest = Destination array + * @src = Source array + * return: -1 error; >0 new count of destination array + */ +int +io_arrayConcat(array_t * __restrict dest, array_t * __restrict src) +{ + int n; + + assert(dest); + assert(src); + if (!dest || !src) + return -1; + + n = io_arraySize(dest); + if (io_arrayGrow(dest, n + io_arraySize(src), 0)) + return -1; + memcpy(dest->arr_data + n, src->arr_data, io_arraySize(src) * sizeof(void*)); + + dest->arr_last = io_arrayLen(dest); + return io_arraySize(dest); +} + +/* + * io_arrayCopy() Copy source array to destination array + * + * @dest = Destination array, after use free with io_arrayDestroy() + * @src = Source array + * return: -1 error; >0 count of destination array + */ +int +io_arrayCopy(array_t ** __restrict dest, array_t * __restrict src) +{ + assert(dest); + assert(src); + if (!dest || !src) + return -1; + + *dest = io_arrayInit(io_arraySize(src)); + if (!*dest) + return -1; + else + (*dest)->arr_last = src->arr_last; + + memcpy((*dest)->arr_data, src->arr_data, io_arraySize(*dest) * sizeof(void*)); + return io_arraySize(*dest); +} + +/* * io_argsNum() Parse and calculate number of arguments + * * @csArgs = Input arguments line * @csDelim = Delimiter(s) for separate * return: 0 error format; -1 error:: can`t read; >0 ok, number of items @@ -211,6 +491,7 @@ io_argsNum(const char *csArgs, const char *csDelim) /* * io_arrayMake() Parse and make array from arguments ... (input string will be modified!!! * and output array must be free with io_arrayDestroy() after use!) + * * @psArgs = Input arguments line, after execute string is modified!!! * @nargs = Maximum requested count of arguments from input string psArgs, if 0 all psArgs * @csDelim = Delimiter(s) for separate @@ -246,6 +527,7 @@ io_arrayMake(char * __restrict psArgs, int nargs, cons /* * io_MakeAV() Parse and make attribute/value pair + * * @csArgs = Input argument line * @csDelim = Delimiter for separate * @psAttr = Output Attribute @@ -267,7 +549,7 @@ io_MakeAV(const char * __restrict csArgs, const char * return -1; else memset(psValue, 0, valLen); - psBuf = strdup(csArgs); + psBuf = io_strdup(csArgs); if (!psBuf) { LOGERR; return -1; @@ -285,7 +567,45 @@ io_MakeAV(const char * __restrict csArgs, const char * strlcpy(psValue, pos, valLen); } - free(psBuf); + io_free(psBuf); return ret; } +/* + * io_MakeAV2() Parse and make attribute/value pair over input string + * + * @csArgs = Input argument line, will be modified! + * @csDelim = Delimiter for separate + * @psAttr = Output Attribute + * @psValue = Output Value, if ==NULL this element not present value or not wanted for return + * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items +*/ +int +io_MakeAV2(char * __restrict psArgs, const char *csDelim, + char * __restrict psAttr, char * __restrict psValue) +{ + register int ret = 0; + char *pos; + + if (!psArgs || !csDelim) + return -1; + + pos = strpbrk(psArgs, csDelim); + if (pos) { + *pos++ = 0; + ret++; + if (psAttr) + psAttr = psArgs; + } else + return 0; + + if (psValue) { + if (pos && *pos) { + ret++; + psValue = pos; + } else + psValue = NULL; + } + + return ret; +}