if (in->copy) fr_dcursor_copy(out, in);
}
+/** Copy a read-only iterator from a parent to a child cursor
+ *
+ * @param[out] out Where to copy the cursor to.
+ * @param[in] in cursor to copy.
+ *
+ * @hidecallergraph
+ */
+CC_HINT(nonnull)
+static inline void fr_dcursor_copy_iter(fr_dcursor_t *out, fr_dcursor_t const *in)
+{
+ fr_assert(!out->iter);
+ fr_assert(!out->iter_uctx);
+
+ out->iter = in->iter;
+ out->iter_uctx = in->iter_uctx;
+
+#ifndef NDEBUG
+ /*
+ * The output cursor has to be read-only.
+ */
+ out->insert = NULL;
+ out->remove = NULL;
+ out->mod_uctx = NULL;
+ out->copy = NULL;
+#endif
+}
+
/** Rewind cursor to the start of the list
*
* @param[in] cursor to operate on.
fr_pair_t *_fr_pair_dcursor_init(fr_dcursor_t *cursor, fr_pair_list_t const *list,
bool is_const) CC_HINT(nonnull);
+/** Initializes a child dcursor from a parent cursor, with an iteration function.
+ *
+ * Filters can be applied later with fr_dcursor_filter_set.
+ *
+ * @note This is the only way to use a dcursor in non-const mode with fr_pair_list_t.
+ *
+ * @param[out] cursor to initialise.
+ * @param[in] list to iterate over.
+ * @param[in] parent parent cursor to take the iterator from
+ * @return
+ * - NULL if src does not point to any items.
+ * - The first pair in the list.
+ */
+static inline fr_pair_t *fr_pair_dcursor_child_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dcursor_t const *parent)
+{
+ fr_pair_t *vp = fr_pair_dcursor_init(cursor, list);
+
+ fr_dcursor_copy_iter(cursor, parent);
+ return vp;
+}
+
/** Initialise a cursor that will return only attributes matching the specified #fr_dict_attr_t
*
* @param[in] _cursor to initialise.
fr_assert(fr_type_is_structural(vp->vp_type));
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
work_dbuff = FR_DBUFF(dbuff);
while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
* Encode the child options.
*/
if (!fr_pair_list_empty(&vp->vp_group)) {
- (void) fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ (void) fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
while (fr_dcursor_current(&child_cursor) != NULL) {
slen = fr_dhcpv6_encode_option(&work_dbuff, &child_cursor, encode_ctx);
fr_assert(fr_type_is_structural(vp->vp_type));
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
work_dbuff = FR_DBUFF(dbuff);
while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
if (vp->vp_type == FR_TYPE_STRUCT) {
fr_dcursor_t child_cursor;
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
slen = fr_struct_to_network(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx, encode_value, encode_child);
if (slen < 0) return slen;
fr_assert(fr_type_is_structural(vp->vp_type));
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
work_dbuff = FR_DBUFF(dbuff);
while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
if (vp->vp_type == FR_TYPE_STRUCT) {
fr_dcursor_t child_cursor;
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
slen = fr_struct_to_network(&work_dbuff, &da_stack, 0, &child_cursor, encode_ctx, encode_value, encode_child);
if (slen <= 0) return slen;
return PAIR_ENCODE_SKIPPED;
}
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
vp = fr_dcursor_current(&child_cursor);
fr_proto_da_stack_build(da_stack, vp->da);
parent = fr_dcursor_current(cursor);
fr_assert(fr_type_is_structural(parent->vp_type));
- (void) fr_pair_dcursor_init(&child_cursor, &parent->vp_group);
+ (void) fr_pair_dcursor_child_iter_init(&child_cursor, &parent->vp_group, cursor);
FR_PROTO_STACK_PRINT(da_stack, depth);
fr_assert(vp->da == da);
work_dbuff = FR_DBUFF(dbuff);
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
fr_proto_da_stack_build(da_stack, vp->da);
* Loop over the children of this Vendor-Specific
* attribute.
*/
- fr_pair_dcursor_init(&child_cursor, &vp->vp_group);
+ fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
while ((vp = fr_dcursor_current(&child_cursor)) != NULL) {
fr_proto_da_stack_build(da_stack, vp->da);