commit 5ffee59: [Rework] Further refactoring

Vsevolod Stakhov vsevolod at rspamd.com
Thu Aug 17 11:49:11 UTC 2023


Author: Vsevolod Stakhov
Date: 2023-08-15 15:49:11 +0100
URL: https://github.com/rspamd/rspamd/commit/5ffee59dfce8b60669f93fc59c8304f9ec4703f7

[Rework] Further refactoring

---
 src/libserver/cfg_file.h  |  31 +-
 src/libserver/cfg_rcl.cxx | 792 ++++++++++++++++++++--------------------------
 src/libserver/cfg_rcl.h   |  28 +-
 3 files changed, 362 insertions(+), 489 deletions(-)

diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index b20739806..703ca57ff 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -303,6 +303,7 @@ struct rspamd_config_post_init_script {
 };
 
 struct rspamd_lang_detector;
+struct rspamd_rcl_sections_map;
 
 enum rspamd_config_settings_policy {
 	RSPAMD_SETTINGS_POLICY_DEFAULT = 0,
@@ -391,21 +392,21 @@ struct rspamd_config {
 	GList *script_modules;        /**< linked list of script modules to load				*/
 	GHashTable *explicit_modules; /**< modules that should be always loaded				*/
 
-	GList *filters;                     /**< linked list of all filters							*/
-	GList *workers;                     /**< linked list of all workers params					*/
-	GHashTable *wrk_parsers;            /**< hash for worker config parsers, indexed by worker quarks */
-	ucl_object_t *rcl_obj;              /**< rcl object											*/
-	ucl_object_t *config_comments;      /**< comments saved from the config						*/
-	ucl_object_t *doc_strings;          /**< documentation strings for config options			*/
-	GPtrArray *c_modules;               /**< list of C modules			*/
-	void *composites_manager;           /**< hash of composite symbols indexed by its name		*/
-	GList *classifiers;                 /**< list of all classifiers defined                    */
-	GList *statfiles;                   /**< list of all statfiles in config file order         */
-	GHashTable *classifiers_symbols;    /**< hashtable indexed by symbol name of classifiers    */
-	GHashTable *cfg_params;             /**< all cfg params indexed by its name in this structure */
-	gchar *dynamic_conf;                /**< path to dynamic configuration						*/
-	ucl_object_t *current_dynamic_conf; /**< currently loaded dynamic configuration				*/
-	gint clock_res;                     /**< resolution of clock used							*/
+	GList *filters;                             /**< linked list of all filters							*/
+	GList *workers;                             /**< linked list of all workers params					*/
+	struct rspamd_rcl_sections_map *rcl_parser; /**< parser for RCL config							*/
+	ucl_object_t *rcl_obj;                      /**< rcl object											*/
+	ucl_object_t *config_comments;              /**< comments saved from the config						*/
+	ucl_object_t *doc_strings;                  /**< documentation strings for config options			*/
+	GPtrArray *c_modules;                       /**< list of C modules			*/
+	void *composites_manager;                   /**< hash of composite symbols indexed by its name		*/
+	GList *classifiers;                         /**< list of all classifiers defined                    */
+	GList *statfiles;                           /**< list of all statfiles in config file order         */
+	GHashTable *classifiers_symbols;            /**< hashtable indexed by symbol name of classifiers    */
+	GHashTable *cfg_params;                     /**< all cfg params indexed by its name in this structure */
+	gchar *dynamic_conf;                        /**< path to dynamic configuration						*/
+	ucl_object_t *current_dynamic_conf;         /**< currently loaded dynamic configuration				*/
+	gint clock_res;                             /**< resolution of clock used							*/
 
 	GList *maps;                       /**< maps active										*/
 	gdouble map_timeout;               /**< maps watch timeout									*/
diff --git a/src/libserver/cfg_rcl.cxx b/src/libserver/cfg_rcl.cxx
index 2fa637889..aadcc50a6 100644
--- a/src/libserver/cfg_rcl.cxx
+++ b/src/libserver/cfg_rcl.cxx
@@ -51,14 +51,14 @@ struct rspamd_rcl_sections_map;
 
 struct rspamd_rcl_section {
 	struct rspamd_rcl_sections_map *top;
-	const gchar *name; /**< name of section */
-	const gchar *key_attr;
-	const gchar *default_key;
+	std::string name; /**< name of section */
+	std::optional<std::string> key_attr;
+	std::optional<std::string> default_key;
 	rspamd_rcl_handler_t handler; /**< handler of section attributes */
 	enum ucl_type type;           /**< type of attribute */
-	gboolean required;            /**< whether this param is required */
-	gboolean strict_type;         /**< whether we need strict type */
-	ankerl::unordered_dense::map<std::string, struct rspamd_rcl_section> subsections;
+	bool required;                /**< whether this param is required */
+	bool strict_type;             /**< whether we need strict type */
+	ankerl::unordered_dense::map<std::string, std::shared_ptr<struct rspamd_rcl_section>> subsections;
 	ankerl::unordered_dense::map<std::string, struct rspamd_rcl_default_handler_data> default_parser; /**< generic parsing fields */
 	rspamd_rcl_section_fin_t fin;                                                                     /** called at the end of section parsing */
 	gpointer fin_ud;
@@ -79,7 +79,8 @@ struct rspamd_worker_cfg_parser {
 };
 
 struct rspamd_rcl_sections_map {
-	ankerl::unordered_dense::map<std::string, struct rspamd_rcl_section> sections;
+	ankerl::unordered_dense::map<std::string, std::shared_ptr<struct rspamd_rcl_section>> sections;
+	std::vector<std::shared_ptr<struct rspamd_rcl_section>> sections_order;
 	ankerl::unordered_dense::map<int, struct rspamd_worker_cfg_parser> workers_parser;
 	ankerl::unordered_dense::set<std::string> lua_modules_seen;
 };
@@ -288,7 +289,7 @@ rspamd_rcl_options_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 	dns = ucl_object_lookup(obj, "dns");
 	if (maybe_subsection && dns != nullptr) {
 		if (!rspamd_rcl_section_parse_defaults(cfg,
-											   maybe_subsection.value().get(), cfg->cfg_pool, dns,
+											   *maybe_subsection.value().get(), cfg->cfg_pool, dns,
 											   cfg, err)) {
 			return FALSE;
 		}
@@ -299,7 +300,7 @@ rspamd_rcl_options_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 	upstream = ucl_object_lookup_any(obj, "upstream", "upstreams", nullptr);
 	if (maybe_subsection && upstream != nullptr) {
 		if (!rspamd_rcl_section_parse_defaults(cfg,
-											   maybe_subsection.value().get(), cfg->cfg_pool,
+											   *maybe_subsection.value().get(), cfg->cfg_pool,
 											   upstream, cfg, err)) {
 			return FALSE;
 		}
@@ -313,7 +314,7 @@ rspamd_rcl_options_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 
 		LL_FOREACH(neighbours, cur)
 		{
-			if (!rspamd_rcl_process_section(cfg, maybe_subsection.value().get(), cfg, cur,
+			if (!rspamd_rcl_process_section(cfg, *maybe_subsection.value().get(), cfg, cur,
 											pool, err)) {
 				return FALSE;
 			}
@@ -441,16 +442,17 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 												description);
 	}
 
-	struct rspamd_rcl_symbol_data sd;
-	sd.gr = gr;
-	sd.cfg = cfg;
+	struct rspamd_rcl_symbol_data sd = {
+		.gr = gr,
+		.cfg = cfg,
+	};
 
 	/* Handle symbols */
 	if (const auto *val = ucl_object_lookup(obj, "symbols"); val != nullptr && ucl_object_type(val) == UCL_OBJECT) {
 		auto subsection = rspamd::find_map(section->subsections, "symbols");
 
 		g_assert(subsection.has_value());
-		if (!rspamd_rcl_process_section(cfg, subsection.value().get(), &sd, val,
+		if (!rspamd_rcl_process_section(cfg, *subsection.value().get(), &sd, val,
 										pool, err)) {
 
 			return FALSE;
@@ -968,26 +970,22 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 						   const gchar *key, gpointer ud,
 						   struct rspamd_rcl_section *section, GError **err)
 {
-	const ucl_object_t *val, *cur;
-	struct rspamd_config *cfg = ud;
-	const gchar *data;
+	auto *cfg = static_cast<rspamd_config *>(ud);
+	const char *data;
 
 	if (obj->type == UCL_OBJECT) {
-		GHashTable *mods_seen = g_hash_table_new(rspamd_strcase_hash,
-												 rspamd_strcase_equal);
-		val = ucl_object_lookup(obj, "path");
+		const auto *val = ucl_object_lookup(obj, "path");
 
 		if (val) {
+			const auto *cur = val;
 			LL_FOREACH(val, cur)
 			{
 				if (ucl_object_tostring_safe(cur, &data)) {
-					if (!rspamd_rcl_add_lua_plugins_path(cfg,
-														 rspamd_mempool_strdup(cfg->cfg_pool, data),
+					if (!rspamd_rcl_add_lua_plugins_path(section->top,
+														 cfg,
+														 data,
 														 TRUE,
-														 mods_seen,
 														 err)) {
-						g_hash_table_unref(mods_seen);
-
 						return FALSE;
 					}
 				}
@@ -998,7 +996,6 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 						CFG_RCL_ERROR,
 						EINVAL,
 						"path attribute is missing");
-			g_hash_table_unref(mods_seen);
 
 			return FALSE;
 		}
@@ -1006,15 +1003,15 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 		val = ucl_object_lookup(obj, "fallback_path");
 
 		if (val) {
+			const auto *cur = val;
 			LL_FOREACH(val, cur)
 			{
 				if (ucl_object_tostring_safe(cur, &data)) {
-					if (!rspamd_rcl_add_lua_plugins_path(cfg,
-														 rspamd_mempool_strdup(cfg->cfg_pool, data),
+					if (!rspamd_rcl_add_lua_plugins_path(section->top,
+														 cfg,
+														 data,
 														 FALSE,
-														 mods_seen,
 														 err)) {
-						g_hash_table_unref(mods_seen);
 
 						return FALSE;
 					}
@@ -1025,27 +1022,24 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 		val = ucl_object_lookup(obj, "try_path");
 
 		if (val) {
+			const auto *cur = val;
 			LL_FOREACH(val, cur)
 			{
 				if (ucl_object_tostring_safe(cur, &data)) {
-					if (!rspamd_rcl_add_lua_plugins_path(cfg,
-														 rspamd_mempool_strdup(cfg->cfg_pool, data),
+					if (!rspamd_rcl_add_lua_plugins_path(section->top,
+														 cfg,
+														 data,
 														 FALSE,
-														 mods_seen,
 														 err)) {
-						g_hash_table_unref(mods_seen);
 
 						return FALSE;
 					}
 				}
 			}
 		}
-
-		g_hash_table_unref(mods_seen);
 	}
 	else if (ucl_object_tostring_safe(obj, &data)) {
-		if (!rspamd_rcl_add_lua_plugins_path(cfg,
-											 rspamd_mempool_strdup(cfg->cfg_pool, data), TRUE, nullptr, err)) {
+		if (!rspamd_rcl_add_lua_plugins_path(section->top, cfg, data, TRUE, err)) {
 			return FALSE;
 		}
 	}
@@ -1070,27 +1064,24 @@ rspamd_rcl_statfile_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 							const gchar *key, gpointer ud,
 							struct rspamd_rcl_section *section, GError **err)
 {
-	struct statfile_parser_data *stud = ud;
-	struct rspamd_classifier_config *ccf;
-	struct rspamd_config *cfg;
-	const ucl_object_t *val;
-	struct rspamd_statfile_config *st;
+	auto *stud = (struct statfile_parser_data *) ud;
 	GList *labels;
 
 	g_assert(key != nullptr);
 
-	cfg = stud->cfg;
-	ccf = stud->ccf;
+	auto *cfg = stud->cfg;
+	auto *ccf = stud->ccf;
 
-	st = rspamd_config_new_statfile(cfg, nullptr);
+	auto *st = rspamd_config_new_statfile(cfg, nullptr);
 	st->symbol = rspamd_mempool_strdup(cfg->cfg_pool, key);
 
-	if (rspamd_rcl_section_parse_defaults(cfg, section, pool, obj, st, err)) {
+	if (rspamd_rcl_section_parse_defaults(cfg, *section, pool, obj, st, err)) {
 		ccf->statfiles = rspamd_mempool_glist_prepend(pool, ccf->statfiles, st);
 
 		if (st->label != nullptr) {
-			labels = g_hash_table_lookup(ccf->labels, st->label);
+			labels = (GList *) g_hash_table_lookup(ccf->labels, st->label);
 			if (labels != nullptr) {
+				/* Must use append to preserve the head stored in the hash table */
 				labels = g_list_append(labels, st);
 			}
 			else {
@@ -1113,7 +1104,7 @@ rspamd_rcl_statfile_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
 		st->opts = (ucl_object_t *) obj;
 		st->clcf = ccf;
 
-		val = ucl_object_lookup(obj, "spam");
+		const auto *val = ucl_object_lookup(obj, "spam");
 		if (val == nullptr) {
 			msg_info_config(
 				"statfile %s has no explicit 'spam' setting, trying to guess by symbol",
@@ -1152,47 +1143,41 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 							  struct rspamd_rcl_section *section,
 							  GError **err)
 {
-	const ucl_object_t *val, *cur;
-	ucl_object_iter_t it = nullptr;
-	struct rspamd_config *cfg = ud;
-	struct statfile_parser_data stud;
-	const gchar *st_key;
-	struct rspamd_classifier_config *ccf;
-	gboolean res = TRUE;
-	struct rspamd_rcl_section *stat_section;
-	struct rspamd_tokenizer_config *tkcf = nullptr;
-	lua_State *L = cfg->lua_state;
+	auto *cfg = static_cast<rspamd_config *>(ud);
 
 	g_assert(key != nullptr);
-	ccf = rspamd_config_new_classifier(cfg, nullptr);
+	auto *ccf = rspamd_config_new_classifier(cfg, nullptr);
+	auto *tkcf = (rspamd_tokenizer_config *) nullptr;
 
 	ccf->classifier = rspamd_mempool_strdup(cfg->cfg_pool, key);
 
-	if (rspamd_rcl_section_parse_defaults(cfg, section, cfg->cfg_pool, obj,
+	if (rspamd_rcl_section_parse_defaults(cfg, *section, cfg->cfg_pool, obj,
 										  ccf, err)) {
 
-		HASH_FIND_STR(section->subsections, "statfile", stat_section);
+		auto stat_section = rspamd::find_map(section->subsections, "statfile");
 
 		if (ccf->classifier == nullptr) {
-			ccf->classifier = "bayes";
+			ccf->classifier = rspamd_mempool_strdup(cfg->cfg_pool, "bayes");
 		}
 
 		if (ccf->name == nullptr) {
 			ccf->name = ccf->classifier;
 		}
 
-		it = ucl_object_iterate_new(obj);
+		auto it = ucl_object_iterate_new(obj);
+		const auto *val = obj;
+		auto res = TRUE;
 
 		while ((val = ucl_object_iterate_safe(it, true)) != nullptr && res) {
-			st_key = ucl_object_key(val);
+			const auto *st_key = ucl_object_key(val);
 
 			if (st_key != nullptr) {
 				if (g_ascii_strcasecmp(st_key, "statfile") == 0) {
+					const auto *cur = val;
 					LL_FOREACH(val, cur)
 					{
-						stud.cfg = cfg;
-						stud.ccf = ccf;
-						res = rspamd_rcl_process_section(cfg, stat_section, &stud,
+						struct statfile_parser_data stud = {.cfg = cfg, .ccf = ccf};
+						res = rspamd_rcl_process_section(cfg, *stat_section.value().get(), &stud,
 														 cur, cfg->cfg_pool, err);
 
 						if (!res) {
@@ -1203,13 +1188,13 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 					}
 				}
 				else if (g_ascii_strcasecmp(st_key, "tokenizer") == 0) {
-					tkcf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*tkcf));
+					tkcf = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_tokenizer_config);
 
 					if (ucl_object_type(val) == UCL_STRING) {
 						tkcf->name = ucl_object_tostring(val);
 					}
 					else if (ucl_object_type(val) == UCL_OBJECT) {
-						cur = ucl_object_lookup(val, "name");
+						const auto *cur = ucl_object_lookup(val, "name");
 						if (cur != nullptr) {
 							tkcf->name = ucl_object_tostring(cur);
 							tkcf->opts = val;
@@ -1233,16 +1218,17 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 	}
 
 	if (tkcf == nullptr) {
-		tkcf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*tkcf));
+		tkcf = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_tokenizer_config);
 		tkcf->name = nullptr;
 	}
 
 	ccf->tokenizer = tkcf;
 
 	/* Handle lua conditions */
-	val = ucl_object_lookup_any(obj, "learn_condition", nullptr);
+	const auto *val = ucl_object_lookup_any(obj, "learn_condition", nullptr);
 
 	if (val) {
+		const auto *cur = val;
 		LL_FOREACH(val, cur)
 		{
 			if (ucl_object_type(cur) == UCL_STRING) {
@@ -1251,14 +1237,14 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 				gint ref_idx;
 
 				lua_script = ucl_object_tolstring(cur, &slen);
-				ref_idx = rspamd_lua_function_ref_from_str(L,
+				ref_idx = rspamd_lua_function_ref_from_str(RSPAMD_LUA_CFG_STATE(cfg),
 														   lua_script, slen, "learn_condition", err);
 
 				if (ref_idx == LUA_NOREF) {
 					return FALSE;
 				}
 
-				rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+				rspamd_lua_add_ref_dtor(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_pool, ref_idx);
 				ccf->learn_conditions = rspamd_mempool_glist_append(
 					cfg->cfg_pool,
 					ccf->learn_conditions,
@@ -1270,6 +1256,7 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 	val = ucl_object_lookup_any(obj, "classify_condition", nullptr);
 
 	if (val) {
+		const auto *cur = val;
 		LL_FOREACH(val, cur)
 		{
 			if (ucl_object_type(cur) == UCL_STRING) {
@@ -1278,14 +1265,14 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 				gint ref_idx;
 
 				lua_script = ucl_object_tolstring(cur, &slen);
-				ref_idx = rspamd_lua_function_ref_from_str(L,
+				ref_idx = rspamd_lua_function_ref_from_str(RSPAMD_LUA_CFG_STATE(cfg),
 														   lua_script, slen, "classify_condition", err);
 
 				if (ref_idx == LUA_NOREF) {
 					return FALSE;
 				}
 
-				rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+				rspamd_lua_add_ref_dtor(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_pool, ref_idx);
 				ccf->classify_conditions = rspamd_mempool_glist_append(
 					cfg->cfg_pool,
 					ccf->classify_conditions,
@@ -1297,7 +1284,7 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
 	ccf->opts = (ucl_object_t *) obj;
 	cfg->classifiers = g_list_prepend(cfg->classifiers, ccf);
 
-	return res;
+	return TRUE;
 }
 
 static gboolean
@@ -1308,7 +1295,7 @@ rspamd_rcl_composite_handler(rspamd_mempool_t *pool,
 							 struct rspamd_rcl_section *section,
 							 GError **err)
 {
-	struct rspamd_config *cfg = ud;
+	auto *cfg = static_cast<rspamd_config *>(ud);
 	void *composite;
 	const gchar *composite_name;
 
@@ -1316,7 +1303,7 @@ rspamd_rcl_composite_handler(rspamd_mempool_t *pool,
 
 	composite_name = key;
 
-	const ucl_object_t *val = ucl_object_lookup(obj, "enabled");
+	const auto *val = ucl_object_lookup(obj, "enabled");
 	if (val != nullptr && !ucl_object_toboolean(val)) {
 		msg_info_config("composite %s is disabled", composite_name);
 		return TRUE;
@@ -1339,11 +1326,10 @@ rspamd_rcl_composites_handler(rspamd_mempool_t *pool,
 							  struct rspamd_rcl_section *section,
 							  GError **err)
 {
-	ucl_object_iter_t it = nullptr;
-	const ucl_object_t *cur;
-	gboolean success = TRUE;
+	auto success = TRUE;
 
-	it = ucl_object_iterate_new(obj);
+	auto it = ucl_object_iterate_new(obj);
+	const auto *cur = obj;
 
 	while ((cur = ucl_object_iterate_safe(it, true))) {
 		success = rspamd_rcl_composite_handler(pool, cur,
@@ -1366,11 +1352,8 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
 							  struct rspamd_rcl_section *section,
 							  GError **err)
 {
-	struct rspamd_config *cfg = ud;
-	const ucl_object_t *hostval, *pathval;
-	ucl_object_t *neigh;
-	gboolean has_port = FALSE, has_proto = FALSE;
-	GString *urlstr;
+	auto *cfg = static_cast<rspamd_config *>(ud);
+	auto has_port = FALSE, has_proto = FALSE;
 	const gchar *p;
 
 	if (key == nullptr) {
@@ -1381,7 +1364,7 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
 		return FALSE;
 	}
 
-	hostval = ucl_object_lookup(obj, "host");
+	const auto *hostval = ucl_object_lookup(obj, "host");
 
 	if (hostval == nullptr || ucl_object_type(hostval) != UCL_STRING) {
 		g_set_error(err,
@@ -1391,7 +1374,7 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
 		return FALSE;
 	}
 
-	neigh = ucl_object_typed_new(UCL_OBJECT);
+	auto *neigh = ucl_object_typed_new(UCL_OBJECT);
 	ucl_object_insert_key(neigh, ucl_object_copy(hostval), "host", 0, false);
 
 	if ((p = strrchr(ucl_object_tostring(hostval), ':')) != nullptr) {
@@ -1405,30 +1388,29 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
 	}
 
 	/* Now make url */
-	urlstr = g_string_sized_new(63);
-	pathval = ucl_object_lookup(obj, "path");
+	auto urlstr = std::string{};
+	const auto *pathval = ucl_object_lookup(obj, "path");
 
 	if (!has_proto) {
-		g_string_append_len(urlstr, "http://", sizeof("http://") - 1);
+		urlstr += "http://";
 	}
 
-	g_string_append(urlstr, ucl_object_tostring(hostval));
+	urlstr += ucl_object_tostring(hostval);
 
 	if (!has_port) {
-		g_string_append(urlstr, ":11334");
+		urlstr += ":11334";
 	}
 
 	if (pathval == nullptr) {
-		g_string_append(urlstr, "/");
+		urlstr += "/";
 	}
 	else {
-		g_string_append(urlstr, ucl_object_tostring(pathval));
+		urlstr += ucl_object_tostring(pathval);
 	}
 
 	ucl_object_insert_key(neigh,
-						  ucl_object_fromlstring(urlstr->str, urlstr->len),
+						  ucl_object_fromlstring(urlstr.data(), urlstr.size()),
 						  "url", 0, false);
-	g_string_free(urlstr, TRUE);
 	ucl_object_insert_key(cfg->neighbours, neigh, key, 0, true);
 
 	return TRUE;
@@ -1436,67 +1418,92 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
 
 
 struct rspamd_rcl_section *
-rspamd_rcl_add_section(struct rspamd_rcl_section **top,
+rspamd_rcl_add_section(struct rspamd_rcl_sections_map **top,
+					   struct rspamd_rcl_section *parent_section,
 					   const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
 					   enum ucl_type type, gboolean required, gboolean strict_type)
 {
-	struct rspamd_rcl_section *new;
-	ucl_object_t *parent_doc;
-
-	new = g_malloc0(sizeof(struct rspamd_rcl_section));
-	new->name = name;
-	new->key_attr = key_attr;
-	new->handler = handler;
-	new->type = type;
-	new->strict_type = strict_type;
-
-	if (*top == nullptr) {
-		parent_doc = nullptr;
-		new->doc_ref = nullptr;
-	}
-	else {
-		parent_doc = (*top)->doc_ref;
-		new->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(parent_doc,
-															 nullptr,
-															 name,
-															 type,
-															 nullptr,
-															 0,
-															 nullptr,
-															 0));
-	}
-
-	HASH_ADD_KEYPTR(hh, *top, new->name, strlen(new->name), new);
-	return new;
+	return rspamd_rcl_add_section_doc(top, parent_section, name, key_attr, handler,
+									  type, required, strict_type, nullptr, nullptr);
 }
 
 struct rspamd_rcl_section *
-rspamd_rcl_add_section_doc(struct rspamd_rcl_section **top,
+rspamd_rcl_add_section_doc(struct rspamd_rcl_sections_map **top,
+						   struct rspamd_rcl_section *parent_section,
 						   const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
 						   enum ucl_type type, gboolean required, gboolean strict_type,
 						   ucl_object_t *doc_target,
 						   const gchar *doc_string)
 {
-	struct rspamd_rcl_section *new_section;
-
-	new_section = g_malloc0(sizeof(struct rspamd_rcl_section));
-	new_section->name = name;
-	new_section->key_attr = key_attr;
-	new_section->handler = handler;
-	new_section->type = type;
-	new_section->strict_type = strict_type;
-
-	new_section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(doc_target,
-																 doc_string,
-																 name,
-																 type,
-																 nullptr,
-																 0,
-																 nullptr,
-																 0));
-
-	HASH_ADD_KEYPTR(hh, *top, new_section->name, strlen(new_section->name), new_section);
-	return new_section;
+	if (top == nullptr) {
+		g_error("invalid arguments to rspamd_rcl_add_section");
+		return nullptr;
+	}
+	if (*top == nullptr) {
+		*top = new rspamd_rcl_sections_map;
+	}
+
+	auto fill_section = [&](struct rspamd_rcl_section *section) {
+		section->name = name;
+		if (key_attr) {
+			section->key_attr = std::string{key_attr};
+		}
+		section->handler = handler;
+		section->type = type;
+		section->strict_type = strict_type;
+
+		if (doc_target == nullptr) {
+			if (parent_section && parent_section->doc_ref) {
+				section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(parent_section->doc_ref,
+																		 doc_string,
+																		 name,
+																		 type,
+																		 nullptr,
+																		 0,
+																		 nullptr,
+																		 0));
+			}
+			else {
+				section->doc_ref = nullptr;
+			}
+		}
+		else {
+			section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(doc_target,
+																	 doc_string,
+																	 name,
+																	 type,
+																	 nullptr,
+																	 0,
+																	 nullptr,
+																	 0));
+		}
+		section->top = *top;
+	};
+
+	/* Select the appropriate container and insert section inside it */
+	if (parent_section) {
+		auto it = parent_section->subsections.insert(std::make_pair(std::string{name},
+																	std::make_shared<rspamd_rcl_section>()));
+		if (!it.second) {
+			g_error("invalid arguments to rspamd_rcl_add_section");
+			return nullptr;
+		}
+
+		fill_section(it.first->second.get());
+		return it.first->second.get();
+	}
+	else {
+		auto it = (*top)->sections.insert(std::make_pair(std::string{name},
+														 std::make_shared<rspamd_rcl_section>()));
+		if (!it.second) {
+			g_error("invalid arguments to rspamd_rcl_add_section");
+			return nullptr;
+		}
+
+		(*top)->sections_order.push_back(it.first->second);
+		fill_section(it.first->second.get());
+		return it.first->second.get();
+	}
 }
 
 struct rspamd_rcl_default_handler_data *
@@ -1507,13 +1514,13 @@ rspamd_rcl_add_default_handler(struct rspamd_rcl_section *section,
 							   gint flags,
 							   const gchar *doc_string)
 {
-	struct rspamd_rcl_default_handler_data *nhandler;
+	auto it = section->default_parser.emplace(std::make_pair(std::string{name}, rspamd_rcl_default_handler_data{}));
 
-	nhandler = g_malloc0(sizeof(struct rspamd_rcl_default_handler_data));
-	nhandler->key = g_strdup(name);
-	nhandler->handler = handler;
-	nhandler->pd.offset = offset;
-	nhandler->pd.flags = flags;
+	auto &nhandler = it.first->second;
+	nhandler.key = name;
+	nhandler.handler = handler;
+	nhandler.pd.offset = offset;
+	nhandler.pd.flags = flags;
 
 	if (section->doc_ref != nullptr) {
 		rspamd_rcl_add_doc_obj(section->doc_ref,
@@ -1526,15 +1533,13 @@ rspamd_rcl_add_default_handler(struct rspamd_rcl_section *section,
*** OUTPUT TRUNCATED, 919 LINES SKIPPED ***


More information about the Commits mailing list