summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/nxt_conf.c170
1 files changed, 141 insertions, 29 deletions
diff --git a/src/nxt_conf.c b/src/nxt_conf.c
index 5ec86cd4..fd6a62f5 100644
--- a/src/nxt_conf.c
+++ b/src/nxt_conf.c
@@ -112,6 +112,8 @@ static void nxt_conf_json_parse_error(nxt_conf_json_error_t *error, u_char *pos,
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);
+static nxt_int_t nxt_conf_copy_array(nxt_mp_t *mp, nxt_conf_op_t *op,
+ nxt_conf_value_t *dst, nxt_conf_value_t *src);
static nxt_int_t nxt_conf_copy_object(nxt_mp_t *mp, nxt_conf_op_t *op,
nxt_conf_value_t *dst, nxt_conf_value_t *src);
@@ -740,6 +742,7 @@ 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_str_t token;
+ nxt_int_t index;
nxt_conf_op_t *op, **parent;
nxt_conf_value_t *node;
nxt_conf_path_parse_t parse;
@@ -762,7 +765,27 @@ nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, nxt_conf_value_t *root,
nxt_conf_path_next_token(&parse, &token);
- node = nxt_conf_get_object_member(root, &token, &op->index);
+ switch (root->type) {
+
+ case NXT_CONF_VALUE_OBJECT:
+ node = nxt_conf_get_object_member(root, &token, &op->index);
+ break;
+
+ case NXT_CONF_VALUE_ARRAY:
+ index = nxt_int_parse(token.start, token.length);
+
+ if (index < 0 || index > NXT_INT32_T_MAX) {
+ return NXT_DECLINED;
+ }
+
+ op->index = index;
+
+ node = nxt_conf_get_array_element(root, index);
+ break;
+
+ default:
+ node = NULL;
+ }
if (parse.last) {
break;
@@ -787,8 +810,23 @@ nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, nxt_conf_value_t *root,
return NXT_OK;
}
- if (node == NULL) {
+ if (node != NULL) {
+ op->action = NXT_CONF_OP_REPLACE;
+ op->ctx = value;
+
+ return NXT_OK;
+ }
+
+ op->action = NXT_CONF_OP_CREATE;
+
+ if (root->type == NXT_CONF_VALUE_ARRAY) {
+ if (op->index > root->u.array->count) {
+ return NXT_DECLINED;
+ }
+
+ op->ctx = value;
+ } else {
member = nxt_mp_zget(mp, sizeof(nxt_conf_object_member_t));
if (nxt_slow_path(member == NULL)) {
return NXT_ERROR;
@@ -799,12 +837,7 @@ nxt_conf_op_compile(nxt_mp_t *mp, nxt_conf_op_t **ops, nxt_conf_value_t *root,
member->value = *value;
op->index = root->u.object->count;
- op->action = NXT_CONF_OP_CREATE;
op->ctx = member;
-
- } else {
- op->action = NXT_CONF_OP_REPLACE;
- op->ctx = value;
}
return NXT_OK;
@@ -836,16 +869,13 @@ 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)
{
- size_t size;
- nxt_int_t rc;
- nxt_uint_t n;
-
- if (op != NULL && src->type != NXT_CONF_VALUE_OBJECT) {
+ if (op != NULL
+ && src->type != NXT_CONF_VALUE_ARRAY
+ && src->type != NXT_CONF_VALUE_OBJECT)
+ {
return NXT_ERROR;
}
- dst->type = src->type;
-
switch (src->type) {
case NXT_CONF_VALUE_STRING:
@@ -863,34 +893,116 @@ nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst,
break;
case NXT_CONF_VALUE_ARRAY:
+ return nxt_conf_copy_array(mp, op, dst, src);
- size = sizeof(nxt_conf_array_t)
- + src->u.array->count * sizeof(nxt_conf_value_t);
+ case NXT_CONF_VALUE_OBJECT:
+ return nxt_conf_copy_object(mp, op, dst, src);
- dst->u.array = nxt_mp_get(mp, size);
- if (nxt_slow_path(dst->u.array == NULL)) {
- return NXT_ERROR;
+ default:
+ dst->u = src->u;
+ }
+
+ dst->type = src->type;
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_conf_copy_array(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst,
+ nxt_conf_value_t *src)
+{
+ size_t size;
+ nxt_int_t rc;
+ nxt_uint_t s, d, count, index;
+ nxt_conf_op_t *pass_op;
+ nxt_conf_value_t *value;
+
+ count = src->u.array->count;
+
+ if (op != NULL) {
+ if (op->action == NXT_CONF_OP_CREATE) {
+ count++;
+
+ } else if (op->action == NXT_CONF_OP_DELETE) {
+ count--;
}
+ }
- dst->u.array->count = src->u.array->count;
+ size = sizeof(nxt_conf_array_t) + count * sizeof(nxt_conf_value_t);
- for (n = 0; n < src->u.array->count; n++) {
- rc = nxt_conf_copy_value(mp, NULL, &dst->u.array->elements[n],
- &src->u.array->elements[n]);
+ dst->u.array = nxt_mp_get(mp, size);
+ if (nxt_slow_path(dst->u.array == NULL)) {
+ return NXT_ERROR;
+ }
+
+ dst->u.array->count = count;
+
+ s = 0;
+ d = 0;
+
+ pass_op = NULL;
+ /*
+ * This initialization is needed only to
+ * suppress a warning on GCC 4.8 and older.
+ */
+ index = 0;
+
+ do {
+ if (pass_op == NULL) {
+ index = (op == NULL) ? src->u.array->count : op->index;
+ }
+
+ while (s != index) {
+ rc = nxt_conf_copy_value(mp, pass_op, &dst->u.array->elements[d],
+ &src->u.array->elements[s]);
if (nxt_slow_path(rc != NXT_OK)) {
return NXT_ERROR;
}
+
+ s++;
+ d++;
}
- break;
+ if (pass_op != NULL) {
+ pass_op = NULL;
+ continue;
+ }
- case NXT_CONF_VALUE_OBJECT:
- return nxt_conf_copy_object(mp, op, dst, src);
+ if (op != NULL) {
+ switch (op->action) {
+ case NXT_CONF_OP_PASS:
+ pass_op = op->ctx;
+ index++;
+ break;
- default:
- dst->u = src->u;
- }
+ case NXT_CONF_OP_CREATE:
+ value = op->ctx;
+ dst->u.array->elements[d] = *value;
+
+ d++;
+ break;
+
+ case NXT_CONF_OP_REPLACE:
+ value = op->ctx;
+ dst->u.array->elements[d] = *value;
+
+ s++;
+ d++;
+ break;
+
+ case NXT_CONF_OP_DELETE:
+ s++;
+ break;
+ }
+
+ op = NULL;
+ }
+
+ } while (d != count);
+
+ dst->type = src->type;
return NXT_OK;
}