[BACK]Return to array.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/array.c, Revision 1.1

1.1     ! tomglok     1: /*
        !             2:  * This program is free software; you can redistribute it and/or modify
        !             3:  * it under the terms of the GNU General Public License as published by
        !             4:  * the Free Software Foundation; either version 2 of the License, or
        !             5:  * (at your option) any later version.
        !             6:  * Please read the file COPYING, README and AUTHORS for more information.
        !             7:  *
        !             8:  * libarray - dynamically allocate arrays.
        !             9:  * Copyright (c) 2005 Florian Westphal (westphal@foo.fh-furtwangen.de)
        !            10:  */
        !            11:
        !            12: /**
        !            13:  * @file
        !            14:  * Functions to dynamically allocate arrays.
        !            15:  */
        !            16:
        !            17: /* Additionan debug messages related to array handling: 0=off / 1=on */
        !            18: #define DEBUG_ARRAY 0
        !            19:
        !            20: #include "array.h"
        !            21:
        !            22: #include <assert.h>
        !            23: #include <stdlib.h>
        !            24: #include <string.h>
        !            25: #include <unistd.h>
        !            26:
        !            27: #if DEBUG_ARRAY
        !            28: # include "log.h"
        !            29: #endif
        !            30:
        !            31: #define array_UNUSABLE(x)      ( !(x)->mem )
        !            32:
        !            33:
        !            34: static bool
        !            35: safemult_sizet(size_t a, size_t b, size_t *res)
        !            36: {
        !            37:        size_t tmp = a * b;
        !            38:
        !            39:        if (b && (tmp / b != a))
        !            40:                return false;
        !            41:
        !            42:        *res = tmp;
        !            43:        return true;
        !            44: }
        !            45:
        !            46:
        !            47: void
        !            48: array_init(array *a)
        !            49: {
        !            50:        assert(a != NULL);
        !            51:        a->mem = NULL;
        !            52:        a->allocated = 0;
        !            53:        a->used = 0;
        !            54: }
        !            55:
        !            56:
        !            57: /* if realloc() fails, array_alloc return NULL. otherwise return pointer to elem pos in array */
        !            58: void *
        !            59: array_alloc(array * a, size_t size, size_t pos)
        !            60: {
        !            61:        size_t alloc, pos_plus1 = pos + 1;
        !            62:        char *tmp;
        !            63:
        !            64:        assert(size > 0);
        !            65:
        !            66:        if (pos_plus1 == 0 || !safemult_sizet(size, pos_plus1, &alloc))
        !            67:                return NULL;
        !            68:
        !            69:        if (a->allocated < alloc) {
        !            70: #if DEBUG_ARRAY
        !            71:                Log(LOG_DEBUG, "array_alloc(): changing size from %u to %u bytes.",
        !            72:                    a->allocated, alloc);
        !            73: #endif
        !            74:                tmp = realloc(a->mem, alloc);
        !            75:                if (!tmp)
        !            76:                        return NULL;
        !            77:
        !            78:                a->mem = tmp;
        !            79:                a->allocated = alloc;
        !            80:                memset(a->mem + a->used, 0, a->allocated - a->used);
        !            81:                a->used = alloc;
        !            82:        }
        !            83:
        !            84:        assert(a->allocated >= a->used);
        !            85:
        !            86:        return a->mem + (pos * size);
        !            87: }
        !            88:
        !            89:
        !            90: /*return number of initialized ELEMS in a. */
        !            91: size_t
        !            92: array_length(const array * const a, size_t membersize)
        !            93: {
        !            94:        assert(a != NULL);
        !            95:        assert(membersize > 0);
        !            96:
        !            97:        if (array_UNUSABLE(a))
        !            98:                return 0;
        !            99:
        !           100:        assert(a->allocated);
        !           101:        return membersize ? a->used / membersize : 0;
        !           102: }
        !           103:
        !           104:
        !           105: /* copy array src to array dest */
        !           106: bool
        !           107: array_copy(array * dest, const array * const src)
        !           108: {
        !           109:        if (array_UNUSABLE(src))
        !           110:                return false;
        !           111:
        !           112:        assert(src->allocated);
        !           113:        return array_copyb(dest, src->mem, src->used);
        !           114: }
        !           115:
        !           116:
        !           117: /* return false on failure (realloc failure, invalid src/dest array) */
        !           118: bool
        !           119: array_copyb(array * dest, const char *src, size_t len)
        !           120: {
        !           121:        assert(dest != NULL);
        !           122:        assert(src != NULL );
        !           123:
        !           124:        if (!src || !dest)
        !           125:                return false;
        !           126:
        !           127:        array_trunc(dest);
        !           128:        return array_catb(dest, src, len);
        !           129: }
        !           130:
        !           131:
        !           132: /* copy string to dest */
        !           133: bool
        !           134: array_copys(array * dest, const char *src)
        !           135: {
        !           136:        return array_copyb(dest, src, strlen(src));
        !           137: }
        !           138:
        !           139:
        !           140: /* append len bytes from src to the array dest.
        !           141: return false if we could not append all bytes (realloc failure, invalid src/dest array) */
        !           142: bool
        !           143: array_catb(array * dest, const char *src, size_t len)
        !           144: {
        !           145:        size_t tmp;
        !           146:        size_t used;
        !           147:        char *ptr;
        !           148:
        !           149:        assert(dest != NULL);
        !           150:        assert(src != NULL);
        !           151:
        !           152:        if (!len)
        !           153:                return true;
        !           154:
        !           155:        if (!src || !dest)
        !           156:                return false;
        !           157:
        !           158:        used = dest->used;
        !           159:        tmp = used + len;
        !           160:
        !           161:        if (tmp < used || tmp < len)    /* integer overflow */
        !           162:                return false;
        !           163:
        !           164:        if (!array_alloc(dest, 1, tmp))
        !           165:                return false;
        !           166:
        !           167:        ptr = dest->mem;
        !           168:
        !           169:        assert(ptr != NULL);
        !           170:
        !           171: #if DEBUG_ARRAY
        !           172:        Log(LOG_DEBUG,
        !           173:            "array_catb(): appending %u bytes to array (now %u bytes in array).",
        !           174:            len, tmp);
        !           175: #endif
        !           176:        memcpy(ptr + used, src, len);
        !           177:        dest->used = tmp;
        !           178:        return true;
        !           179: }
        !           180:
        !           181:
        !           182: /* append string to dest */
        !           183: bool
        !           184: array_cats(array * dest, const char *src)
        !           185: {
        !           186:        return array_catb(dest, src, strlen(src));
        !           187: }
        !           188:
        !           189:
        !           190: /* append trailing NUL byte to array */
        !           191: bool
        !           192: array_cat0(array * a)
        !           193: {
        !           194:        return array_catb(a, "", 1);
        !           195: }
        !           196:
        !           197:
        !           198: /* append trailing NUL byte to array, but do not count it. */
        !           199: bool
        !           200: array_cat0_temporary(array * a)
        !           201: {
        !           202:        char *endpos = array_alloc(a, 1, array_bytes(a));
        !           203:        if (!endpos)
        !           204:                return false;
        !           205:
        !           206:        *endpos = '\0';
        !           207:        return true;
        !           208: }
        !           209:
        !           210: /* add contents of array src to array dest. */
        !           211: bool
        !           212: array_cat(array * dest, const array * const src)
        !           213: {
        !           214:        if (array_UNUSABLE(src))
        !           215:                return false;
        !           216:
        !           217:        return array_catb(dest, src->mem, src->used);
        !           218: }
        !           219:
        !           220:
        !           221: /* return pointer to the element at pos.
        !           222:    return NULL if the array is unallocated, or if pos is larger than
        !           223:    the number of elements stored int the array. */
        !           224: void *
        !           225: array_get(array * a, size_t membersize, size_t pos)
        !           226: {
        !           227:        size_t totalsize;
        !           228:        size_t posplus1 = pos + 1;
        !           229:
        !           230:        assert(membersize > 0);
        !           231:        assert(a != NULL);
        !           232:
        !           233:        if (!posplus1 || array_UNUSABLE(a))
        !           234:                return NULL;
        !           235:
        !           236:        if (!safemult_sizet(posplus1, membersize, &totalsize))
        !           237:                return NULL;
        !           238:
        !           239:        if (a->allocated < totalsize)
        !           240:                return NULL;
        !           241:
        !           242:        totalsize = pos * membersize;
        !           243:        return a->mem + totalsize;
        !           244: }
        !           245:
        !           246:
        !           247: void
        !           248: array_free(array * a)
        !           249: {
        !           250:        assert(a != NULL);
        !           251: #if DEBUG_ARRAY
        !           252:        Log(LOG_DEBUG,
        !           253:            "array_free(): %u bytes free'd (%u bytes still used at time of free()).",
        !           254:            a->allocated, a->used);
        !           255: #endif
        !           256:        free(a->mem);
        !           257:        a->mem = NULL;
        !           258:        a->allocated = 0;
        !           259:        a->used = 0;
        !           260: }
        !           261:
        !           262: void
        !           263: array_free_wipe(array *a)
        !           264: {
        !           265:        size_t bytes = a->allocated;
        !           266:        if (bytes)
        !           267:                memset(a->mem, 0, bytes);
        !           268:        array_free(a);
        !           269: }
        !           270:
        !           271: void *
        !           272: array_start(const array * const a)
        !           273: {
        !           274:        assert(a != NULL);
        !           275:        return a->mem;
        !           276: }
        !           277:
        !           278:
        !           279: void
        !           280: array_trunc(array * a)
        !           281: {
        !           282:        assert(a != NULL);
        !           283:        a->used = 0;
        !           284: }
        !           285:
        !           286:
        !           287: void
        !           288: array_truncate(array * a, size_t membersize, size_t len)
        !           289: {
        !           290:        size_t newlen;
        !           291:        assert(a != NULL);
        !           292:        if (!safemult_sizet(membersize, len, &newlen))
        !           293:                return;
        !           294:
        !           295:        if (newlen <= a->allocated)
        !           296:                a->used = newlen;
        !           297: }
        !           298:
        !           299:
        !           300: /* move elements starting at pos to beginning of array */
        !           301: void
        !           302: array_moveleft(array * a, size_t membersize, size_t pos)
        !           303: {
        !           304:        size_t bytepos;
        !           305:
        !           306:        assert(a != NULL);
        !           307:        assert(membersize > 0);
        !           308:
        !           309:        if (!safemult_sizet(membersize, pos, &bytepos)) {
        !           310:                a->used = 0;
        !           311:                return;
        !           312:        }
        !           313:
        !           314:        if (!bytepos)
        !           315:                return; /* nothing to do */
        !           316:
        !           317: #if DEBUG_ARRAY
        !           318:        Log(LOG_DEBUG,
        !           319:            "array_moveleft(): %u bytes used in array, starting at position %u.",
        !           320:            a->used, bytepos);
        !           321: #endif
        !           322:        if (a->used <= bytepos) {
        !           323:                a->used = 0;
        !           324:                return;
        !           325:        }
        !           326:
        !           327:        a->used -= bytepos;
        !           328:        memmove(a->mem, a->mem + bytepos, a->used);
        !           329: }
        !           330:
        !           331: /* -eof- */

CVSweb