344 lines
6.6 KiB
C
344 lines
6.6 KiB
C
|
|
/*
|
|
* Copyright (C) NGINX, Inc.
|
|
*/
|
|
|
|
#include <nxt_main.h>
|
|
|
|
|
|
typedef enum {
|
|
NXT_TSTR_CONST = 0,
|
|
NXT_TSTR_VAR,
|
|
#if (NXT_HAVE_NJS)
|
|
NXT_TSTR_JS,
|
|
#endif
|
|
} nxt_tstr_type_t;
|
|
|
|
|
|
struct nxt_tstr_s {
|
|
nxt_str_t str;
|
|
|
|
union {
|
|
nxt_var_t *var;
|
|
#if (NXT_HAVE_NJS)
|
|
nxt_js_t *js;
|
|
#endif
|
|
} u;
|
|
|
|
nxt_tstr_flags_t flags;
|
|
nxt_tstr_type_t type;
|
|
};
|
|
|
|
|
|
struct nxt_tstr_query_s {
|
|
nxt_mp_t *pool;
|
|
|
|
nxt_tstr_state_t *state;
|
|
nxt_tstr_cache_t *cache;
|
|
|
|
nxt_uint_t waiting;
|
|
nxt_uint_t failed; /* 1 bit */
|
|
|
|
void *ctx;
|
|
void *data;
|
|
|
|
nxt_work_handler_t ready;
|
|
nxt_work_handler_t error;
|
|
};
|
|
|
|
|
|
#define nxt_tstr_is_js(str) \
|
|
nxt_strchr_start(str, '`')
|
|
|
|
|
|
nxt_tstr_state_t *
|
|
nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test)
|
|
{
|
|
nxt_tstr_state_t *state;
|
|
|
|
state = nxt_mp_get(mp, sizeof(nxt_tstr_state_t));
|
|
if (nxt_slow_path(state == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
state->pool = mp;
|
|
state->test = test;
|
|
|
|
state->var_refs = nxt_array_create(mp, 4, sizeof(nxt_var_ref_t));
|
|
if (nxt_slow_path(state->var_refs == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
#if (NXT_HAVE_NJS)
|
|
state->jcf = nxt_js_conf_new(mp, test);
|
|
if (nxt_slow_path(state->jcf == NULL)) {
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
return state;
|
|
}
|
|
|
|
|
|
nxt_tstr_t *
|
|
nxt_tstr_compile(nxt_tstr_state_t *state, nxt_str_t *str,
|
|
nxt_tstr_flags_t flags)
|
|
{
|
|
u_char *p;
|
|
nxt_tstr_t *tstr;
|
|
nxt_bool_t strz;
|
|
|
|
strz = (flags & NXT_TSTR_STRZ) != 0;
|
|
|
|
tstr = nxt_mp_get(state->pool, sizeof(nxt_tstr_t));
|
|
if (nxt_slow_path(tstr == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
tstr->str.length = str->length + strz;
|
|
|
|
tstr->str.start = nxt_mp_nget(state->pool, tstr->str.length);
|
|
if (nxt_slow_path(tstr->str.start == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
p = nxt_cpymem(tstr->str.start, str->start, str->length);
|
|
|
|
if (strz) {
|
|
*p = '\0';
|
|
}
|
|
|
|
tstr->flags = flags;
|
|
|
|
if (nxt_tstr_is_js(str)) {
|
|
|
|
#if (NXT_HAVE_NJS)
|
|
|
|
nxt_str_t tpl;
|
|
|
|
tstr->type = NXT_TSTR_JS;
|
|
|
|
nxt_tstr_str(tstr, &tpl);
|
|
|
|
tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, strz);
|
|
if (nxt_slow_path(tstr->u.js == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|
|
|
|
} else {
|
|
p = memchr(str->start, '$', str->length);
|
|
|
|
if (p != NULL) {
|
|
tstr->type = NXT_TSTR_VAR;
|
|
|
|
tstr->u.var = nxt_var_compile(state, &tstr->str);
|
|
if (nxt_slow_path(tstr->u.var == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
} else {
|
|
tstr->type = NXT_TSTR_CONST;
|
|
}
|
|
}
|
|
|
|
return tstr;
|
|
}
|
|
|
|
|
|
nxt_int_t
|
|
nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error)
|
|
{
|
|
u_char *p;
|
|
|
|
if (nxt_tstr_is_js(str)) {
|
|
#if (NXT_HAVE_NJS)
|
|
return nxt_js_test(state->jcf, str, error);
|
|
|
|
#else
|
|
nxt_sprintf(error, error + NXT_MAX_ERROR_STR,
|
|
"Unit is built without support of njs: "
|
|
"\"--njs\" ./configure option is missing.");
|
|
return NXT_ERROR;
|
|
#endif
|
|
|
|
} else {
|
|
p = memchr(str->start, '$', str->length);
|
|
|
|
if (p != NULL) {
|
|
return nxt_var_test(state, str, error);
|
|
}
|
|
}
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
nxt_int_t
|
|
nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error)
|
|
{
|
|
#if (NXT_HAVE_NJS)
|
|
if (!state->test) {
|
|
nxt_int_t ret;
|
|
|
|
ret = nxt_js_compile(state->jcf);
|
|
if (nxt_slow_path(ret != NXT_OK)) {
|
|
return NXT_ERROR;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
void
|
|
nxt_tstr_state_release(nxt_tstr_state_t *state)
|
|
{
|
|
#if (NXT_HAVE_NJS)
|
|
nxt_js_conf_release(state->jcf);
|
|
#endif
|
|
}
|
|
|
|
|
|
nxt_bool_t
|
|
nxt_tstr_is_const(nxt_tstr_t *tstr)
|
|
{
|
|
return (tstr->type == NXT_TSTR_CONST);
|
|
}
|
|
|
|
|
|
void
|
|
nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str)
|
|
{
|
|
*str = tstr->str;
|
|
|
|
if (tstr->flags & NXT_TSTR_STRZ) {
|
|
str->length--;
|
|
}
|
|
}
|
|
|
|
|
|
nxt_int_t
|
|
nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state,
|
|
nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp)
|
|
{
|
|
nxt_tstr_query_t *query;
|
|
|
|
query = *query_p;
|
|
|
|
if (*query_p == NULL) {
|
|
query = nxt_mp_zget(mp, sizeof(nxt_tstr_query_t));
|
|
if (nxt_slow_path(query == NULL)) {
|
|
return NXT_ERROR;
|
|
}
|
|
}
|
|
|
|
query->pool = mp;
|
|
query->state = state;
|
|
query->cache = cache;
|
|
query->ctx = ctx;
|
|
|
|
*query_p = query;
|
|
|
|
return NXT_OK;
|
|
}
|
|
|
|
|
|
void
|
|
nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr,
|
|
nxt_str_t *val)
|
|
{
|
|
nxt_int_t ret;
|
|
|
|
if (nxt_tstr_is_const(tstr)) {
|
|
nxt_tstr_str(tstr, val);
|
|
return;
|
|
}
|
|
|
|
if (nxt_slow_path(query->failed)) {
|
|
return;
|
|
}
|
|
|
|
if (tstr->type == NXT_TSTR_VAR) {
|
|
ret = nxt_var_interpreter(task, query->state, &query->cache->var,
|
|
tstr->u.var, val, query->ctx,
|
|
tstr->flags & NXT_TSTR_LOGGING);
|
|
|
|
if (nxt_slow_path(ret != NXT_OK)) {
|
|
query->failed = 1;
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
#if (NXT_HAVE_NJS)
|
|
ret = nxt_js_call(task, query->state->jcf, &query->cache->js,
|
|
tstr->u.js, val, query->ctx);
|
|
|
|
if (nxt_slow_path(ret != NXT_OK)) {
|
|
query->failed = 1;
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (tstr->flags & NXT_TSTR_STRZ) {
|
|
val->length--;
|
|
}
|
|
|
|
#if (NXT_DEBUG)
|
|
nxt_str_t str;
|
|
|
|
nxt_tstr_str(tstr, &str);
|
|
|
|
nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val);
|
|
#endif
|
|
}
|
|
|
|
|
|
nxt_bool_t
|
|
nxt_tstr_query_failed(nxt_tstr_query_t *query)
|
|
{
|
|
return query->failed;
|
|
}
|
|
|
|
|
|
void
|
|
nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, void *data,
|
|
nxt_work_handler_t ready, nxt_work_handler_t error)
|
|
{
|
|
query->data = data;
|
|
query->ready = ready;
|
|
query->error = error;
|
|
|
|
if (query->waiting == 0) {
|
|
nxt_work_queue_add(&task->thread->engine->fast_work_queue,
|
|
query->failed ? query->error : query->ready,
|
|
task, query->ctx, query->data);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query,
|
|
nxt_bool_t failed)
|
|
{
|
|
query->failed |= failed;
|
|
|
|
if (--query->waiting == 0) {
|
|
nxt_work_queue_add(&task->thread->engine->fast_work_queue,
|
|
query->failed ? query->error : query->ready,
|
|
task, query->ctx, query->data);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
nxt_tstr_query_release(nxt_tstr_query_t *query)
|
|
{
|
|
#if (NXT_HAVE_NJS)
|
|
nxt_js_release(&query->cache->js);
|
|
#endif
|
|
}
|