[core] keep a->data[] sorted; remove a->sorted[]
This commit is contained in:
parent
61785d868f
commit
c9f1b612f1
73
src/array.c
73
src/array.c
|
@ -15,9 +15,7 @@ __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));
|
||||
}
|
||||
|
||||
|
@ -41,9 +39,6 @@ array *array_init_array(const array * const src) {
|
|||
|
||||
a->data = calloc(src->size, sizeof(*src->data));
|
||||
force_assert(NULL != a->data);
|
||||
a->sorted = malloc(sizeof(*src->sorted) * src->size);
|
||||
force_assert(NULL != a->sorted);
|
||||
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]);
|
||||
}
|
||||
|
@ -61,8 +56,6 @@ void array_free(array * const a) {
|
|||
}
|
||||
|
||||
if (data) free(data);
|
||||
if (a->sorted) free(a->sorted);
|
||||
|
||||
free(a);
|
||||
}
|
||||
|
||||
|
@ -90,7 +83,6 @@ data_unset *array_pop(array * const a) {
|
|||
|
||||
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;
|
||||
|
||||
return du;
|
||||
|
@ -119,9 +111,9 @@ static int array_keycmp(const char * const a, const size_t alen, const char * co
|
|||
return alen < blen ? -1 : alen > blen ? 1 : array_caseless_compare(a, b, blen);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
/* If key is found, returns pos (pos >= 0) into a->data[]
|
||||
* If key is not found, returns -pos-1 if that is the position-1 in a->data[]
|
||||
* where the key would be inserted (-1 to avoid -0)
|
||||
*/
|
||||
__attribute_hot__
|
||||
__attribute_pure__
|
||||
|
@ -132,7 +124,7 @@ static int32_t array_get_index(const array * const a, const char * const k, cons
|
|||
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;
|
||||
const buffer * const b = a->data[probe]->key;
|
||||
/* key is non-empty (0==b->used), though possibly blank (1==b->used),
|
||||
* if inserted into key-value array */
|
||||
/*force_assert(b && b->used);*/
|
||||
|
@ -152,44 +144,22 @@ static int32_t array_get_index(const array * const a, const char * const k, cons
|
|||
__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;
|
||||
return ipos >= 0 ? a->data[ipos] : NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
const int32_t ipos = array_get_index(a, key, klen);
|
||||
if (ipos < 0) return NULL;
|
||||
|
||||
{
|
||||
/* found */
|
||||
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 */
|
||||
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 == a->sorted[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->used;
|
||||
|
||||
return entry;
|
||||
}
|
||||
/* remove entry from a->data: move everything after pos one step left */
|
||||
data_unset * const entry = a->data[ipos];
|
||||
const uint32_t last_ndx = --a->used;
|
||||
if (last_ndx != (uint32_t)ipos) {
|
||||
data_unset ** const d = a->data + ipos;
|
||||
memmove(d, d+1, (last_ndx - (uint32_t)ipos) * sizeof(*d));
|
||||
}
|
||||
a->data[last_ndx] = NULL;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static data_unset *array_get_unused_element(array * const a, const data_type_t t) {
|
||||
|
@ -231,13 +201,12 @@ static void array_insert_data_at_pos(array * const a, data_unset * const entry,
|
|||
|
||||
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));
|
||||
memmove(a->data + (pos + 1), a->data + (pos), (ndx - pos) * sizeof(*a->data));
|
||||
}
|
||||
a->sorted[pos] = ndx;
|
||||
a->data[pos] = entry;
|
||||
|
||||
if (prev) prev->fn->free(prev); /* free prior data, if any, from slot */
|
||||
}
|
||||
|
@ -262,7 +231,7 @@ static data_string * array_insert_string_at_pos(array * const a, const uint32_t
|
|||
|
||||
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 (ipos >= 0) return &((data_integer *)a->data[ipos])->value;
|
||||
|
||||
data_integer * const di =array_insert_integer_at_pos(a,(uint32_t)(-ipos-1));
|
||||
buffer_copy_string_len(di->key, k, klen);
|
||||
|
@ -272,7 +241,7 @@ int * array_get_int_ptr(array * const a, const char * const k, const size_t klen
|
|||
|
||||
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;
|
||||
if (ipos >= 0) return ((data_string *)a->data[ipos])->value;
|
||||
|
||||
data_string * const ds = array_insert_string_at_pos(a, (uint32_t)(-ipos-1));
|
||||
buffer_copy_string_len(ds->key, k, klen);
|
||||
|
@ -299,7 +268,7 @@ static data_unset **array_find_or_insert(array * const a, data_unset * const ent
|
|||
|
||||
/* 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]];
|
||||
if (ipos >= 0) return &a->data[ipos];
|
||||
|
||||
array_insert_data_at_pos(a, entry, (uint32_t)(-ipos - 1));
|
||||
return NULL;
|
||||
|
|
|
@ -25,9 +25,6 @@ typedef struct data_unset {
|
|||
|
||||
typedef struct {
|
||||
data_unset **data;
|
||||
|
||||
uint32_t *sorted;
|
||||
|
||||
uint32_t used; /* <= INT32_MAX */
|
||||
uint32_t size;
|
||||
} array;
|
||||
|
@ -97,7 +94,6 @@ data_unset *array_extract_element_klen(array *a, const char *key, size_t klen);
|
|||
|
||||
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);
|
||||
|
|
|
@ -99,9 +99,9 @@ SETDEFAULTS_FUNC(mod_alias_set_defaults) {
|
|||
size_t j, k;
|
||||
|
||||
for (j = 0; j < a->used; j ++) {
|
||||
const buffer *prefix = a->data[a->sorted[j]]->key;
|
||||
const buffer *prefix = a->data[j]->key;
|
||||
for (k = j + 1; k < a->used; k ++) {
|
||||
const buffer *key = a->data[a->sorted[k]]->key;
|
||||
const buffer *key = a->data[k]->key;
|
||||
|
||||
if (buffer_string_length(key) < buffer_string_length(prefix)) {
|
||||
break;
|
||||
|
@ -110,7 +110,7 @@ SETDEFAULTS_FUNC(mod_alias_set_defaults) {
|
|||
break;
|
||||
}
|
||||
/* ok, they have same prefix. check position */
|
||||
if (a->sorted[j] < a->sorted[k]) {
|
||||
if (a->data[j] < a->data[k]) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "SBSBS",
|
||||
"url.alias: `", key, "' will never match as `", prefix, "' matched first");
|
||||
return HANDLER_ERROR;
|
||||
|
|
|
@ -742,7 +742,7 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
|
|||
b = srv->tmp_buf;
|
||||
buffer_clear(b);
|
||||
for (i = 0; i < p->ssi_vars->used; i++) {
|
||||
data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
|
||||
data_string *ds = (data_string *)p->ssi_vars->data[i];
|
||||
|
||||
buffer_append_string_buffer(b, ds->key);
|
||||
buffer_append_string_len(b, CONST_STR_LEN("="));
|
||||
|
@ -750,7 +750,7 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
|
|||
buffer_append_string_len(b, CONST_STR_LEN("\n"));
|
||||
}
|
||||
for (i = 0; i < p->ssi_cgi_env->used; i++) {
|
||||
data_string *ds = (data_string *)p->ssi_cgi_env->data[p->ssi_cgi_env->sorted[i]];
|
||||
data_string *ds = (data_string *)p->ssi_cgi_env->data[i];
|
||||
|
||||
buffer_append_string_buffer(b, ds->key);
|
||||
buffer_append_string_len(b, CONST_STR_LEN("="));
|
||||
|
|
|
@ -753,11 +753,9 @@ static handler_t mod_status_handle_server_statistics(server *srv, connection *co
|
|||
|
||||
b = chunkqueue_append_buffer_open(con->write_queue);
|
||||
for (i = 0; i < st->used; i++) {
|
||||
size_t ndx = st->sorted[i];
|
||||
|
||||
buffer_append_string_buffer(b, st->data[ndx]->key);
|
||||
buffer_append_string_buffer(b, st->data[i]->key);
|
||||
buffer_append_string_len(b, CONST_STR_LEN(": "));
|
||||
buffer_append_int(b, ((data_integer *)(st->data[ndx]))->value);
|
||||
buffer_append_int(b, ((data_integer *)(st->data[i]))->value);
|
||||
buffer_append_string_len(b, CONST_STR_LEN("\n"));
|
||||
}
|
||||
chunkqueue_append_buffer_commit(con->write_queue);
|
||||
|
|
Loading…
Reference in New Issue