Line | Count | Source |
1 | | |
2 | | /* |
3 | | * Copyright (C) NGINX, Inc. |
4 | | */ |
5 | | |
6 | | #include <nxt_main.h> |
7 | | |
8 | | |
9 | | typedef enum { |
10 | | NXT_TSTR_CONST = 0, |
11 | | NXT_TSTR_VAR, |
12 | | #if (NXT_HAVE_NJS) |
13 | | NXT_TSTR_JS, |
14 | | #endif |
15 | | } nxt_tstr_type_t; |
16 | | |
17 | | |
18 | | struct nxt_tstr_s { |
19 | | nxt_str_t str; |
20 | | |
21 | | union { |
22 | | nxt_var_t *var; |
23 | | #if (NXT_HAVE_NJS) |
24 | | nxt_js_t *js; |
25 | | #endif |
26 | | } u; |
27 | | |
28 | | nxt_tstr_flags_t flags; |
29 | | nxt_tstr_type_t type; |
30 | | }; |
31 | | |
32 | | |
33 | | struct nxt_tstr_query_s { |
34 | | nxt_mp_t *pool; |
35 | | |
36 | | nxt_tstr_state_t *state; |
37 | | nxt_tstr_cache_t *cache; |
38 | | |
39 | | void *ctx; |
40 | | void *data; |
41 | | }; |
42 | | |
43 | | |
44 | | nxt_tstr_state_t * |
45 | | nxt_tstr_state_new(nxt_mp_t *mp, nxt_bool_t test) |
46 | 0 | { |
47 | 0 | nxt_tstr_state_t *state; |
48 | |
|
49 | 0 | state = nxt_mp_get(mp, sizeof(nxt_tstr_state_t)); |
50 | 0 | if (nxt_slow_path(state == NULL)) { |
51 | 0 | return NULL; |
52 | 0 | } |
53 | | |
54 | 0 | state->pool = mp; |
55 | 0 | state->test = test; |
56 | |
|
57 | 0 | state->var_refs = nxt_array_create(mp, 4, sizeof(nxt_var_ref_t)); |
58 | 0 | if (nxt_slow_path(state->var_refs == NULL)) { |
59 | 0 | return NULL; |
60 | 0 | } |
61 | | |
62 | | #if (NXT_HAVE_NJS) |
63 | | state->jcf = nxt_js_conf_new(mp, test); |
64 | | if (nxt_slow_path(state->jcf == NULL)) { |
65 | | return NULL; |
66 | | } |
67 | | #endif |
68 | | |
69 | 0 | return state; |
70 | 0 | } |
71 | | |
72 | | |
73 | | nxt_tstr_t * |
74 | | nxt_tstr_compile(nxt_tstr_state_t *state, const nxt_str_t *str, |
75 | | nxt_tstr_flags_t flags) |
76 | 0 | { |
77 | 0 | u_char *p; |
78 | 0 | nxt_tstr_t *tstr; |
79 | 0 | nxt_bool_t strz, newline; |
80 | |
|
81 | 0 | strz = (flags & NXT_TSTR_STRZ) != 0; |
82 | 0 | newline = (flags & NXT_TSTR_NEWLINE) != 0; |
83 | |
|
84 | 0 | tstr = nxt_mp_get(state->pool, sizeof(nxt_tstr_t)); |
85 | 0 | if (nxt_slow_path(tstr == NULL)) { |
86 | 0 | return NULL; |
87 | 0 | } |
88 | | |
89 | 0 | tstr->str.length = str->length + newline + strz; |
90 | |
|
91 | 0 | tstr->str.start = nxt_mp_nget(state->pool, tstr->str.length); |
92 | 0 | if (nxt_slow_path(tstr->str.start == NULL)) { |
93 | 0 | return NULL; |
94 | 0 | } |
95 | | |
96 | 0 | p = nxt_cpymem(tstr->str.start, str->start, str->length); |
97 | |
|
98 | 0 | if (newline) { |
99 | 0 | *p++ = '\n'; |
100 | 0 | } |
101 | |
|
102 | 0 | if (strz) { |
103 | 0 | *p = '\0'; |
104 | 0 | } |
105 | |
|
106 | 0 | tstr->flags = flags; |
107 | |
|
108 | 0 | if (nxt_tstr_is_js(str)) { |
109 | |
|
110 | | #if (NXT_HAVE_NJS) |
111 | | |
112 | | nxt_str_t tpl; |
113 | | |
114 | | tstr->type = NXT_TSTR_JS; |
115 | | |
116 | | nxt_tstr_str(tstr, &tpl); |
117 | | |
118 | | tstr->u.js = nxt_js_add_tpl(state->jcf, &tpl, flags); |
119 | | if (nxt_slow_path(tstr->u.js == NULL)) { |
120 | | return NULL; |
121 | | } |
122 | | |
123 | | #endif |
124 | |
|
125 | 0 | } else { |
126 | 0 | p = memchr(str->start, '$', str->length); |
127 | |
|
128 | 0 | if (p != NULL) { |
129 | 0 | tstr->type = NXT_TSTR_VAR; |
130 | |
|
131 | 0 | tstr->u.var = nxt_var_compile(state, &tstr->str); |
132 | 0 | if (nxt_slow_path(tstr->u.var == NULL)) { |
133 | 0 | return NULL; |
134 | 0 | } |
135 | |
|
136 | 0 | } else { |
137 | 0 | tstr->type = NXT_TSTR_CONST; |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | 0 | return tstr; |
142 | 0 | } |
143 | | |
144 | | |
145 | | nxt_int_t |
146 | | nxt_tstr_test(nxt_tstr_state_t *state, nxt_str_t *str, u_char *error) |
147 | 0 | { |
148 | 0 | u_char *p; |
149 | |
|
150 | 0 | if (nxt_tstr_is_js(str)) { |
151 | | #if (NXT_HAVE_NJS) |
152 | | return nxt_js_test(state->jcf, str, error); |
153 | | |
154 | | #else |
155 | 0 | nxt_sprintf(error, error + NXT_MAX_ERROR_STR, |
156 | 0 | "Unit is built without support of njs: " |
157 | 0 | "\"--njs\" ./configure option is missing.%Z"); |
158 | 0 | return NXT_ERROR; |
159 | 0 | #endif |
160 | |
|
161 | 0 | } else { |
162 | 0 | p = memchr(str->start, '$', str->length); |
163 | |
|
164 | 0 | if (p != NULL) { |
165 | 0 | return nxt_var_test(state, str, error); |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | 0 | return NXT_OK; |
170 | 0 | } |
171 | | |
172 | | |
173 | | nxt_int_t |
174 | | nxt_tstr_state_done(nxt_tstr_state_t *state, u_char *error) |
175 | 0 | { |
176 | | #if (NXT_HAVE_NJS) |
177 | | if (!state->test) { |
178 | | nxt_int_t ret; |
179 | | |
180 | | ret = nxt_js_compile(state->jcf); |
181 | | if (nxt_slow_path(ret != NXT_OK)) { |
182 | | return NXT_ERROR; |
183 | | } |
184 | | } |
185 | | #endif |
186 | |
|
187 | 0 | return NXT_OK; |
188 | 0 | } |
189 | | |
190 | | |
191 | | void |
192 | | nxt_tstr_state_release(nxt_tstr_state_t *state) |
193 | 0 | { |
194 | | #if (NXT_HAVE_NJS) |
195 | | nxt_js_conf_release(state->jcf); |
196 | | #endif |
197 | 0 | } |
198 | | |
199 | | |
200 | | nxt_int_t |
201 | | nxt_tstr_cond_compile(nxt_tstr_state_t *state, nxt_str_t *str, |
202 | | nxt_tstr_cond_t *cond) |
203 | 0 | { |
204 | 0 | if (str->length > 0 && str->start[0] == '!') { |
205 | 0 | cond->negate = 1; |
206 | |
|
207 | 0 | str->start++; |
208 | 0 | str->length--; |
209 | 0 | } |
210 | |
|
211 | 0 | cond->expr = nxt_tstr_compile(state, str, 0); |
212 | 0 | if (nxt_slow_path(cond->expr == NULL)) { |
213 | 0 | return NXT_ERROR; |
214 | 0 | } |
215 | | |
216 | 0 | return NXT_OK; |
217 | 0 | } |
218 | | |
219 | | |
220 | | nxt_bool_t |
221 | | nxt_tstr_is_const(nxt_tstr_t *tstr) |
222 | 0 | { |
223 | 0 | return (tstr->type == NXT_TSTR_CONST); |
224 | 0 | } |
225 | | |
226 | | |
227 | | void |
228 | | nxt_tstr_str(nxt_tstr_t *tstr, nxt_str_t *str) |
229 | 0 | { |
230 | 0 | *str = tstr->str; |
231 | |
|
232 | 0 | if (tstr->flags & NXT_TSTR_STRZ) { |
233 | 0 | str->length--; |
234 | 0 | } |
235 | 0 | } |
236 | | |
237 | | |
238 | | nxt_int_t |
239 | | nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_tstr_state_t *state, |
240 | | nxt_tstr_cache_t *cache, void *ctx, nxt_mp_t *mp) |
241 | 0 | { |
242 | 0 | nxt_tstr_query_t *query; |
243 | |
|
244 | 0 | query = *query_p; |
245 | |
|
246 | 0 | if (*query_p == NULL) { |
247 | 0 | query = nxt_mp_zget(mp, sizeof(nxt_tstr_query_t)); |
248 | 0 | if (nxt_slow_path(query == NULL)) { |
249 | 0 | return NXT_ERROR; |
250 | 0 | } |
251 | 0 | } |
252 | | |
253 | 0 | query->pool = mp; |
254 | 0 | query->state = state; |
255 | 0 | query->cache = cache; |
256 | 0 | query->ctx = ctx; |
257 | |
|
258 | 0 | *query_p = query; |
259 | |
|
260 | 0 | return NXT_OK; |
261 | 0 | } |
262 | | |
263 | | |
264 | | nxt_int_t |
265 | | nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, |
266 | | nxt_str_t *val) |
267 | 0 | { |
268 | 0 | nxt_int_t ret; |
269 | |
|
270 | 0 | if (nxt_tstr_is_const(tstr)) { |
271 | 0 | nxt_tstr_str(tstr, val); |
272 | 0 | return NXT_OK; |
273 | 0 | } |
274 | | |
275 | 0 | if (tstr->type == NXT_TSTR_VAR) { |
276 | 0 | ret = nxt_var_interpreter(task, query->state, &query->cache->var, |
277 | 0 | tstr->u.var, val, query->ctx, |
278 | 0 | tstr->flags & NXT_TSTR_LOGGING); |
279 | |
|
280 | 0 | if (nxt_slow_path(ret != NXT_OK)) { |
281 | 0 | return NXT_ERROR; |
282 | 0 | } |
283 | |
|
284 | 0 | } else { |
285 | | #if (NXT_HAVE_NJS) |
286 | | ret = nxt_js_call(task, query->state->jcf, &query->cache->js, |
287 | | tstr->u.js, val, query->ctx); |
288 | | |
289 | | if (nxt_slow_path(ret != NXT_OK)) { |
290 | | return NXT_ERROR; |
291 | | } |
292 | | #endif |
293 | 0 | } |
294 | | |
295 | 0 | if (tstr->flags & NXT_TSTR_STRZ) { |
296 | 0 | val->length--; |
297 | 0 | } |
298 | |
|
299 | | #if (NXT_DEBUG) |
300 | | nxt_str_t str; |
301 | | |
302 | | nxt_tstr_str(tstr, &str); |
303 | | |
304 | | nxt_debug(task, "tstr query: \"%V\", result: \"%V\"", &str, val); |
305 | | #endif |
306 | |
|
307 | 0 | return NXT_OK; |
308 | 0 | } |
309 | | |
310 | | |
311 | | void |
312 | | nxt_tstr_query_release(nxt_tstr_query_t *query) |
313 | 0 | { |
314 | | #if (NXT_HAVE_NJS) |
315 | | nxt_js_release(&query->cache->js); |
316 | | #endif |
317 | 0 | } |