schema compile CHANGE order keys at the beginning of the children list
diff --git a/src/parser_xml.c b/src/parser_xml.c
index e236b69..e6feea0 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -243,14 +243,20 @@
if (parent) {
if (prev && cur->schema->nodetype == LYS_LEAF && (cur->schema->flags & LYS_KEY)) {
/* it is key and we need to insert it into a correct place */
- struct lysc_node_leaf **keys = ((struct lysc_node_list*)parent->schema)->keys;
+ struct lysc_node *key_s;
unsigned int cur_index, key_index;
struct lyd_node *key;
- for (cur_index = 0; keys[cur_index] != (struct lysc_node_leaf*)cur->schema; ++cur_index);
- for (key = prev; !(key->schema->flags & LYS_KEY) && key->prev != prev; key = key->prev);
+ for (cur_index = 0, key_s = ((struct lysc_node_list*)parent->schema)->child;
+ key_s && key_s != cur->schema;
+ ++cur_index, key_s = key_s->next);
+ for (key = prev;
+ !(key->schema->flags & LYS_KEY) && key->prev != prev;
+ key = key->prev);
for (; key->schema->flags & LYS_KEY; key = key->prev) {
- for (key_index = 0; keys[key_index] != (struct lysc_node_leaf*)key->schema; ++key_index);
+ for (key_index = 0, key_s = ((struct lysc_node_list*)parent->schema)->child;
+ key_s && key_s != key->schema;
+ ++key_index, key_s = key_s->next);
if (key_index < cur_index) {
/* cur key is supposed to be placed after the key */
cur->next = key->next;
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 0972653..e7860cd 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -1730,10 +1730,13 @@
}
if (token[0] != '[') {
/* now we should have all the keys */
- if (LY_ARRAY_SIZE(((struct lysc_node_list*)node_s)->keys) != predicates.count) {
+ unsigned int keys_count = 0;
+ for (struct lysc_node *key = ((struct lysc_node_list*)node_s)->child;
+ key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+ keys_count++, key = key->next);
+ if (keys_count != predicates.count) {
asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - missing %u key(s) for the list instance \"%.*s\".",
- (int)value_len, value, LY_ARRAY_SIZE(((struct lysc_node_list*)node_s)->keys) - predicates.count,
- (int)(token - node_start), node_start);
+ (int)value_len, value, keys_count - predicates.count, (int)(token - node_start), node_start);
goto error;
}
}
diff --git a/src/printer_yang.c b/src/printer_yang.c
index c6851db..8736639 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -1725,11 +1725,11 @@
LY_ARRAY_FOR(list->musts, u) {
yprc_must(ctx, &list->musts[u], NULL);
}
- if (list->keys) {
+ if (!(list->flags & LYS_KEYLESS)) {
ypr_open(ctx->out, &flag);
ly_print(ctx->out, "%*skey \"", INDENT);
- LY_ARRAY_FOR(list->keys, u) {
- ly_print(ctx->out, "%s%s", u > 0 ? ", " : "", list->keys[u]->name);
+ for (struct lysc_node *key = list->child; key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY); key = key->next) {
+ ly_print(ctx->out, "%s%s", u > 0 ? ", " : "", key->name);
}
ly_print(ctx->out, "\";\n");
}
diff --git a/src/tree_data.c b/src/tree_data.c
index 27742cb..289f70c 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -566,11 +566,11 @@
iter1 = ((struct lyd_node_inner*)node1)->child;
iter2 = ((struct lyd_node_inner*)node2)->child;
- if (((struct lysc_node_list*)node1->schema)->keys && !(options & LYD_COMPARE_FULL_RECURSION)) {
+ if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
/* lists with keys, their equivalence is based on their keys */
- unsigned int u;
-
- LY_ARRAY_FOR(((struct lysc_node_list*)node1->schema)->keys, u) {
+ for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
+ key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+ key = key->next) {
if (lyd_compare(iter1, iter2, options)) {
return LY_ENOT;
}
@@ -714,15 +714,19 @@
last = lyd_dup_recursive(child, inner, last, options);
LY_CHECK_GOTO(!last, error);
}
- } else if (dup->schema->nodetype == LYS_LIST && ((struct lysc_node_list*)dup->schema)->keys) {
+ } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
/* always duplicate keys of a list */
- unsigned int u;
-
child = orig->child;
- LY_ARRAY_FOR(((struct lysc_node_list*)dup->schema)->keys, u) {
+ for (struct lysc_node *key = ((struct lysc_node_list*)dup->schema)->child;
+ key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+ key = key->next) {
if (!child) {
/* possibly not keys are present in filtered tree */
break;
+ } else if (child->schema != key) {
+ /* possibly not all keys are present in filtered tree,
+ * but there can be also some non-key nodes */
+ continue;
}
last = lyd_dup_recursive(child, inner, last, options);
child = child->next;
@@ -786,7 +790,7 @@
repeat = 0;
/* get know if there is a keyless list which we will have to rehash */
for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
- if (piter->schema->nodetype == LYS_LIST && !((struct lysc_node_list*)piter->schema)->keys) {
+ if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
keyless_parent_list = 1;
break;
}
@@ -845,7 +849,7 @@
if (keyless_parent_list) {
/* rehash */
for (; local_parent; local_parent = local_parent->parent) {
- if (local_parent->schema->nodetype == LYS_LIST && !((struct lysc_node_list*)local_parent->schema)->keys) {
+ if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
lyd_hash((struct lyd_node*)local_parent);
}
}
diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c
index 37d6337..33104cc 100644
--- a/src/tree_data_hash.c
+++ b/src/tree_data_hash.c
@@ -51,10 +51,16 @@
if (node->schema->nodetype == LYS_LIST) {
struct lyd_node_inner *list = (struct lyd_node_inner*)node;
- if (((struct lysc_node_list*)node->schema)->keys) {
+ if (!(node->schema->flags & LYS_KEYLESS)) {
/* list's hash is made of its keys */
- unsigned int keys_count = LY_ARRAY_SIZE(((struct lysc_node_list*)node->schema)->keys);
- for (iter = list->child; iter && keys_count; --keys_count, iter = iter->next) {
+ struct lysc_node *key;
+ for (key = ((struct lysc_node_list*)node->schema)->child, iter = list->child;
+ key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY) && iter;
+ key = key->next, iter = iter->next) {
+ for ( ; iter && iter->schema != key; iter = iter->next);
+ if (!iter) {
+ break;
+ }
int dynamic = 0;
struct lysc_type *type = ((struct lysc_node_leaf*)iter->schema)->type;
const char *value = type->plugin->print(&((struct lyd_node_term*)iter)->value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 004a195..9c3346f 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -462,6 +462,7 @@
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* 10 LYS_SET_DFLT | | |x|x| | |x| | | | | | | | |
* LYS_ISENUM | | | | | | | | | | | | | | |x|
+ * LYS_KEYLESS | | | | |x| | | | | | | | | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* 11 LYS_SET_UNITS | | |x|x| | | | | | | | | | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -494,6 +495,7 @@
#define LYS_PRESENCE 0x80 /**< flag for presence property of a container, applicable only to ::lysc_node_container */
#define LYS_UNIQUE 0x80 /**< flag for leafs being part of a unique set, applicable only to ::lysc_node_leaf */
#define LYS_KEY 0x100 /**< flag for leafs being a key of a list, applicable only to ::lysc_node_leaf */
+#define LYS_KEYLESS 0x200 /**< flag for list without any key, applicable only to ::lysc_node_list */
#define LYS_FENABLED 0x100 /**< feature enabled flag, applicable only to ::lysc_feature */
#define LYS_ORDBY_SYSTEM 0x80 /**< ordered-by user lists, applicable only to ::lysc_node_leaflist/::lysp_node_leaflist and
::lysc_node_list/::lysp_node_list */
@@ -1322,7 +1324,6 @@
struct lysc_action *actions; /**< list of actions ([sized array](@ref sizedarrays)) */
struct lysc_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
- struct lysc_node_leaf **keys; /**< list of pointers to the keys ([sized array](@ref sizedarrays)) */
struct lysc_node_leaf ***uniques; /**< list of sized arrays of pointers to the unique nodes ([sized array](@ref sizedarrays)) */
uint32_t min; /**< min-elements constraint */
uint32_t max; /**< max-elements constraint */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 9d1639d..bea32c1 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -2107,7 +2107,7 @@
const struct lysc_node *src_node, *dst_node;
const char *path_key_expr, *pke_start, *src, *src_prefix, *dst, *dst_prefix;
size_t src_len, src_prefix_len, dst_len, dst_prefix_len;
- unsigned int dest_parent_times, c, u;
+ unsigned int dest_parent_times, c;
const char *start, *end, *pke_end;
struct ly_set keys = {0};
int i;
@@ -2167,10 +2167,11 @@
mod = start_node->module;
}
src_node = NULL;
- if (context_node->keys) {
- for (u = 0; u < LY_ARRAY_SIZE(context_node->keys); ++u) {
- if (!strncmp(src, context_node->keys[u]->name, src_len) && context_node->keys[u]->name[src_len] == '\0') {
- src_node = (const struct lysc_node*)context_node->keys[u];
+ if (!(context_node->flags & LYS_KEYLESS)) {
+ struct lysc_node *key;
+ for (key = context_node->child; key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY); key = key->next) {
+ if (!strncmp(src, key->name, src_len) && key->name[src_len] == '\0') {
+ src_node = key;
break;
}
}
@@ -3785,7 +3786,7 @@
struct lysp_node_list *list_p = (struct lysp_node_list*)node_p;
struct lysc_node_list *list = (struct lysc_node_list*)node;
struct lysp_node *child_p;
- struct lysc_node_leaf **key;
+ struct lysc_node_leaf *key, *prev_key = NULL;
size_t len;
unsigned int u;
const char *keystr, *delim;
@@ -3811,6 +3812,10 @@
/* find all the keys (must be direct children) */
keystr = list_p->key;
+ if (!keystr) {
+ /* keyless list */
+ list->flags |= LYS_KEYLESS;
+ }
while (keystr) {
delim = strpbrk(keystr, " \t\n");
if (delim) {
@@ -3823,42 +3828,41 @@
}
/* key node must be present */
- LY_ARRAY_NEW_RET(ctx->ctx, list->keys, key, LY_EMEM);
- *key = (struct lysc_node_leaf*)lys_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE | LYS_GETNEXT_NOSTATECHECK);
- if (!(*key)) {
+ key = (struct lysc_node_leaf*)lys_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE | LYS_GETNEXT_NOSTATECHECK);
+ if (!(key)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
"The list's key \"%.*s\" not found.", len, keystr);
return LY_EVALID;
}
/* keys must be unique */
- for(u = 0; u < LY_ARRAY_SIZE(list->keys) - 1; ++u) {
- if (*key == list->keys[u]) {
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
- "Duplicated key identifier \"%.*s\".", len, keystr);
- return LY_EVALID;
- }
+ if (key->flags & LYS_KEY) {
+ /* the node was already marked as a key */
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Duplicated key identifier \"%.*s\".", len, keystr);
+ return LY_EVALID;
}
- lysc_update_path(ctx, (struct lysc_node*)list, (*key)->name);
+
+ lysc_update_path(ctx, (struct lysc_node*)list, key->name);
/* key must have the same config flag as the list itself */
- if ((list->flags & LYS_CONFIG_MASK) != ((*key)->flags & LYS_CONFIG_MASK)) {
+ if ((list->flags & LYS_CONFIG_MASK) != (key->flags & LYS_CONFIG_MASK)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Key of the configuration list must not be status leaf.");
return LY_EVALID;
}
if (ctx->mod_def->version < LYS_VERSION_1_1) {
/* YANG 1.0 denies key to be of empty type */
- if ((*key)->type->basetype == LY_TYPE_EMPTY) {
+ if (key->type->basetype == LY_TYPE_EMPTY) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"List's key cannot be of \"empty\" type until it is in YANG 1.1 module.");
return LY_EVALID;
}
} else {
/* when and if-feature are illegal on list keys */
- if ((*key)->when) {
+ if (key->when) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"List's key must not have any \"when\" statement.");
return LY_EVALID;
}
- if ((*key)->iffeatures) {
+ if (key->iffeatures) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"List's key must not have any \"if-feature\" statement.");
return LY_EVALID;
@@ -3867,20 +3871,58 @@
/* check status */
LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
- (*key)->flags, (*key)->module, (*key)->name));
+ key->flags, key->module, key->name));
/* ignore default values of the key */
- if ((*key)->dflt) {
- (*key)->dflt->realtype->plugin->free(ctx->ctx, (*key)->dflt);
- lysc_type_free(ctx->ctx, (*key)->dflt->realtype);
- free((*key)->dflt);
- (*key)->dflt = NULL;
- (*key)->dflt_mod = NULL;
+ if (key->dflt) {
+ key->dflt->realtype->plugin->free(ctx->ctx, key->dflt);
+ lysc_type_free(ctx->ctx, key->dflt->realtype);
+ free(key->dflt);
+ key->dflt = NULL;
+ key->dflt_mod = NULL;
}
/* mark leaf as key */
- (*key)->flags |= LYS_KEY;
+ key->flags |= LYS_KEY;
+
+ /* move it to the correct position */
+ if ((prev_key && (struct lysc_node*)prev_key != key->prev) || (!prev_key && key->prev->next)) {
+ /* fix links in closest previous siblings of the key */
+ if (key->next) {
+ key->next->prev = key->prev;
+ } else {
+ /* last child */
+ list->child->prev = key->prev;
+ }
+ if (key->prev->next) {
+ key->prev->next = key->next;
+ }
+ /* fix links in the key */
+ if (prev_key) {
+ key->prev = (struct lysc_node*)prev_key;
+ key->next = prev_key->next;
+ } else {
+ key->prev = list->child->prev;
+ key->next = list->child;
+ }
+ /* fix links in closes future siblings of the key */
+ if (prev_key) {
+ if (prev_key->next) {
+ prev_key->next->prev = (struct lysc_node*)key;
+ } else {
+ list->child->prev = (struct lysc_node*)key;
+ }
+ prev_key->next = (struct lysc_node*)key;
+ } else {
+ list->child->prev = (struct lysc_node*)key;
+ }
+ /* fix links in parent */
+ if (!key->prev->next) {
+ list->child = (struct lysc_node*)key;
+ }
+ }
/* next key value */
+ prev_key = key;
keystr = delim;
lysc_update_path(ctx, NULL, NULL);
}
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 8383c19..adbc70b 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -731,7 +731,6 @@
}
FREE_ARRAY(ctx, node->musts, lysc_must_free);
- LY_ARRAY_FREE(node->keys);
LY_ARRAY_FOR(node->uniques, u) {
LY_ARRAY_FREE(node->uniques[u]);
}