[core] perf: array.c performance enhancements
mark array_get_index() as hot, rewrite to be pure and return sorted pos mark routines as pure, as appropriate mark routines as cold if used only at startup for config processing mark params const, as appropriate array_get_buf_ptr() for modifiable value buffer after insert into array uint32_t used and size members instead of size_t remove a->unique_ndx member; simply add to end of array for value lists remove du->is_index_key member; simply check buffer_is_empty(du->key) array_insert_key_value() used to be a hint that lookup could be skipped, but the state from array_get_index() is now saved and reused internally, so the distinction is no longer needed. Use array_set_key_value().personal/stbuehler/ci-build
parent
2fd0faf1bf
commit
b2991c686d
412
src/array.c
412
src/array.c
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "array.h"
|
||||
#include "buffer.h"
|
||||
#include "settings.h" /* BUFFER_MAX_REUSE_SIZE */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -10,83 +11,93 @@
|
|||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define ARRAY_NOT_FOUND ((size_t)(-1))
|
||||
__attribute_cold__
|
||||
static void array_extend(array * const a) {
|
||||
a->size += 16;
|
||||
a->data = realloc(a->data, sizeof(*a->data) * a->size);
|
||||
a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size);
|
||||
force_assert(a->data);
|
||||
force_assert(a->sorted);
|
||||
memset(a->data+a->used, 0, (a->size-a->used)*sizeof(*a->data));
|
||||
}
|
||||
|
||||
array *array_init(void) {
|
||||
array *a;
|
||||
|
||||
a = calloc(1, sizeof(*a));
|
||||
force_assert(a);
|
||||
array_extend(a);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
array *array_init_array(array *src) {
|
||||
size_t i;
|
||||
array *array_init_array(const array * const src) {
|
||||
array *a = array_init();
|
||||
|
||||
if (0 == src->size) return a;
|
||||
|
||||
a->used = src->used;
|
||||
a->size = src->size;
|
||||
a->unique_ndx = src->unique_ndx;
|
||||
|
||||
a->data = malloc(sizeof(*src->data) * src->size);
|
||||
a->data = calloc(src->size, sizeof(*src->data));
|
||||
force_assert(NULL != a->data);
|
||||
for (i = 0; i < src->size; i++) {
|
||||
if (src->data[i]) a->data[i] = src->data[i]->fn->copy(src->data[i]);
|
||||
else a->data[i] = NULL;
|
||||
}
|
||||
|
||||
a->sorted = malloc(sizeof(*src->sorted) * src->size);
|
||||
force_assert(NULL != a->sorted);
|
||||
memcpy(a->sorted, src->sorted, sizeof(*src->sorted) * src->size);
|
||||
memcpy(a->sorted, src->sorted, sizeof(*src->sorted) * src->used);
|
||||
for (uint32_t i = 0; i < src->used; ++i) {
|
||||
a->data[i] = src->data[i]->fn->copy(src->data[i]);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void array_free(array *a) {
|
||||
size_t i;
|
||||
void array_free(array * const a) {
|
||||
if (!a) return;
|
||||
|
||||
for (i = 0; i < a->size; i++) {
|
||||
if (a->data[i]) a->data[i]->fn->free(a->data[i]);
|
||||
data_unset ** const data = a->data;
|
||||
const uint32_t sz = a->size;
|
||||
for (uint32_t i = 0; i < sz; ++i) {
|
||||
if (data[i]) data[i]->fn->free(data[i]);
|
||||
}
|
||||
|
||||
if (a->data) free(a->data);
|
||||
if (data) free(data);
|
||||
if (a->sorted) free(a->sorted);
|
||||
|
||||
free(a);
|
||||
}
|
||||
|
||||
void array_reset(array *a) {
|
||||
size_t i;
|
||||
void array_reset(array * const a) {
|
||||
if (!a) return;
|
||||
|
||||
for (i = 0; i < a->used; i++) {
|
||||
a->data[i]->fn->reset(a->data[i]);
|
||||
a->data[i]->is_index_key = 0;
|
||||
}
|
||||
|
||||
data_unset ** const data = a->data;
|
||||
const uint32_t used = a->used;
|
||||
a->used = 0;
|
||||
a->unique_ndx = 0;
|
||||
for (uint32_t i = 0; i < used; ++i) {
|
||||
data[i]->fn->reset(data[i]);
|
||||
data[i]->is_index_key = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void array_reset_data_strings(array *a) {
|
||||
void array_reset_data_strings(array * const a) {
|
||||
if (!a) return;
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
data_string * const ds = (data_string *)a->data[i];
|
||||
data_string ** const data = (data_string **)a->data;
|
||||
const uint32_t used = a->used;
|
||||
a->used = 0;
|
||||
for (uint32_t i = 0; i < used; ++i) {
|
||||
data_string * const ds = data[i];
|
||||
/*force_assert(ds->type == TYPE_STRING);*/
|
||||
ds->is_index_key = 0;
|
||||
buffer_reset(ds->key);
|
||||
buffer_reset(ds->value);
|
||||
buffer * const k = ds->key;
|
||||
buffer * const v = ds->value;
|
||||
buffer_clear(k);
|
||||
buffer_clear(v);
|
||||
if (k->size > BUFFER_MAX_REUSE_SIZE) buffer_reset(k);
|
||||
if (v->size > BUFFER_MAX_REUSE_SIZE) buffer_reset(v);
|
||||
}
|
||||
|
||||
a->used = 0;
|
||||
a->unique_ndx = 0;
|
||||
}
|
||||
|
||||
data_unset *array_pop(array *a) {
|
||||
#if 0 /*(unused; see array_extract_element_klen())*/
|
||||
data_unset *array_pop(array * const a) {
|
||||
data_unset *du;
|
||||
|
||||
force_assert(a->used != 0);
|
||||
|
@ -98,6 +109,7 @@ data_unset *array_pop(array *a) {
|
|||
|
||||
return du;
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute_pure__
|
||||
static int array_caseless_compare(const char * const a, const char * const b, const size_t len) {
|
||||
|
@ -117,72 +129,58 @@ static int array_caseless_compare(const char * const a, const char * const b, co
|
|||
}
|
||||
|
||||
__attribute_pure__
|
||||
static int array_keycmp(const char *a, size_t alen, const char *b, size_t blen) {
|
||||
static int array_keycmp(const char * const a, const size_t alen, const char * const b, const size_t blen) {
|
||||
return alen < blen ? -1 : alen > blen ? 1 : array_caseless_compare(a, b, blen);
|
||||
}
|
||||
|
||||
/* returns index of element or ARRAY_NOT_FOUND
|
||||
* if rndx != NULL it stores the position in a->sorted[] where the key needs
|
||||
* to be inserted
|
||||
/* returns pos into a->sorted[] which contains index to data in a->data[]
|
||||
* if pos >= 0, or returns -pos-1 if that is the position-1 in a->sorted[]
|
||||
* where the key needs to be inserted (-1 to avoid -0)
|
||||
*/
|
||||
static size_t array_get_index(const 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 */
|
||||
|
||||
while (lower != upper) {
|
||||
size_t probe = (lower + upper) / 2;
|
||||
const buffer *b = a->data[a->sorted[probe]]->key;
|
||||
int cmp = array_keycmp(key, keylen, CONST_BUF_LEN(b));
|
||||
|
||||
if (cmp == 0) {
|
||||
/* found */
|
||||
if (rndx) *rndx = probe;
|
||||
return a->sorted[probe];
|
||||
} else if (cmp < 0) {
|
||||
/* key < [probe] */
|
||||
upper = probe; /* still: lower <= upper */
|
||||
} else {
|
||||
/* key > [probe] */
|
||||
lower = probe + 1; /* still: lower <= upper */
|
||||
}
|
||||
}
|
||||
|
||||
/* not found: [lower-1] < key < [upper] = [lower] ==> insert at [lower] */
|
||||
if (rndx) *rndx = lower;
|
||||
return ARRAY_NOT_FOUND;
|
||||
__attribute_hot__
|
||||
__attribute_pure__
|
||||
static int32_t array_get_index(const array * const a, const char * const k, const size_t klen) {
|
||||
/* invariant: [lower-1] < probe < [upper]
|
||||
* invariant: 0 <= lower <= upper <= a->used
|
||||
*/
|
||||
uint32_t lower = 0, upper = a->used;
|
||||
while (lower != upper) {
|
||||
uint32_t probe = (lower + upper) / 2;
|
||||
const buffer * const b = a->data[a->sorted[probe]]->key;
|
||||
int cmp = array_keycmp(k, klen, CONST_BUF_LEN(b));
|
||||
if (cmp < 0) /* key < [probe] */
|
||||
upper = probe; /* still: lower <= upper */
|
||||
else if (cmp > 0) /* key > [probe] */
|
||||
lower = probe + 1; /* still: lower <= upper */
|
||||
else /*(cmp == 0)*/ /* found */
|
||||
return (int32_t)probe;
|
||||
}
|
||||
/* not found: [lower-1] < key < [upper] = [lower] ==> insert at [lower] */
|
||||
return -(int)lower - 1;
|
||||
}
|
||||
|
||||
data_unset *array_get_element_klen(const array *a, const char *key, size_t klen) {
|
||||
size_t ndx;
|
||||
force_assert(NULL != key);
|
||||
|
||||
if (ARRAY_NOT_FOUND != (ndx = array_get_index(a, key, klen, NULL))) {
|
||||
/* found, return it */
|
||||
return a->data[ndx];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
__attribute_hot__
|
||||
data_unset *array_get_element_klen(const array * const a, const char *key, const size_t klen) {
|
||||
const int32_t ipos = array_get_index(a, key, klen);
|
||||
return ipos >= 0 ? a->data[a->sorted[ipos]] : NULL;
|
||||
}
|
||||
|
||||
data_unset *array_extract_element_klen(array *a, const char *key, size_t klen) {
|
||||
size_t ndx, pos;
|
||||
force_assert(NULL != key);
|
||||
data_unset *array_extract_element_klen(array * const a, const char *key, const size_t klen) {
|
||||
const int32_t ipos = array_get_index(a, key, klen);
|
||||
if (ipos < 0) return NULL;
|
||||
|
||||
if (ARRAY_NOT_FOUND != (ndx = array_get_index(a, key, klen, &pos))) {
|
||||
{
|
||||
/* found */
|
||||
const size_t last_ndx = a->used - 1;
|
||||
data_unset *entry = a->data[ndx];
|
||||
const uint32_t last_ndx = a->used - 1;
|
||||
const uint32_t ndx = a->sorted[ipos], pos = (uint32_t)ipos;
|
||||
data_unset * const 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;
|
||||
int32_t last_elem_pos = array_get_index(a, CONST_BUF_LEN(a->data[last_ndx]->key));
|
||||
/* 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));
|
||||
force_assert(last_ndx == a->sorted[last_elem_pos]);
|
||||
|
||||
/* move entry from last_ndx to ndx */
|
||||
a->data[ndx] = a->data[last_ndx];
|
||||
|
@ -198,135 +196,126 @@ data_unset *array_extract_element_klen(array *a, const char *key, size_t klen) {
|
|||
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;
|
||||
}
|
||||
|
||||
static data_unset *array_get_unused_element(array *a, data_type_t t) {
|
||||
data_unset *ds = NULL;
|
||||
unsigned int i;
|
||||
|
||||
for (i = a->used; i < a->size; i++) {
|
||||
if (a->data[i] && a->data[i]->type == t) {
|
||||
ds = a->data[i];
|
||||
static data_unset *array_get_unused_element(array * const a, const data_type_t t) {
|
||||
/* After initial startup and config, most array usage is of homogenous types
|
||||
* and arrays are cleared once per request, so check only the first unused
|
||||
* element to see if it can be reused */
|
||||
#if 1
|
||||
data_unset * const du = (a->used < a->size) ? a->data[a->used] : NULL;
|
||||
if (NULL != du && du->type == t) {
|
||||
a->data[a->used] = NULL;/* make empty slot at a->used for next insert */
|
||||
return du;
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
data_unset ** const data = a->data;
|
||||
for (uint32_t i = a->used, sz = a->size; i < sz; ++i) {
|
||||
if (data[i] && data[i]->type == t) {
|
||||
data_unset * const ds = data[i];
|
||||
|
||||
/* make empty slot at a->used for next insert */
|
||||
a->data[i] = a->data[a->used];
|
||||
a->data[a->used] = NULL;
|
||||
data[i] = data[a->used];
|
||||
data[a->used] = NULL;
|
||||
|
||||
return ds;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
|
||||
data_string *ds;
|
||||
static void array_insert_data_at_pos(array * const a, data_unset * const entry, const uint32_t pos) {
|
||||
/* This data structure should not be used for nearly so many entries */
|
||||
force_assert(a->used + 1 <= INT32_MAX);
|
||||
|
||||
if (NULL != (ds = (data_string *)array_get_element_klen(hdrs, key, key_len))) {
|
||||
buffer_copy_string_len(ds->value, value, val_len);
|
||||
return;
|
||||
}
|
||||
if (a->size == a->used) {
|
||||
array_extend(a);
|
||||
}
|
||||
|
||||
array_insert_key_value(hdrs, key, key_len, value, val_len);
|
||||
const uint32_t ndx = a->used++;
|
||||
data_unset * const prev = a->data[ndx];
|
||||
a->data[ndx] = entry;
|
||||
|
||||
/* move everything one step to the right */
|
||||
if (pos != ndx) {
|
||||
memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
|
||||
}
|
||||
a->sorted[pos] = ndx;
|
||||
|
||||
if (prev) prev->fn->free(prev); /* free prior data, if any, from slot */
|
||||
}
|
||||
|
||||
void array_insert_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
|
||||
data_string *ds;
|
||||
|
||||
if (NULL == (ds = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
|
||||
ds = data_string_init();
|
||||
}
|
||||
|
||||
buffer_copy_string_len(ds->key, key, key_len);
|
||||
buffer_copy_string_len(ds->value, value, val_len);
|
||||
array_insert_unique(hdrs, (data_unset *)ds);
|
||||
static data_integer * array_insert_integer_at_pos(array * const a, const uint32_t pos) {
|
||||
#if 0 /*(not currently used by lighttpd in way that reuse would occur)*/
|
||||
data_integer *di = (data_integer *)array_get_unused_element(a,TYPE_INTEGER);
|
||||
if (NULL == di) di = data_integer_init();
|
||||
#else
|
||||
data_integer * const di = data_integer_init();
|
||||
#endif
|
||||
array_insert_data_at_pos(a, (data_unset *)di, pos);
|
||||
return di;
|
||||
}
|
||||
|
||||
void array_insert_value(array *hdrs, const char *value, size_t val_len) {
|
||||
data_string *ds;
|
||||
|
||||
if (NULL == (ds = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
|
||||
ds = data_string_init();
|
||||
}
|
||||
|
||||
buffer_copy_string_len(ds->value, value, val_len);
|
||||
array_insert_unique(hdrs, (data_unset *)ds);
|
||||
static data_string * array_insert_string_at_pos(array * const a, const uint32_t pos) {
|
||||
data_string *ds = (data_string *)array_get_unused_element(a, TYPE_STRING);
|
||||
if (NULL == ds) ds = data_string_init();
|
||||
array_insert_data_at_pos(a, (data_unset *)ds, pos);
|
||||
return ds;
|
||||
}
|
||||
|
||||
int * array_get_int_ptr(array *a, const char *k, size_t klen) {
|
||||
data_integer *di = (data_integer *)array_get_element_klen(a, k, klen);
|
||||
int * array_get_int_ptr(array * const a, const char * const k, const size_t klen) {
|
||||
int32_t ipos = array_get_index(a, k, klen);
|
||||
if (ipos >= 0) return &((data_integer *)a->data[a->sorted[ipos]])->value;
|
||||
|
||||
if (NULL == di) {
|
||||
di = (data_integer *)array_get_unused_element(a, TYPE_INTEGER);
|
||||
if (NULL == di) di = data_integer_init();
|
||||
buffer_copy_string_len(di->key, k, klen);
|
||||
array_insert_unique(a, (data_unset *)di);
|
||||
}
|
||||
data_integer * const di =array_insert_integer_at_pos(a,(uint32_t)(-ipos-1));
|
||||
buffer_copy_string_len(di->key, k, klen);
|
||||
return &di->value;
|
||||
}
|
||||
|
||||
return &di->value;
|
||||
buffer * array_get_buf_ptr(array * const a, const char * const k, const size_t klen) {
|
||||
int32_t ipos = array_get_index(a, k, klen);
|
||||
if (ipos >= 0) return ((data_string *)a->data[a->sorted[ipos]])->value;
|
||||
|
||||
data_string * const ds = array_insert_string_at_pos(a, (uint32_t)(-ipos-1));
|
||||
buffer_copy_string_len(ds->key, k, klen);
|
||||
return ds->value;
|
||||
}
|
||||
|
||||
void array_insert_value(array * const a, const char * const v, const size_t vlen) {
|
||||
data_string * const ds = array_insert_string_at_pos(a, a->used);
|
||||
buffer_copy_string_len(ds->value, v, vlen);
|
||||
}
|
||||
|
||||
/* if entry already exists return pointer to existing entry, otherwise insert entry and return NULL */
|
||||
static data_unset **array_find_or_insert(array *a, data_unset *entry) {
|
||||
size_t ndx, pos, j;
|
||||
__attribute_cold__
|
||||
static data_unset **array_find_or_insert(array * const a, data_unset * const entry) {
|
||||
force_assert(NULL != entry);
|
||||
|
||||
/* generate unique index if neccesary */
|
||||
if (buffer_is_empty(entry->key) || entry->is_index_key) {
|
||||
buffer_copy_int(entry->key, a->unique_ndx++);
|
||||
entry->is_index_key = 1;
|
||||
force_assert(0 != a->unique_ndx); /* must not wrap or we'll get problems */
|
||||
}
|
||||
/* push value onto end of array if there is no key */
|
||||
if (buffer_is_empty(entry->key)) {
|
||||
array_insert_data_at_pos(a, entry, a->used);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to find the entry */
|
||||
if (ARRAY_NOT_FOUND != (ndx = array_get_index(a, CONST_BUF_LEN(entry->key), &pos))) {
|
||||
/* found collision, return it */
|
||||
return &a->data[ndx];
|
||||
}
|
||||
/* try to find the entry */
|
||||
const int32_t ipos = array_get_index(a, CONST_BUF_LEN(entry->key));
|
||||
if (ipos >= 0) return &a->data[a->sorted[ipos]];
|
||||
|
||||
/* insert */
|
||||
|
||||
/* there couldn't possibly be enough memory to store so many entries */
|
||||
force_assert(a->used + 1 <= SSIZE_MAX);
|
||||
|
||||
if (a->size == a->used) {
|
||||
a->size += 16;
|
||||
a->data = realloc(a->data, sizeof(*a->data) * a->size);
|
||||
a->sorted = realloc(a->sorted, sizeof(*a->sorted) * a->size);
|
||||
force_assert(a->data);
|
||||
force_assert(a->sorted);
|
||||
for (j = a->used; j < a->size; j++) a->data[j] = NULL;
|
||||
}
|
||||
|
||||
ndx = a->used;
|
||||
|
||||
/* make sure there is nothing here */
|
||||
if (a->data[ndx]) a->data[ndx]->fn->free(a->data[ndx]);
|
||||
|
||||
a->data[a->used++] = entry;
|
||||
|
||||
/* move everything one step to the right */
|
||||
if (pos != ndx) {
|
||||
memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
|
||||
}
|
||||
|
||||
/* insert */
|
||||
a->sorted[pos] = ndx;
|
||||
|
||||
return NULL;
|
||||
array_insert_data_at_pos(a, entry, (uint32_t)(-ipos - 1));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* replace or insert data (free existing entry) */
|
||||
void array_replace(array *a, data_unset *entry) {
|
||||
void array_replace(array * const a, data_unset * const entry) {
|
||||
data_unset **old;
|
||||
|
||||
force_assert(NULL != entry);
|
||||
if (NULL != (old = array_find_or_insert(a, entry))) {
|
||||
force_assert(*old != entry);
|
||||
(*old)->fn->free(*old);
|
||||
|
@ -334,44 +323,43 @@ void array_replace(array *a, data_unset *entry) {
|
|||
}
|
||||
}
|
||||
|
||||
void array_insert_unique(array *a, data_unset *entry) {
|
||||
void array_insert_unique(array * const a, data_unset * const entry) {
|
||||
data_unset **old;
|
||||
|
||||
force_assert(NULL != entry);
|
||||
if (NULL != (old = array_find_or_insert(a, entry))) {
|
||||
force_assert((*old)->type == entry->type);
|
||||
entry->fn->insert_dup(*old, entry);
|
||||
}
|
||||
}
|
||||
|
||||
int array_is_vlist(array *a) {
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
int array_is_vlist(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (!du->is_index_key || du->type != TYPE_STRING) return 0;
|
||||
if (!buffer_is_empty(du->key) || du->type != TYPE_STRING) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int array_is_kvany(array *a) {
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
int array_is_kvany(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (du->is_index_key) return 0;
|
||||
if (buffer_is_empty(du->key)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int array_is_kvarray(array *a) {
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
int array_is_kvarray(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (du->is_index_key || du->type != TYPE_ARRAY) return 0;
|
||||
if (buffer_is_empty(du->key) || du->type != TYPE_ARRAY) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int array_is_kvstring(array *a) {
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
int array_is_kvstring(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (du->is_index_key || du->type != TYPE_STRING) return 0;
|
||||
if (buffer_is_empty(du->key) || du->type != TYPE_STRING) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -385,7 +373,7 @@ int array_is_kvstring(array *a) {
|
|||
data_unset *
|
||||
array_match_key_prefix_klen (const array * const a, const char * const s, const size_t slen)
|
||||
{
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = a->data[i]->key;
|
||||
const size_t klen = buffer_string_length(key);
|
||||
if (klen <= slen && 0 == memcmp(s, key->ptr, klen))
|
||||
|
@ -397,7 +385,7 @@ array_match_key_prefix_klen (const array * const a, const char * const s, const
|
|||
data_unset *
|
||||
array_match_key_prefix_nc_klen (const array * const a, const char * const s, const size_t slen)
|
||||
{
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = a->data[i]->key;
|
||||
const size_t klen = buffer_string_length(key);
|
||||
if (klen <= slen && buffer_eq_icase_ssn(s, key->ptr, klen))
|
||||
|
@ -423,7 +411,7 @@ array_match_value_prefix (const array * const a, const buffer * const b)
|
|||
{
|
||||
const size_t blen = buffer_string_length(b);
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = ((data_string *)a->data[i])->value;
|
||||
const size_t vlen = buffer_string_length(value);
|
||||
if (vlen <= blen && 0 == memcmp(b->ptr, value->ptr, vlen))
|
||||
|
@ -437,7 +425,7 @@ array_match_value_prefix_nc (const array * const a, const buffer * const b)
|
|||
{
|
||||
const size_t blen = buffer_string_length(b);
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = ((data_string *)a->data[i])->value;
|
||||
const size_t vlen = buffer_string_length(value);
|
||||
if (vlen <= blen && buffer_eq_icase_ssn(b->ptr, value->ptr, vlen))
|
||||
|
@ -452,7 +440,7 @@ array_match_key_suffix (const array * const a, const buffer * const b)
|
|||
const size_t blen = buffer_string_length(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = a->data[i]->key;
|
||||
const size_t klen = buffer_string_length(key);
|
||||
if (klen <= blen && 0 == memcmp(end - klen, key->ptr, klen))
|
||||
|
@ -467,7 +455,7 @@ array_match_key_suffix_nc (const array * const a, const buffer * const b)
|
|||
const size_t blen = buffer_string_length(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = a->data[i]->key;
|
||||
const size_t klen = buffer_string_length(key);
|
||||
if (klen <= blen && buffer_eq_icase_ssn(end - klen, key->ptr, klen))
|
||||
|
@ -482,7 +470,7 @@ array_match_value_suffix (const array * const a, const buffer * const b)
|
|||
const size_t blen = buffer_string_length(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = ((data_string *)a->data[i])->value;
|
||||
const size_t vlen = buffer_string_length(value);
|
||||
if (vlen <= blen && 0 == memcmp(end - vlen, value->ptr, vlen))
|
||||
|
@ -497,7 +485,7 @@ array_match_value_suffix_nc (const array * const a, const buffer * const b)
|
|||
const size_t blen = buffer_string_length(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = ((data_string *)a->data[i])->value;
|
||||
const size_t vlen = buffer_string_length(value);
|
||||
if (vlen <= blen && buffer_eq_icase_ssn(end - vlen, value->ptr, vlen))
|
||||
|
@ -511,7 +499,7 @@ array_match_path_or_ext (const array * const a, const buffer * const b)
|
|||
{
|
||||
const size_t blen = buffer_string_length(b);
|
||||
|
||||
for (size_t i = 0; i < a->used; ++i) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
/* check extension in the form "^/path" or ".ext$" */
|
||||
const buffer * const key = a->data[i]->key;
|
||||
const size_t klen = buffer_string_length(key);
|
||||
|
@ -536,13 +524,11 @@ void array_print_indent(int depth) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t array_get_max_key_length(array *a) {
|
||||
size_t maxlen, i;
|
||||
|
||||
maxlen = 0;
|
||||
for (i = 0; i < a->used; i ++) {
|
||||
data_unset *du = a->data[i];
|
||||
size_t len = buffer_string_length(du->key);
|
||||
size_t array_get_max_key_length(const array * const a) {
|
||||
size_t maxlen = 0;
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const k = a->data[i]->key;
|
||||
size_t len = buffer_string_length(k);
|
||||
|
||||
if (len > maxlen) {
|
||||
maxlen = len;
|
||||
|
@ -551,8 +537,8 @@ size_t array_get_max_key_length(array *a) {
|
|||
return maxlen;
|
||||
}
|
||||
|
||||
int array_print(array *a, int depth) {
|
||||
size_t i;
|
||||
int array_print(const array * const a, int depth) {
|
||||
uint32_t i;
|
||||
size_t maxlen;
|
||||
int oneline = 1;
|
||||
|
||||
|
@ -561,7 +547,7 @@ int array_print(array *a, int depth) {
|
|||
}
|
||||
for (i = 0; i < a->used && oneline; i++) {
|
||||
data_unset *du = a->data[i];
|
||||
if (!du->is_index_key) {
|
||||
if (!buffer_is_empty(du->key)) {
|
||||
oneline = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -592,11 +578,11 @@ int array_print(array *a, int depth) {
|
|||
for (i = 0; i < a->used; i++) {
|
||||
data_unset *du = a->data[i];
|
||||
array_print_indent(depth + 1);
|
||||
if (!du->is_index_key) {
|
||||
if (!buffer_is_empty(du->key)) {
|
||||
int j;
|
||||
|
||||
if (i && (i % 5) == 0) {
|
||||
fprintf(stdout, "# %zu\n", i);
|
||||
fprintf(stdout, "# %u\n", i);
|
||||
array_print_indent(depth + 1);
|
||||
}
|
||||
fprintf(stdout, "\"%s\"", du->key->ptr);
|
||||
|
@ -610,7 +596,7 @@ int array_print(array *a, int depth) {
|
|||
}
|
||||
if (!(i && (i - 1 % 5) == 0)) {
|
||||
array_print_indent(depth + 1);
|
||||
fprintf(stdout, "# %zu\n", i);
|
||||
fprintf(stdout, "# %u\n", i);
|
||||
}
|
||||
array_print_indent(depth);
|
||||
fprintf(stdout, ")");
|
||||
|
|
108
src/array.h
108
src/array.h
|
@ -18,7 +18,6 @@ typedef enum { TYPE_UNSET, TYPE_STRING, TYPE_OTHER, TYPE_ARRAY, TYPE_INTEGER, TY
|
|||
#define DATA_UNSET \
|
||||
buffer *key; \
|
||||
data_type_t type; \
|
||||
int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
|
||||
const struct data_methods *fn /* function table */
|
||||
|
||||
typedef struct data_unset {
|
||||
|
@ -28,12 +27,10 @@ typedef struct data_unset {
|
|||
typedef struct {
|
||||
data_unset **data;
|
||||
|
||||
size_t *sorted;
|
||||
uint32_t *sorted;
|
||||
|
||||
size_t used; /* <= SSIZE_MAX */
|
||||
size_t size;
|
||||
|
||||
size_t unique_ndx;
|
||||
uint32_t used; /* <= INT32_MAX */
|
||||
uint32_t size;
|
||||
} array;
|
||||
|
||||
typedef struct {
|
||||
|
@ -61,38 +58,99 @@ typedef struct {
|
|||
data_integer *data_integer_init(void);
|
||||
|
||||
array *array_init(void);
|
||||
array *array_init_array(array *a);
|
||||
array *array_init_array(const array *a);
|
||||
void array_free(array *a);
|
||||
void array_reset(array *a);
|
||||
void array_reset_data_strings(array *a);
|
||||
void array_insert_unique(array *a, data_unset *entry);
|
||||
data_unset *array_pop(array *a); /* only works on "simple" lists with autogenerated keys */
|
||||
int array_is_vlist(array *a);
|
||||
int array_is_kvany(array *a);
|
||||
int array_is_kvarray(array *a);
|
||||
int array_is_kvstring(array *a);
|
||||
int array_print(array *a, int depth);
|
||||
#define array_get_element(a, key) array_get_element_klen((a), (key), sizeof(key)-1)
|
||||
data_unset *array_get_element_klen(const array *a, const char *key, size_t klen);
|
||||
data_unset *array_extract_element_klen(array *a, const char *key, size_t klen); /* removes found entry from array */
|
||||
void array_set_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len);
|
||||
void array_insert_key_value(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len);
|
||||
void array_insert_value(array *hdrs, const char *value, size_t val_len);
|
||||
int * array_get_int_ptr(array *a, const char *k, size_t klen);
|
||||
void array_replace(array *a, data_unset *entry);
|
||||
void array_print_indent(int depth);
|
||||
size_t array_get_max_key_length(array *a);
|
||||
|
||||
__attribute_hot__
|
||||
void array_reset_data_strings(array *a);
|
||||
|
||||
__attribute_cold__
|
||||
void array_insert_unique(array *a, data_unset *entry);
|
||||
|
||||
__attribute_cold__
|
||||
data_unset *array_pop(array *a); /* only works on "simple" lists with autogenerated keys */
|
||||
|
||||
__attribute_cold__
|
||||
__attribute_pure__
|
||||
int array_is_vlist(const array *a);
|
||||
|
||||
__attribute_cold__
|
||||
__attribute_pure__
|
||||
int array_is_kvany(const array *a);
|
||||
|
||||
__attribute_cold__
|
||||
__attribute_pure__
|
||||
int array_is_kvarray(const array *a);
|
||||
|
||||
__attribute_cold__
|
||||
__attribute_pure__
|
||||
int array_is_kvstring(const array *a);
|
||||
|
||||
#define array_get_element(a, key) array_get_element_klen((a), (key), sizeof(key)-1)
|
||||
__attribute_pure__
|
||||
data_unset *array_get_element_klen(const array *a, const char *key, size_t klen);
|
||||
|
||||
__attribute_cold__
|
||||
data_unset *array_extract_element_klen(array *a, const char *key, size_t klen); /* removes found entry from array */
|
||||
|
||||
int * array_get_int_ptr(array *a, const char *k, size_t klen);
|
||||
|
||||
__attribute_hot__
|
||||
buffer * array_get_buf_ptr(array *a, const char *k, size_t klen);
|
||||
|
||||
void array_insert_value(array *a, const char *v, size_t vlen);
|
||||
|
||||
static inline void array_set_key_value(array * const a, const char * const k, const size_t klen, const char * const v, const size_t vlen);
|
||||
|
||||
static inline void array_set_key_value(array * const a, const char * const k, const size_t klen, const char * const v, const size_t vlen) {
|
||||
buffer_copy_string_len(array_get_buf_ptr(a, k, klen), v, vlen);
|
||||
}
|
||||
|
||||
__attribute_cold__
|
||||
void array_replace(array *a, data_unset *entry);
|
||||
|
||||
__attribute_cold__
|
||||
int array_print(const array *a, int depth);
|
||||
|
||||
__attribute_cold__
|
||||
void array_print_indent(int depth);
|
||||
|
||||
__attribute_cold__
|
||||
__attribute_pure__
|
||||
size_t array_get_max_key_length(const array *a);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_key_prefix_klen (const array * const a, const char * const s, const size_t slen);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_key_prefix_nc_klen (const array * const a, const char * const s, const size_t slen);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_key_prefix (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_key_prefix_nc (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
const buffer * array_match_value_prefix (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
const buffer * array_match_value_prefix_nc (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_key_suffix (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_key_suffix_nc (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
const buffer * array_match_value_suffix (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
const buffer * array_match_value_suffix_nc (const array * const a, const buffer * const b);
|
||||
|
||||
__attribute_pure__
|
||||
data_unset * array_match_path_or_ext (const array * const a, const buffer * const b);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -99,7 +99,7 @@ static data_unset *configparser_merge_data(data_unset *op1, const data_unset *op
|
|||
for (i = 0; i < src->used; i ++) {
|
||||
du = (data_unset *)src->data[i];
|
||||
if (du) {
|
||||
if (du->is_index_key || buffer_is_empty(du->key) || !array_get_element_klen(dst, CONST_BUF_LEN(du->key))) {
|
||||
if (buffer_is_empty(du->key) || !array_get_element_klen(dst, CONST_BUF_LEN(du->key))) {
|
||||
array_insert_unique(dst, du->fn->copy(du));
|
||||
} else {
|
||||
fprintf(stderr, "Duplicate array-key '%s'\n", du->key->ptr);
|
||||
|
|
|
@ -9,10 +9,9 @@ static data_unset *data_array_copy(const data_unset *s) {
|
|||
data_array *src = (data_array *)s;
|
||||
data_array *ds = data_array_init();
|
||||
|
||||
buffer_copy_buffer(ds->key, src->key);
|
||||
if (!buffer_is_empty(src->key)) buffer_copy_buffer(ds->key, src->key);
|
||||
array_free(ds->value);
|
||||
ds->value = array_init_array(src->value);
|
||||
ds->is_index_key = src->is_index_key;
|
||||
return (data_unset *)ds;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ static data_unset *data_config_copy(const data_unset *s) {
|
|||
data_config *ds = data_config_init();
|
||||
|
||||
ds->comp = src->comp;
|
||||
buffer_copy_buffer(ds->key, src->key);
|
||||
if (!buffer_is_empty(src->key)) buffer_copy_buffer(ds->key, src->key);
|
||||
buffer_copy_buffer(ds->comp_tag, src->comp_tag);
|
||||
buffer_copy_buffer(ds->comp_key, src->comp_key);
|
||||
array_free(ds->value);
|
||||
|
|
|
@ -10,8 +10,7 @@ static data_unset *data_integer_copy(const data_unset *s) {
|
|||
data_integer *src = (data_integer *)s;
|
||||
data_integer *ds = data_integer_init();
|
||||
|
||||
buffer_copy_buffer(ds->key, src->key);
|
||||
ds->is_index_key = src->is_index_key;
|
||||
if (!buffer_is_empty(src->key)) buffer_copy_buffer(ds->key, src->key);
|
||||
ds->value = src->value;
|
||||
return (data_unset *)ds;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ static data_unset *data_string_copy(const data_unset *s) {
|
|||
data_string *src = (data_string *)s;
|
||||
data_string *ds = data_string_init();
|
||||
|
||||
buffer_copy_buffer(ds->key, src->key);
|
||||
if (!buffer_is_empty(src->key)) buffer_copy_buffer(ds->key, src->key);
|
||||
buffer_copy_buffer(ds->value, src->value);
|
||||
ds->is_index_key = src->is_index_key;
|
||||
return (data_unset *)ds;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,42 +102,24 @@ void http_header_response_set(connection *con, enum http_header_e id, const char
|
|||
}
|
||||
|
||||
void http_header_response_append(connection *con, enum http_header_e id, const char *k, size_t klen, const char *v, size_t vlen) {
|
||||
if (vlen) {
|
||||
data_string *ds= (id <= HTTP_HEADER_OTHER || (con->response.htags & id))
|
||||
? (data_string *)array_get_element_klen(con->response.headers,k,klen)
|
||||
: NULL;
|
||||
if (id > HTTP_HEADER_OTHER) con->response.htags |= id;
|
||||
if (NULL == ds) {
|
||||
array_insert_key_value(con->response.headers, k, klen, v, vlen);
|
||||
}
|
||||
else { /* append value */
|
||||
buffer *vb = ds->value;
|
||||
if (!buffer_string_is_empty(vb))
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(", "));
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
}
|
||||
if (0 == vlen) return;
|
||||
if (id > HTTP_HEADER_OTHER) con->response.htags |= id;
|
||||
buffer * const vb = array_get_buf_ptr(con->response.headers, k, klen);
|
||||
if (!buffer_string_is_empty(vb)) /* append value */
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(", "));
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
|
||||
void http_header_response_insert(connection *con, enum http_header_e id, const char *k, size_t klen, const char *v, size_t vlen) {
|
||||
if (vlen) {
|
||||
data_string *ds= (id <= HTTP_HEADER_OTHER || (con->response.htags & id))
|
||||
? (data_string *)array_get_element_klen(con->response.headers,k,klen)
|
||||
: NULL;
|
||||
if (id > HTTP_HEADER_OTHER) con->response.htags |= id;
|
||||
if (NULL == ds) {
|
||||
array_insert_key_value(con->response.headers, k, klen, v, vlen);
|
||||
}
|
||||
else { /* append value */
|
||||
buffer *vb = ds->value;
|
||||
if (!buffer_string_is_empty(vb)) {
|
||||
buffer_append_string_len(vb, CONST_STR_LEN("\r\n"));
|
||||
buffer_append_string_len(vb, k, klen);
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(": "));
|
||||
}
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
if (0 == vlen) return;
|
||||
if (id > HTTP_HEADER_OTHER) con->response.htags |= id;
|
||||
buffer * const vb = array_get_buf_ptr(con->response.headers, k, klen);
|
||||
if (!buffer_string_is_empty(vb)) { /* append value */
|
||||
buffer_append_string_len(vb, CONST_STR_LEN("\r\n"));
|
||||
buffer_append_string_len(vb, k, klen);
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(": "));
|
||||
}
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,21 +149,12 @@ void http_header_request_set(connection *con, enum http_header_e id, const char
|
|||
}
|
||||
|
||||
void http_header_request_append(connection *con, enum http_header_e id, const char *k, size_t klen, const char *v, size_t vlen) {
|
||||
if (vlen) {
|
||||
data_string *ds = (id <= HTTP_HEADER_OTHER || (con->request.htags & id))
|
||||
? (data_string *)array_get_element_klen(con->request.headers, k, klen)
|
||||
: NULL;
|
||||
if (id > HTTP_HEADER_OTHER) con->request.htags |= id;
|
||||
if (NULL == ds) {
|
||||
array_insert_key_value(con->request.headers, k, klen, v, vlen);
|
||||
}
|
||||
else { /* append value */
|
||||
buffer *vb = ds->value;
|
||||
if (!buffer_string_is_empty(vb))
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(", "));
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
}
|
||||
if (0 == vlen) return;
|
||||
if (id > HTTP_HEADER_OTHER) con->request.htags |= id;
|
||||
buffer * const vb = array_get_buf_ptr(con->request.headers, k, klen);
|
||||
if (!buffer_string_is_empty(vb)) /* append value */
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(", "));
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,15 +169,10 @@ void http_header_env_set(connection *con, const char *k, size_t klen, const char
|
|||
}
|
||||
|
||||
void http_header_env_append(connection *con, const char *k, size_t klen, const char *v, size_t vlen) {
|
||||
/*if (vlen)*/ /* skip check; permit env var w/ blank value to be appended */
|
||||
{
|
||||
buffer * const vb = http_header_env_get(con, k, klen);
|
||||
if (NULL == vb) {
|
||||
array_insert_key_value(con->environment, k, klen, v, vlen);
|
||||
}
|
||||
else if (vlen) { /* append value */
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(", "));
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
}
|
||||
/*if (0 == vlen) return;*//* skip check; permit env var w/ blank value */
|
||||
buffer * const vb = array_get_buf_ptr(con->environment, k, klen);
|
||||
if (0 == vlen) return;
|
||||
if (!buffer_string_is_empty(vb)) /* append value */
|
||||
buffer_append_string_len(vb, CONST_STR_LEN(", "));
|
||||
buffer_append_string_len(vb, v, vlen);
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@ static void mod_evhost_parse_host(buffer *key, array *host, buffer *authority) {
|
|||
colon = ptr;
|
||||
}
|
||||
ptr = authority->ptr;
|
||||
array_insert_key_value(host,CONST_STR_LEN("%0"),ptr,colon-ptr);
|
||||
array_set_key_value(host,CONST_STR_LEN("%0"),ptr,colon-ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ static void mod_evhost_parse_host(buffer *key, array *host, buffer *authority) {
|
|||
|
||||
/* if we stopped at a dot, skip the dot */
|
||||
if (*ptr == '.') ptr++;
|
||||
array_insert_key_value(host, CONST_STR_LEN("%0"), ptr, colon-ptr);
|
||||
array_set_key_value(host, CONST_STR_LEN("%0"), ptr, colon-ptr);
|
||||
|
||||
/* if the : is not the start of the authority, go on parsing the hostname */
|
||||
|
||||
|
@ -237,7 +237,7 @@ static void mod_evhost_parse_host(buffer *key, array *host, buffer *authority) {
|
|||
/* is something between the dots */
|
||||
buffer_copy_string_len(key, CONST_STR_LEN("%"));
|
||||
buffer_append_int(key, i++);
|
||||
array_insert_key_value(host, CONST_BUF_LEN(key), ptr+1, colon-ptr-1);
|
||||
array_set_key_value(host, CONST_BUF_LEN(key), ptr+1, colon-ptr-1);
|
||||
}
|
||||
colon = ptr;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ static void mod_evhost_parse_host(buffer *key, array *host, buffer *authority) {
|
|||
if (colon != ptr) {
|
||||
buffer_copy_string_len(key, CONST_STR_LEN("%"));
|
||||
buffer_append_int(key, i /* ++ */);
|
||||
array_insert_key_value(host, CONST_BUF_LEN(key), ptr, colon-ptr);
|
||||
array_set_key_value(host, CONST_BUF_LEN(key), ptr, colon-ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) {
|
|||
|
||||
|
||||
static int ssi_env_add(void *venv, const char *key, size_t klen, const char *val, size_t vlen) {
|
||||
array_insert_key_value((array *)venv, key, klen, val, vlen);
|
||||
array_set_key_value((array *)venv, key, klen, val, vlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -701,7 +701,7 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
|
|||
if (p->if_is_false) break;
|
||||
|
||||
if (key && val) {
|
||||
array_insert_key_value(p->ssi_vars, key, strlen(key), val, strlen(val));
|
||||
array_set_key_value(p->ssi_vars, key, strlen(key), val, strlen(val));
|
||||
} else if (key || val) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sSSss",
|
||||
"ssi: var and value have to be set in <!--#set", l[1], "=", l[2], "-->");
|
||||
|
|
|
@ -40,37 +40,6 @@ static void test_array_insert_value (void) {
|
|||
array_free(a);
|
||||
}
|
||||
|
||||
static void test_array_insert_key_value (void) {
|
||||
data_string *ds;
|
||||
array *a = array_init();
|
||||
|
||||
array_insert_key_value(a, CONST_STR_LEN("abc"), CONST_STR_LEN("alfrag"));
|
||||
ds = (data_string *)array_get_element_klen(a, CONST_STR_LEN("does-not-exist"));
|
||||
assert(NULL == ds);
|
||||
ds = (data_string *)array_get_element_klen(a, CONST_STR_LEN("abc"));
|
||||
assert(NULL != ds);
|
||||
assert(buffer_is_equal_string(ds->key, CONST_STR_LEN("abc")));
|
||||
assert(buffer_is_equal_string(ds->value, CONST_STR_LEN("alfrag")));
|
||||
|
||||
array_insert_key_value(a, CONST_STR_LEN("abc"), CONST_STR_LEN("hameplman"));
|
||||
ds = (data_string *)array_get_element_klen(a, CONST_STR_LEN("does-not-exist"));
|
||||
assert(NULL == ds);
|
||||
ds = (data_string *)array_get_element_klen(a, CONST_STR_LEN("abc"));
|
||||
assert(NULL != ds);
|
||||
assert(buffer_is_equal_string(ds->key, CONST_STR_LEN("abc")));
|
||||
assert(buffer_is_equal_string(ds->value, CONST_STR_LEN("alfrag, hameplman")));
|
||||
|
||||
array_insert_key_value(a, CONST_STR_LEN("123"), CONST_STR_LEN("alfrag"));
|
||||
ds = (data_string *)array_get_element_klen(a, CONST_STR_LEN("does-not-exist"));
|
||||
assert(NULL == ds);
|
||||
ds = (data_string *)array_get_element_klen(a, CONST_STR_LEN("123"));
|
||||
assert(NULL != ds);
|
||||
assert(buffer_is_equal_string(ds->key, CONST_STR_LEN("123")));
|
||||
assert(buffer_is_equal_string(ds->value, CONST_STR_LEN("alfrag")));
|
||||
|
||||
array_free(a);
|
||||
}
|
||||
|
||||
static void test_array_set_key_value (void) {
|
||||
data_string *ds;
|
||||
array *a = array_init();
|
||||
|
@ -97,7 +66,6 @@ static void test_array_set_key_value (void) {
|
|||
int main() {
|
||||
test_array_get_int_ptr();
|
||||
test_array_insert_value();
|
||||
test_array_insert_key_value();
|
||||
test_array_set_key_value();
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue