@@ -3075,117 +3075,220 @@ lyd_diff_reverse_metadata_diff(struct lyd_node *node)
30753075 return rc ;
30763076}
30773077
3078- LIBYANG_API_DEF LY_ERR
3079- lyd_diff_reverse_all (const struct lyd_node * src_diff , struct lyd_node * * diff )
3078+ /**
3079+ * @brief Process a user-ordered node for a reverse diff.
3080+ *
3081+ * @param[in] node Reversed diff user-ordered node. NULL if only collected nodes should be reversed.
3082+ * @param[in,out] schema_p Current siblings user-ordered schema node.
3083+ * @param[in,out] nodes_p Collected diff nodes of @p schema_p whose order is to be reversed.
3084+ * @return LY_ERR value.
3085+ */
3086+ static LY_ERR
3087+ lyd_diff_reverse_userord (struct lyd_node * node , const struct lysc_node * * schema_p , struct lyd_node * * * nodes_p )
30803088{
30813089 LY_ERR rc = LY_SUCCESS ;
3082- const struct lys_module * mod = NULL ;
3083- struct lyd_node * root , * elem , * iter ;
3084- enum lyd_diff_op op ;
3090+ struct lyd_node * * ptr , * anchor ;
3091+ LY_ARRAY_COUNT_TYPE u ;
30853092
3086- LY_CHECK_ARG_RET ( NULL , diff , LY_EINVAL );
3093+ assert ( node || * schema_p );
30873094
3088- if (!src_diff ) {
3089- * diff = NULL ;
3090- return LY_SUCCESS ;
3095+ /* all the schema node instances were collected, reverse their order */
3096+ if (!node || (* schema_p && (node -> schema != * schema_p ))) {
3097+ /* unlink all the nodes except for the last */
3098+ for (u = 0 ; u < LY_ARRAY_COUNT (* nodes_p ) - 1 ; ++ u ) {
3099+ lyd_unlink_tree ((* nodes_p )[u ]);
3100+ }
3101+
3102+ /* use the last as the anchor, becomes the first node */
3103+ anchor = (* nodes_p )[u ];
3104+
3105+ /* link them in reverse order back */
3106+ if (u ) {
3107+ do {
3108+ -- u ;
3109+ LY_CHECK_GOTO (rc = lyd_insert_after (anchor , (* nodes_p )[u ]), cleanup );
3110+ } while (u );
3111+ }
3112+
3113+ /* clear the collected nodes */
3114+ * schema_p = NULL ;
3115+ LY_ARRAY_FREE (* nodes_p );
3116+ * nodes_p = NULL ;
30913117 }
30923118
3093- /* duplicate diff */
3094- LY_CHECK_RET (lyd_dup_siblings (src_diff , NULL , LYD_DUP_RECURSIVE | LYD_DUP_NO_LYDS , diff ));
3095-
3096- LY_LIST_FOR (* diff , root ) {
3097- LYD_TREE_DFS_BEGIN (root , elem ) {
3098- /* skip all keys */
3099- if (!lysc_is_key (elem -> schema )) {
3100- /* find module with metadata needed for later in the current node context */
3101- if (!mod || (mod -> ctx != LYD_CTX (elem ))) {
3102- mod = ly_ctx_get_module_latest (LYD_CTX (elem ), "yang" );
3103- LY_CHECK_ERR_GOTO (!mod , LOGINT (LYD_CTX (src_diff )); rc = LY_EINT , cleanup );
3104- }
3119+ if (!node ) {
3120+ /* nothing more to do */
3121+ goto cleanup ;
3122+ }
31053123
3106- /* find operation attribute, if any */
3107- LY_CHECK_GOTO (rc = lyd_diff_get_op (elem , & op , NULL ), cleanup );
3124+ /* first node */
3125+ if (!* schema_p ) {
3126+ * schema_p = node -> schema ;
3127+ }
3128+ assert (* schema_p == node -> schema );
31083129
3109- switch (op ) {
3110- case LYD_DIFF_OP_CREATE :
3111- /* reverse create to delete */
3112- LY_CHECK_GOTO (rc = lyd_diff_change_op (elem , LYD_DIFF_OP_DELETE ), cleanup );
3130+ /* collect it */
3131+ LY_ARRAY_NEW_GOTO (LYD_CTX (node ), * nodes_p , ptr , rc , cleanup );
3132+ * ptr = node ;
31133133
3114- /* check all the children for the same operation, nothing else is expected */
3115- LY_LIST_FOR (lyd_child (elem ), iter ) {
3116- lyd_diff_reverse_remove_op_r (iter , LYD_DIFF_OP_CREATE );
3117- }
3134+ cleanup :
3135+ return rc ;
3136+ }
31183137
3119- LYD_TREE_DFS_continue = 1 ;
3120- break ;
3121- case LYD_DIFF_OP_DELETE :
3122- /* reverse delete to create */
3123- LY_CHECK_GOTO (rc = lyd_diff_change_op (elem , LYD_DIFF_OP_CREATE ), cleanup );
3138+ /**
3139+ * @brief Reverse all sibling diff nodes, recursively.
3140+ *
3141+ * @param[in,out] sibling First sibling to reverse.
3142+ * @param[in] yang_mod YANG module 'yang' to use for metadata.
3143+ * @return LY_ERR value.
3144+ */
3145+ static LY_ERR
3146+ lyd_diff_reverse_siblings_r (struct lyd_node * sibling , const struct lys_module * yang_mod )
3147+ {
3148+ LY_ERR rc = LY_SUCCESS ;
3149+ struct lyd_node * iter , * iter2 , * * userord = NULL ;
3150+ const struct lysc_node * userord_schema = NULL ;
3151+ enum lyd_diff_op op ;
3152+ ly_bool recursive ;
31243153
3125- /* check all the children for the same operation, nothing else is expected */
3126- LY_LIST_FOR (lyd_child (elem ), iter ) {
3127- lyd_diff_reverse_remove_op_r (iter , LYD_DIFF_OP_DELETE );
3128- }
3154+ LY_LIST_FOR (sibling , iter ) {
3155+ /* skip all keys */
3156+ if (lysc_is_key (iter -> schema )) {
3157+ continue ;
3158+ }
31293159
3130- LYD_TREE_DFS_continue = 1 ;
3131- break ;
3132- case LYD_DIFF_OP_REPLACE :
3133- switch (elem -> schema -> nodetype ) {
3134- case LYS_LEAF :
3135- /* leaf value change */
3136- LY_CHECK_GOTO (rc = lyd_diff_reverse_value (elem , mod ), cleanup );
3137- LY_CHECK_GOTO (rc = lyd_diff_reverse_default (elem , mod ), cleanup );
3138- break ;
3139- case LYS_ANYXML :
3140- case LYS_ANYDATA :
3141- /* any value change */
3142- LY_CHECK_GOTO (rc = lyd_diff_reverse_value (elem , mod ), cleanup );
3143- break ;
3144- case LYS_LEAFLIST :
3145- /* leaf-list move */
3146- LY_CHECK_GOTO (rc = lyd_diff_reverse_default (elem , mod ), cleanup );
3147- if (lysc_is_dup_inst_list (elem -> schema )) {
3148- LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (elem , mod , "orig-position" , "position" ), cleanup );
3149- } else {
3150- LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (elem , mod , "orig-value" , "value" ), cleanup );
3151- }
3152- break ;
3153- case LYS_LIST :
3154- /* list move */
3155- if (lysc_is_dup_inst_list (elem -> schema )) {
3156- LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (elem , mod , "orig-position" , "position" ), cleanup );
3157- } else {
3158- LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (elem , mod , "orig-key" , "key" ), cleanup );
3159- }
3160- break ;
3161- default :
3162- LOGINT (LYD_CTX (src_diff ));
3163- rc = LY_EINT ;
3164- goto cleanup ;
3165- }
3166- break ;
3167- case LYD_DIFF_OP_NONE :
3168- switch (elem -> schema -> nodetype ) {
3169- case LYS_LEAF :
3170- case LYS_LEAFLIST :
3171- /* default flag change */
3172- LY_CHECK_GOTO (rc = lyd_diff_reverse_default (elem , mod ), cleanup );
3173- break ;
3174- default :
3175- /* nothing to do */
3176- break ;
3177- }
3178- break ;
3160+ /* update module if needed */
3161+ if (LYD_CTX (iter ) != yang_mod -> ctx ) {
3162+ yang_mod = ly_ctx_get_module_implemented (LYD_CTX (iter ), "yang" );
3163+ assert (yang_mod );
3164+ }
3165+
3166+ /* find operation attribute, if any */
3167+ LY_CHECK_GOTO (rc = lyd_diff_get_op (iter , & op , NULL ), cleanup );
3168+
3169+ recursive = 1 ;
3170+ switch (op ) {
3171+ case LYD_DIFF_OP_CREATE :
3172+ /* reverse create to delete */
3173+ LY_CHECK_GOTO (rc = lyd_diff_change_op (iter , LYD_DIFF_OP_DELETE ), cleanup );
3174+
3175+ /* check all the children for the same operation, nothing else is expected */
3176+ LY_LIST_FOR (lyd_child (iter ), iter2 ) {
3177+ lyd_diff_reverse_remove_op_r (iter2 , LYD_DIFF_OP_CREATE );
3178+ }
3179+
3180+ recursive = 0 ;
3181+ break ;
3182+
3183+ case LYD_DIFF_OP_DELETE :
3184+ /* reverse delete to create */
3185+ LY_CHECK_GOTO (rc = lyd_diff_change_op (iter , LYD_DIFF_OP_CREATE ), cleanup );
3186+
3187+ /* check all the children for the same operation, nothing else is expected */
3188+ LY_LIST_FOR (lyd_child (iter ), iter2 ) {
3189+ lyd_diff_reverse_remove_op_r (iter2 , LYD_DIFF_OP_DELETE );
3190+ }
3191+
3192+ recursive = 0 ;
3193+ break ;
3194+
3195+ case LYD_DIFF_OP_REPLACE :
3196+ switch (iter -> schema -> nodetype ) {
3197+ case LYS_LEAF :
3198+ /* leaf value change */
3199+ LY_CHECK_GOTO (rc = lyd_diff_reverse_value (iter , yang_mod ), cleanup );
3200+ LY_CHECK_GOTO (rc = lyd_diff_reverse_default (iter , yang_mod ), cleanup );
3201+ break ;
3202+ case LYS_ANYXML :
3203+ case LYS_ANYDATA :
3204+ /* any value change */
3205+ LY_CHECK_GOTO (rc = lyd_diff_reverse_value (iter , yang_mod ), cleanup );
3206+ break ;
3207+ case LYS_LEAFLIST :
3208+ /* leaf-list move */
3209+ LY_CHECK_GOTO (rc = lyd_diff_reverse_default (iter , yang_mod ), cleanup );
3210+ if (lysc_is_dup_inst_list (iter -> schema )) {
3211+ LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (iter , yang_mod , "orig-position" , "position" ), cleanup );
3212+ } else {
3213+ LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (iter , yang_mod , "orig-value" , "value" ), cleanup );
3214+ }
3215+ break ;
3216+ case LYS_LIST :
3217+ /* list move */
3218+ if (lysc_is_dup_inst_list (iter -> schema )) {
3219+ LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (iter , yang_mod , "orig-position" , "position" ), cleanup );
3220+ } else {
3221+ LY_CHECK_GOTO (rc = lyd_diff_reverse_meta (iter , yang_mod , "orig-key" , "key" ), cleanup );
31793222 }
3223+ break ;
3224+ default :
3225+ LOGINT (LYD_CTX (iter ));
3226+ rc = LY_EINT ;
3227+ goto cleanup ;
31803228 }
3229+ break ;
31813230
3182- /* reverse any metadata diff */
3183- LY_CHECK_GOTO (rc = lyd_diff_reverse_metadata_diff (elem ), cleanup );
3231+ case LYD_DIFF_OP_NONE :
3232+ switch (iter -> schema -> nodetype ) {
3233+ case LYS_LEAF :
3234+ case LYS_LEAFLIST :
3235+ /* default flag change */
3236+ LY_CHECK_GOTO (rc = lyd_diff_reverse_default (iter , yang_mod ), cleanup );
3237+ break ;
3238+ default :
3239+ /* nothing to do */
3240+ break ;
3241+ }
3242+ break ;
3243+ }
3244+
3245+ /* reverse any metadata diff */
3246+ LY_CHECK_GOTO (rc = lyd_diff_reverse_metadata_diff (iter ), cleanup );
3247+
3248+ /* revursively reverse all descendants */
3249+ if (recursive ) {
3250+ LY_CHECK_GOTO (rc = lyd_diff_reverse_siblings_r (lyd_child (iter ), yang_mod ), cleanup );
3251+ }
31843252
3185- LYD_TREE_DFS_END (root , elem );
3253+ if (lysc_is_userordered (iter -> schema )) {
3254+ /* special user-ordered nodes processing */
3255+ LY_CHECK_GOTO (rc = lyd_diff_reverse_userord (iter , & userord_schema , & userord ), cleanup );
31863256 }
31873257 }
31883258
3259+ if (userord_schema ) {
3260+ /* finish user-ordered nodes processing */
3261+ LY_CHECK_GOTO (rc = lyd_diff_reverse_userord (NULL , & userord_schema , & userord ), cleanup );
3262+ }
3263+
3264+ cleanup :
3265+ LY_ARRAY_FREE (userord );
3266+ return rc ;
3267+ }
3268+
3269+ LIBYANG_API_DEF LY_ERR
3270+ lyd_diff_reverse_all (const struct lyd_node * src_diff , struct lyd_node * * diff )
3271+ {
3272+ LY_ERR rc = LY_SUCCESS ;
3273+ const struct lys_module * mod = NULL ;
3274+
3275+ LY_CHECK_ARG_RET (NULL , diff , LY_EINVAL );
3276+
3277+ if (!src_diff ) {
3278+ * diff = NULL ;
3279+ return LY_SUCCESS ;
3280+ }
3281+
3282+ /* duplicate diff */
3283+ LY_CHECK_GOTO (rc = lyd_dup_siblings (src_diff , NULL , LYD_DUP_RECURSIVE | LYD_DUP_NO_LYDS , diff ), cleanup );
3284+
3285+ /* find 'yang' module */
3286+ mod = ly_ctx_get_module_implemented (LYD_CTX (src_diff ), "yang" );
3287+ assert (mod );
3288+
3289+ /* reverse it */
3290+ LY_CHECK_GOTO (rc = lyd_diff_reverse_siblings_r (* diff , mod ), cleanup );
3291+
31893292cleanup :
31903293 if (rc ) {
31913294 lyd_free_siblings (* diff );
0 commit comments