summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_var.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nxt_var.c')
-rw-r--r--src/nxt_var.c196
1 files changed, 89 insertions, 107 deletions
diff --git a/src/nxt_var.c b/src/nxt_var.c
index e113969f..729de788 100644
--- a/src/nxt_var.c
+++ b/src/nxt_var.c
@@ -50,14 +50,11 @@ struct nxt_var_query_s {
static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name);
-static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields,
- uint32_t *index);
-static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name,
- uint32_t hash);
+static nxt_var_ref_t *nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name);
static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data);
-static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache,
- uint32_t index, void *ctx);
+static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state,
+ nxt_var_cache_t *cache, uint32_t index, void *ctx);
static u_char *nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part);
@@ -80,7 +77,7 @@ static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = {
static nxt_lvlhsh_t nxt_var_hash;
static uint32_t nxt_var_count;
-static nxt_var_handler_t *nxt_var_index;
+static nxt_var_decl_t **nxt_vars;
static nxt_int_t
@@ -111,95 +108,70 @@ nxt_var_hash_find(nxt_str_t *name)
}
-static nxt_var_decl_t *
-nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index)
+static nxt_var_ref_t *
+nxt_var_ref_get(nxt_tstr_state_t *state, nxt_str_t *name)
{
- u_char *p, *end;
- int64_t hash;
- uint16_t field;
- nxt_str_t str;
- nxt_var_decl_t *decl;
- nxt_var_field_t *f;
-
- f = NULL;
- field = 0;
- decl = nxt_var_hash_find(name);
+ nxt_int_t ret;
+ nxt_uint_t i;
+ nxt_var_ref_t *ref;
+ nxt_var_decl_t *decl;
- if (decl == NULL) {
- p = name->start;
- end = p + name->length;
+ ref = state->var_refs->elts;
- while (p < end) {
- if (*p++ == '_') {
- break;
- }
- }
+ for (i = 0; i < state->var_refs->nelts; i++) {
- if (p == end) {
- return NULL;
+ if (nxt_strstr_eq(ref[i].name, name)) {
+ return &ref[i];
}
+ }
- str.start = name->start;
- str.length = p - 1 - name->start;
+ ref = nxt_array_add(state->var_refs);
+ if (nxt_slow_path(ref == NULL)) {
+ return NULL;
+ }
- decl = nxt_var_hash_find(&str);
+ ref->index = state->var_refs->nelts - 1;
- if (decl != NULL) {
- str.start = p;
- str.length = end - p;
+ ref->name = nxt_str_dup(state->pool, NULL, name);
+ if (nxt_slow_path(ref->name == NULL)) {
+ return NULL;
+ }
- hash = decl->field_hash(fields->mem_pool, &str);
- if (nxt_slow_path(hash == -1)) {
- return NULL;
- }
+ decl = nxt_var_hash_find(name);
- f = nxt_var_field_add(fields, &str, (uint32_t) hash);
- if (nxt_slow_path(f == NULL)) {
- return NULL;
- }
+ if (decl != NULL) {
+ ref->handler = decl->handler;
+ ref->cacheable = decl->cacheable;
- field = f->index;
- }
+ return ref;
}
- if (decl != NULL) {
- if (decl->field_hash != NULL && f == NULL) {
- return NULL;
- }
-
- if (index != NULL) {
- *index = (decl->index << 16) | field;
- }
+ ret = nxt_http_unknown_var_ref(state, ref, name);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
}
- return decl;
+ return ref;
}
-static nxt_var_field_t *
-nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash)
+nxt_var_field_t *
+nxt_var_field_new(nxt_mp_t *mp, nxt_str_t *name, uint32_t hash)
{
- nxt_uint_t i;
+ nxt_str_t *str;
nxt_var_field_t *field;
- field = fields->elts;
-
- for (i = 0; i < fields->nelts; i++) {
- if (field[i].hash == hash
- && nxt_strstr_eq(&field[i].name, name))
- {
- return field;
- }
+ field = nxt_mp_alloc(mp, sizeof(nxt_var_field_t));
+ if (nxt_slow_path(field == NULL)) {
+ return NULL;
}
- field = nxt_array_add(fields);
- if (nxt_slow_path(field == NULL)) {
+ str = nxt_str_dup(mp, &field->name, name);
+ if (nxt_slow_path(str == NULL)) {
return NULL;
}
- field->name = *name;
field->hash = hash;
- field->index = fields->nelts - 1;
return field;
}
@@ -230,13 +202,17 @@ nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
static nxt_str_t *
-nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index,
- void *ctx)
+nxt_var_cache_value(nxt_task_t *task, nxt_tstr_state_t *state,
+ nxt_var_cache_t *cache, uint32_t index, void *ctx)
{
nxt_int_t ret;
nxt_str_t *value;
+ nxt_var_ref_t *ref;
nxt_lvlhsh_query_t lhq;
+ ref = state->var_refs->elts;
+ ref = &ref[index];
+
value = cache->spare;
if (value == NULL) {
@@ -248,6 +224,10 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index,
cache->spare = value;
}
+ if (!ref->cacheable) {
+ goto not_cached;
+ }
+
lhq.key_hash = nxt_murmur_hash2_uint32(&index);
lhq.replace = 0;
lhq.key.length = sizeof(uint32_t);
@@ -261,16 +241,20 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_cache_t *cache, uint32_t index,
return NULL;
}
- if (ret == NXT_OK) {
- ret = nxt_var_index[index >> 16](task, value, ctx, index & 0xffff);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NULL;
- }
+ if (ret == NXT_DECLINED) {
+ return lhq.value;
+ }
+
+not_cached:
- cache->spare = NULL;
+ ret = ref->handler(task, value, ctx, ref->data);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
}
- return lhq.value;
+ cache->spare = NULL;
+
+ return value;
}
@@ -303,12 +287,11 @@ nxt_int_t
nxt_var_index_init(void)
{
nxt_uint_t i;
- nxt_var_decl_t *decl;
- nxt_var_handler_t *index;
+ nxt_var_decl_t *decl, **vars;
nxt_lvlhsh_each_t lhe;
- index = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_handler_t));
- if (index == NULL) {
+ vars = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_decl_t *));
+ if (vars == NULL) {
return NXT_ERROR;
}
@@ -316,27 +299,25 @@ nxt_var_index_init(void)
for (i = 0; i < nxt_var_count; i++) {
decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe);
- decl->index = i;
- index[i] = decl->handler;
+ vars[i] = decl;
}
- nxt_var_index = index;
+ nxt_vars = vars;
return NXT_OK;
}
nxt_var_t *
-nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields)
+nxt_var_compile(nxt_tstr_state_t *state, nxt_str_t *str)
{
- u_char *p, *end, *next, *src;
- size_t size;
- uint32_t index;
- nxt_var_t *var;
- nxt_str_t part;
- nxt_uint_t n;
- nxt_var_sub_t *subs;
- nxt_var_decl_t *decl;
+ u_char *p, *end, *next, *src;
+ size_t size;
+ nxt_var_t *var;
+ nxt_str_t part;
+ nxt_uint_t n;
+ nxt_var_sub_t *subs;
+ nxt_var_ref_t *ref;
n = 0;
@@ -356,7 +337,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields)
size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length;
- var = nxt_mp_get(mp, size);
+ var = nxt_mp_get(state->pool, size);
if (nxt_slow_path(var == NULL)) {
return NULL;
}
@@ -376,12 +357,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields)
next = nxt_var_next_part(p, end, &part);
if (part.start != NULL) {
- decl = nxt_var_decl_get(&part, fields, &index);
- if (nxt_slow_path(decl == NULL)) {
+ ref = nxt_var_ref_get(state, &part);
+ if (nxt_slow_path(ref == NULL)) {
return NULL;
}
- subs[n].index = index;
+ subs[n].index = ref->index;
subs[n].length = next - p;
subs[n].position = p - str->start;
@@ -396,11 +377,11 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields)
nxt_int_t
-nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error)
+nxt_var_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error)
{
- u_char *p, *end, *next;
- nxt_str_t part;
- nxt_var_decl_t *decl;
+ u_char *p, *end, *next;
+ nxt_str_t part;
+ nxt_var_ref_t *ref;
p = str->start;
end = p + str->length;
@@ -416,9 +397,9 @@ nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error)
}
if (part.start != NULL) {
- decl = nxt_var_decl_get(&part, fields, NULL);
+ ref = nxt_var_ref_get(state, &part);
- if (decl == NULL) {
+ if (ref == NULL) {
nxt_sprintf(error, error + NXT_MAX_ERROR_STR,
"Unknown variable \"%V\"%Z", &part);
@@ -504,8 +485,9 @@ nxt_var_next_part(u_char *start, u_char *end, nxt_str_t *part)
nxt_int_t
-nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var,
- nxt_str_t *str, void *ctx, nxt_bool_t logging)
+nxt_var_interpreter(nxt_task_t *task, nxt_tstr_state_t *state,
+ nxt_var_cache_t *cache, nxt_var_t *var, nxt_str_t *str, void *ctx,
+ nxt_bool_t logging)
{
u_char *p, *src;
size_t length, last, next;
@@ -522,7 +504,7 @@ nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache, nxt_var_t *var,
length = var->length;
for (i = 0; i < var->vars; i++) {
- value = nxt_var_cache_value(task, cache, subs[i].index, ctx);
+ value = nxt_var_cache_value(task, state, cache, subs[i].index, ctx);
if (nxt_slow_path(value == NULL)) {
return NXT_ERROR;
}