root/trunk/src/array.c

Revision 2263, 8.2 kB (checked in by stbuehler, 2 months ago)

Replace buffer_{append,copy}_string with the _len variant where possible (#1732, thx crypt)
Replace BUFFER_{APPEND,COPY}_STRING_CONST with _len(b, CONST_STRL_LEN(x))

  • Property svn:eol-style set to native
Line 
1#include <string.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <limits.h>
5
6#include <errno.h>
7#include <assert.h>
8
9#include "array.h"
10#include "buffer.h"
11
12array *array_init(void) {
13        array *a;
14
15        a = calloc(1, sizeof(*a));
16        assert(a);
17
18        a->next_power_of_2 = 1;
19
20        return a;
21}
22
23array *array_init_array(array *src) {
24        size_t i;
25        array *a = array_init();
26
27        a->used = src->used;
28        a->size = src->size;
29        a->next_power_of_2 = src->next_power_of_2;
30        a->unique_ndx = src->unique_ndx;
31
32        a->data = malloc(sizeof(*src->data) * src->size);
33        for (i = 0; i < src->size; i++) {
34                if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]);
35                else a->data[i] = NULL;
36        }
37
38        a->sorted = malloc(sizeof(*src->sorted)   * src->size);
39        memcpy(a->sorted, src->sorted, sizeof(*src->sorted)   * src->size);
40        return a;
41}
42
43void array_free(array *a) {
44        size_t i;
45        if (!a) return;
46
47        if (!a->is_weakref) {
48                for (i = 0; i < a->size; i++) {
49                        if (a->data[i]) a->data[i]->free(a->data[i]);
50                }
51        }
52
53        if (a->data) free(a->data);
54        if (a->sorted) free(a->sorted);
55
56        free(a);
57}
58
59void array_reset(array *a) {
60        size_t i;
61        if (!a) return;
62
63        if (!a->is_weakref) {
64                for (i = 0; i < a->used; i++) {
65                        a->data[i]->reset(a->data[i]);
66                }
67        }
68
69        a->used = 0;
70}
71
72data_unset *array_pop(array *a) {
73        data_unset *du;
74
75        assert(a->used != 0);
76
77        a->used --;
78        du = a->data[a->used];
79        a->data[a->used] = NULL;
80
81        return du;
82}
83
84static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
85        int ndx = -1;
86        int i, pos = 0;
87
88        if (key == NULL) return -1;
89
90        /* try to find the string */
91        for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
92                int cmp;
93
94                if (pos < 0) {
95                        pos += i;
96                } else if (pos >= (int)a->used) {
97                        pos -= i;
98                } else {
99                        cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
100
101                        if (cmp == 0) {
102                                /* found */
103                                ndx = a->sorted[pos];
104                                break;
105                        } else if (cmp < 0) {
106                                pos -= i;
107                        } else {
108                                pos += i;
109                        }
110                }
111                if (i == 0) break;
112        }
113
114        if (rndx) *rndx = pos;
115
116        return ndx;
117}
118
119data_unset *array_get_element(array *a, const char *key, size_t keylen) {
120        int ndx;
121
122        if (-1 != (ndx = array_get_index(a, key, keylen + 1, NULL))) {
123                /* found, leave here */
124
125                return a->data[ndx];
126        }
127
128        return NULL;
129}
130
131data_unset *array_get_unused_element(array *a, data_type_t t) {
132        data_unset *ds = NULL;
133
134        UNUSED(t);
135
136        if (a->size == 0) return NULL;
137
138        if (a->used == a->size) return NULL;
139
140        if (a->data[a->used]) {
141                ds = a->data[a->used];
142
143                a->data[a->used] = NULL;
144        }
145
146        return ds;
147}
148
149void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
150        data_string *ds_dst;
151
152        if (NULL != (ds_dst = (data_string *)array_get_element(hdrs, key, key_len))) {
153                buffer_copy_string_len(ds_dst->value, value, val_len);
154                return;
155        }
156
157        if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
158                ds_dst = data_string_init();
159        }
160
161        buffer_copy_string_len(ds_dst->key, key, key_len);
162        buffer_copy_string_len(ds_dst->value, value, val_len);
163        array_insert_unique(hdrs, (data_unset *)ds_dst);
164}
165
166void array_append_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
167        data_string *ds_dst;
168
169        if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
170                ds_dst = data_string_init();
171        }
172
173        buffer_copy_string_len(ds_dst->key, key, key_len);
174        buffer_copy_string_len(ds_dst->value, value, val_len);
175        array_insert_unique(hdrs, (data_unset *)ds_dst);
176}
177
178/* replace or insert data, return the old one with the same key */
179data_unset *array_replace(array *a, data_unset *du) {
180        int ndx;
181
182        if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
183                array_insert_unique(a, du);
184                return NULL;
185        } else {
186                data_unset *old = a->data[ndx];
187                a->data[ndx] = du;
188                return old;
189        }
190}
191
192int array_insert_unique(array *a, data_unset *str) {
193        int ndx = -1;
194        int pos = 0;
195        size_t j;
196
197        /* generate unique index if necessary */
198        if (str->key->used == 0 || str->is_index_key) {
199                buffer_copy_long(str->key, a->unique_ndx++);
200                str->is_index_key = 1;
201        }
202
203        /* try to find the string */
204        if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
205                /* found, leave here */
206                if (a->data[ndx]->type == str->type) {
207                        str->insert_dup(a->data[ndx], str);
208                } else {
209                        fprintf(stderr, "a\n");
210                }
211                return 0;
212        }
213
214        /* insert */
215
216        if (a->used+1 > INT_MAX) {
217                /* we can't handle more then INT_MAX entries: see array_get_index() */
218                return -1;
219        }
220
221        if (a->size == 0) {
222                a->size   = 16;
223                a->data   = malloc(sizeof(*a->data)     * a->size);
224                a->sorted = malloc(sizeof(*a->sorted)   * a->size);
225                assert(a->data);
226                assert(a->sorted);
227                for (j = a->used; j < a->size; j++) a->data[j] = NULL;
228        } else if (a->size == a->used) {
229                a->size  += 16;
230                a->data   = realloc(a->data,   sizeof(*a->data)   * a->size);
231                a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size);
232                assert(a->data);
233                assert(a->sorted);
234                for (j = a->used; j < a->size; j++) a->data[j] = NULL;
235        }
236
237        ndx = (int) a->used;
238
239        a->data[a->used++] = str;
240
241        if (pos != ndx &&
242            ((pos < 0) ||
243             buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
244                pos++;
245        }
246
247        /* move everything one step to the right */
248        if (pos != ndx) {
249                memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
250        }
251
252        /* insert */
253        a->sorted[pos] = ndx;
254
255        if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
256
257        return 0;
258}
259
260void array_print_indent(int depth) {
261        int i;
262        for (i = 0; i < depth; i ++) {
263                fprintf(stdout, "    ");
264        }
265}
266
267size_t array_get_max_key_length(array *a) {
268        size_t maxlen, i;
269
270        maxlen = 0;
271        for (i = 0; i < a->used; i ++) {
272                data_unset *du = a->data[i];
273                size_t len = strlen(du->key->ptr);
274
275                if (len > maxlen) {
276                        maxlen = len;
277                }
278        }
279        return maxlen;
280}
281
282int array_print(array *a, int depth) {
283        size_t i;
284        size_t maxlen;
285        int oneline = 1;
286
287        if (a->used > 5) {
288                oneline = 0;
289        }
290        for (i = 0; i < a->used && oneline; i++) {
291                data_unset *du = a->data[i];
292                if (!du->is_index_key) {
293                        oneline = 0;
294                        break;
295                }
296                switch (du->type) {
297                        case TYPE_INTEGER:
298                        case TYPE_STRING:
299                        case TYPE_COUNT:
300                                break;
301                        default:
302                                oneline = 0;
303                                break;
304                }
305        }
306        if (oneline) {
307                fprintf(stdout, "(");
308                for (i = 0; i < a->used; i++) {
309                        data_unset *du = a->data[i];
310                        if (i != 0) {
311                                fprintf(stdout, ", ");
312                        }
313                        du->print(du, depth + 1);
314                }
315                fprintf(stdout, ")");
316                return 0;
317        }
318
319        maxlen = array_get_max_key_length(a);
320        fprintf(stdout, "(\n");
321        for (i = 0; i < a->used; i++) {
322                data_unset *du = a->data[i];
323                array_print_indent(depth + 1);
324                if (!du->is_index_key) {
325                        int j;
326
327                        if (i && (i % 5) == 0) {
328                                fprintf(stdout, "# %zd\n", i);
329                                array_print_indent(depth + 1);
330                        }
331                        fprintf(stdout, "\"%s\"", du->key->ptr);
332                        for (j = maxlen - strlen(du->key->ptr); j > 0; j --) {
333                                fprintf(stdout, " ");
334                        }
335                        fprintf(stdout, " => ");
336                }
337                du->print(du, depth + 1);
338                fprintf(stdout, ",\n");
339        }
340        if (!(i && (i - 1 % 5) == 0)) {
341                array_print_indent(depth + 1);
342                fprintf(stdout, "# %zd\n", i);
343        }
344        array_print_indent(depth);
345        fprintf(stdout, ")");
346
347        return 0;
348}
349
350#ifdef DEBUG_ARRAY
351int main (int argc, char **argv) {
352        array *a;
353        data_string *ds;
354        data_count *dc;
355
356        UNUSED(argc);
357        UNUSED(argv);
358
359        a = array_init();
360
361        ds = data_string_init();
362        buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
363        buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
364
365        array_insert_unique(a, (data_unset *)ds);
366
367        ds = data_string_init();
368        buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
369        buffer_copy_string_len(ds->value, CONST_STR_LEN("hameplman"));
370
371        array_insert_unique(a, (data_unset *)ds);
372
373        ds = data_string_init();
374        buffer_copy_string_len(ds->key, CONST_STR_LEN("123"));
375        buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
376
377        array_insert_unique(a, (data_unset *)ds);
378
379        dc = data_count_init();
380        buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
381
382        array_insert_unique(a, (data_unset *)dc);
383
384        dc = data_count_init();
385        buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
386
387        array_insert_unique(a, (data_unset *)dc);
388
389        array_print(a, 0);
390
391        array_free(a);
392
393        fprintf(stderr, "%d\n",
394               buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
395
396        return 0;
397}
398#endif
Note: See TracBrowser for help on using the browser.