Configuration: support for manipulations of array elements.

Now PUT and DELETE operations also work on elements.
This closes #242 issue on GitHub.
This commit is contained in:
Valentin Bartenev 2019-04-24 20:31:00 +03:00
parent 30768b7b3c
commit 4d35a7bbac

View file

@ -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,27 +893,7 @@ nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst,
break;
case NXT_CONF_VALUE_ARRAY:
size = sizeof(nxt_conf_array_t)
+ src->u.array->count * sizeof(nxt_conf_value_t);
dst->u.array = nxt_mp_get(mp, size);
if (nxt_slow_path(dst->u.array == NULL)) {
return NXT_ERROR;
}
dst->u.array->count = src->u.array->count;
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]);
if (nxt_slow_path(rc != NXT_OK)) {
return NXT_ERROR;
}
}
break;
return nxt_conf_copy_array(mp, op, dst, src);
case NXT_CONF_VALUE_OBJECT:
return nxt_conf_copy_object(mp, op, dst, src);
@ -892,6 +902,108 @@ nxt_conf_copy_value(nxt_mp_t *mp, nxt_conf_op_t *op, nxt_conf_value_t *dst,
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--;
}
}
size = sizeof(nxt_conf_array_t) + count * sizeof(nxt_conf_value_t);
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++;
}
if (pass_op != NULL) {
pass_op = NULL;
continue;
}
if (op != NULL) {
switch (op->action) {
case NXT_CONF_OP_PASS:
pass_op = op->ctx;
index++;
break;
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;
}