* existent.
*/
+isc_result_t
+cfg_map_addclone(cfg_obj_t *map, const cfg_obj_t *obj,
+ const cfg_clausedef_t *clause);
+/*%<
+ * Add a clone of 'obj' to the specified clause in mapbody 'mapobj'.
+ * If the clause is tagged with CFG_CLAUSEFLAG_MULTI, the function expects
+ * that 'obj' is a list and will clone each element and sequentially add them
+ * (preserving the order), instead of adding a list as single element of
+ * map[clausename].
+ *
+ * Require:
+ * \li 'obj' is a valid cfg_obj_t.
+ * \li 'mapobj' is a valid cfg_obj_t of type map.
+ * \li 'clause' is a valid clause definition.
+ */
+
+void
+cfg_list_addclone(cfg_obj_t *dst, const cfg_obj_t *src, bool prepend);
+/*%<
+ * Clone each `src` element and add them into the existing list `dst`. If
+ * `prepend` is set, the `src` elements will be added at the beginning of
+ * `src`, and the order of `src` is preserved.
+ *
+ * Both `dst` and `src` must be valid pointers to cfg objects of type list.
+ */
+
void
cfg_obj_clone(const cfg_obj_t *source, cfg_obj_t **target);
/*%<
cfg_doc_obj(&pctx, type);
}
-isc_result_t
-cfg_map_add(cfg_obj_t *mapobj, cfg_obj_t *obj, const char *clausename) {
- isc_result_t result = ISC_R_SUCCESS;
- const cfg_map_t *map = NULL;
- isc_symvalue_t symval;
+static const cfg_clausedef_t *
+map_lookup_clause(const cfg_obj_t *mapobj, const char *clausename) {
+ const cfg_map_t *map = &mapobj->value.map;
const cfg_clausedef_t *const *clauseset = NULL;
const cfg_clausedef_t *clause = NULL;
- REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
- REQUIRE(obj != NULL);
- REQUIRE(clausename != NULL);
-
- map = &mapobj->value.map;
-
- clause = NULL;
for (clauseset = map->clausesets; *clauseset != NULL; clauseset++) {
for (clause = *clauseset; clause->name != NULL; clause++) {
if (strcasecmp(clause->name, clausename) == 0) {
- goto breakout;
+ return clause;
}
}
}
-breakout:
- if (clause == NULL || clause->name == NULL) {
- return ISC_R_FAILURE;
- }
+ return NULL;
+}
- result = isc_symtab_lookup(map->symtab, clausename, SYMTAB_DUMMY_TYPE,
+static isc_result_t
+map_define(cfg_obj_t *mapobj, cfg_obj_t *obj, const cfg_clausedef_t *clause) {
+ isc_result_t result;
+ const cfg_map_t *map;
+ isc_symvalue_t symval;
+
+ map = &mapobj->value.map;
+
+ result = isc_symtab_lookup(map->symtab, clause->name, SYMTAB_DUMMY_TYPE,
&symval);
if (result == ISC_R_NOTFOUND) {
if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
return result;
}
+isc_result_t
+cfg_map_add(cfg_obj_t *mapobj, cfg_obj_t *obj, const char *clausename) {
+ const cfg_clausedef_t *clause;
+
+ REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
+ REQUIRE(obj != NULL);
+ REQUIRE(clausename != NULL);
+
+ clause = map_lookup_clause(mapobj, clausename);
+ if (clause == NULL || clause->name == NULL) {
+ return ISC_R_FAILURE;
+ }
+
+ return map_define(mapobj, obj, clause);
+}
+
+isc_result_t
+cfg_map_addclone(cfg_obj_t *map, const cfg_obj_t *obj,
+ const cfg_clausedef_t *clause) {
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_obj_t *clone = NULL;
+
+ REQUIRE(map != NULL && map->type->rep == &cfg_rep_map);
+ REQUIRE(obj != NULL);
+ REQUIRE(clause != NULL && clause->name != NULL);
+
+ /*
+ * Repeatable clauses aren't explicitly defined as cfg_list types,
+ * but a list is created internally if the clause has
+ * CFG_CLAUSEFLAG_MULTI set.
+ */
+ if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
+ const cfg_listelt_t *elt = NULL;
+
+ REQUIRE(cfg_obj_islist(obj));
+
+ elt = cfg_list_first(obj);
+ while (elt != NULL && result == ISC_R_SUCCESS) {
+ cfg_obj_clone(elt->obj, &clone);
+ result = map_define(map, clone, clause);
+ elt = cfg_list_next(elt);
+
+ /*
+ * map_define internally attach each added node
+ * in the implicit list
+ */
+ cfg_obj_detach(&clone);
+ }
+ } else {
+ cfg_obj_clone(obj, &clone);
+ result = map_define(map, clone, clause);
+ }
+
+ return result;
+}
+
+void
+cfg_list_addclone(cfg_obj_t *dst, const cfg_obj_t *src, bool prepend) {
+ const cfg_listelt_t *srcelt = NULL;
+ cfg_list_t list = ISC_LIST_INITIALIZER;
+
+ REQUIRE(cfg_obj_islist(dst));
+ REQUIRE(cfg_obj_islist(src));
+
+ srcelt = cfg_list_first(src);
+ while (srcelt != NULL) {
+ cfg_listelt_t *dstelt = isc_mem_get(dst->mctx, sizeof(*dstelt));
+
+ *dstelt = (cfg_listelt_t){ .link = ISC_LINK_INITIALIZER };
+ cfg_obj_clone(srcelt->obj, &dstelt->obj);
+
+ if (prepend) {
+ ISC_LIST_APPEND(list, dstelt, link);
+ } else {
+ ISC_LIST_APPEND(dst->value.list, dstelt, link);
+ }
+ srcelt = cfg_list_next(srcelt);
+ }
+ if (prepend) {
+ ISC_LIST_PREPENDLIST(dst->value.list, list, link);
+ }
+}
+
isc_result_t
cfg_pluginlist_foreach(const cfg_obj_t *config, const cfg_obj_t *list,
cfg_aclconfctx_t *aclctx, pluginlist_cb_t *callback,