Annotation of ircnowd/src/ngircd/array.c, Revision 1.1.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