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:
parent
30768b7b3c
commit
4d35a7bbac
1 changed files with 147 additions and 35 deletions
182
src/nxt_conf.c
182
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,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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue