Browse files

Added custom config validator for unrecognized options

  • Loading branch information...
1 parent 883f68a commit c908a04979f208e50257de8c65e8127b601c95b9 @saleyn committed Jul 15, 2014
Showing with 62 additions and 34 deletions.
  1. +11 −11 bin/config_validator_codegen.py
  2. +22 −7 include/utxx/config_validator.hpp
  3. +4 −1 include/utxx/variant_tree.hpp
  4. +25 −15 src/config_validator.cpp
View
22 bin/config_validator_codegen.py
@@ -330,21 +330,12 @@ def run(self):
f.write(" using namespace utxx;\n")
f.write(" typedef\n")
f.write(" boost::property_tree::translator_between<variant, std::string>\n")
- f.write(" translator;\n\n")
+ f.write(" translator;\n")
max_name_size = max([len(n) for n in names])
max_val_size = max([len(n) for n in values]) if len(values) > 0 else 0
max_width = max(max_name_size, max_val_size)
- f.write(" //---------- Configuration Options ------------\n")
- for n in names:
- u = format_name(n)
- f.write(' static const char CFG_%s[]%s = "%s";\n' % (u, ' ' * (max_width - len(n) + 4), n))
- f.write("\n")
- f.write(" //---------- Configuration Values -------------\n")
- for n in values:
- u = n.upper()
- f.write(' static const char CFG_VAL_%s[]%s = "%s";\n' % (u, ' ' * (max_width - len(n)), n))
f.write("\n" +
" namespace {\n" +
" typedef config::option_map ovec;\n" +
@@ -357,6 +348,15 @@ def run(self):
f.write(" variant v() const { return variant(); }\n")
f.write(" variant v(const char* s) const { return *tr.put_value(s); }\n")
f.write(" public:\n")
+ f.write(" //---------- Configuration Options ------------\n")
+ for n in names:
+ u = format_name(n)
+ f.write(' static constexpr const char* %s()%s { return "%s"; }\n' % (u, ' ' * (max_width - len(n)), n))
+ f.write(" //---------- Configuration Values -------------\n")
+ for n in values:
+ u = n.upper()
+ f.write(' static constexpr const char* VAL_%s()%s { return "%s"; }\n' % (u, ' ' * (max_width - len(n)), n))
+ f.write("\n")
f.write(" static const %s* instance() {\n" % name)
f.write(" static %s s_instance;\n" % name)
f.write(" return &s_instance;\n")
@@ -465,7 +465,7 @@ def process_options(self, f, root, level=0, arg='m_options'):
valtp = 'string' if not tp and subopts else valtype;
f.write("%sadd_option(%s,\n" % (ws1, arg))
- f.write("%sconfig::option(CFG_%s, %s, %s,\n"
+ f.write("%sconfig::option(%s(), %s, %s,\n"
'%s "%s", %s, %s, %s,\n'
"%s v(%s), v(%s), v(%s), l_names, l_values, l_children%d));\n"
"%s}\n" % (
View
29 include/utxx/config_validator.hpp
@@ -237,12 +237,20 @@ namespace config {
variant default_subst_value() const;
};
+ /// Performs custom validation of unrecognized options
+ /// @return true if given option is valid.
+ typedef std::function
+ <bool (const tree_path& a_path,
+ const std::string& a_name,
+ const variant& a_value)> custom_validator;
+
class validator {
void check_option(
const tree_path& a_root,
typename variant_tree_base::value_type& a_vt,
const option& a_opt,
- bool a_fill_defaults
+ bool a_fill_defaults,
+ const custom_validator& a_custom_validator
) const throw(std::invalid_argument, variant_tree_error);
void check_unique(const tree_path& a_root, const variant_tree_base& a_config,
@@ -277,14 +285,18 @@ namespace config {
throw ();
protected:
- tree_path m_root; // Path from configuration root
+ tree_path m_root; // Path from configuration root
option_map m_options;
void validate(const tree_path& a_root, variant_tree_base& a_config,
- const option_map& a_opts, bool fill_defaults) const throw(variant_tree_error);
+ const option_map& a_opts, bool fill_defaults,
+ const custom_validator& a_custom_validator
+ ) const throw(variant_tree_error);
void validate(variant_tree& a_config,
- const option_map& a_opts, bool fill_defaults) const throw(variant_tree_error);
+ const option_map& a_opts, bool fill_defaults,
+ const custom_validator& a_custom_validator
+ ) const throw(variant_tree_error);
static void add_option(option_map& a, const option& a_opt) {
a.insert(std::make_pair(a_opt.name, a_opt));
@@ -327,10 +339,13 @@ namespace config {
/// property
const tree_path& root() const { return m_root; }
- void validate(variant_tree& a_config, bool a_fill_defaults)
- const throw(variant_tree_error);
+ void validate(variant_tree& a_config, bool a_fill_defaults,
+ const custom_validator& a_custom_validator = NULL
+ ) const throw(variant_tree_error);
- void validate(const variant_tree& a_config) const throw(variant_tree_error);
+ void validate(const variant_tree& a_config,
+ const custom_validator& a_custom_validator = NULL
+ ) const throw(variant_tree_error);
};
} // namespace config
View
5 include/utxx/variant_tree.hpp
@@ -514,7 +514,10 @@ class basic_variant_tree : public basic_variant_tree_base<Ch>
/// Validate content of this tree against the custom validator
/// @param a_schema if not NULL use this schema validator otherwise
/// use internal validator().
- void validate(const config::validator* a_schema = NULL) const {
+ void validate(
+ const config::validator* a_schema = NULL,
+ const config::custom_validator& a_custom_validator = NULL
+ ) const {
if (!a_schema && !m_schema_validator)
throw std::runtime_error("Unassigned validator!");
if (a_schema)
View
40 src/config_validator.cpp
@@ -225,35 +225,40 @@ tree_path validator::format_name
void validator::validate
(
- variant_tree& a_config, bool a_fill_defaults
+ variant_tree& a_config, bool a_fill_defaults,
+ const custom_validator& a_custom_validator
)
const throw(variant_tree_error)
{
- validate(a_config, m_options, a_fill_defaults);
+ validate(a_config, m_options, a_fill_defaults, a_custom_validator);
}
-void validator::validate(const variant_tree& a_config)
- const throw(variant_tree_error)
+void validator::validate(const variant_tree& a_config,
+ const custom_validator& a_custom_validator
+) const throw(variant_tree_error)
{
variant_tree l_config(a_config);
- validate(l_config, false);
+ validate(l_config, false, a_custom_validator);
}
void validator::validate
(
- variant_tree& a_config,
- const option_map& a_opts,
- bool fill_defaults
+ variant_tree& a_config,
+ const option_map& a_opts,
+ bool a_fill_defaults,
+ const custom_validator& a_custom_validator
)
const throw(variant_tree_error)
{
- validate(a_config.root_path(), a_config.to_base(), a_opts, fill_defaults);
+ validate(a_config.root_path(), a_config.to_base(), a_opts, a_fill_defaults,
+ a_custom_validator);
}
void validator::validate
(
const tree_path& a_root, variant_tree_base& a_config,
- const option_map& a_opts, bool a_fill_defaults
+ const option_map& a_opts, bool a_fill_defaults,
+ const custom_validator& a_custom_validator
)
const throw (variant_tree_error)
{
@@ -270,18 +275,21 @@ void validator::validate
vt.first, vt.second.data().to_string()),
"Check XML spec. Cannot mix anonymous and named options "
"in one section!");
- check_option(a_root, vt, opt, a_fill_defaults);
+ check_option(a_root, vt, opt, a_fill_defaults, a_custom_validator);
l_match = true;
break;
} else if (opt.name == vt.first) {
- check_option(a_root, vt, opt, a_fill_defaults);
+ check_option(a_root, vt, opt, a_fill_defaults, a_custom_validator);
l_match = true;
break;
}
}
if (!l_match) {
tree_path p; p /= vt.first;
- throw variant_tree_error(p, "Unsupported config option!");
+ if (a_custom_validator)
+ l_match = a_custom_validator(a_root, vt.first, vt.second.data());
+ if (!l_match)
+ throw variant_tree_error(p, "Unsupported config option!");
}
}
}
@@ -406,7 +414,8 @@ check_option
(
const tree_path& a_root,
typename variant_tree_base::value_type& a_vt,
- const option& a_opt, bool a_fill_defaults
+ const option& a_opt, bool a_fill_defaults,
+ const custom_validator& a_custom_validator
)
const throw(std::invalid_argument, variant_tree_error)
{
@@ -505,7 +514,8 @@ check_option
"Value is not allowed for option!");
}
if (!a_opt.children.empty())
- validate(a_root / a_opt.name, a_vt.second, a_opt.children, a_fill_defaults);
+ validate(a_root / a_opt.name, a_vt.second, a_opt.children, a_fill_defaults,
+ a_custom_validator);
} catch (std::invalid_argument& e) {
throw variant_tree_error(format_name(a_root, a_opt, a_vt.first,
a_vt.second.data().to_string()),

0 comments on commit c908a04

Please sign in to comment.