Annotation of libelwix/src/array.c, revision 1.1
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 $
! 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, 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: */
! 55: inline array_t *
! 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: */
! 140: inline void
! 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: */
! 163: inline void
! 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: */
! 181: inline int
! 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: *
! 322: * @dest = Destination array, after use free with io_arrayDestroy()
! 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: */
! 350: inline void *
! 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: */
! 376: inline int
! 377: array_Push(array_t * __restrict arr, void **data, int nogrow)
! 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:
! 390: ret = arr->arr_last++;
! 391: if (data)
! 392: arr->arr_data[arr->arr_last] = *data;
! 393:
! 394: return ret;
! 395: }
! 396:
! 397: /*
! 398: * array_Pop() - Pop element from dynamic array like stack manner, last used position
! 399: *
! 400: * @arr = Array
! 401: * @data = Element, if set NULL return only last used position
! 402: * @nodel = Don't delete after Pop element
! 403: * return: -1 not found used position, array is empty!, >-1 return element position
! 404: */
! 405: inline int
! 406: array_Pop(array_t * __restrict arr, void ** __restrict data, int nodel)
! 407: {
! 408: int ret = -1;
! 409:
! 410: if (!arr)
! 411: return -1;
! 412:
! 413: ret = array_Last(arr);
! 414:
! 415: if (data)
! 416: *data = arr->arr_data[ret];
! 417: if (!nodel)
! 418: arr->arr_data[arr->arr_last--] = NULL;
! 419:
! 420: return ret;
! 421: }
! 422:
! 423: /*
! 424: * array_Args() Parse and make array from arguments ... (input string will be modified!!!
! 425: * and output array must be free with io_arrayDestroy() after use!)
! 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>