Skip to content

Commit 21f5a09

Browse files
committed
Merge branch 'devel'
2 parents 6c78f83 + 0fc888e commit 21f5a09

7 files changed

Lines changed: 179 additions & 112 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ set(CMAKE_MACOSX_RPATH TRUE)
1111
# set version
1212
set(LIBYANG_MAJOR_VERSION 0)
1313
set(LIBYANG_MINOR_VERSION 13)
14-
set(LIBYANG_MICRO_VERSION 62)
14+
set(LIBYANG_MICRO_VERSION 63)
1515
set(LIBYANG_VERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION}.${LIBYANG_MICRO_VERSION})
1616
set(LIBYANG_SOVERSION ${LIBYANG_MAJOR_VERSION}.${LIBYANG_MINOR_VERSION})
1717
configure_file(${PROJECT_SOURCE_DIR}/src/libyang.h.in ${PROJECT_SOURCE_DIR}/src/libyang.h)

src/resolve.c

Lines changed: 136 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -3910,142 +3910,160 @@ resolve_schema_leafref(const char *path, struct lys_node *parent, const struct l
39103910
*
39113911
* @param[in] prev_mod Previous module to use in case there is no prefix.
39123912
* @param[in] pred Predicate to use.
3913-
* @param[in,out] node_match Nodes matching the restriction without
3914-
* the predicate. Nodes not satisfying
3915-
* the predicate are removed.
3913+
* @param[in,out] node Node matching the restriction without
3914+
* the predicate. If it does not satisfy the predicate,
3915+
* it is set to NULL.
39163916
*
39173917
* @return Number of characters successfully parsed,
39183918
* positive on success, negative on failure.
39193919
*/
39203920
static int
3921-
resolve_instid_predicate(const struct lys_module *prev_mod, const char *pred, struct unres_data *node_match)
3921+
resolve_instid_predicate(const struct lys_module *prev_mod, const char *pred, struct lyd_node **node, int cur_idx)
39223922
{
3923-
/* ... /node[target = value] ... */
3924-
struct lyd_node *target;
3923+
/* ... /node[key=value] ... */
3924+
struct lyd_node_leaf_list *key;
3925+
struct lys_node_leaf **list_keys = NULL;
3926+
struct lys_node_list *slist;
39253927
const char *model, *name, *value;
3926-
int mod_len, nam_len, val_len, i, has_predicate, cur_idx, idx, parsed, pred_iter, k;
3927-
uint32_t j;
3928+
int mod_len, nam_len, val_len, i, has_predicate, parsed;
39283929

3929-
assert(pred && node_match->count);
3930+
assert(pred && node && *node);
39303931

3931-
idx = -1;
39323932
parsed = 0;
3933-
3934-
pred_iter = -1;
39353933
do {
3936-
if ((i = parse_predicate(pred, &model, &mod_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1) {
3937-
return -parsed+i;
3934+
if ((i = parse_predicate(pred + parsed, &model, &mod_len, &name, &nam_len, &value, &val_len, &has_predicate)) < 1) {
3935+
return -parsed + i;
39383936
}
39393937
parsed += i;
3940-
pred += i;
39413938

3942-
if (isdigit(name[0])) {
3943-
/* pos */
3944-
assert(!value);
3945-
idx = atoi(name);
3946-
} else if (name[0] != '.') {
3947-
/* list keys */
3948-
if (pred_iter < 0) {
3949-
pred_iter = 1;
3950-
} else {
3951-
++pred_iter;
3939+
/* target */
3940+
if (name[0] == '.') {
3941+
/* leaf-list value */
3942+
if ((*node)->schema->nodetype != LYS_LEAFLIST) {
3943+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects leaf-list, but have %s \"%s\".",
3944+
strnodetype((*node)->schema->nodetype), (*node)->schema->name);
3945+
parsed = -1;
3946+
goto cleanup;
39523947
}
3953-
}
39543948

3955-
for (cur_idx = 1, j = 0; j < node_match->count; ++cur_idx) {
3956-
/* target */
3957-
if (name[0] == '.') {
3958-
/* leaf-list value */
3959-
if (node_match->node[j]->schema->nodetype != LYS_LEAFLIST) {
3960-
goto remove_instid;
3961-
}
3949+
/* check the value */
3950+
if (strncmp(((struct lyd_node_leaf_list *)*node)->value_str, value, val_len)
3951+
|| ((struct lyd_node_leaf_list *)*node)->value_str[val_len]) {
3952+
*node = NULL;
3953+
goto cleanup;
3954+
}
39623955

3963-
target = node_match->node[j];
3964-
/* check the value */
3965-
if (strncmp(((struct lyd_node_leaf_list *)target)->value_str, value, val_len)
3966-
|| ((struct lyd_node_leaf_list *)target)->value_str[val_len]) {
3967-
goto remove_instid;
3968-
}
3956+
} else if (isdigit(name[0])) {
3957+
assert(!value);
39693958

3970-
} else if (!value) {
3971-
/* keyless list position */
3972-
if ((node_match->node[j]->schema->nodetype != LYS_LIST)
3973-
|| ((struct lys_node_list *)node_match->node[j]->schema)->keys) {
3974-
goto remove_instid;
3975-
}
3959+
/* keyless list position */
3960+
if ((*node)->schema->nodetype != LYS_LIST) {
3961+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects list, but have %s \"%s\".",
3962+
strnodetype((*node)->schema->nodetype), (*node)->schema->name);
3963+
parsed = -1;
3964+
goto cleanup;
3965+
}
39763966

3977-
if (idx != cur_idx) {
3978-
goto remove_instid;
3979-
}
3967+
if (((struct lys_node_list *)(*node)->schema)->keys) {
3968+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects list without keys, but have list \"%s\".",
3969+
(*node)->schema->name);
3970+
parsed = -1;
3971+
goto cleanup;
3972+
}
39803973

3981-
} else {
3982-
/* list key value */
3983-
if (node_match->node[j]->schema->nodetype != LYS_LIST) {
3984-
goto remove_instid;
3985-
}
3974+
/* check the index */
3975+
if (atoi(name) != cur_idx) {
3976+
*node = NULL;
3977+
goto cleanup;
3978+
}
39863979

3987-
/* find the key leaf */
3988-
for (k = 1, target = node_match->node[j]->child; target && (k < pred_iter); k++, target = target->next);
3989-
if (!target) {
3990-
goto remove_instid;
3991-
}
3992-
if ((struct lys_node_leaf *)target->schema !=
3993-
((struct lys_node_list *)node_match->node[j]->schema)->keys[pred_iter - 1]) {
3994-
goto remove_instid;
3980+
} else {
3981+
/* list key value */
3982+
if ((*node)->schema->nodetype != LYS_LIST) {
3983+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects list, but have %s \"%s\".",
3984+
strnodetype((*node)->schema->nodetype), (*node)->schema->name);
3985+
parsed = -1;
3986+
goto cleanup;
3987+
}
3988+
slist = (struct lys_node_list *)(*node)->schema;
3989+
3990+
/* prepare key array */
3991+
if (!list_keys) {
3992+
list_keys = malloc(slist->keys_size * sizeof *list_keys);
3993+
LY_CHECK_ERR_RETURN(!list_keys, LOGMEM, -1);
3994+
for (i = 0; i < slist->keys_size; ++i) {
3995+
list_keys[i] = slist->keys[i];
39953996
}
3997+
}
39963998

3997-
/* check name */
3998-
if (strncmp(target->schema->name, name, nam_len) || target->schema->name[nam_len]) {
3999-
goto remove_instid;
3999+
/* find the schema key leaf */
4000+
for (i = 0; i < slist->keys_size; ++i) {
4001+
if (list_keys[i] && !strncmp(list_keys[i]->name, name, nam_len) && !list_keys[i]->name[nam_len]) {
4002+
break;
40004003
}
4004+
}
4005+
if (i == slist->keys_size) {
4006+
/* this list has no such key */
4007+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects list with the key \"%.*s\","
4008+
" but list \"%s\" does not define it.", nam_len, name, slist->name);
4009+
parsed = -1;
4010+
goto cleanup;
4011+
}
40014012

4002-
/* check module */
4003-
if (model) {
4004-
if (strncmp(target->schema->module->name, model, mod_len)
4005-
|| target->schema->module->name[mod_len]) {
4006-
goto remove_instid;
4007-
}
4008-
} else {
4009-
if (target->schema->module != prev_mod) {
4010-
goto remove_instid;
4011-
}
4013+
/* check module */
4014+
if (model) {
4015+
if (strncmp(list_keys[i]->module->name, model, mod_len) || list_keys[i]->module->name[mod_len]) {
4016+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects key \"%s\" from module \"%.*s\", not \"%s\".",
4017+
list_keys[i]->name, model, mod_len, list_keys[i]->module->name);
4018+
parsed = -1;
4019+
goto cleanup;
4020+
}
4021+
} else {
4022+
if (list_keys[i]->module != prev_mod) {
4023+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier expects key \"%s\" from module \"%s\", not \"%s\".",
4024+
list_keys[i]->name, prev_mod->name, list_keys[i]->module->name);
4025+
parsed = -1;
4026+
goto cleanup;
40124027
}
4028+
}
40134029

4014-
/* check the value */
4015-
if (strncmp(((struct lyd_node_leaf_list *)target)->value_str, value, val_len)
4016-
|| ((struct lyd_node_leaf_list *)target)->value_str[val_len]) {
4017-
goto remove_instid;
4030+
/* find the actual data key */
4031+
for (key = (struct lyd_node_leaf_list *)(*node)->child; key; key = (struct lyd_node_leaf_list *)key->next) {
4032+
if (key->schema == (struct lys_node *)list_keys[i]) {
4033+
break;
40184034
}
40194035
}
4036+
if (!key) {
4037+
/* list instance is missing a key? definitely should not happen */
4038+
LOGINT;
4039+
parsed = -1;
4040+
goto cleanup;
4041+
}
40204042

4021-
/* instid is ok, continue check with the next one */
4022-
++j;
4023-
continue;
4043+
/* check the value */
4044+
if (strncmp(key->value_str, value, val_len) || key->value_str[val_len]) {
4045+
*node = NULL;
4046+
goto cleanup;
4047+
}
40244048

4025-
remove_instid:
4026-
/* does not fulfill conditions, remove instid record */
4027-
unres_data_del(node_match, j);
4049+
/* everything is fine, mark this key as resolved */
4050+
list_keys[i] = NULL;
40284051
}
40294052
} while (has_predicate);
40304053

40314054
/* check that all list keys were specified */
4032-
if ((pred_iter > 0) && node_match->count) {
4033-
j = 0;
4034-
while (j < node_match->count) {
4035-
assert(node_match->node[j]->schema->nodetype == LYS_LIST);
4036-
if (pred_iter < ((struct lys_node_list *)node_match->node[j]->schema)->keys_size) {
4037-
/* not enough predicates, just remove the list instance */
4038-
unres_data_del(node_match, j);
4039-
} else {
4040-
++j;
4055+
if (list_keys) {
4056+
for (i = 0; i < slist->keys_size; ++i) {
4057+
if (list_keys[i]) {
4058+
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier is missing list key \"%s\".", list_keys[i]->name);
4059+
parsed = -1;
4060+
goto cleanup;
40414061
}
40424062
}
4043-
4044-
if (!node_match->count) {
4045-
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Instance identifier is missing some list keys.");
4046-
}
40474063
}
40484064

4065+
cleanup:
4066+
free(list_keys);
40494067
return parsed;
40504068
}
40514069

@@ -7260,10 +7278,10 @@ check_instid_ext_dep(const struct lys_node *sleaf, const char *json_instid)
72607278
static int
72617279
resolve_instid(struct lyd_node *data, const char *path, int req_inst, struct lyd_node **ret)
72627280
{
7263-
int i = 0, j;
7281+
int i = 0, j, parsed, cur_idx;
72647282
const struct lys_module *mod, *prev_mod = NULL;
72657283
struct ly_ctx *ctx = data->schema->module->ctx;
7266-
struct lyd_node *root;
7284+
struct lyd_node *root, *node;
72677285
const char *model, *name;
72687286
char *str;
72697287
int mod_len, name_len, has_predicate;
@@ -7323,17 +7341,27 @@ resolve_instid(struct lyd_node *data, const char *path, int req_inst, struct lyd
73237341

73247342
if (has_predicate) {
73257343
/* we have predicate, so the current results must be list or leaf-list */
7326-
j = resolve_instid_predicate(mod, &path[i], &node_match);
7327-
if (j < 1) {
7328-
LOGVAL(LYE_INPRED, LY_VLOG_LYD, data, &path[i-j]);
7329-
goto error;
7330-
}
7331-
i += j;
7344+
j = 0;
7345+
/* index of the current node (for lists with position predicates) */
7346+
cur_idx = 1;
7347+
while (j < (signed)node_match.count) {
7348+
node = node_match.node[j];
7349+
parsed = resolve_instid_predicate(mod, &path[i], &node, cur_idx);
7350+
if (parsed < 1) {
7351+
LOGVAL(LYE_INPRED, LY_VLOG_LYD, data, &path[i - parsed]);
7352+
goto error;
7353+
}
73327354

7333-
if (!node_match.count) {
7334-
/* no instance exists */
7335-
break;
7355+
if (!node) {
7356+
/* current node does not satisfy the predicate */
7357+
unres_data_del(&node_match, j);
7358+
} else {
7359+
++j;
7360+
}
7361+
++cur_idx;
73367362
}
7363+
7364+
i += parsed;
73377365
} else if (node_match.count) {
73387366
/* check that we are not addressing lists */
73397367
for (j = 0; (unsigned)j < node_match.count; ++j) {

tests/data/files/all-data.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"leaf13": "aGVsbG8h",
1616
"leaf14": "ident2",
1717
"leaf15": [null],
18-
"leaf16": "/all:cont1/all:leaf2",
18+
"leaf16": "/all:cont1/leaf2",
1919
"leaf17": "ident2",
2020
"list1": [
2121
{
@@ -34,6 +34,13 @@
3434
"aaa",
3535
"aaaa",
3636
"aaaaaaaaa"
37-
]
37+
],
38+
"list2": [
39+
{
40+
"leaf27": 3,
41+
"leaf28": 4
42+
}
43+
],
44+
"leaf29": "/all:cont1/list2[leaf28='4'][leaf27='3']"
3845
}
3946
}

tests/data/files/all-data.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@
3333
<llist1>aaa</llist1>
3434
<llist1>aaaa</llist1>
3535
<llist1>aaaaaaaaa</llist1>
36+
<list2>
37+
<leaf27>3</leaf27>
38+
<leaf28>4</leaf28>
39+
</list2>
40+
<leaf29 xmlns:all_mod="urn:all">/all_mod:cont1/all_mod:list2[all_mod:leaf28='4'][all_mod:leaf27='3']</leaf29>
3641
</cont1>

tests/data/files/all.yang

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,21 @@ module all {
199199
ordered-by user;
200200
}
201201

202+
list list2 {
203+
key "leaf27 leaf28";
204+
leaf leaf27 {
205+
type uint8;
206+
}
207+
208+
leaf leaf28 {
209+
type uint8;
210+
}
211+
}
212+
213+
leaf leaf29 {
214+
type instance-identifier;
215+
}
216+
202217
leaf leaf23 {
203218
type empty;
204219
}

tests/data/files/all.yin

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,18 @@
175175
<type name="tdef1"/>
176176
<ordered-by value="user"/>
177177
</leaf-list>
178+
<list name="list2">
179+
<key value="leaf27 leaf28"/>
180+
<leaf name="leaf27">
181+
<type name="uint8"/>
182+
</leaf>
183+
<leaf name="leaf28">
184+
<type name="uint8"/>
185+
</leaf>
186+
</list>
187+
<leaf name="leaf29">
188+
<type name="instance-identifier"/>
189+
</leaf>
178190
<leaf name="leaf23">
179191
<type name="empty"/>
180192
</leaf>

0 commit comments

Comments
 (0)