[core] more memory-efficient fn table for data_*
save 40 bytes (64-bit), or 16 bytes (32-bit) per data_* element at the cost of going through indirect function pointer to execute methods. At runtime, the reset() method is most used among them.
This commit is contained in:
parent
002a4c524d
commit
8c7f1dfb03
16
src/array.c
16
src/array.c
|
@ -34,7 +34,7 @@ array *array_init_array(array *src) {
|
|||
a->data = malloc(sizeof(*src->data) * src->size);
|
||||
force_assert(NULL != a->data);
|
||||
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]->fn->copy(src->data[i]);
|
||||
else a->data[i] = NULL;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ void array_free(array *a) {
|
|||
if (!a) return;
|
||||
|
||||
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]->fn->free(a->data[i]);
|
||||
}
|
||||
|
||||
if (a->data) free(a->data);
|
||||
|
@ -63,7 +63,7 @@ void array_reset(array *a) {
|
|||
if (!a) return;
|
||||
|
||||
for (i = 0; i < a->used; i++) {
|
||||
a->data[i]->reset(a->data[i]);
|
||||
a->data[i]->fn->reset(a->data[i]);
|
||||
}
|
||||
|
||||
a->used = 0;
|
||||
|
@ -277,7 +277,7 @@ static data_unset **array_find_or_insert(array *a, data_unset *entry) {
|
|||
ndx = a->used;
|
||||
|
||||
/* make sure there is nothing here */
|
||||
if (a->data[ndx]) a->data[ndx]->free(a->data[ndx]);
|
||||
if (a->data[ndx]) a->data[ndx]->fn->free(a->data[ndx]);
|
||||
|
||||
a->data[a->used++] = entry;
|
||||
|
||||
|
@ -299,7 +299,7 @@ void array_replace(array *a, data_unset *entry) {
|
|||
force_assert(NULL != entry);
|
||||
if (NULL != (old = array_find_or_insert(a, entry))) {
|
||||
force_assert(*old != entry);
|
||||
(*old)->free(*old);
|
||||
(*old)->fn->free(*old);
|
||||
*old = entry;
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ void array_insert_unique(array *a, data_unset *entry) {
|
|||
force_assert(NULL != entry);
|
||||
if (NULL != (old = array_find_or_insert(a, entry))) {
|
||||
force_assert((*old)->type == entry->type);
|
||||
entry->insert_dup(*old, entry);
|
||||
entry->fn->insert_dup(*old, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ int array_print(array *a, int depth) {
|
|||
if (i != 0) {
|
||||
fprintf(stdout, ", ");
|
||||
}
|
||||
du->print(du, depth + 1);
|
||||
du->fn->print(du, depth + 1);
|
||||
}
|
||||
fprintf(stdout, ")");
|
||||
return 0;
|
||||
|
@ -575,7 +575,7 @@ int array_print(array *a, int depth) {
|
|||
}
|
||||
fprintf(stdout, " => ");
|
||||
}
|
||||
du->print(du, depth + 1);
|
||||
du->fn->print(du, depth + 1);
|
||||
fprintf(stdout, ",\n");
|
||||
}
|
||||
if (!(i && (i - 1 % 5) == 0)) {
|
||||
|
|
18
src/array.h
18
src/array.h
|
@ -4,16 +4,22 @@
|
|||
|
||||
#include "buffer.h"
|
||||
|
||||
struct data_unset; /* declaration */
|
||||
|
||||
struct data_methods {
|
||||
void (*reset)(struct data_unset *p); \
|
||||
struct data_unset *(*copy)(const struct data_unset *src); \
|
||||
void (*free)(struct data_unset *p); \
|
||||
int (*insert_dup)(struct data_unset *dst, struct data_unset *src); \
|
||||
void (*print)(const struct data_unset *p, int depth);
|
||||
};
|
||||
|
||||
typedef enum { TYPE_UNSET, TYPE_STRING, TYPE_OTHER, TYPE_ARRAY, TYPE_INTEGER, TYPE_DONOTUSE, TYPE_CONFIG } data_type_t;
|
||||
#define DATA_UNSET \
|
||||
data_type_t type; \
|
||||
buffer *key; \
|
||||
data_type_t type; \
|
||||
int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
|
||||
struct data_unset *(*copy)(const struct data_unset *src); \
|
||||
void (* free)(struct data_unset *p); \
|
||||
void (* reset)(struct data_unset *p); \
|
||||
int (*insert_dup)(struct data_unset *dst, struct data_unset *src); \
|
||||
void (*print)(const struct data_unset *p, int depth)
|
||||
const struct data_methods *fn /* function table */
|
||||
|
||||
typedef struct data_unset {
|
||||
DATA_UNSET;
|
||||
|
|
|
@ -57,7 +57,7 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t
|
|||
for (j = 0; j < da->value->used; j++) {
|
||||
data_unset *ds = da->value->data[j];
|
||||
if (ds->type == TYPE_STRING || ds->type == TYPE_INTEGER || ds->type == TYPE_ARRAY) {
|
||||
array_insert_unique(cv[i].destination, ds->copy(ds));
|
||||
array_insert_unique(cv[i].destination, ds->fn->copy(ds));
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sssbsd",
|
||||
"the value of an array can only be a string, variable:",
|
||||
|
|
|
@ -52,7 +52,7 @@ static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
|
|||
array_print(dc->value, 0);
|
||||
#endif
|
||||
if (NULL != (du = array_get_element_klen(dc->value, CONST_BUF_LEN(key)))) {
|
||||
du = du->copy(du);
|
||||
du = du->fn->copy(du);
|
||||
buffer_reset(du->key);
|
||||
return du;
|
||||
}
|
||||
|
@ -74,11 +74,11 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
|
|||
data_string *ds = data_string_init();
|
||||
buffer_append_int(ds->value, ((data_integer*)op1)->value);
|
||||
buffer_append_string_buffer(ds->value, ((data_string*)op2)->value);
|
||||
op1->free(op1);
|
||||
op1->fn->free(op1);
|
||||
return (data_unset *)ds;
|
||||
} else {
|
||||
fprintf(stderr, "data type mismatch, cannot merge\n");
|
||||
op1->free(op1);
|
||||
op1->fn->free(op1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -100,10 +100,10 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
|
|||
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))) {
|
||||
array_insert_unique(dst, du->copy(du));
|
||||
array_insert_unique(dst, du->fn->copy(du));
|
||||
} else {
|
||||
fprintf(stderr, "Duplicate array-key '%s'\n", du->key->ptr);
|
||||
op1->free(op1);
|
||||
op1->fn->free(op1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -174,9 +174,9 @@ metaline ::= EOL.
|
|||
|
||||
%type cond {config_cond_t }
|
||||
|
||||
%destructor value { if ($$) $$->free($$); }
|
||||
%destructor expression { if ($$) $$->free($$); }
|
||||
%destructor aelement { if ($$) $$->free($$); }
|
||||
%destructor value { if ($$) $$->fn->free($$); }
|
||||
%destructor expression { if ($$) $$->fn->free($$); }
|
||||
%destructor aelement { if ($$) $$->fn->free($$); }
|
||||
%destructor aelements { array_free($$); }
|
||||
%destructor array { array_free($$); }
|
||||
%destructor key { buffer_free($$); }
|
||||
|
@ -205,7 +205,7 @@ varline ::= key(A) ASSIGN expression(B). {
|
|||
}
|
||||
buffer_free(A);
|
||||
A = NULL;
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ varline ::= key(A) FORCE_ASSIGN expression(B). {
|
|||
}
|
||||
buffer_free(A);
|
||||
A = NULL;
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ varline ::= key(A) APPEND expression(B). {
|
|||
}
|
||||
buffer_free(A);
|
||||
A = NULL;
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
|
@ -280,9 +280,9 @@ expression(A) ::= expression(B) PLUS value(C). {
|
|||
ctx->ok = 0;
|
||||
}
|
||||
}
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
if (C) C->free(C);
|
||||
if (C) C->fn->free(C);
|
||||
C = NULL;
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ aelements(A) ::= aelements(C) COMMA aelement(B). {
|
|||
}
|
||||
array_free(C);
|
||||
C = NULL;
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
|
@ -385,7 +385,7 @@ aelements(A) ::= aelement(B). {
|
|||
array_insert_unique(A, B);
|
||||
B = NULL;
|
||||
}
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
|
@ -401,7 +401,7 @@ aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). {
|
|||
A = C;
|
||||
C = NULL;
|
||||
}
|
||||
if (C) C->free(C);
|
||||
if (C) C->fn->free(C);
|
||||
C = NULL;
|
||||
buffer_free(B);
|
||||
B = NULL;
|
||||
|
@ -493,7 +493,7 @@ condlines(A) ::= condlines(B) eols ELSE cond_else(C). {
|
|||
} else {
|
||||
fprintf(stderr, "unreachable else condition\n");
|
||||
ctx->ok = 0;
|
||||
C->free((data_unset *)C);
|
||||
C->fn->free((data_unset *)C);
|
||||
C = dc;
|
||||
}
|
||||
|
||||
|
@ -715,7 +715,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio
|
|||
if (ctx->ok) {
|
||||
configparser_push(ctx, dc, 1);
|
||||
} else {
|
||||
dc->free((data_unset*) dc);
|
||||
dc->fn->free((data_unset*) dc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio
|
|||
B = NULL;
|
||||
buffer_free(C);
|
||||
C = NULL;
|
||||
if (D) D->free(D);
|
||||
if (D) D->fn->free(D);
|
||||
D = NULL;
|
||||
}
|
||||
|
||||
|
@ -768,7 +768,7 @@ stringop(A) ::= expression(B). {
|
|||
ctx->ok = 0;
|
||||
}
|
||||
}
|
||||
if (B) B->free(B);
|
||||
if (B) B->fn->free(B);
|
||||
B = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static void data_array_reset(data_unset *d) {
|
|||
static int data_array_insert_dup(data_unset *dst, data_unset *src) {
|
||||
UNUSED(dst);
|
||||
|
||||
src->free(src);
|
||||
src->fn->free(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -48,6 +48,13 @@ static void data_array_print(const data_unset *d, int depth) {
|
|||
}
|
||||
|
||||
data_array *data_array_init(void) {
|
||||
static const struct data_methods fn = {
|
||||
data_array_reset,
|
||||
data_array_copy,
|
||||
data_array_free,
|
||||
data_array_insert_dup,
|
||||
data_array_print,
|
||||
};
|
||||
data_array *ds;
|
||||
|
||||
ds = calloc(1, sizeof(*ds));
|
||||
|
@ -56,12 +63,8 @@ data_array *data_array_init(void) {
|
|||
ds->key = buffer_init();
|
||||
ds->value = array_init();
|
||||
|
||||
ds->copy = data_array_copy;
|
||||
ds->free = data_array_free;
|
||||
ds->reset = data_array_reset;
|
||||
ds->insert_dup = data_array_insert_dup;
|
||||
ds->print = data_array_print;
|
||||
ds->type = TYPE_ARRAY;
|
||||
ds->fn = &fn;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ static void data_config_reset(data_unset *d) {
|
|||
static int data_config_insert_dup(data_unset *dst, data_unset *src) {
|
||||
UNUSED(dst);
|
||||
|
||||
src->free(src);
|
||||
src->fn->free(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ static void data_config_print(const data_unset *d, int depth) {
|
|||
fprintf(stdout, " ");
|
||||
}
|
||||
fprintf(stdout, " = ");
|
||||
du->print(du, depth);
|
||||
du->fn->print(du, depth);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ static void data_config_print(const data_unset *d, int depth) {
|
|||
if (NULL == dc->prev) {
|
||||
fprintf(stdout, "\n");
|
||||
array_print_indent(depth);
|
||||
dc->print((data_unset *) dc, depth);
|
||||
dc->fn->print((data_unset *) dc, depth);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
|
@ -129,11 +129,18 @@ static void data_config_print(const data_unset *d, int depth) {
|
|||
fprintf(stdout, "\n");
|
||||
array_print_indent(depth);
|
||||
fprintf(stdout, "else ");
|
||||
ds->next->print((data_unset *)ds->next, depth);
|
||||
ds->next->fn->print((data_unset *)ds->next, depth);
|
||||
}
|
||||
}
|
||||
|
||||
data_config *data_config_init(void) {
|
||||
static const struct data_methods fn = {
|
||||
data_config_reset,
|
||||
data_config_copy,
|
||||
data_config_free,
|
||||
data_config_insert_dup,
|
||||
data_config_print,
|
||||
};
|
||||
data_config *ds;
|
||||
|
||||
ds = calloc(1, sizeof(*ds));
|
||||
|
@ -145,12 +152,8 @@ data_config *data_config_init(void) {
|
|||
ds->value = array_init();
|
||||
vector_config_weak_init(&ds->children);
|
||||
|
||||
ds->copy = data_config_copy;
|
||||
ds->free = data_config_free;
|
||||
ds->reset = data_config_reset;
|
||||
ds->insert_dup = data_config_insert_dup;
|
||||
ds->print = data_config_print;
|
||||
ds->type = TYPE_CONFIG;
|
||||
ds->fn = &fn;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ static void data_integer_reset(data_unset *d) {
|
|||
static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
|
||||
UNUSED(dst);
|
||||
|
||||
src->free(src);
|
||||
src->fn->free(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,6 +49,13 @@ static void data_integer_print(const data_unset *d, int depth) {
|
|||
|
||||
|
||||
data_integer *data_integer_init(void) {
|
||||
static const struct data_methods fn = {
|
||||
data_integer_reset,
|
||||
data_integer_copy,
|
||||
data_integer_free,
|
||||
data_integer_insert_dup,
|
||||
data_integer_print,
|
||||
};
|
||||
data_integer *ds;
|
||||
|
||||
ds = calloc(1, sizeof(*ds));
|
||||
|
@ -57,12 +64,8 @@ data_integer *data_integer_init(void) {
|
|||
ds->key = buffer_init();
|
||||
ds->value = 0;
|
||||
|
||||
ds->copy = data_integer_copy;
|
||||
ds->free = data_integer_free;
|
||||
ds->reset = data_integer_reset;
|
||||
ds->insert_dup = data_integer_insert_dup;
|
||||
ds->print = data_integer_print;
|
||||
ds->type = TYPE_INTEGER;
|
||||
ds->fn = &fn;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ static int data_string_insert_dup(data_unset *dst, data_unset *src) {
|
|||
buffer_copy_buffer(ds_dst->value, ds_src->value);
|
||||
}
|
||||
|
||||
src->free(src);
|
||||
src->fn->free(src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -76,6 +76,13 @@ static void data_string_print(const data_unset *d, int depth) {
|
|||
|
||||
|
||||
data_string *data_string_init(void) {
|
||||
static const struct data_methods fn = {
|
||||
data_string_reset,
|
||||
data_string_copy,
|
||||
data_string_free,
|
||||
data_string_insert_dup,
|
||||
data_string_print,
|
||||
};
|
||||
data_string *ds;
|
||||
|
||||
ds = calloc(1, sizeof(*ds));
|
||||
|
@ -84,12 +91,8 @@ data_string *data_string_init(void) {
|
|||
ds->key = buffer_init();
|
||||
ds->value = buffer_init();
|
||||
|
||||
ds->copy = data_string_copy;
|
||||
ds->free = data_string_free;
|
||||
ds->reset = data_string_reset;
|
||||
ds->insert_dup = data_string_insert_dup;
|
||||
ds->print = data_string_print;
|
||||
ds->type = TYPE_STRING;
|
||||
ds->fn = &fn;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
|
|
@ -95,14 +95,17 @@ static void data_auth_free(data_unset *d)
|
|||
|
||||
static data_auth *data_auth_init(void)
|
||||
{
|
||||
static const struct data_methods fn = {
|
||||
NULL, /* reset must not be called on this data */
|
||||
NULL, /* copy must not be called on this data */
|
||||
data_auth_free,
|
||||
NULL, /* insert_dup must not be called on this data */
|
||||
NULL /* print must not be called on this data */
|
||||
};
|
||||
data_auth * const dauth = calloc(1, sizeof(*dauth));
|
||||
force_assert(NULL != dauth);
|
||||
dauth->copy = NULL; /* must not be called on this data */
|
||||
dauth->free = data_auth_free;
|
||||
dauth->reset = NULL; /* must not be called on this data */
|
||||
dauth->insert_dup = NULL; /* must not be called on this data */
|
||||
dauth->print = NULL; /* must not be called on this data */
|
||||
dauth->type = TYPE_OTHER;
|
||||
dauth->fn = &fn;
|
||||
|
||||
dauth->key = buffer_init();
|
||||
dauth->require = http_auth_require_init();
|
||||
|
@ -327,7 +330,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) {
|
|||
dauth->require->scheme = auth_scheme;
|
||||
buffer_copy_buffer(dauth->require->realm, realm);
|
||||
if (!mod_auth_require_parse(srv, dauth->require, require)) {
|
||||
dauth->free((data_unset *)dauth);
|
||||
dauth->fn->free((data_unset *)dauth);
|
||||
return HANDLER_ERROR;
|
||||
}
|
||||
array_insert_unique(s->auth_require, (data_unset *)dauth);
|
||||
|
|
|
@ -1055,7 +1055,7 @@ static int server_main (server * const srv, int argc, char **argv) {
|
|||
if (print_config) {
|
||||
data_unset *dc = srv->config_context->data[0];
|
||||
if (dc) {
|
||||
dc->print(dc, 0);
|
||||
dc->fn->print(dc, 0);
|
||||
fprintf(stdout, "\n");
|
||||
} else {
|
||||
/* shouldn't happend */
|
||||
|
|
Loading…
Reference in New Issue