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>