xref: /unit/src/nxt_conf.c (revision 2139:99d792169ffb)
1106Svbart@nginx.com 
2106Svbart@nginx.com /*
3106Svbart@nginx.com  * Copyright (C) Igor Sysoev
4106Svbart@nginx.com  * Copyright (C) Valentin V. Bartenev
5106Svbart@nginx.com  * Copyright (C) NGINX, Inc.
6106Svbart@nginx.com  */
7106Svbart@nginx.com 
8106Svbart@nginx.com #include <nxt_main.h>
9106Svbart@nginx.com #include <nxt_conf.h>
101439Svbart@nginx.com 
111439Svbart@nginx.com #include <float.h>
12106Svbart@nginx.com #include <math.h>
13106Svbart@nginx.com 
14106Svbart@nginx.com 
15106Svbart@nginx.com #define NXT_CONF_MAX_SHORT_STRING  14
161439Svbart@nginx.com #define NXT_CONF_MAX_NUMBER_LEN    14
17172Svbart@nginx.com #define NXT_CONF_MAX_STRING        NXT_INT32_T_MAX
18106Svbart@nginx.com 
191174Svbart@nginx.com #define NXT_CONF_MAX_TOKEN_LEN     256
201174Svbart@nginx.com 
21106Svbart@nginx.com 
22106Svbart@nginx.com typedef enum {
23116Svbart@nginx.com     NXT_CONF_VALUE_NULL = 0,
24116Svbart@nginx.com     NXT_CONF_VALUE_BOOLEAN,
25116Svbart@nginx.com     NXT_CONF_VALUE_INTEGER,
26116Svbart@nginx.com     NXT_CONF_VALUE_NUMBER,
27116Svbart@nginx.com     NXT_CONF_VALUE_SHORT_STRING,
28116Svbart@nginx.com     NXT_CONF_VALUE_STRING,
29116Svbart@nginx.com     NXT_CONF_VALUE_ARRAY,
30116Svbart@nginx.com     NXT_CONF_VALUE_OBJECT,
31116Svbart@nginx.com } nxt_conf_value_type_t;
32106Svbart@nginx.com 
33106Svbart@nginx.com 
34106Svbart@nginx.com typedef enum {
35106Svbart@nginx.com     NXT_CONF_OP_PASS = 0,
36106Svbart@nginx.com     NXT_CONF_OP_CREATE,
37106Svbart@nginx.com     NXT_CONF_OP_REPLACE,
38106Svbart@nginx.com     NXT_CONF_OP_DELETE,
39106Svbart@nginx.com } nxt_conf_op_action_t;
40106Svbart@nginx.com 
41106Svbart@nginx.com 
42106Svbart@nginx.com typedef struct nxt_conf_array_s   nxt_conf_array_t;
43106Svbart@nginx.com typedef struct nxt_conf_object_s  nxt_conf_object_t;
44106Svbart@nginx.com 
45106Svbart@nginx.com 
46180Smax.romanov@nginx.com struct nxt_conf_value_s {
47187Smax.romanov@nginx.com     union {
48171Svbart@nginx.com         uint8_t               boolean;  /* 1 bit. */
491439Svbart@nginx.com         u_char                number[NXT_CONF_MAX_NUMBER_LEN + 1];;
50173Svbart@nginx.com 
51173Svbart@nginx.com         struct {
52208Svbart@nginx.com             u_char            start[NXT_CONF_MAX_SHORT_STRING];
53173Svbart@nginx.com             uint8_t           length;
54173Svbart@nginx.com         } str;
55172Svbart@nginx.com 
56187Smax.romanov@nginx.com         struct {
57172Svbart@nginx.com             u_char            *start;
58172Svbart@nginx.com             uint32_t          length;
59187Smax.romanov@nginx.com         } nxt_packed string;
60172Svbart@nginx.com 
61106Svbart@nginx.com         nxt_conf_array_t      *array;
62106Svbart@nginx.com         nxt_conf_object_t     *object;
63187Smax.romanov@nginx.com     } nxt_packed u;
64106Svbart@nginx.com 
65171Svbart@nginx.com     uint8_t                   type;  /* 3 bits. */
66180Smax.romanov@nginx.com } nxt_aligned(8);
67106Svbart@nginx.com 
68106Svbart@nginx.com 
69106Svbart@nginx.com struct nxt_conf_array_s {
70106Svbart@nginx.com     nxt_uint_t                count;
71106Svbart@nginx.com     nxt_conf_value_t          elements[];
72106Svbart@nginx.com };
73106Svbart@nginx.com 
74106Svbart@nginx.com 
75106Svbart@nginx.com typedef struct {
76106Svbart@nginx.com     nxt_conf_value_t          name;
77106Svbart@nginx.com     nxt_conf_value_t          value;
78106Svbart@nginx.com } nxt_conf_object_member_t;
79106Svbart@nginx.com 
80106Svbart@nginx.com 
81106Svbart@nginx.com struct nxt_conf_object_s {
82106Svbart@nginx.com     nxt_uint_t                count;
83106Svbart@nginx.com     nxt_conf_object_member_t  members[];
84106Svbart@nginx.com };
85106Svbart@nginx.com 
86106Svbart@nginx.com 
87106Svbart@nginx.com struct nxt_conf_op_s {
88106Svbart@nginx.com     uint32_t                  index;
89106Svbart@nginx.com     uint32_t                  action;  /* nxt_conf_op_action_t */
90106Svbart@nginx.com     void                      *ctx;
91106Svbart@nginx.com };
92106Svbart@nginx.com 
93106Svbart@nginx.com 
941174Svbart@nginx.com typedef struct {
951174Svbart@nginx.com     u_char                    *start;
961174Svbart@nginx.com     u_char                    *end;
971174Svbart@nginx.com     nxt_bool_t                last;
981174Svbart@nginx.com     u_char                    buf[NXT_CONF_MAX_TOKEN_LEN];
991174Svbart@nginx.com } nxt_conf_path_parse_t;
1001174Svbart@nginx.com 
1011174Svbart@nginx.com 
1021174Svbart@nginx.com static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse,
1031174Svbart@nginx.com     nxt_str_t *token);
1041174Svbart@nginx.com 
105*2139Sandrew@digital-domain.net static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end);
106106Svbart@nginx.com static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value,
107208Svbart@nginx.com     u_char *start, u_char *end, nxt_conf_json_error_t *error);
108106Svbart@nginx.com static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value,
109208Svbart@nginx.com     u_char *start, u_char *end, nxt_conf_json_error_t *error);
110106Svbart@nginx.com static nxt_int_t nxt_conf_object_hash_add(nxt_mp_t *mp,
111106Svbart@nginx.com     nxt_lvlhsh_t *lvlhsh, nxt_conf_object_member_t *member);
112106Svbart@nginx.com static nxt_int_t nxt_conf_object_hash_test(nxt_lvlhsh_query_t *lhq,
113106Svbart@nginx.com     void *data);
114106Svbart@nginx.com static void *nxt_conf_object_hash_alloc(void *data, size_t size);
115106Svbart@nginx.com static void nxt_conf_object_hash_free(void *data, void *p);
116106Svbart@nginx.com static u_char *nxt_conf_json_parse_array(nxt_mp_t *mp, nxt_conf_value_t *value,
117208Svbart@nginx.com     u_char *start, u_char *end, nxt_conf_json_error_t *error);
118106Svbart@nginx.com static u_char *nxt_conf_json_parse_string(nxt_mp_t *mp, nxt_conf_value_t *value,
119208Svbart@nginx.com     u_char *start, u_char *end, nxt_conf_json_error_t *error);
120106Svbart@nginx.com static u_char *nxt_conf_json_parse_number(nxt_mp_t *mp, nxt_conf_value_t *value,
121208Svbart@nginx.com     u_char *start, u_char *end, nxt_conf_json_error_t *error);
122208Svbart@nginx.com static void nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos,
123208Svbart@nginx.com     const char *detail);
124106Svbart@nginx.com 
125106Svbart@nginx.com static nxt_int_t nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op,
126106Svbart@nginx.com     nxt_conf_value_t *dst, nxt_conf_value_t *src);
1271048Svbart@nginx.com static nxt_int_t nxt_conf_copy_array(nxt_mp_t *mp, nxt_conf_op_t *op,
1281048Svbart@nginx.com     nxt_conf_value_t *dst, nxt_conf_value_t *src);
129106Svbart@nginx.com static nxt_int_t nxt_conf_copy_object(nxt_mp_t *mp, nxt_conf_op_t *op,
130106Svbart@nginx.com     nxt_conf_value_t *dst, nxt_conf_value_t *src);
131106Svbart@nginx.com 
132106Svbart@nginx.com static size_t nxt_conf_json_string_length(nxt_conf_value_t *value);
133106Svbart@nginx.com static u_char *nxt_conf_json_print_string(u_char *p, nxt_conf_value_t *value);
134106Svbart@nginx.com static size_t nxt_conf_json_array_length(nxt_conf_value_t *value,
135106Svbart@nginx.com     nxt_conf_json_pretty_t *pretty);
136106Svbart@nginx.com static u_char *nxt_conf_json_print_array(u_char *p, nxt_conf_value_t *value,
137106Svbart@nginx.com     nxt_conf_json_pretty_t *pretty);
138106Svbart@nginx.com static size_t nxt_conf_json_object_length(nxt_conf_value_t *value,
139106Svbart@nginx.com     nxt_conf_json_pretty_t *pretty);
140106Svbart@nginx.com static u_char *nxt_conf_json_print_object(u_char *p, nxt_conf_value_t *value,
141106Svbart@nginx.com     nxt_conf_json_pretty_t *pretty);
142106Svbart@nginx.com 
143106Svbart@nginx.com static size_t nxt_conf_json_escape_length(u_char *p, size_t size);
144106Svbart@nginx.com static u_char *nxt_conf_json_escape(u_char *dst, u_char *src, size_t size);
145106Svbart@nginx.com 
146106Svbart@nginx.com 
147106Svbart@nginx.com #define nxt_conf_json_newline(p)                                              \
148106Svbart@nginx.com     ((p)[0] = '\r', (p)[1] = '\n', (p) + 2)
149106Svbart@nginx.com 
150106Svbart@nginx.com 
151106Svbart@nginx.com nxt_inline u_char *
nxt_conf_json_indentation(u_char * p,uint32_t level)152106Svbart@nginx.com nxt_conf_json_indentation(u_char *p, uint32_t level)
153106Svbart@nginx.com {
154106Svbart@nginx.com     while (level) {
155106Svbart@nginx.com         *p++ = '\t';
156106Svbart@nginx.com         level--;
157106Svbart@nginx.com     }
158106Svbart@nginx.com 
159106Svbart@nginx.com     return p;
160106Svbart@nginx.com }
161106Svbart@nginx.com 
162106Svbart@nginx.com 
163121Svbart@nginx.com void
nxt_conf_get_string(nxt_conf_value_t * value,nxt_str_t * str)164106Svbart@nginx.com nxt_conf_get_string(nxt_conf_value_t *value, nxt_str_t *str)
165106Svbart@nginx.com {
166116Svbart@nginx.com     if (value->type == NXT_CONF_VALUE_SHORT_STRING) {
167173Svbart@nginx.com         str->length = value->u.str.length;
168173Svbart@nginx.com         str->start = value->u.str.start;
169106Svbart@nginx.com 
170106Svbart@nginx.com     } else {
171172Svbart@nginx.com         str->length = value->u.string.length;
172172Svbart@nginx.com         str->start = value->u.string.start;
173106Svbart@nginx.com     }
174106Svbart@nginx.com }
175106Svbart@nginx.com 
176106Svbart@nginx.com 
177773Svbart@nginx.com void
nxt_conf_set_string(nxt_conf_value_t * value,nxt_str_t * str)178773Svbart@nginx.com nxt_conf_set_string(nxt_conf_value_t *value, nxt_str_t *str)
179773Svbart@nginx.com {
180773Svbart@nginx.com     if (str->length > NXT_CONF_MAX_SHORT_STRING) {
181773Svbart@nginx.com         value->type = NXT_CONF_VALUE_STRING;
182773Svbart@nginx.com         value->u.string.length = str->length;
183773Svbart@nginx.com         value->u.string.start = str->start;
184773Svbart@nginx.com 
185773Svbart@nginx.com     } else {
186773Svbart@nginx.com         value->type = NXT_CONF_VALUE_SHORT_STRING;
187773Svbart@nginx.com         value->u.str.length = str->length;
188773Svbart@nginx.com 
189773Svbart@nginx.com         nxt_memcpy(value->u.str.start, str->start, str->length);
190773Svbart@nginx.com     }
191773Svbart@nginx.com }
192773Svbart@nginx.com 
193773Svbart@nginx.com 
194774Svbart@nginx.com nxt_int_t
nxt_conf_set_string_dup(nxt_conf_value_t * value,nxt_mp_t * mp,const nxt_str_t * str)1952075Salx.manpages@gmail.com nxt_conf_set_string_dup(nxt_conf_value_t *value, nxt_mp_t *mp,
1962075Salx.manpages@gmail.com     const nxt_str_t *str)
197774Svbart@nginx.com {
198774Svbart@nginx.com     nxt_str_t  tmp, *ptr;
199774Svbart@nginx.com 
200774Svbart@nginx.com     if (str->length > NXT_CONF_MAX_SHORT_STRING) {
201774Svbart@nginx.com         value->type = NXT_CONF_VALUE_STRING;
202774Svbart@nginx.com 
203774Svbart@nginx.com         ptr = nxt_str_dup(mp, &tmp, str);
204774Svbart@nginx.com         if (nxt_slow_path(ptr == NULL)) {
205774Svbart@nginx.com             return NXT_ERROR;
206774Svbart@nginx.com         }
207774Svbart@nginx.com 
208774Svbart@nginx.com         value->u.string.length = tmp.length;
209774Svbart@nginx.com         value->u.string.start = tmp.start;
210774Svbart@nginx.com 
211774Svbart@nginx.com     } else {
212774Svbart@nginx.com         value->type = NXT_CONF_VALUE_SHORT_STRING;
213774Svbart@nginx.com         value->u.str.length = str->length;
214774Svbart@nginx.com 
215774Svbart@nginx.com         nxt_memcpy(value->u.str.start, str->start, str->length);
216774Svbart@nginx.com     }
217774Svbart@nginx.com 
218774Svbart@nginx.com     return NXT_OK;
219774Svbart@nginx.com }
220774Svbart@nginx.com 
221774Svbart@nginx.com 
2221439Svbart@nginx.com double
nxt_conf_get_number(nxt_conf_value_t * value)2231439Svbart@nginx.com nxt_conf_get_number(nxt_conf_value_t *value)
224507Smax.romanov@nginx.com {
2251439Svbart@nginx.com     return nxt_strtod(value->u.number, NULL);
226507Smax.romanov@nginx.com }
227507Smax.romanov@nginx.com 
228507Smax.romanov@nginx.com 
2291236St.nateldemoura@f5.com uint8_t
nxt_conf_get_boolean(nxt_conf_value_t * value)2301236St.nateldemoura@f5.com nxt_conf_get_boolean(nxt_conf_value_t *value)
2311236St.nateldemoura@f5.com {
2321236St.nateldemoura@f5.com     return value->u.boolean;
2331236St.nateldemoura@f5.com }
2341236St.nateldemoura@f5.com 
2351236St.nateldemoura@f5.com 
236116Svbart@nginx.com nxt_uint_t
nxt_conf_object_members_count(nxt_conf_value_t * value)237121Svbart@nginx.com nxt_conf_object_members_count(nxt_conf_value_t *value)
238121Svbart@nginx.com {
239121Svbart@nginx.com     return value->u.object->count;
240121Svbart@nginx.com }
241121Svbart@nginx.com 
242121Svbart@nginx.com 
243121Svbart@nginx.com nxt_conf_value_t *
nxt_conf_create_object(nxt_mp_t * mp,nxt_uint_t count)244121Svbart@nginx.com nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count)
245121Svbart@nginx.com {
246121Svbart@nginx.com     size_t            size;
247121Svbart@nginx.com     nxt_conf_value_t  *value;
248121Svbart@nginx.com 
249121Svbart@nginx.com     size = sizeof(nxt_conf_value_t)
250121Svbart@nginx.com            + sizeof(nxt_conf_object_t)
251121Svbart@nginx.com            + count * sizeof(nxt_conf_object_member_t);
252121Svbart@nginx.com 
253121Svbart@nginx.com     value = nxt_mp_get(mp, size);
254121Svbart@nginx.com     if (nxt_slow_path(value == NULL)) {
255121Svbart@nginx.com         return NULL;
256121Svbart@nginx.com     }
257121Svbart@nginx.com 
258121Svbart@nginx.com     value->u.object = nxt_pointer_to(value, sizeof(nxt_conf_value_t));
259121Svbart@nginx.com     value->u.object->count = count;
260121Svbart@nginx.com 
261121Svbart@nginx.com     value->type = NXT_CONF_VALUE_OBJECT;
262121Svbart@nginx.com 
263121Svbart@nginx.com     return value;
264121Svbart@nginx.com }
265121Svbart@nginx.com 
266121Svbart@nginx.com 
267208Svbart@nginx.com void
nxt_conf_set_member(nxt_conf_value_t * object,nxt_str_t * name,const nxt_conf_value_t * value,uint32_t index)268208Svbart@nginx.com nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name,
269*2139Sandrew@digital-domain.net     const nxt_conf_value_t *value, uint32_t index)
270121Svbart@nginx.com {
271121Svbart@nginx.com     nxt_conf_object_member_t  *member;
272121Svbart@nginx.com 
273121Svbart@nginx.com     member = &object->u.object->members[index];
274773Svbart@nginx.com 
275773Svbart@nginx.com     nxt_conf_set_string(&member->name, name);
276121Svbart@nginx.com 
277121Svbart@nginx.com     member->value = *value;
278208Svbart@nginx.com }
279208Svbart@nginx.com 
280208Svbart@nginx.com 
281208Svbart@nginx.com void
nxt_conf_set_member_string(nxt_conf_value_t * object,nxt_str_t * name,nxt_str_t * value,uint32_t index)282208Svbart@nginx.com nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name,
283208Svbart@nginx.com     nxt_str_t *value, uint32_t index)
284208Svbart@nginx.com {
285208Svbart@nginx.com     nxt_conf_object_member_t  *member;
286208Svbart@nginx.com 
287208Svbart@nginx.com     member = &object->u.object->members[index];
288773Svbart@nginx.com 
289773Svbart@nginx.com     nxt_conf_set_string(&member->name, name);
290773Svbart@nginx.com 
291773Svbart@nginx.com     nxt_conf_set_string(&member->value, value);
292208Svbart@nginx.com }
293208Svbart@nginx.com 
294208Svbart@nginx.com 
295774Svbart@nginx.com nxt_int_t
nxt_conf_set_member_string_dup(nxt_conf_value_t * object,nxt_mp_t * mp,nxt_str_t * name,nxt_str_t * value,uint32_t index)296774Svbart@nginx.com nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp,
297774Svbart@nginx.com     nxt_str_t *name, nxt_str_t *value, uint32_t index)
298774Svbart@nginx.com {
299774Svbart@nginx.com     nxt_conf_object_member_t  *member;
300774Svbart@nginx.com 
301774Svbart@nginx.com     member = &object->u.object->members[index];
302774Svbart@nginx.com 
303774Svbart@nginx.com     nxt_conf_set_string(&member->name, name);
304774Svbart@nginx.com 
305774Svbart@nginx.com     return nxt_conf_set_string_dup(&member->value, mp, value);
306774Svbart@nginx.com }
307774Svbart@nginx.com 
308774Svbart@nginx.com 
309208Svbart@nginx.com void
nxt_conf_set_member_integer(nxt_conf_value_t * object,nxt_str_t * name,int64_t value,uint32_t index)310208Svbart@nginx.com nxt_conf_set_member_integer(nxt_conf_value_t *object, nxt_str_t *name,
311208Svbart@nginx.com     int64_t value, uint32_t index)
312208Svbart@nginx.com {
3131439Svbart@nginx.com     u_char                    *p, *end;
314208Svbart@nginx.com     nxt_conf_object_member_t  *member;
315208Svbart@nginx.com 
316208Svbart@nginx.com     member = &object->u.object->members[index];
317773Svbart@nginx.com 
318773Svbart@nginx.com     nxt_conf_set_string(&member->name, name);
319208Svbart@nginx.com 
3201439Svbart@nginx.com     p = member->value.u.number;
3211439Svbart@nginx.com     end = p + NXT_CONF_MAX_NUMBER_LEN;
3221439Svbart@nginx.com 
3231439Svbart@nginx.com     end = nxt_sprintf(p, end, "%L", value);
3241439Svbart@nginx.com     *end = '\0';
3251439Svbart@nginx.com 
326208Svbart@nginx.com     member->value.type = NXT_CONF_VALUE_INTEGER;
327121Svbart@nginx.com }
328121Svbart@nginx.com 
329121Svbart@nginx.com 
330774Svbart@nginx.com void
nxt_conf_set_member_null(nxt_conf_value_t * object,nxt_str_t * name,uint32_t index)331774Svbart@nginx.com nxt_conf_set_member_null(nxt_conf_value_t *object, nxt_str_t *name,
332774Svbart@nginx.com     uint32_t index)
333774Svbart@nginx.com {
334774Svbart@nginx.com     nxt_conf_object_member_t  *member;
335774Svbart@nginx.com 
336774Svbart@nginx.com     member = &object->u.object->members[index];
337774Svbart@nginx.com 
338774Svbart@nginx.com     nxt_conf_set_string(&member->name, name);
339774Svbart@nginx.com 
340774Svbart@nginx.com     member->value.type = NXT_CONF_VALUE_NULL;
341774Svbart@nginx.com }
342774Svbart@nginx.com 
343774Svbart@nginx.com 
344774Svbart@nginx.com nxt_conf_value_t *
nxt_conf_create_array(nxt_mp_t * mp,nxt_uint_t count)345774Svbart@nginx.com nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count)
346774Svbart@nginx.com {
347774Svbart@nginx.com     size_t            size;
348774Svbart@nginx.com     nxt_conf_value_t  *value;
349774Svbart@nginx.com 
350774Svbart@nginx.com     size = sizeof(nxt_conf_value_t)
351774Svbart@nginx.com            + sizeof(nxt_conf_array_t)
352774Svbart@nginx.com            + count * sizeof(nxt_conf_value_t);
353774Svbart@nginx.com 
354774Svbart@nginx.com     value = nxt_mp_get(mp, size);
355774Svbart@nginx.com     if (nxt_slow_path(value == NULL)) {
356774Svbart@nginx.com         return NULL;
357774Svbart@nginx.com     }
358774Svbart@nginx.com 
359774Svbart@nginx.com     value->u.array = nxt_pointer_to(value, sizeof(nxt_conf_value_t));
360774Svbart@nginx.com     value->u.array->count = count;
361774Svbart@nginx.com 
362774Svbart@nginx.com     value->type = NXT_CONF_VALUE_ARRAY;
363774Svbart@nginx.com 
364774Svbart@nginx.com     return value;
365774Svbart@nginx.com }
366774Svbart@nginx.com 
367774Svbart@nginx.com 
368774Svbart@nginx.com void
nxt_conf_set_element(nxt_conf_value_t * array,nxt_uint_t index,const nxt_conf_value_t * value)369774Svbart@nginx.com nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index,
370*2139Sandrew@digital-domain.net     const nxt_conf_value_t *value)
371774Svbart@nginx.com {
372774Svbart@nginx.com     array->u.array->elements[index] = *value;
373774Svbart@nginx.com }
374774Svbart@nginx.com 
375774Svbart@nginx.com 
376774Svbart@nginx.com nxt_int_t
nxt_conf_set_element_string_dup(nxt_conf_value_t * array,nxt_mp_t * mp,nxt_uint_t index,nxt_str_t * value)377774Svbart@nginx.com nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp,
378774Svbart@nginx.com     nxt_uint_t index, nxt_str_t *value)
379774Svbart@nginx.com {
380774Svbart@nginx.com     nxt_conf_value_t  *element;
381774Svbart@nginx.com 
382774Svbart@nginx.com     element = &array->u.array->elements[index];
383774Svbart@nginx.com 
384774Svbart@nginx.com     return nxt_conf_set_string_dup(element, mp, value);
385774Svbart@nginx.com }
386774Svbart@nginx.com 
387774Svbart@nginx.com 
388121Svbart@nginx.com nxt_uint_t
nxt_conf_array_elements_count(nxt_conf_value_t * value)389961Sigor@sysoev.ru nxt_conf_array_elements_count(nxt_conf_value_t *value)
390961Sigor@sysoev.ru {
391961Sigor@sysoev.ru     return value->u.array->count;
392961Sigor@sysoev.ru }
393961Sigor@sysoev.ru 
394961Sigor@sysoev.ru 
395961Sigor@sysoev.ru nxt_uint_t
nxt_conf_array_elements_count_or_1(nxt_conf_value_t * value)3962076Salx.manpages@gmail.com nxt_conf_array_elements_count_or_1(nxt_conf_value_t *value)
3972076Salx.manpages@gmail.com {
3982076Salx.manpages@gmail.com     return (value->type == NXT_CONF_VALUE_ARRAY) ? value->u.array->count : 1;
3992076Salx.manpages@gmail.com }
4002076Salx.manpages@gmail.com 
4012076Salx.manpages@gmail.com 
4022076Salx.manpages@gmail.com nxt_uint_t
nxt_conf_type(nxt_conf_value_t * value)403116Svbart@nginx.com nxt_conf_type(nxt_conf_value_t *value)
404116Svbart@nginx.com {
405116Svbart@nginx.com     switch (value->type) {
406116Svbart@nginx.com 
407116Svbart@nginx.com     case NXT_CONF_VALUE_NULL:
408116Svbart@nginx.com         return NXT_CONF_NULL;
409116Svbart@nginx.com 
410116Svbart@nginx.com     case NXT_CONF_VALUE_BOOLEAN:
411116Svbart@nginx.com         return NXT_CONF_BOOLEAN;
412116Svbart@nginx.com 
413116Svbart@nginx.com     case NXT_CONF_VALUE_INTEGER:
414116Svbart@nginx.com         return NXT_CONF_INTEGER;
415116Svbart@nginx.com 
416116Svbart@nginx.com     case NXT_CONF_VALUE_NUMBER:
417116Svbart@nginx.com         return NXT_CONF_NUMBER;
418116Svbart@nginx.com 
419116Svbart@nginx.com     case NXT_CONF_VALUE_SHORT_STRING:
420116Svbart@nginx.com     case NXT_CONF_VALUE_STRING:
421116Svbart@nginx.com         return NXT_CONF_STRING;
422116Svbart@nginx.com 
423116Svbart@nginx.com     case NXT_CONF_VALUE_ARRAY:
424116Svbart@nginx.com         return NXT_CONF_ARRAY;
425116Svbart@nginx.com 
426116Svbart@nginx.com     case NXT_CONF_VALUE_OBJECT:
427116Svbart@nginx.com         return NXT_CONF_OBJECT;
428116Svbart@nginx.com     }
429116Svbart@nginx.com 
430116Svbart@nginx.com     nxt_unreachable();
431116Svbart@nginx.com 
432116Svbart@nginx.com     return 0;
433116Svbart@nginx.com }
434116Svbart@nginx.com 
435116Svbart@nginx.com 
436106Svbart@nginx.com nxt_conf_value_t *
nxt_conf_get_path(nxt_conf_value_t * value,nxt_str_t * path)437106Svbart@nginx.com nxt_conf_get_path(nxt_conf_value_t *value, nxt_str_t *path)
438106Svbart@nginx.com {
439106Svbart@nginx.com     nxt_str_t              token;
4401174Svbart@nginx.com     nxt_int_t              ret, index;
441106Svbart@nginx.com     nxt_conf_path_parse_t  parse;
442106Svbart@nginx.com 
443106Svbart@nginx.com     parse.start = path->start;
444106Svbart@nginx.com     parse.end = path->start + path->length;
445106Svbart@nginx.com     parse.last = 0;
446106Svbart@nginx.com 
447106Svbart@nginx.com     do {
4481174Svbart@nginx.com         ret = nxt_conf_path_next_token(&parse, &token);
4491174Svbart@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
4501174Svbart@nginx.com             return NULL;
4511174Svbart@nginx.com         }
452106Svbart@nginx.com 
453106Svbart@nginx.com         if (token.length == 0) {
454106Svbart@nginx.com 
455106Svbart@nginx.com             if (parse.last) {
456106Svbart@nginx.com                 break;
457106Svbart@nginx.com             }
458106Svbart@nginx.com 
459106Svbart@nginx.com             return NULL;
460106Svbart@nginx.com         }
461106Svbart@nginx.com 
462775Svbart@nginx.com         switch (value->type) {
463775Svbart@nginx.com 
464775Svbart@nginx.com         case NXT_CONF_VALUE_OBJECT:
465775Svbart@nginx.com             value = nxt_conf_get_object_member(value, &token, NULL);
466775Svbart@nginx.com             break;
467775Svbart@nginx.com 
468775Svbart@nginx.com         case NXT_CONF_VALUE_ARRAY:
469775Svbart@nginx.com             index = nxt_int_parse(token.start, token.length);
470775Svbart@nginx.com 
471775Svbart@nginx.com             if (index < 0 || index > NXT_INT32_T_MAX) {
472775Svbart@nginx.com                 return NULL;
473775Svbart@nginx.com             }
474775Svbart@nginx.com 
475775Svbart@nginx.com             value = nxt_conf_get_array_element(value, index);
476775Svbart@nginx.com             break;
477775Svbart@nginx.com 
478775Svbart@nginx.com         default:
479775Svbart@nginx.com             return NULL;
480775Svbart@nginx.com         }
481106Svbart@nginx.com 
482106Svbart@nginx.com         if (value == NULL) {
483106Svbart@nginx.com             return NULL;
484106Svbart@nginx.com         }
485106Svbart@nginx.com 
486106Svbart@nginx.com     } while (parse.last == 0);
487106Svbart@nginx.com 
488106Svbart@nginx.com     return value;
489106Svbart@nginx.com }
490106Svbart@nginx.com 
491106Svbart@nginx.com 
4921174Svbart@nginx.com static nxt_int_t
nxt_conf_path_next_token(nxt_conf_path_parse_t * parse,nxt_str_t * token)493106Svbart@nginx.com nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token)
494106Svbart@nginx.com {
4951174Svbart@nginx.com     u_char  *p, *start, *end;
4961174Svbart@nginx.com     size_t  length;
4971174Svbart@nginx.com 
4981174Svbart@nginx.com     start = parse->start + 1;
4991174Svbart@nginx.com 
5001174Svbart@nginx.com     p = start;
5011174Svbart@nginx.com 
5021174Svbart@nginx.com     while (p < parse->end && *p != '/') {
503106Svbart@nginx.com         p++;
504106Svbart@nginx.com     }
505106Svbart@nginx.com 
506106Svbart@nginx.com     parse->start = p;
5071174Svbart@nginx.com     parse->last = (p >= parse->end);
5081174Svbart@nginx.com 
5091174Svbart@nginx.com     length = p - start;
5101174Svbart@nginx.com 
5111174Svbart@nginx.com     if (nxt_slow_path(length > NXT_CONF_MAX_TOKEN_LEN)) {
5121174Svbart@nginx.com         return NXT_ERROR;
5131174Svbart@nginx.com     }
5141174Svbart@nginx.com 
5151174Svbart@nginx.com     end = nxt_decode_uri(parse->buf, start, length);
5161174Svbart@nginx.com     if (nxt_slow_path(end == NULL)) {
5171174Svbart@nginx.com         return NXT_ERROR;
5181174Svbart@nginx.com     }
5191174Svbart@nginx.com 
5201174Svbart@nginx.com     token->length = end - parse->buf;
5211174Svbart@nginx.com     token->start = parse->buf;
5221174Svbart@nginx.com 
5231174Svbart@nginx.com     return NXT_OK;
524106Svbart@nginx.com }
525106Svbart@nginx.com 
526106Svbart@nginx.com 
527106Svbart@nginx.com nxt_conf_value_t *
nxt_conf_get_object_member(nxt_conf_value_t * value,nxt_str_t * name,uint32_t * index)528106Svbart@nginx.com nxt_conf_get_object_member(nxt_conf_value_t *value, nxt_str_t *name,
529106Svbart@nginx.com     uint32_t *index)
530106Svbart@nginx.com {
531106Svbart@nginx.com     nxt_str_t                 str;
532106Svbart@nginx.com     nxt_uint_t                n;
533106Svbart@nginx.com     nxt_conf_object_t         *object;
534106Svbart@nginx.com     nxt_conf_object_member_t  *member;
535106Svbart@nginx.com 
536116Svbart@nginx.com     if (value->type != NXT_CONF_VALUE_OBJECT) {
537106Svbart@nginx.com         return NULL;
538106Svbart@nginx.com     }
539106Svbart@nginx.com 
540106Svbart@nginx.com     object = value->u.object;
541106Svbart@nginx.com 
542106Svbart@nginx.com     for (n = 0; n < object->count; n++) {
543106Svbart@nginx.com         member = &object->members[n];
544106Svbart@nginx.com 
545106Svbart@nginx.com         nxt_conf_get_string(&member->name, &str);
546106Svbart@nginx.com 
547106Svbart@nginx.com         if (nxt_strstr_eq(&str, name)) {
548106Svbart@nginx.com 
549106Svbart@nginx.com             if (index != NULL) {
550106Svbart@nginx.com                 *index = n;
551106Svbart@nginx.com             }
552106Svbart@nginx.com 
553106Svbart@nginx.com             return &member->value;
554106Svbart@nginx.com         }
555106Svbart@nginx.com     }
556106Svbart@nginx.com 
557106Svbart@nginx.com     return NULL;
558106Svbart@nginx.com }
559106Svbart@nginx.com 
560106Svbart@nginx.com 
561106Svbart@nginx.com nxt_int_t
nxt_conf_map_object(nxt_mp_t * mp,nxt_conf_value_t * value,nxt_conf_map_t * map,nxt_uint_t n,void * data)562213Svbart@nginx.com nxt_conf_map_object(nxt_mp_t *mp, nxt_conf_value_t *value, nxt_conf_map_t *map,
563213Svbart@nginx.com     nxt_uint_t n, void *data)
564106Svbart@nginx.com {
5651439Svbart@nginx.com     double            num;
566213Svbart@nginx.com     nxt_str_t         str, *s;
567106Svbart@nginx.com     nxt_uint_t        i;
568106Svbart@nginx.com     nxt_conf_value_t  *v;
569106Svbart@nginx.com 
570106Svbart@nginx.com     union {
571111Sigor@sysoev.ru         uint8_t     ui8;
572111Sigor@sysoev.ru         int32_t     i32;
573111Sigor@sysoev.ru         int64_t     i64;
574839Svbart@nginx.com         int         i;
575111Sigor@sysoev.ru         ssize_t     size;
576111Sigor@sysoev.ru         off_t       off;
577111Sigor@sysoev.ru         nxt_msec_t  msec;
578111Sigor@sysoev.ru         double      dbl;
579111Sigor@sysoev.ru         nxt_str_t   str;
580213Svbart@nginx.com         char        *cstrz;
581111Sigor@sysoev.ru         void        *v;
582106Svbart@nginx.com     } *ptr;
583106Svbart@nginx.com 
584136Svbart@nginx.com     for (i = 0; i < n; i++) {
585106Svbart@nginx.com 
586106Svbart@nginx.com         v = nxt_conf_get_object_member(value, &map[i].name, NULL);
587106Svbart@nginx.com 
588116Svbart@nginx.com         if (v == NULL || v->type == NXT_CONF_VALUE_NULL) {
589106Svbart@nginx.com             continue;
590106Svbart@nginx.com         }
591106Svbart@nginx.com 
592106Svbart@nginx.com         ptr = nxt_pointer_to(data, map[i].offset);
593106Svbart@nginx.com 
594106Svbart@nginx.com         switch (map[i].type) {
595106Svbart@nginx.com 
596106Svbart@nginx.com         case NXT_CONF_MAP_INT8:
597106Svbart@nginx.com 
598136Svbart@nginx.com             if (v->type == NXT_CONF_VALUE_BOOLEAN) {
599136Svbart@nginx.com                 ptr->ui8 = v->u.boolean;
600106Svbart@nginx.com             }
601106Svbart@nginx.com 
602106Svbart@nginx.com             break;
603106Svbart@nginx.com 
604106Svbart@nginx.com         case NXT_CONF_MAP_INT32:
605106Svbart@nginx.com         case NXT_CONF_MAP_INT64:
606106Svbart@nginx.com         case NXT_CONF_MAP_INT:
607106Svbart@nginx.com         case NXT_CONF_MAP_SIZE:
608106Svbart@nginx.com         case NXT_CONF_MAP_OFF:
609111Sigor@sysoev.ru         case NXT_CONF_MAP_MSEC:
610106Svbart@nginx.com 
611116Svbart@nginx.com             if (v->type != NXT_CONF_VALUE_INTEGER) {
612136Svbart@nginx.com                 break;
613106Svbart@nginx.com             }
614106Svbart@nginx.com 
6151439Svbart@nginx.com             num = nxt_strtod(v->u.number, NULL);
6161439Svbart@nginx.com 
617106Svbart@nginx.com             switch (map[i].type) {
618106Svbart@nginx.com 
619106Svbart@nginx.com             case NXT_CONF_MAP_INT32:
6201439Svbart@nginx.com                 ptr->i32 = num;
621106Svbart@nginx.com                 break;
622106Svbart@nginx.com 
623106Svbart@nginx.com             case NXT_CONF_MAP_INT64:
6241439Svbart@nginx.com                 ptr->i64 = num;
625106Svbart@nginx.com                 break;
626106Svbart@nginx.com 
627106Svbart@nginx.com             case NXT_CONF_MAP_INT:
6281439Svbart@nginx.com                 ptr->i = num;
629106Svbart@nginx.com                 break;
630106Svbart@nginx.com 
631106Svbart@nginx.com             case NXT_CONF_MAP_SIZE:
6321439Svbart@nginx.com                 ptr->size = num;
633106Svbart@nginx.com                 break;
634106Svbart@nginx.com 
635106Svbart@nginx.com             case NXT_CONF_MAP_OFF:
6361439Svbart@nginx.com                 ptr->off = num;
637106Svbart@nginx.com                 break;
638106Svbart@nginx.com 
639111Sigor@sysoev.ru             case NXT_CONF_MAP_MSEC:
6401439Svbart@nginx.com                 ptr->msec = (nxt_msec_t) num * 1000;
641111Sigor@sysoev.ru                 break;
642111Sigor@sysoev.ru 
643106Svbart@nginx.com             default:
644106Svbart@nginx.com                 nxt_unreachable();
645106Svbart@nginx.com             }
646106Svbart@nginx.com 
647106Svbart@nginx.com             break;
648106Svbart@nginx.com 
649106Svbart@nginx.com         case NXT_CONF_MAP_DOUBLE:
650106Svbart@nginx.com 
651116Svbart@nginx.com             if (v->type == NXT_CONF_VALUE_NUMBER) {
6521439Svbart@nginx.com                 ptr->dbl = nxt_strtod(v->u.number, NULL);
653106Svbart@nginx.com             }
654106Svbart@nginx.com 
655106Svbart@nginx.com             break;
656106Svbart@nginx.com 
657106Svbart@nginx.com         case NXT_CONF_MAP_STR:
658213Svbart@nginx.com         case NXT_CONF_MAP_STR_COPY:
659213Svbart@nginx.com         case NXT_CONF_MAP_CSTRZ:
660213Svbart@nginx.com 
661213Svbart@nginx.com             if (v->type != NXT_CONF_VALUE_SHORT_STRING
662213Svbart@nginx.com                 && v->type != NXT_CONF_VALUE_STRING)
663106Svbart@nginx.com             {
664213Svbart@nginx.com                 break;
665213Svbart@nginx.com             }
666213Svbart@nginx.com 
667213Svbart@nginx.com             nxt_conf_get_string(v, &str);
668213Svbart@nginx.com 
669213Svbart@nginx.com             switch (map[i].type) {
670213Svbart@nginx.com 
671213Svbart@nginx.com             case NXT_CONF_MAP_STR:
672213Svbart@nginx.com                 ptr->str = str;
673213Svbart@nginx.com                 break;
674213Svbart@nginx.com 
675213Svbart@nginx.com             case NXT_CONF_MAP_STR_COPY:
676213Svbart@nginx.com 
677213Svbart@nginx.com                 s = nxt_str_dup(mp, &ptr->str, &str);
678213Svbart@nginx.com 
679213Svbart@nginx.com                 if (nxt_slow_path(s == NULL)) {
680213Svbart@nginx.com                     return NXT_ERROR;
681213Svbart@nginx.com                 }
682213Svbart@nginx.com 
683213Svbart@nginx.com                 break;
684213Svbart@nginx.com 
685213Svbart@nginx.com             case NXT_CONF_MAP_CSTRZ:
686213Svbart@nginx.com 
687213Svbart@nginx.com                 ptr->cstrz = nxt_str_cstrz(mp, &str);
688213Svbart@nginx.com 
689213Svbart@nginx.com                 if (nxt_slow_path(ptr->cstrz == NULL)) {
690213Svbart@nginx.com                     return NXT_ERROR;
691213Svbart@nginx.com                 }
692213Svbart@nginx.com 
693213Svbart@nginx.com                 break;
694213Svbart@nginx.com 
695213Svbart@nginx.com             default:
696213Svbart@nginx.com                 nxt_unreachable();
697106Svbart@nginx.com             }
698106Svbart@nginx.com 
699106Svbart@nginx.com             break;
700106Svbart@nginx.com 
701106Svbart@nginx.com         case NXT_CONF_MAP_PTR:
702106Svbart@nginx.com 
703106Svbart@nginx.com             ptr->v = v;
704106Svbart@nginx.com 
705106Svbart@nginx.com             break;
706106Svbart@nginx.com         }
707106Svbart@nginx.com     }
708106Svbart@nginx.com 
709106Svbart@nginx.com     return NXT_OK;
710106Svbart@nginx.com }
711106Svbart@nginx.com 
712106Svbart@nginx.com 
713106Svbart@nginx.com nxt_conf_value_t *
nxt_conf_next_object_member(nxt_conf_value_t * value,nxt_str_t * name,uint32_t * next)714106Svbart@nginx.com nxt_conf_next_object_member(nxt_conf_value_t *value, nxt_str_t *name,
715106Svbart@nginx.com     uint32_t *next)
716106Svbart@nginx.com {
717106Svbart@nginx.com     uint32_t                  n;
718106Svbart@nginx.com     nxt_conf_object_t         *object;
719106Svbart@nginx.com     nxt_conf_object_member_t  *member;
720106Svbart@nginx.com 
721116Svbart@nginx.com     if (value->type != NXT_CONF_VALUE_OBJECT) {
722106Svbart@nginx.com         return NULL;
723106Svbart@nginx.com     }
724106Svbart@nginx.com 
725106Svbart@nginx.com     n = *next;
726106Svbart@nginx.com     object = value->u.object;
727106Svbart@nginx.com 
728106Svbart@nginx.com     if (n >= object->count) {
729106Svbart@nginx.com         return NULL;
730106Svbart@nginx.com     }
731106Svbart@nginx.com 
732106Svbart@nginx.com     member = &object->members[n];
733106Svbart@nginx.com     *next = n + 1;
734106Svbart@nginx.com 
735106Svbart@nginx.com     nxt_conf_get_string(&member->name, name);
736106Svbart@nginx.com 
737106Svbart@nginx.com     return &member->value;
738106Svbart@nginx.com }
739106Svbart@nginx.com 
740106Svbart@nginx.com 
741214Svbart@nginx.com nxt_conf_value_t *
nxt_conf_get_array_element(nxt_conf_value_t * value,uint32_t index)742214Svbart@nginx.com nxt_conf_get_array_element(nxt_conf_value_t *value, uint32_t index)
743214Svbart@nginx.com {
744214Svbart@nginx.com     nxt_conf_array_t  *array;
745214Svbart@nginx.com 
746214Svbart@nginx.com     if (value->type != NXT_CONF_VALUE_ARRAY) {
747214Svbart@nginx.com         return NULL;
748214Svbart@nginx.com     }
749214Svbart@nginx.com 
750214Svbart@nginx.com     array = value->u.array;
751214Svbart@nginx.com 
752214Svbart@nginx.com     if (index >= array->count) {
753214Svbart@nginx.com         return NULL;
754214Svbart@nginx.com     }
755214Svbart@nginx.com 
756214Svbart@nginx.com     return &array->elements[index];
757214Svbart@nginx.com }
758214Svbart@nginx.com 
759214Svbart@nginx.com 
7602076Salx.manpages@gmail.com nxt_conf_value_t *
nxt_conf_get_array_element_or_itself(nxt_conf_value_t * value,uint32_t index)7612076Salx.manpages@gmail.com nxt_conf_get_array_element_or_itself(nxt_conf_value_t *value, uint32_t index)
7622076Salx.manpages@gmail.com {
7632076Salx.manpages@gmail.com     nxt_conf_array_t  *array;
7642076Salx.manpages@gmail.com 
7652076Salx.manpages@gmail.com     if (value->type != NXT_CONF_VALUE_ARRAY) {
7662076Salx.manpages@gmail.com         return (index == 0) ? value : NULL;
7672076Salx.manpages@gmail.com     }
7682076Salx.manpages@gmail.com 
7692076Salx.manpages@gmail.com     array = value->u.array;
7702076Salx.manpages@gmail.com 
7712076Salx.manpages@gmail.com     if (index >= array->count) {
7722076Salx.manpages@gmail.com         return NULL;
7732076Salx.manpages@gmail.com     }
7742076Salx.manpages@gmail.com 
7752076Salx.manpages@gmail.com     return &array->elements[index];
7762076Salx.manpages@gmail.com }
7772076Salx.manpages@gmail.com 
7782076Salx.manpages@gmail.com 
779962Sigor@sysoev.ru void
nxt_conf_array_qsort(nxt_conf_value_t * value,int (* compare)(const void *,const void *))780962Sigor@sysoev.ru nxt_conf_array_qsort(nxt_conf_value_t *value,
781962Sigor@sysoev.ru     int (*compare)(const void *, const void *))
782962Sigor@sysoev.ru {
783962Sigor@sysoev.ru     nxt_conf_array_t  *array;
784962Sigor@sysoev.ru 
785962Sigor@sysoev.ru     if (value->type != NXT_CONF_VALUE_ARRAY) {
786962Sigor@sysoev.ru         return;
787962Sigor@sysoev.ru     }
788962Sigor@sysoev.ru 
789962Sigor@sysoev.ru     array = value->u.array;
790962Sigor@sysoev.ru 
791962Sigor@sysoev.ru     nxt_qsort(array->elements, array->count, sizeof(nxt_conf_value_t), compare);
792962Sigor@sysoev.ru }
793962Sigor@sysoev.ru 
794962Sigor@sysoev.ru 
7951049Svbart@nginx.com nxt_conf_op_ret_t
nxt_conf_op_compile(nxt_mp_t * mp,nxt_conf_op_t ** ops,nxt_conf_value_t * root,nxt_str_t * path,nxt_conf_value_t * value,nxt_bool_t add)796106Svbart@nginx.com nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, nxt_conf_value_t *root,
7971049Svbart@nginx.com     nxt_str_t *path, nxt_conf_value_t *value, nxt_bool_t add)
798106Svbart@nginx.com {
799106Svbart@nginx.com     nxt_str_t                 token;
8001174Svbart@nginx.com     nxt_int_t                 ret, index;
801106Svbart@nginx.com     nxt_conf_op_t             *op, **parent;
8021047Svbart@nginx.com     nxt_conf_value_t          *node;
803106Svbart@nginx.com     nxt_conf_path_parse_t     parse;
804106Svbart@nginx.com     nxt_conf_object_member_t  *member;
805106Svbart@nginx.com 
806106Svbart@nginx.com     parse.start = path->start;
807106Svbart@nginx.com     parse.end = path->start + path->length;
808106Svbart@nginx.com     parse.last = 0;
809106Svbart@nginx.com 
810106Svbart@nginx.com     parent = ops;
811106Svbart@nginx.com 
812106Svbart@nginx.com     for ( ;; ) {
813106Svbart@nginx.com         op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t));
814106Svbart@nginx.com         if (nxt_slow_path(op == NULL)) {
8151049Svbart@nginx.com             return NXT_CONF_OP_ERROR;
816106Svbart@nginx.com         }
817106Svbart@nginx.com 
818106Svbart@nginx.com         *parent = op;
819106Svbart@nginx.com         parent = (nxt_conf_op_t **) &op->ctx;
820106Svbart@nginx.com 
8211174Svbart@nginx.com         ret = nxt_conf_path_next_token(&parse, &token);
8221174Svbart@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
8231174Svbart@nginx.com             return NXT_CONF_OP_ERROR;
8241174Svbart@nginx.com         }
825106Svbart@nginx.com 
8261048Svbart@nginx.com         switch (root->type) {
8271048Svbart@nginx.com 
8281048Svbart@nginx.com         case NXT_CONF_VALUE_OBJECT:
8291048Svbart@nginx.com             node = nxt_conf_get_object_member(root, &token, &op->index);
8301048Svbart@nginx.com             break;
8311048Svbart@nginx.com 
8321048Svbart@nginx.com         case NXT_CONF_VALUE_ARRAY:
8331048Svbart@nginx.com             index = nxt_int_parse(token.start, token.length);
8341048Svbart@nginx.com 
8351048Svbart@nginx.com             if (index < 0 || index > NXT_INT32_T_MAX) {
8361049Svbart@nginx.com                 return NXT_CONF_OP_NOT_FOUND;
8371048Svbart@nginx.com             }
8381048Svbart@nginx.com 
8391048Svbart@nginx.com             op->index = index;
8401048Svbart@nginx.com 
8411048Svbart@nginx.com             node = nxt_conf_get_array_element(root, index);
8421048Svbart@nginx.com             break;
8431048Svbart@nginx.com 
8441048Svbart@nginx.com         default:
8451048Svbart@nginx.com             node = NULL;
8461048Svbart@nginx.com         }
847106Svbart@nginx.com 
848106Svbart@nginx.com         if (parse.last) {
849106Svbart@nginx.com             break;
850106Svbart@nginx.com         }
851106Svbart@nginx.com 
8521047Svbart@nginx.com         if (node == NULL) {
8531049Svbart@nginx.com             return NXT_CONF_OP_NOT_FOUND;
854106Svbart@nginx.com         }
855106Svbart@nginx.com 
856106Svbart@nginx.com         op->action = NXT_CONF_OP_PASS;
8571047Svbart@nginx.com         root = node;
858106Svbart@nginx.com     }
859106Svbart@nginx.com 
860106Svbart@nginx.com     if (value == NULL) {
861106Svbart@nginx.com 
8621047Svbart@nginx.com         if (node == NULL) {
8631049Svbart@nginx.com             return NXT_CONF_OP_NOT_FOUND;
864106Svbart@nginx.com         }
865106Svbart@nginx.com 
866106Svbart@nginx.com         op->action = NXT_CONF_OP_DELETE;
867106Svbart@nginx.com 
8681049Svbart@nginx.com         return NXT_CONF_OP_OK;
8691049Svbart@nginx.com     }
8701049Svbart@nginx.com 
8711049Svbart@nginx.com     if (add) {
8721049Svbart@nginx.com         if (node == NULL) {
8731049Svbart@nginx.com             return NXT_CONF_OP_NOT_FOUND;
8741049Svbart@nginx.com         }
8751049Svbart@nginx.com 
8761049Svbart@nginx.com         if (node->type != NXT_CONF_VALUE_ARRAY) {
8771049Svbart@nginx.com             return NXT_CONF_OP_NOT_ALLOWED;
8781049Svbart@nginx.com         }
8791049Svbart@nginx.com 
8801049Svbart@nginx.com         op->action = NXT_CONF_OP_PASS;
8811049Svbart@nginx.com 
8821049Svbart@nginx.com         op = nxt_mp_zget(mp, sizeof(nxt_conf_op_t));
8831049Svbart@nginx.com         if (nxt_slow_path(op == NULL)) {
8841049Svbart@nginx.com             return NXT_CONF_OP_ERROR;
8851049Svbart@nginx.com         }
8861049Svbart@nginx.com 
8871049Svbart@nginx.com         *parent = op;
8881049Svbart@nginx.com 
8891049Svbart@nginx.com         op->index = node->u.array->count;
8901049Svbart@nginx.com         op->action = NXT_CONF_OP_CREATE;
8911049Svbart@nginx.com         op->ctx = value;
8921049Svbart@nginx.com 
8931049Svbart@nginx.com         return NXT_CONF_OP_OK;
894106Svbart@nginx.com     }
895106Svbart@nginx.com 
8961048Svbart@nginx.com     if (node != NULL) {
8971048Svbart@nginx.com         op->action = NXT_CONF_OP_REPLACE;
8981048Svbart@nginx.com         op->ctx = value;
8991048Svbart@nginx.com 
9001049Svbart@nginx.com         return NXT_CONF_OP_OK;
9011048Svbart@nginx.com     }
9021048Svbart@nginx.com 
9031048Svbart@nginx.com     op->action = NXT_CONF_OP_CREATE;
9041048Svbart@nginx.com 
9051048Svbart@nginx.com     if (root->type == NXT_CONF_VALUE_ARRAY) {
9061048Svbart@nginx.com         if (op->index > root->u.array->count) {
9071049Svbart@nginx.com             return NXT_CONF_OP_NOT_FOUND;
9081048Svbart@nginx.com         }
9091048Svbart@nginx.com 
9101048Svbart@nginx.com         op->ctx = value;
9111048Svbart@nginx.com 
9121048Svbart@nginx.com     } else {
913106Svbart@nginx.com         member = nxt_mp_zget(mp, sizeof(nxt_conf_object_member_t));
914106Svbart@nginx.com         if (nxt_slow_path(member == NULL)) {
9151049Svbart@nginx.com             return NXT_CONF_OP_ERROR;
916106Svbart@nginx.com         }
917106Svbart@nginx.com 
9181174Svbart@nginx.com         ret = nxt_conf_set_string_dup(&member->name, mp, &token);
9191174Svbart@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
9201174Svbart@nginx.com             return NXT_CONF_OP_ERROR;
9211174Svbart@nginx.com         }
922106Svbart@nginx.com 
923106Svbart@nginx.com         member->value = *value;
924106Svbart@nginx.com 
9251047Svbart@nginx.com         op->index = root->u.object->count;
926106Svbart@nginx.com         op->ctx = member;
927106Svbart@nginx.com     }
928106Svbart@nginx.com 
9291049Svbart@nginx.com     return NXT_CONF_OP_OK;
930106Svbart@nginx.com }
931106Svbart@nginx.com 
932106Svbart@nginx.com 
933106Svbart@nginx.com nxt_conf_value_t *
nxt_conf_clone(nxt_mp_t * mp,nxt_conf_op_t * op,nxt_conf_value_t * value)934106Svbart@nginx.com nxt_conf_clone(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *value)
935106Svbart@nginx.com {
936106Svbart@nginx.com     nxt_int_t         rc;
937106Svbart@nginx.com     nxt_conf_value_t  *copy;
938106Svbart@nginx.com 
939106Svbart@nginx.com     copy = nxt_mp_get(mp, sizeof(nxt_conf_value_t));
940106Svbart@nginx.com     if (nxt_slow_path(copy == NULL)) {
941106Svbart@nginx.com         return NULL;
942106Svbart@nginx.com     }
943106Svbart@nginx.com 
944106Svbart@nginx.com     rc = nxt_conf_copy_value(mp, op, copy, value);
945106Svbart@nginx.com 
946106Svbart@nginx.com     if (nxt_slow_path(rc != NXT_OK)) {
947106Svbart@nginx.com         return NULL;
948106Svbart@nginx.com     }
949106Svbart@nginx.com 
950106Svbart@nginx.com     return copy;
951106Svbart@nginx.com }
952106Svbart@nginx.com 
953106Svbart@nginx.com 
954106Svbart@nginx.com static nxt_int_t
nxt_conf_copy_value(nxt_mp_t * mp,nxt_conf_op_t * op,nxt_conf_value_t * dst,nxt_conf_value_t * src)955106Svbart@nginx.com nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst,
956106Svbart@nginx.com     nxt_conf_value_t *src)
957106Svbart@nginx.com {
9581048Svbart@nginx.com     if (op != NULL
9591048Svbart@nginx.com         && src->type != NXT_CONF_VALUE_ARRAY
9601048Svbart@nginx.com         && src->type != NXT_CONF_VALUE_OBJECT)
9611048Svbart@nginx.com     {
962106Svbart@nginx.com         return NXT_ERROR;
963106Svbart@nginx.com     }
964106Svbart@nginx.com 
965106Svbart@nginx.com     switch (src->type) {
966106Svbart@nginx.com 
967116Svbart@nginx.com     case NXT_CONF_VALUE_STRING:
968106Svbart@nginx.com 
969172Svbart@nginx.com         dst->u.string.start = nxt_mp_nget(mp, src->u.string.length);
970172Svbart@nginx.com         if (nxt_slow_path(dst->u.string.start == NULL)) {
971106Svbart@nginx.com             return NXT_ERROR;
972106Svbart@nginx.com         }
973106Svbart@nginx.com 
974172Svbart@nginx.com         nxt_memcpy(dst->u.string.start, src->u.string.start,
975172Svbart@nginx.com                    src->u.string.length);
976