From: Alan T. DeKok Date: Sun, 14 Nov 2021 03:07:15 +0000 (-0500) Subject: add fr_edit_list_free_children() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83205ac7314517c33f9c2a5e369ca01837b91798;p=thirdparty%2Ffreeradius-server.git add fr_edit_list_free_children() which will clear the children of a structural type --- diff --git a/src/lib/util/edit.c b/src/lib/util/edit.c index bd3be7e9e77..4a91d0e9bae 100644 --- a/src/lib/util/edit.c +++ b/src/lib/util/edit.c @@ -33,6 +33,7 @@ typedef enum { FR_EDIT_INVALID = 0, FR_EDIT_DELETE, //!< delete a VP FR_EDIT_VALUE, //!< edit a VP in place + FR_EDIT_CLEAR, //!< clear the children of a structural entry. FR_EDIT_INSERT, //!< insert a VP into a list, after another one. } fr_edit_op_t; @@ -44,6 +45,7 @@ static const char *edit_names[4] = { "invalid", "delete", "value", + "clear", "insert", }; #endif @@ -74,8 +76,7 @@ typedef struct { union { fr_value_box_t data; //!< original data - fr_pair_list_t children; //!< original child list, - //!< for T_OP_SET of structural entries + fr_pair_list_t children; //!< original child list, for "clear" struct { fr_pair_list_t *list; //!< parent list @@ -107,6 +108,13 @@ static int edit_undo(fr_edit_t *e) fr_value_box_copy_shallow(NULL, &vp->data, &e->data); break; + case FR_EDIT_CLEAR: + fr_assert(fr_type_is_structural(vp->vp_type)); + + fr_pair_list_free(&vp->vp_group); + fr_pair_list_append(&vp->vp_group, &e->children); + break; + case FR_EDIT_DELETE: fr_assert(e->list != NULL); #ifndef NDEBUG @@ -249,6 +257,26 @@ static int edit_record(fr_edit_list_t *el, fr_edit_op_t op, fr_pair_t *vp, fr_pa fr_assert(0); return -1; + case FR_EDIT_CLEAR: + /* + * If we're clearing it, we MUST have + * previously inserted it. So just nuke + * it's children, as merging the + * operations of "insert with stuff" and + * then "clear" is just "insert empty + * pair". + * + * However, we don't yet delete the + * children, as there may be other edit + * operations which are referring to + * them. + */ + fr_assert(e->op == FR_EDIT_INSERT); + fr_assert(fr_type_is_structural(vp->vp_type)); + + fr_pair_list_append(&el->deleted_pairs, &vp->vp_group); + break; + /* * We're being asked to delete something * we previously inserted, or previously @@ -293,7 +321,6 @@ static int edit_record(fr_edit_list_t *el, fr_edit_op_t op, fr_pair_t *vp, fr_pa * original one, and then track the * deletion. */ - fr_assert(e->op == FR_EDIT_VALUE); edit_undo(e); /* @@ -338,6 +365,15 @@ static int edit_record(fr_edit_list_t *el, fr_edit_op_t op, fr_pair_t *vp, fr_pa e->data.tainted); break; + case FR_EDIT_CLEAR: + fr_assert(list == NULL); + fr_assert(ref == NULL); + + fr_assert(fr_type_is_structural(vp->vp_type)); + fr_pair_list_init(&e->children); + fr_pair_list_append(&e->children, &vp->vp_group); + break; + case FR_EDIT_INSERT: fr_assert(list != NULL); @@ -464,10 +500,31 @@ int fr_edit_list_replace(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to } +/** Replace a pair with another one. + * + * This function mirrors fr_pair_replace(). + * + * After this function returns, the new VP has replaced the old one, + * and the new one can be edited. + */ +int fr_edit_list_free_children(fr_edit_list_t *el, fr_pair_t *vp) +{ + if (!el) return 0; + + if (!fr_type_is_structural(vp->vp_type)) return -1; + + /* + * Record the list, even if it's empty. That way if we + * later add children to it, the "undo" operation can + * reset the children list to be empty. + */ + return edit_record(el, FR_EDIT_CLEAR, vp, NULL, NULL); +} + /** Finalize the edits when we destroy the edit list. * * Which in large part means freeing the VPs which have been deleted, - * and then deleting the edit list. + * or saved, and then deleting the edit list. */ static int _edit_list_destructor(fr_edit_list_t *el) { @@ -491,6 +548,10 @@ static int _edit_list_destructor(fr_edit_list_t *el) talloc_free(e->vp); break; + case FR_EDIT_CLEAR: + fr_pair_list_free(&e->children); + break; + case FR_EDIT_VALUE: fr_assert(fr_type_is_leaf(e->vp->vp_type)); fr_value_box_clear(&e->data); diff --git a/src/lib/util/edit.h b/src/lib/util/edit.h index e9fc463a8bd..b8917de626d 100644 --- a/src/lib/util/edit.h +++ b/src/lib/util/edit.h @@ -49,6 +49,8 @@ int fr_edit_list_replace_value(fr_edit_list_t *el, fr_pair_t *vp, fr_value_box_t int fr_edit_list_replace(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp) CC_HINT(nonnull(2,3,4)); +int fr_edit_list_free_children(fr_edit_list_t *el, fr_pair_t *vp) CC_HINT(nonnull(2)); + #ifdef __cplusplus } #endif