Diff for /embedaddon/lighttpd/src/array.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2014/06/15 20:20:06 version 1.1.1.3, 2016/11/02 10:35:00
Line 1 Line 1
   #include "first.h"
   
 #include "array.h"  #include "array.h"
 #include "buffer.h"  #include "buffer.h"
   
Line 9 Line 11
 #include <errno.h>  #include <errno.h>
 #include <assert.h>  #include <assert.h>
   
   #define ARRAY_NOT_FOUND ((size_t)(-1))
   
 array *array_init(void) {  array *array_init(void) {
         array *a;          array *a;
   
         a = calloc(1, sizeof(*a));          a = calloc(1, sizeof(*a));
         force_assert(a);          force_assert(a);
   
         a->next_power_of_2 = 1;  
   
         return a;          return a;
 }  }
   
Line 28  array *array_init_array(array *src) { Line 30  array *array_init_array(array *src) {
   
         a->used = src->used;          a->used = src->used;
         a->size = src->size;          a->size = src->size;
         a->next_power_of_2 = src->next_power_of_2;  
         a->unique_ndx = src->unique_ndx;          a->unique_ndx = src->unique_ndx;
   
         a->data = malloc(sizeof(*src->data) * src->size);          a->data = malloc(sizeof(*src->data) * src->size);
           force_assert(NULL != a->data);
         for (i = 0; i < src->size; i++) {          for (i = 0; i < src->size; i++) {
                 if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]);                  if (src->data[i]) a->data[i] = src->data[i]->copy(src->data[i]);
                 else a->data[i] = NULL;                  else a->data[i] = NULL;
         }          }
   
        a->sorted = malloc(sizeof(*src->sorted)   * src->size);        a->sorted = malloc(sizeof(*src->sorted) * src->size);
        memcpy(a->sorted, src->sorted, sizeof(*src->sorted)   * src->size);        force_assert(NULL != a->sorted);
         memcpy(a->sorted, src->sorted, sizeof(*src->sorted) * src->size);
         return a;          return a;
 }  }
   
Line 46  void array_free(array *a) { Line 49  void array_free(array *a) {
         size_t i;          size_t i;
         if (!a) return;          if (!a) return;
   
        if (!a->is_weakref) {        for (i = 0; i < a->size; i++) {
                for (i = 0; i < a->size; i++) {                if (a->data[i]) a->data[i]->free(a->data[i]);
                        if (a->data[i]) a->data[i]->free(a->data[i]); 
                } 
         }          }
   
         if (a->data) free(a->data);          if (a->data) free(a->data);
Line 62  void array_reset(array *a) { Line 63  void array_reset(array *a) {
         size_t i;          size_t i;
         if (!a) return;          if (!a) return;
   
        if (!a->is_weakref) {        for (i = 0; i < a->used; i++) {
                for (i = 0; i < a->used; i++) {                a->data[i]->reset(a->data[i]);
                        a->data[i]->reset(a->data[i]); 
                } 
         }          }
   
         a->used = 0;          a->used = 0;
           a->unique_ndx = 0;
 }  }
   
 data_unset *array_pop(array *a) {  data_unset *array_pop(array *a) {
Line 78  data_unset *array_pop(array *a) { Line 78  data_unset *array_pop(array *a) {
   
         a->used --;          a->used --;
         du = a->data[a->used];          du = a->data[a->used];
           force_assert(a->sorted[a->used] == a->used); /* only works on "simple" lists */
         a->data[a->used] = NULL;          a->data[a->used] = NULL;
   
         return du;          return du;
 }  }
   
static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {/* returns index of element or ARRAY_NOT_FOUND
        int ndx = -1; * if rndx != NULL it stores the position in a->sorted[] where the key needs
        int i, pos = 0; * to be inserted
  */
 static size_t array_get_index(array *a, const char *key, size_t keylen, size_t *rndx) {
         /* invariant: [lower-1] < key < [upper]
          * "virtual elements": [-1] = -INFTY, [a->used] = +INFTY
          * also an invariant: 0 <= lower <= upper <= a->used
          */
         size_t lower = 0, upper = a->used;
         force_assert(upper <= SSIZE_MAX); /* (lower + upper) can't overflow */
   
        if (key == NULL) return -1;        while (lower != upper) {
                 size_t probe = (lower + upper) / 2;
                 int cmp = buffer_caseless_compare(key, keylen, CONST_BUF_LEN(a->data[a->sorted[probe]]->key));
                 assert(lower < upper); /* from loop invariant (lower <= upper) + (lower != upper) */
                 assert((lower <= probe) && (probe < upper)); /* follows from lower < upper */
   
        /* try to find the string */                if (cmp == 0) {
        for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {                        /* found */
                int cmp;                        if (rndx) *rndx = probe;
                        return a->sorted[probe];
                if (pos < 0) {                } else if (cmp < 0) {
                        pos += i;                        /* key < [probe] */
                } else if (pos >= (int)a->used) {                        upper = probe; /* still: lower <= upper */
                        pos -= i; 
                 } else {                  } else {
                        cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);                        /* key > [probe] */
                        lower = probe + 1; /* still: lower <= upper */
                        if (cmp == 0) { 
                                /* found */ 
                                ndx = a->sorted[pos]; 
                                break; 
                        } else if (cmp < 0) { 
                                pos -= i; 
                        } else { 
                                pos += i; 
                        } 
                 }                  }
                 if (i == 0) break;  
         }          }
   
        if (rndx) *rndx = pos;        /* not found: [lower-1] < key < [upper] = [lower] ==> insert at [lower] */
        if (rndx) *rndx = lower;
        return ndx;        return ARRAY_NOT_FOUND;
 }  }
   
 data_unset *array_get_element(array *a, const char *key) {  data_unset *array_get_element(array *a, const char *key) {
        int ndx;        size_t ndx;
         force_assert(NULL != key);
   
        if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {        if (ARRAY_NOT_FOUND != (ndx = array_get_index(a, key, strlen(key), NULL))) {
                /* found, leave here */                /* found, return it */
 
                 return a->data[ndx];                  return a->data[ndx];
         }          }
   
         return NULL;          return NULL;
 }  }
   
   data_unset *array_extract_element(array *a, const char *key) {
           size_t ndx, pos;
           force_assert(NULL != key);
   
           if (ARRAY_NOT_FOUND != (ndx = array_get_index(a, key, strlen(key), &pos))) {
                   /* found */
                   const size_t last_ndx = a->used - 1;
                   data_unset *entry = a->data[ndx];
   
                   /* now we need to swap it with the last element (if it isn't already the last element) */
                   if (ndx != last_ndx) {
                           /* to swap we also need to modify the index in a->sorted - find pos of last_elem there */
                           size_t last_elem_pos;
                           /* last element must be present at the expected position */
                           force_assert(last_ndx == array_get_index(a, CONST_BUF_LEN(a->data[last_ndx]->key), &last_elem_pos));
   
                           /* move entry from last_ndx to ndx */
                           a->data[ndx] = a->data[last_ndx];
                           a->data[last_ndx] = NULL;
   
                           /* fix index entry for moved entry */
                           a->sorted[last_elem_pos] = ndx;
                   } else {
                           a->data[ndx] = NULL;
                   }
   
                   /* remove entry in a->sorted: move everything after pos one step to the left */
                   if (pos != last_ndx) {
                           memmove(a->sorted + pos, a->sorted + pos + 1, (last_ndx - pos) * sizeof(*a->sorted));
                   }
                   a->sorted[last_ndx] = ARRAY_NOT_FOUND;
                   --a->used;
   
                   return entry;
           }
   
           return NULL;
   }
   
 data_unset *array_get_unused_element(array *a, data_type_t t) {  data_unset *array_get_unused_element(array *a, data_type_t t) {
         data_unset *ds = NULL;          data_unset *ds = NULL;
         unsigned int i;          unsigned int i;
Line 166  void array_set_key_value(array *hdrs, const char *key, Line 207  void array_set_key_value(array *hdrs, const char *key,
         array_insert_unique(hdrs, (data_unset *)ds_dst);          array_insert_unique(hdrs, (data_unset *)ds_dst);
 }  }
   
/* replace or insert data, return the old one with the same key *//* if entry already exists return pointer to existing entry, otherwise insert entry and return NULL */
data_unset *array_replace(array *a, data_unset *du) {static data_unset **array_find_or_insert(array *a, data_unset *entry) {
        int ndx;        size_t ndx, pos, j;
   
         force_assert(NULL != du);  
         if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {  
                 array_insert_unique(a, du);  
                 return NULL;  
         } else {  
                 data_unset *old = a->data[ndx];  
                 a->data[ndx] = du;  
                 return old;  
         }  
 }  
   
 int array_insert_unique(array *a, data_unset *str) {  
         int ndx = -1;  
         int pos = 0;  
         size_t j;  
   
         /* generate unique index if neccesary */          /* generate unique index if neccesary */
        if (str->key->used == 0 || str->is_index_key) {        if (buffer_is_empty(entry->key) || entry->is_index_key) {
                buffer_copy_long(str->key, a->unique_ndx++);                buffer_copy_int(entry->key, a->unique_ndx++);
                str->is_index_key = 1;                entry->is_index_key = 1;
                 force_assert(0 != a->unique_ndx); /* must not wrap or we'll get problems */
         }          }
   
        /* try to find the string */        /* try to find the entry */
        if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {        if (ARRAY_NOT_FOUND != (ndx = array_get_index(a, CONST_BUF_LEN(entry->key), &pos))) {
                /* found, leave here */                /* found collision, return it */
                if (a->data[ndx]->type == str->type) {                return &a->data[ndx];
                        str->insert_dup(a->data[ndx], str); 
                } else { 
                        SEGFAULT(); 
                } 
                return 0; 
         }          }
   
         /* insert */          /* insert */
   
        if (a->used+1 > INT_MAX) {        /* there couldn't possibly be enough memory to store so many entries */
                /* we can't handle more then INT_MAX entries: see array_get_index() */        force_assert(a->used + 1 <= SSIZE_MAX);
                return -1; 
        } 
   
         if (a->size == 0) {          if (a->size == 0) {
                 a->size   = 16;                  a->size   = 16;
Line 226  int array_insert_unique(array *a, data_unset *str) { Line 245  int array_insert_unique(array *a, data_unset *str) {
                 for (j = a->used; j < a->size; j++) a->data[j] = NULL;                  for (j = a->used; j < a->size; j++) a->data[j] = NULL;
         }          }
   
        ndx = (int) a->used;        ndx = a->used;
   
         /* make sure there is nothing here */          /* make sure there is nothing here */
         if (a->data[ndx]) a->data[ndx]->free(a->data[ndx]);          if (a->data[ndx]) a->data[ndx]->free(a->data[ndx]);
   
        a->data[a->used++] = str;        a->data[a->used++] = entry;
   
        if (pos != ndx &&        /* move everything one step to the right */
            ((pos < 0) || 
             buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) { 
                pos++; 
        } 
 
        /* move everything on step to the right */ 
         if (pos != ndx) {          if (pos != ndx) {
                 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));                  memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
         }          }
Line 247  int array_insert_unique(array *a, data_unset *str) { Line 260  int array_insert_unique(array *a, data_unset *str) {
         /* insert */          /* insert */
         a->sorted[pos] = ndx;          a->sorted[pos] = ndx;
   
        if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;        return NULL;
 }
   
        return 0;/* replace or insert data (free existing entry) */
 void array_replace(array *a, data_unset *entry) {
         data_unset **old;
 
         force_assert(NULL != entry);
         if (NULL != (old = array_find_or_insert(a, entry))) {
                 force_assert(*old != entry);
                 (*old)->free(*old);
                 *old = entry;
         }
 }  }
   
   void array_insert_unique(array *a, data_unset *entry) {
           data_unset **old;
   
           force_assert(NULL != entry);
           if (NULL != (old = array_find_or_insert(a, entry))) {
                   force_assert((*old)->type == entry->type);
                   entry->insert_dup(*old, entry);
           }
   }
   
 void array_print_indent(int depth) {  void array_print_indent(int depth) {
         int i;          int i;
         for (i = 0; i < depth; i ++) {          for (i = 0; i < depth; i ++) {
Line 320  int array_print(array *a, int depth) { Line 353  int array_print(array *a, int depth) {
                         int j;                          int j;
   
                         if (i && (i % 5) == 0) {                          if (i && (i % 5) == 0) {
                                fprintf(stdout, "# %zd\n", i);                                fprintf(stdout, "# %zu\n", i);
                                 array_print_indent(depth + 1);                                  array_print_indent(depth + 1);
                         }                          }
                         fprintf(stdout, "\"%s\"", du->key->ptr);                          fprintf(stdout, "\"%s\"", du->key->ptr);
Line 334  int array_print(array *a, int depth) { Line 367  int array_print(array *a, int depth) {
         }          }
         if (!(i && (i - 1 % 5) == 0)) {          if (!(i && (i - 1 % 5) == 0)) {
                 array_print_indent(depth + 1);                  array_print_indent(depth + 1);
                fprintf(stdout, "# %zd\n", i);                fprintf(stdout, "# %zu\n", i);
         }          }
         array_print_indent(depth);          array_print_indent(depth);
         fprintf(stdout, ")");          fprintf(stdout, ")");

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


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