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