@@ -1020,6 +1020,95 @@ ly_path_append(const struct ly_ctx *ctx, const struct ly_path *src, struct ly_pa
10201020 return ret ;
10211021}
10221022
1023+ /**
1024+ * @brief Compile deref XPath function into ly_path structure.
1025+ *
1026+ * @param[in] ctx libyang context.
1027+ * @param[in] cur_node Current (original context) node.
1028+ * @param[in] target_node The deref target schema node.
1029+ * @param[in] cur_type The currently evaluated type of deref target node.
1030+ * @param[in] top_ext Extension instance containing the definition of the data being created. It is used to find
1031+ * the top-level node inside the extension instance instead of a module. Note that this is the case not only if
1032+ * the @p ctx_node is NULL, but also if the relative path starting in @p ctx_node reaches the document root
1033+ * via double dots.
1034+ * @param[in] expr Parsed path.
1035+ * @param[in] oper Oper option (@ref path_oper_options).
1036+ * @param[in] target Target option (@ref path_target_options).
1037+ * @param[in] format Format of the path.
1038+ * @param[in] prefix_data Format-specific data for resolving any prefixes (see ::ly_resolve_prefix).
1039+ * @param[in] log Whether to generate log message or not
1040+ * @param[in,out] tok_idx Index in @p exp, is adjusted.
1041+ * @param[out] path Compiled path.
1042+ * @return LY_ERR value.
1043+ */
1044+ static LY_ERR
1045+ ly_path_compile_deref_type (const struct ly_ctx * ctx , const struct lysc_node * cur_node , const struct lysc_node * target_node ,
1046+ const struct lysc_type * cur_type , const struct lysc_ext_instance * top_ext , const struct lyxp_expr * expr , uint16_t oper , uint16_t target ,
1047+ LY_VALUE_FORMAT format , void * prefix_data , ly_bool log , uint32_t * tok_idx , struct ly_path * * path )
1048+ {
1049+ LY_ERR ret = LY_SUCCESS ;
1050+ struct lyxp_expr expr2 ;
1051+ struct ly_path * path2 = NULL ;
1052+ const struct lysc_type_union * union_type ;
1053+ const struct lysc_type_leafref * lref ;
1054+ uint32_t cur_tok_idx = * tok_idx ;
1055+ LY_ARRAY_COUNT_TYPE u ;
1056+
1057+ if (cur_type -> basetype == LY_TYPE_UNION ) {
1058+ union_type = (const struct lysc_type_union * )cur_type ;
1059+ ret = LY_EVALID ;
1060+ LY_ARRAY_FOR (union_type -> types , u ) {
1061+ * tok_idx = cur_tok_idx ;
1062+ if (ly_path_compile_deref_type (ctx , cur_node , target_node , union_type -> types [u ], top_ext , expr , oper , target , format , prefix_data , 0 , tok_idx , path ) == LY_SUCCESS ) {
1063+ ret = LY_SUCCESS ;
1064+ }
1065+ }
1066+ if (log && ret ) {
1067+ LOGVAL_PATH (ctx , cur_node , target_node , LYVE_XPATH , "Deref function target node \"%s\" is union type with no leafrefs." , target_node -> name );
1068+ }
1069+ goto cleanup ;
1070+ } else if (cur_type -> basetype != LY_TYPE_LEAFREF ) {
1071+ if (log ) {
1072+ LOGVAL_PATH (ctx , cur_node , target_node , LYVE_XPATH , "Deref function target node \"%s\" is not leafref." , target_node -> name );
1073+ }
1074+ ret = LY_EVALID ;
1075+ goto cleanup ;
1076+ }
1077+ lref = (const struct lysc_type_leafref * )cur_type ;
1078+
1079+ /* compile dereferenced leafref expression and append it to the path */
1080+ LY_CHECK_GOTO (ret = ly_path_compile_leafref (ctx , target_node , top_ext , lref -> path , oper , target , format , prefix_data ,
1081+ & path2 ), cleanup );
1082+ target_node = path2 [LY_ARRAY_COUNT (path2 ) - 1 ].node ;
1083+ LY_CHECK_GOTO (ret = ly_path_append (ctx , path2 , path ), cleanup );
1084+ ly_path_free (path2 );
1085+ path2 = NULL ;
1086+
1087+ /* properly parsed path must always continue with ')' and '/' */
1088+ assert (!lyxp_check_token (NULL , expr , * tok_idx , LYXP_TOKEN_PAR2 ));
1089+ (* tok_idx )++ ;
1090+ assert (!lyxp_check_token (NULL , expr , * tok_idx , LYXP_TOKEN_OPER_PATH ));
1091+ (* tok_idx )++ ;
1092+
1093+ /* prepare expr representing rest of the path after deref */
1094+ expr2 .tokens = & expr -> tokens [* tok_idx ];
1095+ expr2 .tok_pos = & expr -> tok_pos [* tok_idx ];
1096+ expr2 .tok_len = & expr -> tok_len [* tok_idx ];
1097+ expr2 .repeat = & expr -> repeat [* tok_idx ];
1098+ expr2 .used = expr -> used - * tok_idx ;
1099+ expr2 .size = expr -> size - * tok_idx ;
1100+ expr2 .expr = expr -> expr ;
1101+
1102+ /* compile rest of the path and append it to the path */
1103+ LY_CHECK_GOTO (ret = ly_path_compile_leafref (ctx , target_node , top_ext , & expr2 , oper , target , format , prefix_data , & path2 ),
1104+ cleanup );
1105+ LY_CHECK_GOTO (ret = ly_path_append (ctx , path2 , path ), cleanup );
1106+
1107+ cleanup :
1108+ ly_path_free (path2 );
1109+ return ret ;
1110+ }
1111+
10231112/**
10241113 * @brief Compile deref XPath function into ly_path structure.
10251114 *
@@ -1049,7 +1138,6 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *cur_node
10491138 struct ly_path * path2 = NULL ;
10501139 const struct lysc_node * node2 ;
10511140 const struct lysc_node_leaf * deref_leaf_node ;
1052- const struct lysc_type_leafref * lref ;
10531141 uint32_t begin_token ;
10541142
10551143 * path = NULL ;
@@ -1083,50 +1171,22 @@ ly_path_compile_deref(const struct ly_ctx *ctx, const struct lysc_node *cur_node
10831171 LY_CHECK_GOTO (ret = ly_path_compile_leafref (ctx , ctx_node , top_ext , & expr2 , oper , target , format , prefix_data ,
10841172 & path2 ), cleanup );
10851173 node2 = path2 [LY_ARRAY_COUNT (path2 ) - 1 ].node ;
1086- if (( node2 -> nodetype != LYS_LEAF ) && ( node2 -> nodetype != LYS_LEAFLIST ) ) {
1087- LOGVAL_PATH (ctx , cur_node , node2 , LYVE_XPATH , "Deref function target node \"%s\" is not leaf nor leaflist ." ,
1174+ if (node2 == ctx_node ) {
1175+ LOGVAL_PATH (ctx , cur_node , node2 , LYVE_XPATH , "Deref function target node \"%s\" is node itself ." ,
10881176 node2 -> name );
10891177 ret = LY_EVALID ;
10901178 goto cleanup ;
10911179 }
1092- deref_leaf_node = ( const struct lysc_node_leaf * ) node2 ;
1093- if ( deref_leaf_node -> type -> basetype != LY_TYPE_LEAFREF ) {
1094- LOGVAL_PATH ( ctx , cur_node , node2 , LYVE_XPATH , "Deref function target node \"%s\" is not leafref." , node2 -> name );
1180+ if (( node2 -> nodetype != LYS_LEAF ) && ( node2 -> nodetype != LYS_LEAFLIST )) {
1181+ LOGVAL_PATH ( ctx , cur_node , node2 , LYVE_XPATH , "Deref function target node \"%s\" is not leaf nor leaflist." ,
1182+ node2 -> name );
10951183 ret = LY_EVALID ;
10961184 goto cleanup ;
10971185 }
1098- lref = (const struct lysc_type_leafref * )deref_leaf_node -> type ;
1099- LY_CHECK_GOTO (ret = ly_path_append (ctx , path2 , path ), cleanup );
1100- ly_path_free (path2 );
1101- path2 = NULL ;
11021186
1103- /* compile dereferenced leafref expression and append it to the path */
1104- LY_CHECK_GOTO (ret = ly_path_compile_leafref (ctx , node2 , top_ext , lref -> path , oper , target , format , prefix_data ,
1105- & path2 ), cleanup );
1106- node2 = path2 [LY_ARRAY_COUNT (path2 ) - 1 ].node ;
1107- LY_CHECK_GOTO (ret = ly_path_append (ctx , path2 , path ), cleanup );
1108- ly_path_free (path2 );
1109- path2 = NULL ;
1110-
1111- /* properly parsed path must always continue with ')' and '/' */
1112- assert (!lyxp_check_token (NULL , expr , * tok_idx , LYXP_TOKEN_PAR2 ));
1113- (* tok_idx )++ ;
1114- assert (!lyxp_check_token (NULL , expr , * tok_idx , LYXP_TOKEN_OPER_PATH ));
1115- (* tok_idx )++ ;
1116-
1117- /* prepare expr representing rest of the path after deref */
1118- expr2 .tokens = & expr -> tokens [* tok_idx ];
1119- expr2 .tok_pos = & expr -> tok_pos [* tok_idx ];
1120- expr2 .tok_len = & expr -> tok_len [* tok_idx ];
1121- expr2 .repeat = & expr -> repeat [* tok_idx ];
1122- expr2 .used = expr -> used - * tok_idx ;
1123- expr2 .size = expr -> size - * tok_idx ;
1124- expr2 .expr = expr -> expr ;
1125-
1126- /* compile rest of the path and append it to the path */
1127- LY_CHECK_GOTO (ret = ly_path_compile_leafref (ctx , node2 , top_ext , & expr2 , oper , target , format , prefix_data , & path2 ),
1128- cleanup );
11291187 LY_CHECK_GOTO (ret = ly_path_append (ctx , path2 , path ), cleanup );
1188+ deref_leaf_node = (const struct lysc_node_leaf * )node2 ;
1189+ ret = ly_path_compile_deref_type (ctx , cur_node , node2 , deref_leaf_node -> type , top_ext , expr , oper , target , format , prefix_data , 1 , tok_idx , path );
11301190
11311191cleanup :
11321192 ly_path_free (path2 );
0 commit comments