Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 747 lines (556 sloc) 19.802 kb
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
1 #define DDEBUG 0
2dcc752 @agentzh added boilerplate
agentzh authored
2 #include "ddebug.h"
3
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
4 #include "ngx_http_array_var_util.h"
5
2dcc752 @agentzh added boilerplate
agentzh authored
6 #include <ndk.h>
7
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
8 static ngx_str_t ngx_http_array_it_key = ngx_string("array_it");
2dcc752 @agentzh added boilerplate
agentzh authored
9
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
10 typedef struct {
11 ngx_uint_t nargs;
12
13 } ngx_http_array_split_data_t;
14
15 typedef struct {
16 ngx_flag_t in_place;
17 ngx_http_complex_value_t *template;
18 ngx_int_t array_it_index;
19
20 } ngx_http_array_map_data_t;
21
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
22 typedef struct {
23 ngx_flag_t in_place;
24
25 } ngx_http_array_map_op_data_t;
26
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
27
2dcc752 @agentzh added boilerplate
agentzh authored
28 static char * ngx_http_array_split(ngx_conf_t *cf, ngx_command_t *cmd,
29 void *conf);
30
31 static char * ngx_http_array_map(ngx_conf_t *cf, ngx_command_t *cmd,
32 void *conf);
33
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
34 static char * ngx_http_array_map_op(ngx_conf_t *cf, ngx_command_t *cmd,
35 void *conf);
36
37 static char * ngx_http_array_join(ngx_conf_t *cf, ngx_command_t *cmd,
2dcc752 @agentzh added boilerplate
agentzh authored
38 void *conf);
39
40 static ngx_int_t ngx_http_array_var_split(ngx_http_request_t *r,
41 ngx_str_t *res, ngx_http_variable_value_t *v, void *data);
42
43 static ngx_int_t ngx_http_array_var_map(ngx_http_request_t *r,
44 ngx_str_t *res, ngx_http_variable_value_t *v, void *data);
45
46 static ngx_int_t ngx_http_array_var_map_op(ngx_http_request_t *r,
47 ngx_str_t *res, ngx_http_variable_value_t *v, void *data);
48
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
49 static ngx_int_t ngx_http_array_var_join(ngx_http_request_t *r,
50 ngx_str_t *res, ngx_http_variable_value_t *v);
2dcc752 @agentzh added boilerplate
agentzh authored
51
52
53 static ngx_command_t ngx_http_array_var_commands[] = {
54 {
55 ngx_string ("array_split"),
56 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
57 |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
58 ngx_http_array_split,
59 0,
60 0,
61 NULL
62 },
63 {
64 ngx_string ("array_map"),
65 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
66 |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23,
2dcc752 @agentzh added boilerplate
agentzh authored
67 ngx_http_array_map,
68 0,
69 0,
70 NULL
71 },
72 {
73 ngx_string ("array_map_op"),
74 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
75 |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23,
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
76 ngx_http_array_map_op,
2dcc752 @agentzh added boilerplate
agentzh authored
77 0,
78 0,
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
79 ngx_http_array_var_map_op
2dcc752 @agentzh added boilerplate
agentzh authored
80 },
81 {
82 ngx_string("array_join"),
83 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
84 |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23,
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
85 ngx_http_array_join,
2dcc752 @agentzh added boilerplate
agentzh authored
86 0,
87 0,
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
88 ngx_http_array_var_join
2dcc752 @agentzh added boilerplate
agentzh authored
89 },
90
91 ngx_null_command
92 };
93
94
95 static ngx_http_module_t ngx_http_array_var_module_ctx = {
96 NULL, /* preconfiguration */
97 NULL, /* postconfiguration */
98
99 NULL, /* create main configuration */
100 NULL, /* init main configuration */
101
102 NULL, /* create server configuration */
103 NULL, /* merge server configuration */
104
105 NULL, /* create location configuration */
106 NULL, /* merge location configuration */
107 };
108
109
110 ngx_module_t ngx_http_array_var_module = {
111 NGX_MODULE_V1,
112 &ngx_http_array_var_module_ctx, // module context
113 ngx_http_array_var_commands, // module directives
114 NGX_HTTP_MODULE, // module type
115 NULL, // init master
116 NULL, // init module
117 NULL, // init process
118 NULL, // init thread
119 NULL, // exit thread
120 NULL, // exit process
121 NULL, // exit master
122 NGX_MODULE_V1_PADDING
123 };
124
125
126 static char *
127 ngx_http_array_split(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
128 {
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
129 ndk_set_var_t filter;
130 ngx_str_t target;
131 ngx_str_t *value;
132 ngx_str_t *bad_arg;
133 ngx_http_array_split_data_t *data = NULL;
134
135 data = ngx_palloc(cf->pool, sizeof(ngx_http_array_split_data_t));
136 if (data == NULL) {
137 return NGX_CONF_ERROR;
138 }
139
140 filter.type = NDK_SET_VAR_MULTI_VALUE_DATA;
141 filter.func = ngx_http_array_var_split;
142 filter.data = data;
143
144 value = cf->args->elts;
145
146 if (cf->args->nelts == 2 + 1) {
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
147 dd("array_split $sep $var");
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
148 data->nargs = filter.size = 2;
149 target = value[2];
150 return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
151 }
152
153 /* cf->args->nelts >= 3 + 1 */
154
155 if (value[3].len >= sizeof("to=") - 1
156 && ngx_str3cmp(value[3].data, 't', 'o', '='))
157 {
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
158 dd("array_split $sep $str to=$array");
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
159 data->nargs = filter.size = 2;
160
161 target.data = value[3].data + sizeof("to=") - 1;
162 target.len = value[3].len - (sizeof("to=") - 1);
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
163 dd("split target: %.*s", target.len, target.data);
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
164
165 if (cf->args->nelts > 3 + 1) {
166 bad_arg = &value[4];
167 goto unexpected_arg;
168 }
169
170 return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
171 }
172
173 /* the 3rd argument is max_items */
174
175 if (cf->args->nelts > 4 + 1) {
176 bad_arg = &value[5];
177 goto unexpected_arg;
178 }
179
180 if (cf->args->nelts == 4 + 1) {
181 /* array_split $sep $str $max to=$array */
182
183 if (value[4].len < sizeof("to=") - 1
184 || ! (ngx_str3cmp(value[4].data, 't', 'o', '=')))
185 {
186 ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
187 "%V: expecting the \"to\" option at the "
188 "4th argument: \"%V\"",
189 &cmd->name, &value[4]);
190
191 return NGX_CONF_ERROR;
192 }
193
194 data->nargs = filter.size = 3;
195
196 target.data = value[4].data + sizeof("to=") - 1;
197 target.len = value[4].len - (sizeof("to=") - 1);
198
199 return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
200 }
201
202 /* cf->args->nelts == 3 + 1 */
203
204 /* array_split $sep $var $max */
205
206 target = value[2];
207 data->nargs = filter.size = 3;
208
209 return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
210
211 unexpected_arg:
212
213 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
214 "%V: unexpected argument \"%V\"",
215 &cmd->name, bad_arg);
216
217 return NGX_CONF_ERROR;
2dcc752 @agentzh added boilerplate
agentzh authored
218 }
219
220
221 static char *
222 ngx_http_array_map(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
223 {
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
224 ndk_set_var_t filter;
225 ngx_str_t target;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
226 ngx_str_t *value;
227 ngx_http_array_map_data_t *data;
228 ngx_http_compile_complex_value_t ccv;
2dcc752 @agentzh added boilerplate
agentzh authored
229
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
230 data = ngx_palloc(cf->pool, sizeof(ngx_http_array_map_data_t));
231 if (data == NULL) {
232 return NGX_CONF_ERROR;
233 }
2dcc752 @agentzh added boilerplate
agentzh authored
234
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
235 data->template = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
236 if (data->template == NULL) {
237 return NGX_CONF_ERROR;
238 }
239
240 value = cf->args->elts;
241
242 if (value[1].len == 0) {
243 ngx_memzero(data->template, sizeof(ngx_http_complex_value_t));
244
245 } else {
0932573 @agentzh fixed a nasty use of unitialized value bug in array_map: we should al…
agentzh authored
246 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
247
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
248 ccv.cf = cf;
249 ccv.value = &value[1];
250 ccv.complex_value = data->template;
251
252 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
253 return NGX_CONF_ERROR;
254 }
255 }
256
257 filter.type = NDK_SET_VAR_VALUE_DATA;
258 filter.func = ngx_http_array_var_map;
259 filter.data = data;
260 filter.size = 1;
261
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
262 data->array_it_index = ngx_http_array_var_add_variable(cf,
263 &ngx_http_array_it_key);
264
265 if (data->array_it_index == NGX_ERROR) {
266 return NGX_CONF_ERROR;
267 }
268
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
269 if (cf->args->nelts == 2 + 1) {
270 /* array_map $template $array */
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
271 data->in_place = 1;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
272 target = value[2];
273
274 } else {
275 /* cf->args->nelts == 3 + 1 */
276
277 if (value[3].len < sizeof("to=") - 1
278 || ! (ngx_str3cmp(value[3].data, 't', 'o', '=')))
279 {
280 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
281 "%V: expecting the \"to\" option at "
282 "the 3rd argument: \"%V\"",
283 &cmd->name, &value[3]);
fb1155a @agentzh array_map_op now works.
agentzh authored
284
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
285 return NGX_CONF_ERROR;
286 }
287
288 target.data = value[3].data + sizeof("to=") - 1;
289 target.len = value[3].len - (sizeof("to=") - 1);
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
290 data->in_place = 0;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
291 }
292
293 return ndk_set_var_value_core(cf, &target, &value[2], &filter);
2dcc752 @agentzh added boilerplate
agentzh authored
294 }
295
296
297 static char *
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
298 ngx_http_array_map_op(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
299 {
300 ngx_http_array_map_op_data_t *data;
301 ndk_set_var_t filter;
302 ngx_str_t target;
303 ngx_str_t *value;
304 ngx_str_t *bad_arg;
305
306 data = ngx_palloc(cf->pool, sizeof(ngx_http_array_map_op_data_t));
307 if (data == NULL) {
308 return NGX_CONF_ERROR;
309 }
310
311 filter.type = NDK_SET_VAR_MULTI_VALUE_DATA;
312 filter.func = (ndk_set_var_value_pt) cmd->post;
313 filter.data = data;
314
315 value = cf->args->elts;
316
317 if (cf->args->nelts == 2 + 1) {
318 dd("array_join $sep $var");
319
320 filter.size = 2;
321 data->in_place = 1;
322
323 target = value[2];
324
325 dd("array join target: %.*s", target.len, target.data);
326
327 return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
328 }
329
330 /* cf->args->nelts == 3 + 1 */
331
332 if (value[3].len >= sizeof("to=") - 1
333 && ngx_str3cmp(value[3].data, 't', 'o', '='))
334 {
335 /* array_join $sep $str to=$array */
336 filter.size = 2;
337 data->in_place = 0;
338
339 target.data = value[3].data + sizeof("to=") - 1;
340 target.len = value[3].len - (sizeof("to=") - 1);
341
342 if (cf->args->nelts > 3 + 1) {
343 bad_arg = &value[4];
fb1155a @agentzh array_map_op now works.
agentzh authored
344
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
345 } else {
346 return ndk_set_var_multi_value_core(cf, &target, &value[1],
347 &filter);
348 }
349
350 } else {
351 bad_arg = &value[3];
352 }
353
354 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
355 "%V: unexpected argument \"%V\"",
356 &cmd->name, bad_arg);
357
358 return NGX_CONF_ERROR;
359 }
360
361
362 static char *
363 ngx_http_array_join(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2dcc752 @agentzh added boilerplate
agentzh authored
364 {
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
365 ndk_set_var_t filter;
366 ngx_str_t target;
367 ngx_str_t *value;
368 ngx_str_t *bad_arg;
369
370 filter.type = NDK_SET_VAR_MULTI_VALUE;
371 filter.func = (ndk_set_var_value_pt) cmd->post;
372
373 value = cf->args->elts;
374
375 if (cf->args->nelts == 2 + 1) {
376 dd("array_join $sep $var");
377
378 filter.size = 2;
379 target = value[2];
380
381 dd("array join target: %.*s", target.len, target.data);
382
383 return ndk_set_var_multi_value_core(cf, &target, &value[1], &filter);
384 }
385
386 /* cf->args->nelts == 3 + 1 */
387
388 if (value[3].len >= sizeof("to=") - 1
389 && ngx_str3cmp(value[3].data, 't', 'o', '='))
390 {
391 /* array_join $sep $str to=$array */
392 filter.size = 2;
393
394 target.data = value[3].data + sizeof("to=") - 1;
395 target.len = value[3].len - (sizeof("to=") - 1);
396
397 if (cf->args->nelts > 3 + 1) {
398 bad_arg = &value[4];
399 } else {
400 return ndk_set_var_multi_value_core(cf, &target, &value[1],
401 &filter);
402 }
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
403
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
404 } else {
405 bad_arg = &value[3];
406 }
407
408 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
409 "%V: unexpected argument \"%V\"",
410 &cmd->name, bad_arg);
411
412 return NGX_CONF_ERROR;
2dcc752 @agentzh added boilerplate
agentzh authored
413 }
414
415
416 static ngx_int_t
417 ngx_http_array_var_split(ngx_http_request_t *r,
418 ngx_str_t *res, ngx_http_variable_value_t *v, void *data)
419 {
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
420 ngx_http_array_split_data_t *conf = data;
421 ngx_http_variable_value_t *sep, *str;
422 ngx_str_t *s;
423 u_char *pos, *end, *last;
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
424 ssize_t max, i;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
425 ngx_array_t *array;
426
427 if (conf->nargs == 3) {
428 max = ngx_atosz(v[2].data, v[2].len);
429 if (max == NGX_ERROR) {
430 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
431 "array_split: invalid max items: \"%V\"",
432 &v[2]);
433
434 return NGX_ERROR;
435 }
436 } else {
437 max = 0;
438 }
439
440 if (max) {
441 array = ngx_array_create(r->pool, max,
442 sizeof(ngx_str_t));
443 } else {
444 array = ngx_array_create(r->pool, 4,
445 sizeof(ngx_str_t));
446 }
447
448 if (array == NULL) {
449 return NGX_ERROR;
450 }
451
452 sep = &v[0];
453 str = &v[1];
454
455 pos = str->data;
456 end = str->data + str->len;
457
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
458 i = 0;
459
1ea5a69 @agentzh clears $array_it after calling array_map and fixed a bug in array_spl…
agentzh authored
460 if (sep->len == 0) {
461 /* split each char into an array elem */
462
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
463 while (i != max - 1 && pos < end - 1) {
1ea5a69 @agentzh clears $array_it after calling array_map and fixed a bug in array_spl…
agentzh authored
464 s = ngx_array_push(array);
465 if (s == NULL) {
466 return NGX_ERROR;
467 }
468
469 s->data = pos;
470 s->len = 1;
471
472 pos++;
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
473 i++;
1ea5a69 @agentzh clears $array_it after calling array_map and fixed a bug in array_spl…
agentzh authored
474 }
475
476 goto done;
477 }
478
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
479 while (i != max - 1 && (last = ngx_http_array_var_strlstrn(pos, end,
480 sep->data, sep->len - 1)))
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
481 {
482 s = ngx_array_push(array);
483 if (s == NULL) {
484 return NGX_ERROR;
485 }
486
487 s->data = pos;
488 s->len = last - pos;
489
490 dd("split item %.*s", s->len, s->data);
491
492 pos = last + sep->len;
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
493 i++;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
494 }
495
58f10d6 @agentzh implemented the LIMIT argument for "array_split", mimicing the split …
agentzh authored
496 done:
6431ba5 @agentzh fixed a bug in empty value lists.
agentzh authored
497 dd("pos %p, last %p, end %p", pos, last, end);
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
498
6431ba5 @agentzh fixed a bug in empty value lists.
agentzh authored
499 s = ngx_array_push(array);
500 if (s == NULL) {
501 return NGX_ERROR;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
502 }
503
6431ba5 @agentzh fixed a bug in empty value lists.
agentzh authored
504 s->data = pos;
505 s->len = end - pos;
506
507 dd("split item %.*s", s->len, s->data);
508
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
509 dd("split: array size: %d", array->nelts);
510 dd("split array ptr: %p", array);
511
512 res->data = (u_char *) array;
513 res->len = sizeof(ngx_array_t);
514
2dcc752 @agentzh added boilerplate
agentzh authored
515 return NGX_OK;
516 }
517
518
519 static ngx_int_t
520 ngx_http_array_var_map(ngx_http_request_t *r,
521 ngx_str_t *res, ngx_http_variable_value_t *v, void *data)
522 {
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
523 ngx_http_array_map_data_t *conf = data;
524 ngx_http_variable_value_t *array_it;
525 ngx_uint_t i;
526 ngx_str_t *value, *new_value;
527 ngx_array_t *array, *new_array;
528
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
529 dd("entered array var map");
530
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
531 if (conf->template == NULL) {
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
532 dd("template empty");
533
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
534 return NGX_OK;
535 }
536
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
537 if (v[0].len != sizeof(ngx_array_t)) {
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
538 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
539 "array_join: invalid array variable value in the 2nd "
540 "argument: \"%.*s\"", &v[0]);
541
542 return NGX_ERROR;
543 }
544
545 array = (ngx_array_t *) v[0].data;
546
547 value = array->elts;
548
549 array_it = ngx_http_get_indexed_variable(r, conf->array_it_index);
550
551 if ( conf->in_place) {
552 new_array = array;
553 } else {
554 new_array = ngx_array_create(r->pool, array->nelts,
555 sizeof(ngx_str_t));
556 if (new_array == NULL) {
557 return NGX_ERROR;
558 }
559 }
560
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
561 dd("array var map: array size: %d", array->nelts);
562
563 array_it->not_found = 0;
564 array_it->valid = 1;
565
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
566 for (i = 0; i < array->nelts; i++) {
567 array_it->data = value[i].data;
568 array_it->len = value[i].len;
569
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
570 dd("array it: %.*s", array_it->len, array_it->data);
571
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
572 if (conf->in_place) {
573 new_value = &value[i];
574
575 } else {
576 new_value = ngx_array_push(new_array);
577 if (new_value == NULL) {
578 return NGX_ERROR;
579 }
580 }
581
582 if (ngx_http_complex_value(r, conf->template, new_value) != NGX_OK) {
583 return NGX_ERROR;
584 }
d15c4c7 @agentzh now the array_map directive passes tests.
agentzh authored
585
586 dd("array var map: new item: %.*s", new_value->len, new_value->data);
446f3f1 @agentzh implemented functions ngx_http_array_split and ngx_http_array_var_map.
agentzh authored
587 }
588
1ea5a69 @agentzh clears $array_it after calling array_map and fixed a bug in array_spl…
agentzh authored
589 array_it->not_found = 1;
590 array_it->valid = 0;
591
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
592 res->data = (u_char *) new_array;
593 res->len = sizeof(ngx_array_t);
594
2dcc752 @agentzh added boilerplate
agentzh authored
595 return NGX_OK;
596 }
597
598
599 static ngx_int_t
600 ngx_http_array_var_map_op(ngx_http_request_t *r,
601 ngx_str_t *res, ngx_http_variable_value_t *v, void *data)
602 {
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
603 ngx_http_variable_value_t arg;
604 ngx_http_array_map_op_data_t *conf = data;
605 ndk_set_var_value_pt func;
606 ngx_int_t rc;
607 ngx_uint_t i;
608 ngx_str_t *value;
609 ngx_str_t *new_value;
610 ngx_array_t *array;
611 ngx_array_t *new_array;
612
613 func = ngx_http_array_var_get_func_from_cmd(v[0].data, v[0].len);
614
615 if (func == NULL) {
616 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
617 "array_map_op: directive \"%v\" not found "
618 "or does not use ndk_set_var_value",
619 &v[0]);
620
621 return NGX_ERROR;
622 }
623
624 if (v[1].len != sizeof(ngx_array_t)) {
625 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
626 "array_map_op: invalid array variable value in the 2nd "
627 "argument: \"%.*s\"", &v[0]);
628
629 return NGX_ERROR;
630 }
631
632 array = (ngx_array_t *) v[1].data;
633
634 value = array->elts;
635
636 if ( conf->in_place) {
637 new_array = array;
638
639 } else {
640 new_array = ngx_array_create(r->pool, array->nelts,
641 sizeof(ngx_str_t));
642 if (new_array == NULL) {
643 return NGX_ERROR;
644 }
645 }
646
647 for (i = 0; i < array->nelts; i++) {
648 arg.data = value[i].data;
649 arg.len = value[i].len;
c3c0b1e @agentzh array_map_op: explicitly set .valid and .not_found for variable value…
agentzh authored
650 arg.valid = 1;
651 arg.not_found = 0;
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
652
653 if (conf->in_place) {
654 new_value = &value[i];
655
656 } else {
657 new_value = ngx_array_push(new_array);
658 if (new_value == NULL) {
659 return NGX_ERROR;
660 }
661 }
662
663 rc = func(r, new_value, &arg);
664 if (rc != NGX_OK) {
665 return NGX_ERROR;
666 }
667 }
668
669 res->data = (u_char *) new_array;
fb1155a @agentzh array_map_op now works.
agentzh authored
670 res->len = sizeof(ngx_array_t);
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
671
2dcc752 @agentzh added boilerplate
agentzh authored
672 return NGX_OK;
673 }
674
675
676 static ngx_int_t
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
677 ngx_http_array_var_join(ngx_http_request_t *r,
678 ngx_str_t *res, ngx_http_variable_value_t *v)
2dcc752 @agentzh added boilerplate
agentzh authored
679 {
5ba87a9 @agentzh array_split and array_join directives have passed the test suite.
agentzh authored
680 ngx_http_variable_value_t *sep;
681 ngx_array_t *array;
682 size_t len;
683 ngx_str_t *value;
684 ngx_uint_t i;
685 u_char *p;
686
687 sep = &v[0];
688
689 dd("sep %.*s", sep->len, sep->data);
690
691 if (v[1].len != sizeof(ngx_array_t)) {
692 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
693 "array_join: invalid array variable value in the "
694 "2nd argument: \"%V\"", &v[1]);
695
696 return NGX_ERROR;
697 }
698
699 array = (ngx_array_t *) v[1].data;
700
701 dd("join array ptr %p", array);
702 dd("array->nelts: %d", array->nelts);
703
704 if (array->nelts == 0) {
705 res->data = NULL;
706 res->len = 0;
707 return NGX_OK;
708 }
709
710 value = array->elts;
711
712 len = sep->len * (array->nelts - 1);
713
714 for (i = 0; i < array->nelts; i++) {
715 len += value[i].len;
716 }
717
718 dd("buf len %d", len);
719
720 res->data = ngx_palloc(r->pool, len);
721 if (res->data == NULL) {
722 return NGX_ERROR;
723 }
724
725 res->len = len;
726
727 p = res->data;
728
729 for (i = 0; i < array->nelts; i++) {
730 dd("copying elem of size %d", value[i].len);
731 p = ngx_copy(p, value[i].data, value[i].len);
732 if (i < array->nelts - 1) {
733 p = ngx_copy(p, sep->data, sep->len);
734 }
735 }
736
737 if (p != res->data + res->len) {
738 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
739 "array_join: buffer error");
740
741 return NGX_ERROR;
742 }
743
2dcc752 @agentzh added boilerplate
agentzh authored
744 return NGX_OK;
745 }
746
Something went wrong with that request. Please try again.