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 23*6e78c2c8SJan Kneschke array *array_init_array(array *src) { 24*6e78c2c8SJan Kneschke size_t i; 25*6e78c2c8SJan Kneschke array *a = array_init(); 26*6e78c2c8SJan Kneschke 27*6e78c2c8SJan Kneschke a->used = src->used; 28*6e78c2c8SJan Kneschke a->size = src->size; 29*6e78c2c8SJan Kneschke a->next_power_of_2 = src->next_power_of_2; 30*6e78c2c8SJan Kneschke a->unique_ndx = src->unique_ndx; 31*6e78c2c8SJan Kneschke 32*6e78c2c8SJan Kneschke a->data = malloc(sizeof(*src->data) * src->size); 33*6e78c2c8SJan Kneschke for (i = 0; i < src->size; i++) { 34*6e78c2c8SJan Kneschke if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]); 35*6e78c2c8SJan Kneschke else a->data[i] = NULL; 36*6e78c2c8SJan Kneschke } 37*6e78c2c8SJan Kneschke 38*6e78c2c8SJan Kneschke a->sorted = malloc(sizeof(*src->sorted) * src->size); 39*6e78c2c8SJan Kneschke memcpy(a->sorted, src->sorted, sizeof(*src->sorted) * src->size); 40*6e78c2c8SJan Kneschke return a; 41*6e78c2c8SJan Kneschke } 42*6e78c2c8SJan Kneschke 43bcdc6a3bSJan Kneschke void array_free(array *a) { 44bcdc6a3bSJan Kneschke size_t i; 45bcdc6a3bSJan Kneschke if (!a) return; 46bcdc6a3bSJan Kneschke 47bcdc6a3bSJan Kneschke for (i = 0; i < a->size; i++) { 48bcdc6a3bSJan Kneschke if (a->data[i]) a->data[i]->free(a->data[i]); 49bcdc6a3bSJan Kneschke } 50bcdc6a3bSJan Kneschke 51bcdc6a3bSJan Kneschke if (a->data) free(a->data); 52bcdc6a3bSJan Kneschke if (a->sorted) free(a->sorted); 53bcdc6a3bSJan Kneschke 54bcdc6a3bSJan Kneschke free(a); 55bcdc6a3bSJan Kneschke } 56bcdc6a3bSJan Kneschke 57bcdc6a3bSJan Kneschke void array_reset(array *a) { 58bcdc6a3bSJan Kneschke size_t i; 59bcdc6a3bSJan Kneschke if (!a) return; 60bcdc6a3bSJan Kneschke 61bcdc6a3bSJan Kneschke for (i = 0; i < a->used; i++) { 62bcdc6a3bSJan Kneschke a->data[i]->reset(a->data[i]); 63bcdc6a3bSJan Kneschke } 64bcdc6a3bSJan Kneschke 65bcdc6a3bSJan Kneschke a->used = 0; 66bcdc6a3bSJan Kneschke } 67bcdc6a3bSJan Kneschke 688073d5feSJan Kneschke data_unset *array_pop(array *a) { 698073d5feSJan Kneschke data_unset *du; 708073d5feSJan Kneschke 718073d5feSJan Kneschke assert(a->used != 0); 728073d5feSJan Kneschke 738073d5feSJan Kneschke a->used --; 748073d5feSJan Kneschke du = a->data[a->used]; 758073d5feSJan Kneschke a->data[a->used] = NULL; 768073d5feSJan Kneschke 778073d5feSJan Kneschke return du; 788073d5feSJan Kneschke } 798073d5feSJan Kneschke 80bcdc6a3bSJan Kneschke static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) { 81bcdc6a3bSJan Kneschke int ndx = -1; 82bcdc6a3bSJan Kneschke int i, pos = 0; 83bcdc6a3bSJan Kneschke 84bcdc6a3bSJan Kneschke if (key == NULL) return -1; 85bcdc6a3bSJan Kneschke 86bcdc6a3bSJan Kneschke /* try to find the string */ 87bcdc6a3bSJan Kneschke for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) { 88bcdc6a3bSJan Kneschke int cmp; 89bcdc6a3bSJan Kneschke 90bcdc6a3bSJan Kneschke if (pos < 0) { 91bcdc6a3bSJan Kneschke pos += i; 92bcdc6a3bSJan Kneschke } else if (pos >= (int)a->used) { 93bcdc6a3bSJan Kneschke pos -= i; 94bcdc6a3bSJan Kneschke } else { 95bcdc6a3bSJan Kneschke cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used); 96bcdc6a3bSJan Kneschke 97bcdc6a3bSJan Kneschke if (cmp == 0) { 98bcdc6a3bSJan Kneschke /* found */ 99bcdc6a3bSJan Kneschke ndx = a->sorted[pos]; 100bcdc6a3bSJan Kneschke break; 101bcdc6a3bSJan Kneschke } else if (cmp < 0) { 102bcdc6a3bSJan Kneschke pos -= i; 103bcdc6a3bSJan Kneschke } else { 104bcdc6a3bSJan Kneschke pos += i; 105bcdc6a3bSJan Kneschke } 106bcdc6a3bSJan Kneschke } 107bcdc6a3bSJan Kneschke if (i == 0) break; 108bcdc6a3bSJan Kneschke } 109bcdc6a3bSJan Kneschke 110bcdc6a3bSJan Kneschke if (rndx) *rndx = pos; 111bcdc6a3bSJan Kneschke 112bcdc6a3bSJan Kneschke return ndx; 113bcdc6a3bSJan Kneschke } 114bcdc6a3bSJan Kneschke 115bcdc6a3bSJan Kneschke data_unset *array_get_element(array *a, const char *key) { 116bcdc6a3bSJan Kneschke int ndx; 117bcdc6a3bSJan Kneschke 118bcdc6a3bSJan Kneschke if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) { 119bcdc6a3bSJan Kneschke /* found, leave here */ 120bcdc6a3bSJan Kneschke 121bcdc6a3bSJan Kneschke return a->data[ndx]; 122bcdc6a3bSJan Kneschke } 123bcdc6a3bSJan Kneschke 124bcdc6a3bSJan Kneschke return NULL; 125bcdc6a3bSJan Kneschke } 126bcdc6a3bSJan Kneschke 127bcdc6a3bSJan Kneschke data_unset *array_get_unused_element(array *a, data_type_t t) { 128bcdc6a3bSJan Kneschke data_unset *ds = NULL; 129bcdc6a3bSJan Kneschke 130bcdc6a3bSJan Kneschke UNUSED(t); 131bcdc6a3bSJan Kneschke 132bcdc6a3bSJan Kneschke if (a->size == 0) return NULL; 133bcdc6a3bSJan Kneschke 134bcdc6a3bSJan Kneschke if (a->used == a->size) return NULL; 135bcdc6a3bSJan Kneschke 136bcdc6a3bSJan Kneschke if (a->data[a->used]) { 137bcdc6a3bSJan Kneschke ds = a->data[a->used]; 138bcdc6a3bSJan Kneschke 139bcdc6a3bSJan Kneschke a->data[a->used] = NULL; 140bcdc6a3bSJan Kneschke } 141bcdc6a3bSJan Kneschke 142bcdc6a3bSJan Kneschke return ds; 143bcdc6a3bSJan Kneschke } 144bcdc6a3bSJan Kneschke 145*6e78c2c8SJan Kneschke /* replace or insert data, return the old one with the same key */ 146*6e78c2c8SJan Kneschke data_unset *array_replace(array *a, data_unset *du) { 147*6e78c2c8SJan Kneschke int ndx; 148*6e78c2c8SJan Kneschke if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) { 149*6e78c2c8SJan Kneschke array_insert_unique(a, du); 150*6e78c2c8SJan Kneschke return NULL; 151*6e78c2c8SJan Kneschke } 152*6e78c2c8SJan Kneschke else { 153*6e78c2c8SJan Kneschke data_unset *old = a->data[ndx]; 154*6e78c2c8SJan Kneschke a->data[ndx] = du; 155*6e78c2c8SJan Kneschke return old; 156*6e78c2c8SJan Kneschke } 157*6e78c2c8SJan Kneschke } 158*6e78c2c8SJan Kneschke 159bcdc6a3bSJan Kneschke int array_insert_unique(array *a, data_unset *str) { 160bcdc6a3bSJan Kneschke int ndx = -1; 161bcdc6a3bSJan Kneschke int pos = 0; 162bcdc6a3bSJan Kneschke size_t j; 163bcdc6a3bSJan Kneschke 164bcdc6a3bSJan Kneschke /* generate unique index if neccesary */ 165bcdc6a3bSJan Kneschke if (str->key->used == 0) { 166bcdc6a3bSJan Kneschke buffer_copy_long(str->key, a->unique_ndx++); 167bcdc6a3bSJan Kneschke } 168bcdc6a3bSJan Kneschke 169bcdc6a3bSJan Kneschke /* try to find the string */ 170bcdc6a3bSJan Kneschke 171bcdc6a3bSJan Kneschke if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) { 172bcdc6a3bSJan Kneschke /* found, leave here */ 173bcdc6a3bSJan Kneschke if (a->data[ndx]->type == str->type) { 174bcdc6a3bSJan Kneschke str->insert_dup(a->data[ndx], str); 175bcdc6a3bSJan Kneschke } else { 176bcdc6a3bSJan Kneschke fprintf(stderr, "a\n"); 177bcdc6a3bSJan Kneschke } 178bcdc6a3bSJan Kneschke return 0; 179bcdc6a3bSJan Kneschke } 180bcdc6a3bSJan Kneschke 181bcdc6a3bSJan Kneschke /* insert */ 182bcdc6a3bSJan Kneschke 183bcdc6a3bSJan Kneschke if (a->used+1 > INT_MAX) { 184bcdc6a3bSJan Kneschke /* we can't handle more then INT_MAX entries: see array_get_index() */ 185bcdc6a3bSJan Kneschke return -1; 186bcdc6a3bSJan Kneschke } 187bcdc6a3bSJan Kneschke 188bcdc6a3bSJan Kneschke if (a->size == 0) { 189bcdc6a3bSJan Kneschke a->size = 16; 190bcdc6a3bSJan Kneschke a->data = malloc(sizeof(*a->data) * a->size); 191bcdc6a3bSJan Kneschke a->sorted = malloc(sizeof(*a->sorted) * a->size); 192bcdc6a3bSJan Kneschke assert(a->data); 193bcdc6a3bSJan Kneschke assert(a->sorted); 194bcdc6a3bSJan Kneschke for (j = a->used; j < a->size; j++) a->data[j] = NULL; 195bcdc6a3bSJan Kneschke } else if (a->size == a->used) { 196bcdc6a3bSJan Kneschke a->size += 16; 197bcdc6a3bSJan Kneschke a->data = realloc(a->data, sizeof(*a->data) * a->size); 198bcdc6a3bSJan Kneschke a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size); 199bcdc6a3bSJan Kneschke assert(a->data); 200bcdc6a3bSJan Kneschke assert(a->sorted); 201bcdc6a3bSJan Kneschke for (j = a->used; j < a->size; j++) a->data[j] = NULL; 202bcdc6a3bSJan Kneschke } 203bcdc6a3bSJan Kneschke 204bcdc6a3bSJan Kneschke ndx = (int) a->used; 205bcdc6a3bSJan Kneschke 206bcdc6a3bSJan Kneschke a->data[a->used++] = str; 207bcdc6a3bSJan Kneschke 208bcdc6a3bSJan Kneschke if (pos != ndx && 209bcdc6a3bSJan Kneschke ((pos < 0) || 210bcdc6a3bSJan 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)) { 211bcdc6a3bSJan Kneschke pos++; 212bcdc6a3bSJan Kneschke } 213bcdc6a3bSJan Kneschke 214bcdc6a3bSJan Kneschke /* move everything on step to the right */ 215bcdc6a3bSJan Kneschke if (pos != ndx) { 216bcdc6a3bSJan Kneschke memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted)); 217bcdc6a3bSJan Kneschke } 218bcdc6a3bSJan Kneschke 219bcdc6a3bSJan Kneschke /* insert */ 220bcdc6a3bSJan Kneschke a->sorted[pos] = ndx; 221bcdc6a3bSJan Kneschke 222bcdc6a3bSJan Kneschke if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1; 223bcdc6a3bSJan Kneschke 224bcdc6a3bSJan Kneschke return 0; 225bcdc6a3bSJan Kneschke } 226bcdc6a3bSJan Kneschke 2279e75ba00SJan Kneschke void array_print_indent(int depth) { 2289e75ba00SJan Kneschke int i; 2299e75ba00SJan Kneschke for (i = 0; i < depth; i ++) { 2309e75ba00SJan Kneschke fprintf(stderr, " "); 2319e75ba00SJan Kneschke } 2329e75ba00SJan Kneschke } 2339e75ba00SJan Kneschke 2349e75ba00SJan Kneschke int array_print(array *a, int depth) { 235bcdc6a3bSJan Kneschke size_t i; 236bcdc6a3bSJan Kneschke 237bcdc6a3bSJan Kneschke for (i = 0; i < a->used; i++) { 2389e75ba00SJan Kneschke array_print_indent(depth); 239bcdc6a3bSJan Kneschke fprintf(stderr, "%d: ", i); 2409e75ba00SJan Kneschke a->data[i]->print(a->data[i], depth + 1); 241bcdc6a3bSJan Kneschke fprintf(stderr, "\n"); 242bcdc6a3bSJan Kneschke } 243bcdc6a3bSJan Kneschke 244bcdc6a3bSJan Kneschke return 0; 245bcdc6a3bSJan Kneschke } 246bcdc6a3bSJan Kneschke 247bcdc6a3bSJan Kneschke #ifdef DEBUG_ARRAY 248bcdc6a3bSJan Kneschke int main (int argc, char **argv) { 249bcdc6a3bSJan Kneschke array *a; 250bcdc6a3bSJan Kneschke data_string *ds; 251bcdc6a3bSJan Kneschke data_count *dc; 252bcdc6a3bSJan Kneschke 253bcdc6a3bSJan Kneschke UNUSED(argc); 254bcdc6a3bSJan Kneschke UNUSED(argv); 255bcdc6a3bSJan Kneschke 256bcdc6a3bSJan Kneschke a = array_init(); 257bcdc6a3bSJan Kneschke 258bcdc6a3bSJan Kneschke ds = data_string_init(); 259bcdc6a3bSJan Kneschke buffer_copy_string(ds->key, "abc"); 260bcdc6a3bSJan Kneschke buffer_copy_string(ds->value, "alfrag"); 261bcdc6a3bSJan Kneschke 262bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)ds); 263bcdc6a3bSJan Kneschke 264bcdc6a3bSJan Kneschke ds = data_string_init(); 265bcdc6a3bSJan Kneschke buffer_copy_string(ds->key, "abc"); 266bcdc6a3bSJan Kneschke buffer_copy_string(ds->value, "hameplman"); 267bcdc6a3bSJan Kneschke 268bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)ds); 269bcdc6a3bSJan Kneschke 270bcdc6a3bSJan Kneschke ds = data_string_init(); 271bcdc6a3bSJan Kneschke buffer_copy_string(ds->key, "123"); 272bcdc6a3bSJan Kneschke buffer_copy_string(ds->value, "alfrag"); 273bcdc6a3bSJan Kneschke 274bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)ds); 275bcdc6a3bSJan Kneschke 276bcdc6a3bSJan Kneschke dc = data_count_init(); 277bcdc6a3bSJan Kneschke buffer_copy_string(dc->key, "def"); 278bcdc6a3bSJan Kneschke 279bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)dc); 280bcdc6a3bSJan Kneschke 281bcdc6a3bSJan Kneschke dc = data_count_init(); 282bcdc6a3bSJan Kneschke buffer_copy_string(dc->key, "def"); 283bcdc6a3bSJan Kneschke 284bcdc6a3bSJan Kneschke array_insert_unique(a, (data_unset *)dc); 285bcdc6a3bSJan Kneschke 2869e75ba00SJan Kneschke array_print(a, 0); 287bcdc6a3bSJan Kneschke 288bcdc6a3bSJan Kneschke array_free(a); 289bcdc6a3bSJan Kneschke 290bcdc6a3bSJan Kneschke fprintf(stderr, "%d\n", 291bcdc6a3bSJan Kneschke buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type"))); 292bcdc6a3bSJan Kneschke 293bcdc6a3bSJan Kneschke return 0; 294bcdc6a3bSJan Kneschke } 295bcdc6a3bSJan Kneschke #endif 296