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>