Permalink
Browse files

now the array_map directive passes tests.

  • Loading branch information...
1 parent 6431ba5 commit d15c4c75128754e40c90bac4649259b1f83b2198 @agentzh agentzh committed Feb 12, 2010
Showing with 234 additions and 7 deletions.
  1. +2 −0 .gitignore
  2. +99 −7 src/ngx_http_array_var_module.c
  3. +103 −0 src/ngx_http_array_var_util.c
  4. +2 −0 src/ngx_http_array_var_util.h
  5. +28 −0 test/t/sanity.t
View
2 .gitignore
@@ -30,3 +30,5 @@ genmobi.sh
misc/chunked
ctags
src/module.c
+src/util.c
+src/util.h
View
106 src/ngx_http_array_var_module.c
@@ -1,10 +1,11 @@
-#define DDEBUG 1
+#define DDEBUG 0
#include "ddebug.h"
#include "ngx_http_array_var_util.h"
#include <ndk.h>
+static ngx_str_t ngx_http_array_it_key = ngx_string("array_it");
typedef struct {
ngx_uint_t nargs;
@@ -30,7 +31,10 @@ static char * ngx_http_array_split(ngx_conf_t *cf, ngx_command_t *cmd,
static char * ngx_http_array_map(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static char * ngx_http_array_join_or_map_op(ngx_conf_t *cf, ngx_command_t *cmd,
+static char * ngx_http_array_map_op(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+
+static char * ngx_http_array_join(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_int_t ngx_http_array_var_split(ngx_http_request_t *r,
@@ -69,7 +73,7 @@ static ngx_command_t ngx_http_array_var_commands[] = {
ngx_string ("array_map_op"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23,
- ngx_http_array_join_or_map_op,
+ ngx_http_array_map_op,
0,
0,
ngx_http_array_var_map_op
@@ -78,7 +82,7 @@ static ngx_command_t ngx_http_array_var_commands[] = {
ngx_string("array_join"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23,
- ngx_http_array_join_or_map_op,
+ ngx_http_array_join,
0,
0,
ngx_http_array_var_join
@@ -217,8 +221,8 @@ ngx_http_array_split(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
ngx_http_array_map(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ndk_set_var_t filter;
- ngx_str_t target;
+ ndk_set_var_t filter;
+ ngx_str_t target;
ngx_str_t *value;
ngx_http_array_map_data_t *data;
ngx_http_compile_complex_value_t ccv;
@@ -253,8 +257,16 @@ ngx_http_array_map(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
filter.data = data;
filter.size = 1;
+ data->array_it_index = ngx_http_array_var_add_variable(cf,
+ &ngx_http_array_it_key);
+
+ if (data->array_it_index == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
if (cf->args->nelts == 2 + 1) {
/* array_map $template $array */
+ data->in_place = 1;
target = value[2];
} else {
@@ -272,14 +284,80 @@ ngx_http_array_map(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
target.data = value[3].data + sizeof("to=") - 1;
target.len = value[3].len - (sizeof("to=") - 1);
+ data->in_place = 0;
}
return ndk_set_var_value_core(cf, &target, &value[2], &filter);
}
static char *
-ngx_http_array_join_or_map_op(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ngx_http_array_map_op(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_array_map_op_data_t *data;
+ ndk_set_var_t filter;
+ ngx_str_t target;
+ ngx_str_t *value;
+ ngx_str_t *bad_arg;
+
+ data = ngx_palloc(cf->pool, sizeof(ngx_http_array_map_op_data_t));
+ if (data == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ filter.type = NDK_SET_VAR_MULTI_VALUE_DATA;
+ filter.func = (ndk_set_var_value_pt) cmd->post;
+ filter.data = data;
+
+ value = cf->args->elts;
+
+ if (cf->args->nelts == 2 + 1) {
+ dd("array_join $sep $var");
+
+ filter.size = 2;
+ data->in_place = 1;
+
+ target = value[2];
+
+ dd("array join target: %.*s", target.len, target.data);
+
+ return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
+ }
+
+ /* cf->args->nelts == 3 + 1 */
+
+ if (value[3].len >= sizeof("to=") - 1
+ && ngx_str3cmp(value[3].data, 't', 'o', '='))
+ {
+ /* array_join $sep $str to=$array */
+ filter.size = 2;
+ data->in_place = 0;
+
+ target.data = value[3].data + sizeof("to=") - 1;
+ target.len = value[3].len - (sizeof("to=") - 1);
+
+ if (cf->args->nelts > 3 + 1) {
+ bad_arg = &value[4];
+ } else {
+ return ndk_set_var_multi_value_core(cf, &target, &value[1],
+ &filter);
+ }
+
+ } else {
+ bad_arg = &value[3];
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%V: unexpected argument \"%V\"",
+ &cmd->name, bad_arg);
+
+ return NGX_CONF_ERROR;
+}
+
+
+
+static char *
+ngx_http_array_join(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ndk_set_var_t filter;
ngx_str_t target;
@@ -319,6 +397,7 @@ ngx_http_array_join_or_map_op(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return ndk_set_var_multi_value_core(cf, &target, &value[1],
&filter);
}
+
} else {
bad_arg = &value[3];
}
@@ -421,7 +500,11 @@ ngx_http_array_var_map(ngx_http_request_t *r,
ngx_str_t *value, *new_value;
ngx_array_t *array, *new_array;
+ dd("entered array var map");
+
if (conf->template == NULL) {
+ dd("template empty");
+
return NGX_OK;
}
@@ -449,10 +532,17 @@ ngx_http_array_var_map(ngx_http_request_t *r,
}
}
+ dd("array var map: array size: %d", array->nelts);
+
+ array_it->not_found = 0;
+ array_it->valid = 1;
+
for (i = 0; i < array->nelts; i++) {
array_it->data = value[i].data;
array_it->len = value[i].len;
+ dd("array it: %.*s", array_it->len, array_it->data);
+
if (conf->in_place) {
new_value = &value[i];
@@ -466,6 +556,8 @@ ngx_http_array_var_map(ngx_http_request_t *r,
if (ngx_http_complex_value(r, conf->template, new_value) != NGX_OK) {
return NGX_ERROR;
}
+
+ dd("array var map: new item: %.*s", new_value->len, new_value->data);
}
res->data = (u_char *) new_array;
View
103 src/ngx_http_array_var_util.c
@@ -0,0 +1,103 @@
+#define DDEBUG 0
+#include "ddebug.h"
+
+#include "ngx_http_array_var_util.h"
+
+
+static ngx_int_t ngx_http_array_var_variable_not_found(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
+
+
+/* Modified from the ngx_strlcasestrn function in ngx_string.h
+ * Copyright (C) by Igor Sysoev */
+u_char *
+ngx_http_array_var_strlstrn(u_char *s1, u_char *last, u_char *s2, size_t n)
+{
+ ngx_uint_t c1, c2;
+
+ c2 = (ngx_uint_t) *s2++;
+ last -= n;
+
+ do {
+ do {
+ if (s1 >= last) {
+ return NULL;
+ }
+
+ c1 = (ngx_uint_t) *s1++;
+
+ } while (c1 != c2);
+
+ } while (ngx_strncmp(s1, s2, n) != 0);
+
+ return --s1;
+}
+
+
+ndk_set_var_value_pt
+ngx_http_array_var_get_func_from_cmd(u_char *name,
+ size_t name_len)
+{
+ ndk_set_var_t *filter;
+ ngx_uint_t i;
+ ngx_module_t *module;
+ ngx_command_t *cmd;
+
+ for (i = 0; ngx_modules[i]; i++) {
+ module = ngx_modules[i];
+ if (module->type != NGX_HTTP_MODULE) {
+ continue;
+ }
+
+ cmd = ngx_modules[i]->commands;
+ if (cmd == NULL) {
+ continue;
+ }
+
+ for ( /* void */ ; cmd->name.len; cmd++) {
+ if (cmd->set != ndk_set_var_value) {
+ continue;
+ }
+
+ filter = cmd->post;
+ if (filter == NULL) {
+ continue;
+ }
+
+ if (cmd->name.len != name_len
+ || ngx_strncmp(cmd->name.data, name, name_len) != 0)
+ {
+ continue;
+ }
+
+ return filter->func;
+ }
+ }
+
+ return NULL;
+}
+
+
+ngx_int_t
+ngx_http_array_var_add_variable(ngx_conf_t *cf, ngx_str_t *name) {
+ ngx_http_variable_t *v;
+
+ v = ngx_http_add_variable(cf, name, NGX_HTTP_VAR_CHANGEABLE);
+ if (v == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->get_handler = ngx_http_array_var_variable_not_found;
+
+ return ngx_http_get_variable_index(cf, name);
+}
+
+
+static ngx_int_t
+ngx_http_array_var_variable_not_found(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ v->not_found = 1;
+ return NGX_OK;
+}
+
View
2 src/ngx_http_array_var_util.h
@@ -6,6 +6,8 @@
#include <ngx_http.h>
+ngx_int_t ngx_http_array_var_add_variable(ngx_conf_t *cf, ngx_str_t *name);
+
u_char * ngx_http_array_var_strlstrn(u_char *s1, u_char *last, u_char *s2,
size_t n);
View
28 test/t/sanity.t
@@ -70,3 +70,31 @@ GET /foo?names=,,,
--- response_body
[+++]
+
+=== TEST 4: array map
+--- config
+ location /foo {
+ array_split ',' $arg_names to=$names;
+ array_map 'hi' $names;
+ array_join '+' $names;
+ echo "[$names]";
+ }
+--- request
+GET /foo?names=,,,
+--- response_body
+[hi+hi+hi+hi]
+
+
+=== TEST 4: array map
+--- config
+ location /foo {
+ array_split ',' $arg_names to=$names;
+ array_map '[$array_it]' $names;
+ array_join '+' $names;
+ echo "$names";
+ }
+--- request
+GET /foo?names=bob,marry,nomas
+--- response_body
+[bob]+[marry]+[nomas]
+

0 comments on commit d15c4c7

Please sign in to comment.