Coverage Report

Created: 2025-10-13 06:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/unit/src/nxt_tstr.c
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
}