ngx_http_script_flush_complex_value()

ngx_http_complex_value()
ngx_http_compile_complex_value()
This commit is contained in:
Igor Sysoev 2009-03-22 09:36:51 +00:00
parent c7ce3a99bc
commit 8508c10bb8
2 changed files with 371 additions and 54 deletions

View File

@ -12,7 +12,7 @@
static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc); static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc); static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
ngx_str_t *value); ngx_str_t *value, ngx_uint_t last);
static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
ngx_str_t *name); ngx_str_t *name);
static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc); static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
@ -20,6 +20,10 @@ static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
ngx_uint_t n); ngx_uint_t n);
#endif #endif
static ngx_int_t
ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
#define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
@ -27,6 +31,186 @@ static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL; static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
void
ngx_http_scrip_flush_complex_value(ngx_http_request_t *r,
ngx_http_complex_value_t *val)
{
ngx_uint_t *index;
index = val->flushes;
if (index) {
while (*index != (ngx_uint_t) -1) {
if (r->variables[*index].no_cacheable) {
r->variables[*index].valid = 0;
r->variables[*index].not_found = 0;
}
index++;
}
}
}
ngx_int_t
ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
ngx_str_t *value)
{
size_t len;
ngx_http_script_code_pt code;
ngx_http_script_len_code_pt lcode;
ngx_http_script_engine_t e;
if (val->lengths == NULL) {
*value = val->value;
return NGX_OK;
}
ngx_http_scrip_flush_complex_value(r, val);
ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
e.ip = val->lengths;
e.request = r;
e.flushed = 1;
len = 0;
while (*(uintptr_t *) e.ip) {
lcode = *(ngx_http_script_len_code_pt *) e.ip;
len += lcode(&e);
}
value->len = len;
value->data = ngx_pnalloc(r->pool, len);
if (value->data == NULL) {
return NGX_ERROR;
}
e.ip = val->values;
e.pos = value->data;
e.buf = *value;
while (*(uintptr_t *) e.ip) {
code = *(ngx_http_script_code_pt *) e.ip;
code((ngx_http_script_engine_t *) &e);
}
*value = e.buf;
return NGX_OK;
}
ngx_int_t
ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
{
ngx_str_t *v;
ngx_uint_t i, n, nv, nc;
ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
ngx_http_script_compile_t sc;
v = ccv->value;
if (v->len == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, ccv->cf, 0, "empty parameter");
return NGX_ERROR;
}
ccv->complex_value->value = *v;
ccv->complex_value->flushes = NULL;
ccv->complex_value->lengths = NULL;
ccv->complex_value->values = NULL;
nv = 0;
nc = 0;
for (i = 0; i < v->len; i++) {
if (v->data[i] == '$') {
if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
nc++;
} else {
nv++;
}
}
}
if (v->data[0] != '$' && (ccv->conf_prefix || ccv->root_prefix)) {
if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
return NGX_ERROR;
}
ccv->conf_prefix = 0;
ccv->root_prefix = 0;
}
if (nv == 0 && nc == 0) {
return NGX_OK;
}
n = nv + 1;
if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
!= NGX_OK)
{
return NGX_ERROR;
}
n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
+ sizeof(ngx_http_script_var_code_t))
+ sizeof(uintptr_t);
if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
return NGX_ERROR;
}
n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
+ sizeof(ngx_http_script_var_code_t))
+ sizeof(uintptr_t)
+ v->len
+ sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1);
if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
return NGX_ERROR;
}
pf = &flushes;
pl = &lengths;
pv = &values;
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
sc.cf = ccv->cf;
sc.source = v;
sc.flushes = &pf;
sc.lengths = &pl;
sc.values = &pv;
sc.complete_lengths = 1;
sc.complete_values = 1;
sc.zero = ccv->zero;
sc.conf_prefix = ccv->conf_prefix;
sc.root_prefix = ccv->root_prefix;
if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_ERROR;
}
if (flushes.nelts) {
ccv->complex_value->flushes = flushes.elts;
ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
}
ccv->complex_value->lengths = lengths.elts;
ccv->complex_value->values = values.elts;
return NGX_OK;
}
ngx_uint_t ngx_uint_t
ngx_http_script_variables_count(ngx_str_t *value) ngx_http_script_variables_count(ngx_str_t *value)
{ {
@ -180,7 +364,9 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc)
sc->size += name.len; sc->size += name.len;
if (ngx_http_script_add_copy_code(sc, &name) != NGX_OK) { if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
!= NGX_OK)
{
return NGX_ERROR; return NGX_ERROR;
} }
} }
@ -309,8 +495,25 @@ ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
static ngx_int_t static ngx_int_t
ngx_http_script_done(ngx_http_script_compile_t *sc) ngx_http_script_done(ngx_http_script_compile_t *sc)
{ {
ngx_str_t zero;
uintptr_t *code; uintptr_t *code;
if (sc->zero) {
zero.len = 1;
zero.data = (u_char *) "\0";
if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
return NGX_ERROR;
}
}
if (sc->conf_prefix || sc->root_prefix) {
if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
return NGX_ERROR;
}
}
if (sc->complete_lengths) { if (sc->complete_lengths) {
code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL); code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
if (code == NULL) { if (code == NULL) {
@ -373,11 +576,16 @@ ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
static ngx_int_t static ngx_int_t
ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value) ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
ngx_uint_t last)
{ {
size_t size; u_char *p;
size_t size, len, zero;
ngx_http_script_copy_code_t *code; ngx_http_script_copy_code_t *code;
zero = (sc->zero && last);
len = value->len + zero;
code = ngx_http_script_add_code(*sc->lengths, code = ngx_http_script_add_code(*sc->lengths,
sizeof(ngx_http_script_copy_code_t), NULL); sizeof(ngx_http_script_copy_code_t), NULL);
if (code == NULL) { if (code == NULL) {
@ -385,10 +593,9 @@ ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value)
} }
code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
code->len = value->len; code->len = len;
size = (sizeof(ngx_http_script_copy_code_t) + value->len size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
+ sizeof(uintptr_t) - 1)
& ~(sizeof(uintptr_t) - 1); & ~(sizeof(uintptr_t) - 1);
code = ngx_http_script_add_code(*sc->values, size, &sc->main); code = ngx_http_script_add_code(*sc->values, size, &sc->main);
@ -397,11 +604,16 @@ ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value)
} }
code->code = ngx_http_script_copy_code; code->code = ngx_http_script_copy_code;
code->len = value->len; code->len = len;
ngx_memcpy((u_char *) code + sizeof(ngx_http_script_copy_code_t), p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
value->data, value->len); value->data, value->len);
if (zero) {
*p = '\0';
sc->zero = 0;
}
return NGX_OK; return NGX_OK;
} }
@ -988,6 +1200,77 @@ ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
#endif #endif
static ngx_int_t
ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
{
ngx_http_script_full_name_code_t *code;
code = ngx_http_script_add_code(*sc->lengths,
sizeof(ngx_http_script_full_name_code_t),
NULL);
if (code == NULL) {
return NGX_ERROR;
}
code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
code->prefix = sc->conf_prefix;
code = ngx_http_script_add_code(*sc->values,
sizeof(ngx_http_script_full_name_code_t),
&sc->main);
if (code == NULL) {
return NGX_ERROR;
}
code->code = ngx_http_script_full_name_code;
code->prefix = sc->conf_prefix;
return NGX_OK;
}
static size_t
ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
{
ngx_http_script_full_name_code_t *code;
code = (ngx_http_script_full_name_code_t *) e->ip;
e->ip += sizeof(ngx_http_script_full_name_code_t);
return code->prefix ? sizeof(NGX_CONF_PREFIX) : ngx_cycle->root.len;
}
static void
ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
{
ngx_http_script_full_name_code_t *code;
ngx_str_t value;
code = (ngx_http_script_full_name_code_t *) e->ip;
value.data = e->buf.data;
value.len = e->pos - e->buf.data;
if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &value, code->prefix)
!= NGX_OK)
{
e->ip = ngx_http_script_exit;
e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
return;
}
e->buf = value;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script fullname: \"%V\"", &value);
e->ip += sizeof(ngx_http_script_full_name_code_t);
}
void void
ngx_http_script_return_code(ngx_http_script_engine_t *e) ngx_http_script_return_code(ngx_http_script_engine_t *e)
{ {

View File

@ -53,12 +53,34 @@ typedef struct {
unsigned compile_args:1; unsigned compile_args:1;
unsigned complete_lengths:1; unsigned complete_lengths:1;
unsigned complete_values:1; unsigned complete_values:1;
unsigned dup_capture:1; unsigned zero:1;
unsigned conf_prefix:1;
unsigned root_prefix:1;
unsigned dup_capture:1;
unsigned args:1; unsigned args:1;
} ngx_http_script_compile_t; } ngx_http_script_compile_t;
typedef struct {
ngx_str_t value;
ngx_uint_t *flushes;
void *lengths;
void *values;
} ngx_http_complex_value_t;
typedef struct {
ngx_conf_t *cf;
ngx_str_t *value;
ngx_http_complex_value_t *complex_value;
unsigned zero:1;
unsigned conf_prefix:1;
unsigned root_prefix:1;
} ngx_http_compile_complex_value_t;
typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e); typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e);
typedef size_t (*ngx_http_script_len_code_pt) (ngx_http_script_engine_t *e); typedef size_t (*ngx_http_script_len_code_pt) (ngx_http_script_engine_t *e);
@ -129,6 +151,12 @@ typedef struct {
#endif #endif
typedef struct {
ngx_http_script_code_pt code;
uintptr_t prefix;
} ngx_http_script_full_name_code_t;
typedef struct { typedef struct {
ngx_http_script_code_pt code; ngx_http_script_code_pt code;
uintptr_t status; uintptr_t status;
@ -175,6 +203,12 @@ typedef struct {
} ngx_http_script_value_code_t; } ngx_http_script_value_code_t;
void ngx_http_scrip_flush_complex_value(ngx_http_request_t *r,
ngx_http_complex_value_t *val);
ngx_int_t ngx_http_complex_value(ngx_http_request_t *r,
ngx_http_complex_value_t *val, ngx_str_t *value);
ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv);
ngx_uint_t ngx_http_script_variables_count(ngx_str_t *value); ngx_uint_t ngx_http_script_variables_count(ngx_str_t *value);
ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc); ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc);
u_char *ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value, u_char *ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,