Annotation of embedaddon/lighttpd/src/array.c, revision 1.1

1.1     ! misho       1: #include "array.h"
        !             2: #include "buffer.h"
        !             3: 
        !             4: #include <string.h>
        !             5: #include <stdio.h>
        !             6: #include <stdlib.h>
        !             7: #include <limits.h>
        !             8: 
        !             9: #include <errno.h>
        !            10: #include <assert.h>
        !            11: 
        !            12: array *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: 
        !            23: array *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: 
        !            43: void 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: 
        !            59: void 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: 
        !            72: data_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: 
        !            84: static 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: 
        !           119: data_unset *array_get_element(array *a, const char *key) {
        !           120:        int ndx;
        !           121: 
        !           122:        if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
        !           123:                /* found, leave here */
        !           124: 
        !           125:                return a->data[ndx];
        !           126:        }
        !           127: 
        !           128:        return NULL;
        !           129: }
        !           130: 
        !           131: data_unset *array_get_unused_element(array *a, data_type_t t) {
        !           132:        data_unset *ds = NULL;
        !           133:        unsigned int i;
        !           134: 
        !           135:        for (i = a->used; i < a->size; i++) {
        !           136:                if (a->data[i] && a->data[i]->type == t) {
        !           137:                        ds = a->data[i];
        !           138: 
        !           139:                        /* make empty slot at a->used for next insert */
        !           140:                        a->data[i] = a->data[a->used];
        !           141:                        a->data[a->used] = NULL;
        !           142: 
        !           143:                        return ds;
        !           144:                }
        !           145:        }
        !           146: 
        !           147:        return NULL;
        !           148: }
        !           149: 
        !           150: void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
        !           151:        data_string *ds_dst;
        !           152: 
        !           153:        if (NULL != (ds_dst = (data_string *)array_get_element(hdrs, key))) {
        !           154:                buffer_copy_string_len(ds_dst->value, value, val_len);
        !           155:                return;
        !           156:        }
        !           157: 
        !           158:        if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
        !           159:                ds_dst = data_string_init();
        !           160:        }
        !           161: 
        !           162:        buffer_copy_string_len(ds_dst->key, key, key_len);
        !           163:        buffer_copy_string_len(ds_dst->value, value, val_len);
        !           164:        array_insert_unique(hdrs, (data_unset *)ds_dst);
        !           165: }
        !           166: 
        !           167: /* replace or insert data, return the old one with the same key */
        !           168: data_unset *array_replace(array *a, data_unset *du) {
        !           169:        int ndx;
        !           170: 
        !           171:        if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
        !           172:                array_insert_unique(a, du);
        !           173:                return NULL;
        !           174:        } else {
        !           175:                data_unset *old = a->data[ndx];
        !           176:                a->data[ndx] = du;
        !           177:                return old;
        !           178:        }
        !           179: }
        !           180: 
        !           181: int array_insert_unique(array *a, data_unset *str) {
        !           182:        int ndx = -1;
        !           183:        int pos = 0;
        !           184:        size_t j;
        !           185: 
        !           186:        /* generate unique index if neccesary */
        !           187:        if (str->key->used == 0 || str->is_index_key) {
        !           188:                buffer_copy_long(str->key, a->unique_ndx++);
        !           189:                str->is_index_key = 1;
        !           190:        }
        !           191: 
        !           192:        /* try to find the string */
        !           193:        if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
        !           194:                /* found, leave here */
        !           195:                if (a->data[ndx]->type == str->type) {
        !           196:                        str->insert_dup(a->data[ndx], str);
        !           197:                } else {
        !           198:                        SEGFAULT();
        !           199:                }
        !           200:                return 0;
        !           201:        }
        !           202: 
        !           203:        /* insert */
        !           204: 
        !           205:        if (a->used+1 > INT_MAX) {
        !           206:                /* we can't handle more then INT_MAX entries: see array_get_index() */
        !           207:                return -1;
        !           208:        }
        !           209: 
        !           210:        if (a->size == 0) {
        !           211:                a->size   = 16;
        !           212:                a->data   = malloc(sizeof(*a->data)     * a->size);
        !           213:                a->sorted = malloc(sizeof(*a->sorted)   * a->size);
        !           214:                assert(a->data);
        !           215:                assert(a->sorted);
        !           216:                for (j = a->used; j < a->size; j++) a->data[j] = NULL;
        !           217:        } else if (a->size == a->used) {
        !           218:                a->size  += 16;
        !           219:                a->data   = realloc(a->data,   sizeof(*a->data)   * a->size);
        !           220:                a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size);
        !           221:                assert(a->data);
        !           222:                assert(a->sorted);
        !           223:                for (j = a->used; j < a->size; j++) a->data[j] = NULL;
        !           224:        }
        !           225: 
        !           226:        ndx = (int) a->used;
        !           227: 
        !           228:        /* make sure there is nothing here */
        !           229:        if (a->data[ndx]) a->data[ndx]->free(a->data[ndx]);
        !           230: 
        !           231:        a->data[a->used++] = str;
        !           232: 
        !           233:        if (pos != ndx &&
        !           234:            ((pos < 0) ||
        !           235:             buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
        !           236:                pos++;
        !           237:        }
        !           238: 
        !           239:        /* move everything on step to the right */
        !           240:        if (pos != ndx) {
        !           241:                memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
        !           242:        }
        !           243: 
        !           244:        /* insert */
        !           245:        a->sorted[pos] = ndx;
        !           246: 
        !           247:        if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
        !           248: 
        !           249:        return 0;
        !           250: }
        !           251: 
        !           252: void array_print_indent(int depth) {
        !           253:        int i;
        !           254:        for (i = 0; i < depth; i ++) {
        !           255:                fprintf(stdout, "    ");
        !           256:        }
        !           257: }
        !           258: 
        !           259: size_t array_get_max_key_length(array *a) {
        !           260:        size_t maxlen, i;
        !           261: 
        !           262:        maxlen = 0;
        !           263:        for (i = 0; i < a->used; i ++) {
        !           264:                data_unset *du = a->data[i];
        !           265:                size_t len = strlen(du->key->ptr);
        !           266: 
        !           267:                if (len > maxlen) {
        !           268:                        maxlen = len;
        !           269:                }
        !           270:        }
        !           271:        return maxlen;
        !           272: }
        !           273: 
        !           274: int array_print(array *a, int depth) {
        !           275:        size_t i;
        !           276:        size_t maxlen;
        !           277:        int oneline = 1;
        !           278: 
        !           279:        if (a->used > 5) {
        !           280:                oneline = 0;
        !           281:        }
        !           282:        for (i = 0; i < a->used && oneline; i++) {
        !           283:                data_unset *du = a->data[i];
        !           284:                if (!du->is_index_key) {
        !           285:                        oneline = 0;
        !           286:                        break;
        !           287:                }
        !           288:                switch (du->type) {
        !           289:                        case TYPE_INTEGER:
        !           290:                        case TYPE_STRING:
        !           291:                        case TYPE_COUNT:
        !           292:                                break;
        !           293:                        default:
        !           294:                                oneline = 0;
        !           295:                                break;
        !           296:                }
        !           297:        }
        !           298:        if (oneline) {
        !           299:                fprintf(stdout, "(");
        !           300:                for (i = 0; i < a->used; i++) {
        !           301:                        data_unset *du = a->data[i];
        !           302:                        if (i != 0) {
        !           303:                                fprintf(stdout, ", ");
        !           304:                        }
        !           305:                        du->print(du, depth + 1);
        !           306:                }
        !           307:                fprintf(stdout, ")");
        !           308:                return 0;
        !           309:        }
        !           310: 
        !           311:        maxlen = array_get_max_key_length(a);
        !           312:        fprintf(stdout, "(\n");
        !           313:        for (i = 0; i < a->used; i++) {
        !           314:                data_unset *du = a->data[i];
        !           315:                array_print_indent(depth + 1);
        !           316:                if (!du->is_index_key) {
        !           317:                        int j;
        !           318: 
        !           319:                        if (i && (i % 5) == 0) {
        !           320:                                fprintf(stdout, "# %zd\n", i);
        !           321:                                array_print_indent(depth + 1);
        !           322:                        }
        !           323:                        fprintf(stdout, "\"%s\"", du->key->ptr);
        !           324:                        for (j = maxlen - strlen(du->key->ptr); j > 0; j --) {
        !           325:                                fprintf(stdout, " ");
        !           326:                        }
        !           327:                        fprintf(stdout, " => ");
        !           328:                }
        !           329:                du->print(du, depth + 1);
        !           330:                fprintf(stdout, ",\n");
        !           331:        }
        !           332:        if (!(i && (i - 1 % 5) == 0)) {
        !           333:                array_print_indent(depth + 1);
        !           334:                fprintf(stdout, "# %zd\n", i);
        !           335:        }
        !           336:        array_print_indent(depth);
        !           337:        fprintf(stdout, ")");
        !           338: 
        !           339:        return 0;
        !           340: }
        !           341: 
        !           342: #ifdef DEBUG_ARRAY
        !           343: int main (int argc, char **argv) {
        !           344:        array *a;
        !           345:        data_string *ds;
        !           346:        data_count *dc;
        !           347: 
        !           348:        UNUSED(argc);
        !           349:        UNUSED(argv);
        !           350: 
        !           351:        a = array_init();
        !           352: 
        !           353:        ds = data_string_init();
        !           354:        buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
        !           355:        buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
        !           356: 
        !           357:        array_insert_unique(a, (data_unset *)ds);
        !           358: 
        !           359:        ds = data_string_init();
        !           360:        buffer_copy_string_len(ds->key, CONST_STR_LEN("abc"));
        !           361:        buffer_copy_string_len(ds->value, CONST_STR_LEN("hameplman"));
        !           362: 
        !           363:        array_insert_unique(a, (data_unset *)ds);
        !           364: 
        !           365:        ds = data_string_init();
        !           366:        buffer_copy_string_len(ds->key, CONST_STR_LEN("123"));
        !           367:        buffer_copy_string_len(ds->value, CONST_STR_LEN("alfrag"));
        !           368: 
        !           369:        array_insert_unique(a, (data_unset *)ds);
        !           370: 
        !           371:        dc = data_count_init();
        !           372:        buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
        !           373: 
        !           374:        array_insert_unique(a, (data_unset *)dc);
        !           375: 
        !           376:        dc = data_count_init();
        !           377:        buffer_copy_string_len(dc->key, CONST_STR_LEN("def"));
        !           378: 
        !           379:        array_insert_unique(a, (data_unset *)dc);
        !           380: 
        !           381:        array_print(a, 0);
        !           382: 
        !           383:        array_free(a);
        !           384: 
        !           385:        fprintf(stderr, "%d\n",
        !           386:               buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
        !           387: 
        !           388:        return 0;
        !           389: }
        !           390: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>