[core] provide array_extract_element and use it

From: Stefan Bühler <stbuehler@web.de>

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3102 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/heads/lighttpd-1.4.x
Stefan Bühler 7 years ago
parent e7a39cde36
commit 68e4a416cc

@ -30,6 +30,7 @@ NEWS
* [core] improve array API to prevent memory leaks
* [core] refactor array search; raise array size limit to SSIZE_MAX
* [core] fix memory leak in configparser_merge_data
* [core] provide array_extract_element and use it
- 1.4.39 - 2016-01-02
* [core] fix memset_s call (fixes #2698)

@ -134,6 +134,45 @@ data_unset *array_get_element(array *a, const char *key) {
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 *ds = NULL;
unsigned int i;

@ -166,6 +166,7 @@ data_unset *array_pop(array *a); /* only works on "simple" lists with autogenera
int array_print(array *a, int depth);
data_unset *array_get_unused_element(array *a, data_type_t t);
data_unset *array_get_element(array *a, const char *key);
data_unset *array_extract_element(array *a, const char *key); /* 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_replace(array *a, data_unset *entry);
int array_strcasecmp(const char *a, size_t a_len, const char *b, size_t b_len);

@ -177,27 +177,7 @@ varline ::= key(A) APPEND expression(B). {
ctx->current->context_ndx,
ctx->current->key->ptr, A->ptr);
ctx->ok = 0;
} else if (NULL != (du = array_get_element(vars, A->ptr))) {
/* exists in current block */
if (du->type != B->type) {
/* might create new data when merging different types; need to replace old array entry */
/* also merging will kill the old data */
du = du->copy(du);
du = configparser_merge_data(du, B);
if (NULL != du) {
buffer_copy_buffer(du->key, A);
array_replace(vars, du);
}
} else {
data_unset *old_du = du;
du = configparser_merge_data(old_du, B);
force_assert((NULL == du) || (du == old_du)); /* must not create new data when types match */
}
if (NULL == du) {
ctx->ok = 0;
}
B->free(B);
} else if (NULL != (du = configparser_get_variable(ctx, A))) {
} else if (NULL != (du = array_extract_element(vars, A->ptr)) || NULL != (du = configparser_get_variable(ctx, A))) {
du = configparser_merge_data(du, B);
if (NULL == du) {
ctx->ok = 0;

Loading…
Cancel
Save