@@ -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 */
39203920static 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)
72607278static int
72617279resolve_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 ) {
0 commit comments