1bcdc6a3bSJan Kneschke #include <string.h> 2bcdc6a3bSJan Kneschke #include <stdio.h> 3bcdc6a3bSJan Kneschke #include <stdlib.h> 4bcdc6a3bSJan Kneschke #include <limits.h> 5bcdc6a3bSJan Kneschke 6bcdc6a3bSJan Kneschke #include <errno.h> 7bcdc6a3bSJan Kneschke #include <assert.h> 8bcdc6a3bSJan Kneschke 9bcdc6a3bSJan Kneschke #include "array.h" 10bcdc6a3bSJan Kneschke #include "buffer.h" 11bcdc6a3bSJan Kneschke 12bcdc6a3bSJan Kneschke array *array_init(void) { 13bcdc6a3bSJan Kneschke array *a; 14bcdc6a3bSJan Kneschke 15bcdc6a3bSJan Kneschke a = calloc(1, sizeof(*a)); 16bcdc6a3bSJan Kneschke assert(a); 17bcdc6a3bSJan Kneschke 18bcdc6a3bSJan Kneschke a->next_power_of_2 = 1; 19bcdc6a3bSJan Kneschke 20bcdc6a3bSJan Kneschke return a; 21bcdc6a3bSJan Kneschke } 22bcdc6a3bSJan Kneschke 236e78c2c8SJan Kneschke array *array_init_array(array *src) { 246e78c2c8SJan Kneschke size_t i; 256e78c2c8SJan Kneschke array *a = array_init(); 266e78c2c8SJan Kneschke 276e78c2c8SJan Kneschke a->used = src->used; 286e78c2c8SJan Kneschke a->size = src->size; 296e78c2c8SJan Kneschke a->next_power_of_2 = src->next_power_of_2; 306e78c2c8SJan Kneschke a->unique_ndx = src->unique_ndx; 316e78c2c8SJan Kneschke 326e78c2c8SJan Kneschke a->data = malloc(sizeof(*src->data) * src->size); 336e78c2c8SJan Kneschke for (i = 0; i < src->size; i++) { 346e78c2c8SJan Kneschke if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]); 356e78c2c8SJan Kneschke else a->data[i] = NULL; 366e78c2c8SJan Kneschke } 376e78c2c8SJan Kneschke 386e78c2c8SJan Kneschke a->sorted = malloc(sizeof(*src->sorted) * src->size); 396e78c2c8SJan Kneschke memcpy(a->sorted, src->sorted, sizeof(*src->sorted) * src->size); 406e78c2c8SJan Kneschke return a; 416e78c2c8SJan Kneschke } 426e78c2c8SJan Kneschke 43bcdc6a3bSJan Kneschke void array_free(array *a) { 44bcdc6a3bSJan Kneschke size_t i; 45bcdc6a3bSJan Kneschke if (!a) return; 46bcdc6a3bSJan Kneschke 478b07d57dSJan Kneschke if (!a->is_weakref) { 48bcdc6a3bSJan Kneschke for (i = 0; i < a->size; i++) { 49bcdc6a3bSJan Kneschke if (a->data[i]) a->data[i]->free(a->data[i]); 50bcdc6a3bSJan Kneschke } 518b07d57dSJan Kneschke } 52bcdc6a3bSJan Kneschke 53bcdc6a3bSJan Kneschke if (a->data) free(a->data); 54bcdc6a3bSJan Kneschke if (a->sorted) free(a->sorted); 55bcdc6a3bSJan Kneschke 56bcdc6a3bSJan Kneschke free(a); 57bcdc6a3bSJan Kneschke } 58bcdc6a3bSJan Kneschke 59bcdc6a3bSJan Kneschke void array_reset(array *a) { 60bcdc6a3bSJan Kneschke size_t i; 61bcdc6a3bSJan Kneschke if (!a) return; 62bcdc6a3bSJan Kneschke 638b07d57dSJan Kneschke if (!a->is_weakref) { 64bcdc6a3bSJan Kneschke for (i = 0; i < a->used; i++) { 65bcdc6a3bSJan Kneschke a->data[i]->reset(a->data[i]); 66bcdc6a3bSJan Kneschke } 678b07d57dSJan Kneschke } 68bcdc6a3bSJan Kneschke 69bcdc6a3bSJan Kneschke a->used = 0; 70bcdc6a3bSJan Kneschke } 71bcdc6a3bSJan Kneschke 728073d5feSJan Kneschke data_unset *array_pop(array *a) { 738073d5feSJan Kneschke data_unset *du; 748073d5feSJan Kneschke 758073d5feSJan Kneschke assert(a->used != 0); 768073d5feSJan Kneschke 778073d5feSJan Kneschke a->used --; 788073d5feSJan Kneschke du = a->data[a->used]; 798073d5feSJan Kneschke a->data[a->used] = NULL; 808073d5feSJan Kneschke 818073d5feSJan Kneschke return du; 828073d5feSJan Kneschke } 838073d5feSJan Kneschke 84bcdc6a3bSJan Kneschke static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) { 85bcdc6a3bSJan Kneschke int ndx = -1; 86bcdc6a3bSJan Kneschke int i, pos = 0; 87bcdc6a3bSJan Kneschke 88bcdc6a3bSJan Kneschke if (key == NULL) return -1; 89bcdc6a3bSJan Kneschke 90bcdc6a3bSJan Kneschke /* try to find the string */ 91bcdc6a3bSJan Kneschke for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) { 92bcdc6a3bSJan Kneschke int cmp; 93bcdc6a3bSJan Kneschke 94bcdc6a3bSJan Kneschke if (pos < 0) { 95bcdc6a3bSJan Kneschke pos += i; 96bcdc6a3bSJan Kneschke } else if (pos >= (int)a->used) { 97bcdc6a3bSJan Kneschke pos -= i; 98bcdc6a3bSJan Kneschke } else { 99bcdc6a3bSJan Kneschke cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used); 100bcdc6a3bSJan Kneschke 101bcdc6a3bSJan Kneschke if (cmp == 0) { 102bcdc6a3bSJan Kneschke /* found */ 103bcdc6a3bSJan Kneschke ndx = a->sorted[pos]; 104bcdc6a3bSJan Kneschke break; 105bcdc6a3bSJan Kneschke } else if (cmp < 0) { 106bcdc6a3bSJan Kneschke pos -= i; 107bcdc6a3bSJan Kneschke } else { 108bcdc6a3bSJan Kneschke pos += i; 109bcdc6a3bSJan Kneschke } 110bcdc6a3bSJan Kneschke } 111bcdc6a3bSJan Kneschke if (i == 0) break; 112bcdc6a3bSJan Kneschke } 113bcdc6a3bSJan Kneschke 114bcdc6a3bSJan Kneschke if (rndx) *rndx = pos; 115bcdc6a3bSJan Kneschke 116bcdc6a3bSJan Kneschke return ndx; 117bcdc6a3bSJan Kneschke } 118bcdc6a3bSJan Kneschke 119bcdc6a3bSJan Kneschke data_unset *array_get_element(array *a, const char *key) { 120bcdc6a3bSJan Kneschke int ndx; 121bcdc6a3bSJan Kneschke 122bcdc6a3bSJan Kneschke if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) { 123bcdc6a3bSJan Kneschke /* found, leave here */ 124bcdc6a3bSJan Kneschke 125bcdc6a3bSJan Kneschke return a->data[ndx]; 126bcdc6a3bSJan Kneschke } 127bcdc6a3bSJan Kneschke 128bcdc6a3bSJan Kneschke return NULL; 129bcdc6a3bSJan Kneschke } 130bcdc6a3bSJan Kneschke 131bcdc6a3bSJan Kneschke data_unset *array_get_unused_element(array *a, data_type_t t) { 132bcdc6a3bSJan Kneschke data_unset *ds = NULL; 133bcdc6a3bSJan Kneschke 134bcdc6a3bSJan Kneschke UNUSED(t); 135bcdc6a3bSJan Kneschke 136bcdc6a3bSJan Kneschke if (a->size == 0) return NULL; 137bcdc6a3bSJan Kneschke 138bcdc6a3bSJan Kneschke if (a->used == a->size) return NULL; 139bcdc6a3bSJan Kneschke 140bcdc6a3bSJan Kneschke if (a->data[a->used]) { 141bcdc6a3bSJan Kneschke ds = a->data[a->used]; 142bcdc6a3bSJan Kneschke 143bcdc6a3bSJan Kneschke a->data[a->used] = NULL; 144bcdc6a3bSJan Kneschke } 145bcdc6a3bSJan Kneschke 146bcdc6a3bSJan Kneschke return ds; 147bcdc6a3bSJan Kneschke } 148bcdc6a3bSJan Kneschke 1496e78c2c8SJan Kneschke /* replace or insert data, return the old one with the same key */ 1506e78c2c8SJan Kneschke data_unset *array_replace(array *a, data_unset *du) { 1516e78c2c8SJan Kneschke int ndx; 152cf002f68SJan Kneschke 1536e78c2c8SJan Kneschke if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) { 1546e78c2c8SJan Kneschke array_insert_unique(a, du); 1556e78c2c8SJan Kneschke return NULL; 156cf002f68SJan Kneschke } else { 1576e78c2c8SJan Kneschke data_unset *old = a->data[ndx]; 1586e78c2c8SJan Kneschke a->data[ndx] = du; 1596e78c2c8SJan Kneschke return old; 1606e78c2c8SJan Kneschke } 1616e78c2c8SJan Kneschke } 1626e78c2c8SJan Kneschke 163bcdc6a3bSJan Kneschke int array_insert_unique(array *a, data_unset *str) { 164bcdc6a3bSJan Kneschke int ndx = -1; 165bcdc6a3bSJan Kneschke int pos = 0; 166bcdc6a3bSJan Kneschke size_t j; 167bcdc6a3bSJan Kneschke 168bcdc6a3bSJan Kneschke /* generate unique index if neccesary */ 169bcdc6a3bSJan Kneschke if (str->key->used == 0) { 170bcdc6a3bSJan Kneschke buffer_copy_long(str->key, a->unique_ndx++); 171bcdc6a3bSJan Kneschke } 172bcdc6a3bSJan Kneschke 173bcdc6a3bSJan Kneschke /* try to find the string */ 174bcdc6a3bSJan Kneschke 175bcdc6a3bSJan Kneschke if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) { 176bcdc6a3bSJan Kneschke /* found, leave here */ 177bcdc6a3bSJan Kneschke if (a->data[ndx]->type == str->type) { 178bcdc6a3bSJan Kneschke str->insert_dup(a->data[ndx], str); 179bcdc6a3bSJan Kneschke } else { 180bcdc6a3bSJan Kneschke fprintf(stderr, "a\n"); 181bcdc6a3bSJan Kneschke } 182bcdc6a3bSJan Kneschke return 0; 183bcdc6a3bSJan Kneschke } 184bcdc6a3bSJan Kneschke 185bcdc6a3bSJan Kneschke /* insert */ 186bcdc6a3bSJan Kneschke 187bcdc6a3bSJan Kneschke if (a->used+1 > INT_MAX) { 188bcdc6a3bSJan Kneschke /* we can't handle more then INT_MAX entries: see array_get_index() */ 189bcdc6a3bSJan Kneschke return -1; 190bcdc6a3bSJan Kneschke } 191bcdc6a3bSJan Kneschke 192bcdc6a3bSJan Kneschke if (a->size == 0) { 193bcdc6a3bSJan Kneschke a->size = 16; 194bcdc6a3bSJan Kneschke a->data = malloc(sizeof(*a->data) * a->size); 195bcdc6a3bSJan Kneschke a->sorted = malloc(sizeof(*a->sorted) * a->size); 196bcdc6a3bSJan Kneschke assert(a->data); 197bcdc6a3bSJan Kneschke assert(a->sorted); 198bcdc6a3bSJan Kneschke for (j = a->used; j < a->size; j++) a->data[j] = NULL; 199bcdc6a3bSJan Kneschke } else if (a->size == a->used) { 200bcdc6a3bSJan Kneschke a->size += 16; 201bcdc6a3bSJan Kneschke a->data = realloc(a->data, sizeof(*a->data) * a->size); 202bcdc6a3bSJan Kneschke a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size); 203bcdc6a3bSJan Kneschke assert(a->data); 204bcdc6a3bSJan Kneschke assert(a->sorted); 205bcdc6a3bSJan Kneschke for (j = a->used; j < a->size; j++) a->data[j] = NULL; 206bcdc6a3bSJan Kneschke } 207bcdc6a3bSJan Kneschke 208bcdc6a3bSJan Kneschke ndx = (int) a->used; 209bcdc6a3bSJan Kneschke 210bcdc6a3bSJan Kneschke a->data[a->used++] = str; 211bcdc6a3bSJan Kneschke 212bcdc6a3bSJan Kneschke if (pos != ndx && 213bcdc6a3bSJan Kneschke ((pos < 0) || 214bcdc6a3bSJan Kneschke buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) { 215bcdc6a3bSJan Kneschke pos++; 216bcdc6a3bSJan Kneschke } 217bcdc6a3bSJan Kneschke 218bcdc6a3bSJan Kneschke /* move everything on step to the right */ 219bcdc6a3bSJan Kneschke if (pos != ndx) { 220bcdc6a3bSJan Kneschke memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted)); 221bcdc6a3bSJan Kneschke } 222bcdc6a3bSJan Kneschke 223bcdc6a3bSJan Kneschke /* insert */ 224bcdc6a3bSJan Kneschke a->sorted[pos] = ndx; 225bcdc6a3bSJan Kneschke 226bcdc6a3bSJan Kneschke if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1; 227bcdc6a3bSJan Kneschke 228bcdc6a3bSJan Kneschke return 0; 229bcdc6a3bSJan Kneschke } 230bcdc6a3bSJan Kneschke 2319e75ba00SJan Kneschke void array_print_indent(int depth) { 2329e75ba00SJan Kneschke int i; 2339e75ba00SJan Kneschke for (i = 0; i < depth; i ++) { 2349e75ba00SJan Kneschke fprintf(stderr, " "); 2359e75ba00SJan Kneschke } 2369e75ba00SJan Kneschke } 2379e75ba00SJan Kneschke 238*6044dbc5SmOo size_t array_get_max_key_length(array *a) { 239*6044dbc5SmOo size_t maxlen, i; 240*6044dbc5SmOo 241*6044dbc5SmOo maxlen = 0; 242*6044dbc5SmOo for (i = 0; i < a->used; i ++) { 243*6044dbc5SmOo data_unset *du = a->data[i]; 244*6044dbc5SmOo size_t len = strlen(du->key->ptr); 245*6044dbc5SmOo 246*6044dbc5SmOo if (len > maxlen) { 247*6044dbc5SmOo maxlen = len; 248*6044dbc5SmOo } 249*6044dbc5SmOo } 250*6044dbc5SmOo return maxlen; 251*6044dbc5SmOo } 252*6044dbc5SmOo 253*6044dbc5SmOo static inline int str_int_equal(const char *str, int i) { 254*6044dbc5SmOo char buf[16]; 255*6044dbc5SmOo snprintf(buf, sizeof(buf), "%d", i); 256*6044dbc5SmOo return strcmp(str, buf) == 0; 257*6044dbc5SmOo } 258*6044dbc5SmOo 2599e75ba00SJan Kneschke int array_print(array *a, int depth) { 260bcdc6a3bSJan Kneschke size_t i; 261*6044dbc5SmOo size_t maxlen; 262*6044dbc5SmOo int oneline = 1; 263bcdc6a3bSJan Kneschke 264*6044dbc5SmOo if (a->used > 5) { 265*6044dbc5SmOo oneline = 0; 266*6044dbc5SmOo } 267*6044dbc5SmOo for (i = 0; i < a->used && oneline; i++) { 268*6044dbc5SmOo data_unset *du = a->data[i]; 269*6044dbc5SmOo if (!str_int_equal(du->key->ptr, i)) { 270*6044dbc5SmOo oneline = 0; 271*6044dbc5SmOo break; 272*6044dbc5SmOo } 273*6044dbc5SmOo switch (du->type) { 274*6044dbc5SmOo case TYPE_INTEGER: 275*6044dbc5SmOo case TYPE_STRING: 276*6044dbc5SmOo case TYPE_COUNT: 277*6044dbc5SmOo break; 278*6044dbc5SmOo default: 279*6044dbc5SmOo oneline = 0; 280*6044dbc5SmOo break; 281*6044dbc5SmOo } 282*6044dbc5SmOo } 283*6044dbc5SmOo if (oneline) { 284*6044dbc5SmOo fprintf(stderr, "("); 285bcdc6a3bSJan Kneschke for (i = 0; i < a->used; i++) { 286*6044dbc5SmOo data_unset *du = a->data[i]; 287*6044dbc5SmOo if (i != 0) { 288*6044dbc5SmOo fprintf(stderr, ", "); 289*6044dbc5SmOo } 290*6044dbc5SmOo du->print(du, depth + 1); 291*6044dbc5SmOo } 292*6044dbc5SmOo fprintf(stderr, ")"); 293*6044dbc5SmOo return 0; 294*6044dbc5SmOo } 295*6044dbc5SmOo 296*6044dbc5SmOo maxlen = array_get_max_key_length(a); 297*6044dbc5SmOo fprintf(stderr, "(\n"); 298*6044dbc5SmOo for (i = 0; i < a->used; i++) { 299*6044dbc5SmOo data_unset *du = a->data[i]; 3008b07d57dSJan Kneschke array_print_indent(depth + 1); 301*6044dbc5SmOo if (!str_int_equal(du->key->ptr, i)) { 302*6044dbc5SmOo int j; 303*6044dbc5SmOo 304*6044dbc5SmOo if (i && (i % 5) == 0) { 305*6044dbc5SmOo fprintf(stderr, "# %d\n", i); 306*6044dbc5SmOo array_print_indent(depth + 1); 307*6044dbc5SmOo } 308*6044dbc5SmOo fprintf(stderr, "\"%s\"", du->key->ptr); 309*6044dbc5SmOo for (j = maxlen - strlen(du->key->ptr); j > 0; j --) { 310*6044dbc5SmOo fprintf(stderr, " "); 311*6044dbc5SmOo } 312*6044dbc5SmOo fprintf(stderr, " => "); 313*6044dbc5SmOo } 314*6044dbc5SmOo du->print(du, depth + 1); 315*6044dbc5SmOo fprintf(stderr, ",\n"); 316*6044dbc5SmOo } 317*6044dbc5SmOo if (!(i && (i - 1 % 5) == 0)) { 318*6044dbc5SmOo array_print_indent(depth + 1); 319*6044dbc5SmOo fprintf(stderr, "# %d\n", i); 320bcdc6a3bSJan Kneschke } 3218b07d57dSJan Kneschke array_print_indent(depth); 322*6044dbc5SmOo fprintf(stderr, ")"); 323bcdc6a3bSJan Kneschke 324bcdc6a3bSJan Kneschke return 0; 325bcdc6a3bSJan Kneschke } 326bcdc6a3bSJan Kneschke 327bcdc6a3bSJan Kneschke #ifdef DEBUG_ARRAY 328bcdc6a3bSJan Kneschke int main (int argc, char **argv) { 329bcdc6a3bSJan Kneschke array *a; 330bcdc6a3bSJan Kneschke data_string *ds; 331bcdc6a3bSJan Kneschke data_count *dc; 332bcdc6a3bSJan Kneschke 333bcdc6a3bSJan Kneschke UNUSED(argc); 334bcdc6a3bSJan Kneschke UNUSED(argv); 335bcdc6a3bSJan Kneschke 336bcdc6a3bSJan Kneschke a = array_init(); 337bcdc6a3bSJan Kneschke 338bcdc6a3bSJan Kneschke ds = data_string_init(); 339bcdc6a3bSJan Kneschke buffer_copy_string(ds->key, "abc"); 340bcdc6a3bSJan Kneschke buffer_copy_string(ds->value, "alfrag"); 341bcdc6a3bSJan Kneschke 342bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)ds); 343bcdc6a3bSJan Kneschke 344bcdc6a3bSJan Kneschke ds = data_string_init(); 345bcdc6a3bSJan Kneschke buffer_copy_string(ds->key, "abc"); 346bcdc6a3bSJan Kneschke buffer_copy_string(ds->value, "hameplman"); 347bcdc6a3bSJan Kneschke 348bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)ds); 349bcdc6a3bSJan Kneschke 350bcdc6a3bSJan Kneschke ds = data_string_init(); 351bcdc6a3bSJan Kneschke buffer_copy_string(ds->key, "123"); 352bcdc6a3bSJan Kneschke buffer_copy_string(ds->value, "alfrag"); 353bcdc6a3bSJan Kneschke 354bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)ds); 355bcdc6a3bSJan Kneschke 356bcdc6a3bSJan Kneschke dc = data_count_init(); 357bcdc6a3bSJan Kneschke buffer_copy_string(dc->key, "def"); 358bcdc6a3bSJan Kneschke 359bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)dc); 360bcdc6a3bSJan Kneschke 361bcdc6a3bSJan Kneschke dc = data_count_init(); 362bcdc6a3bSJan Kneschke buffer_copy_string(dc->key, "def"); 363bcdc6a3bSJan Kneschke 364bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)dc); 365bcdc6a3bSJan Kneschke 3669e75ba00SJan Kneschke array_print(a, 0); 367bcdc6a3bSJan Kneschke 368bcdc6a3bSJan Kneschke array_free(a); 369bcdc6a3bSJan Kneschke 370bcdc6a3bSJan Kneschke fprintf(stderr, "%d\n", 371bcdc6a3bSJan Kneschke buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type"))); 372bcdc6a3bSJan Kneschke 373bcdc6a3bSJan Kneschke return 0; 374bcdc6a3bSJan Kneschke } 375bcdc6a3bSJan Kneschke #endif 376