23#include "flow/error/error.hpp"
25#include <boost/algorithm/string.hpp>
26#include <boost/unordered_set.hpp>
54 S_FILL_PARSING_ROLE_OPT_TABLE,
62 S_FILL_OUTPUT_HELP_ROLE_OPT_TABLE,
71 S_FILL_OUTPUT_CURRENT_ROLE_OPT_TABLE,
80 S_COMPARE_PARSED_VALS,
90 S_LOAD_VALS_AS_IF_PARSED,
100 S_VALIDATE_STORED_VALS
129 template<
typename Value>
131 const Value& value_default,
const Value& current_value,
155 template<
typename Value>
157 Function<
bool (
const Value& val)>&& validator_func_moved,
235 template<
typename Value>
238 Function<
bool (
const Value& val)>&& validator_func_moved,
417template<
typename Value_set>
421 private boost::noncopyable
699 bool* success_or_null = 0);
809 bool* success_or_null = 0,
810 const boost::unordered_set<std::string>& allowed_unregistered_opts_or_empty = {});
926 template<
typename Value>
928 Function<
bool (
const Value& val)>&& validator_func_moved,
950 template<
typename Value>
969 template<
typename Value>
993 template<
typename Value>
1022 const boost::unordered_set<std::string>&
option_names()
const;
1157#define FLOW_CFG_OPTION_SET_DECLARE_OPTION(ARG_m_value, ARG_description, ARG_bool_validate_expr) \
1158 FLOW_CFG_OPTION_SET_DECLARE_OPTION_WITH_KNOBS(ARG_m_value, ARG_description, ARG_bool_validate_expr, false)
1178#define FLOW_CFG_OPTION_SET_DECLARE_OPTION_NO_ACC(ARG_m_value, ARG_description, ARG_bool_validate_expr) \
1179 FLOW_CFG_OPTION_SET_DECLARE_OPTION_WITH_KNOBS(ARG_m_value, ARG_description, ARG_bool_validate_expr, true)
1277#define FLOW_CFG_OPTION_SET_DECLARE_OPTION_KEYED(ARG_m_value, ARG_description, ARG_bool_validate_expr, ARG_key) \
1278 FLOW_UTIL_SEMICOLON_SAFE \
1280 const ::std::string FLOW_CFG_SET_DECL_OPT_KEYED_name \
1281 = ::flow::cfg::value_set_member_id_to_opt_name_keyed(#ARG_m_value, ARG_key); \
1282 FLOW_CFG_OPTION_SET_DECLARE_OPTION_MANUALLY_NAMED \
1283 (ARG_m_value, FLOW_CFG_SET_DECL_OPT_KEYED_name.c_str(), ARG_description, ARG_bool_validate_expr, false); \
1301#define FLOW_CFG_OPTION_SET_DECLARE_OPTION_KEYED_NO_ACC(ARG_m_value, ARG_description, ARG_bool_validate_expr, ARG_key) \
1302 FLOW_UTIL_SEMICOLON_SAFE \
1304 const ::std::string FLOW_CFG_SET_DECL_OPT_KEYED_name \
1305 = ::flow::cfg::value_set_member_id_to_opt_name_keyed(#ARG_m_value, ARG_key); \
1306 FLOW_CFG_OPTION_SET_DECLARE_OPTION_MANUALLY_NAMED \
1307 (ARG_m_value, FLOW_CFG_SET_DECL_OPT_KEYED_name.c_str(), ARG_description, ARG_bool_validate_expr, true); \
1330#define FLOW_CFG_OPTION_SET_DECLARE_OPTION_WITH_KNOBS(ARG_m_value, ARG_description, ARG_bool_validate_expr, \
1331 ARG_no_accumulation) \
1332 FLOW_UTIL_SEMICOLON_SAFE \
1334 const ::std::string FLOW_CFG_SET_DECL_OPT_name = ::flow::cfg::value_set_member_id_to_opt_name(#ARG_m_value); \
1335 FLOW_CFG_OPTION_SET_DECLARE_OPTION_MANUALLY_NAMED \
1336 (ARG_m_value, FLOW_CFG_SET_DECL_OPT_name.c_str(), ARG_description, ARG_bool_validate_expr, \
1337 ARG_no_accumulation); \
1369#define FLOW_CFG_OPTION_SET_DECLARE_OPTION_MANUALLY_NAMED(ARG_m_value, ARG_opt_name_c_str, \
1370 ARG_description, ARG_bool_validate_expr, \
1371 ARG_no_accumulation) \
1372 FLOW_UTIL_SEMICOLON_SAFE \
1374 char const * const FLOW_CFG_SET_DECL_OPT_MANUAL_name_c_str = ARG_opt_name_c_str; \
1376 const ::flow::util::String_view FLOW_CFG_SET_DECL_OPT_MANUAL_name_view(FLOW_CFG_SET_DECL_OPT_MANUAL_name_c_str); \
1377 const bool FLOW_CFG_SET_DECL_OPT_MANUAL_no_acc = ARG_no_accumulation; \
1378 switch (args.m_call_type) \
1380 case ::flow::cfg::Option_set_base::Declare_options_func_call_type::S_FILL_PARSING_ROLE_OPT_TABLE: \
1382 using Value = decltype(args.m_args.m_fill_parsing_role_opt_table_args.m_values_candidate->ARG_m_value); \
1385 flow::Function<bool (const Value&)> FLOW_CFG_SET_DECL_OPT_MANUAL_validator_func \
1386 = [FLOW_CFG_SET_DECL_OPT_MANUAL_name_std_str = std::string(FLOW_CFG_SET_DECL_OPT_MANUAL_name_c_str)] \
1387 ([[maybe_unused]] const Value& val) -> bool { return ARG_bool_validate_expr; }; \
1388 args.m_args.m_fill_parsing_role_opt_table_args.m_option_set \
1389 ->declare_option_for_parsing \
1390 (FLOW_CFG_SET_DECL_OPT_MANUAL_name_view, \
1391 &args.m_args.m_fill_parsing_role_opt_table_args.m_values_candidate->ARG_m_value, \
1397 FLOW_CFG_SET_DECL_OPT_MANUAL_no_acc \
1398 ? &args.m_args.m_fill_parsing_role_opt_table_args.m_values_default_no_acc->ARG_m_value \
1400 ::std::move(FLOW_CFG_SET_DECL_OPT_MANUAL_validator_func), \
1401 ::flow::util::String_view(#ARG_bool_validate_expr)); \
1404 case ::flow::cfg::Option_set_base::Declare_options_func_call_type::S_FILL_OUTPUT_HELP_ROLE_OPT_TABLE: \
1405 args.m_args.m_fill_output_help_role_opt_table_args.m_option_set \
1406 ->declare_option_for_help \
1407 (FLOW_CFG_SET_DECL_OPT_MANUAL_name_view, \
1408 args.m_args.m_fill_output_help_role_opt_table_args.m_values_default->ARG_m_value, \
1411 case ::flow::cfg::Option_set_base::Declare_options_func_call_type::S_FILL_OUTPUT_CURRENT_ROLE_OPT_TABLE: \
1412 ::flow::cfg::Option_set_base::declare_option_for_output \
1413 (FLOW_CFG_SET_DECL_OPT_MANUAL_name_view, \
1414 args.m_args.m_fill_output_current_role_opt_table_args.m_target_opts, \
1415 args.m_args.m_fill_output_current_role_opt_table_args.m_values_default->ARG_m_value, \
1416 args.m_args.m_fill_output_current_role_opt_table_args.m_values_current->ARG_m_value, \
1419 case ::flow::cfg::Option_set_base::Declare_options_func_call_type::S_COMPARE_PARSED_VALS: \
1420 args.m_args.m_compare_parsed_vals_args.m_option_set \
1421 ->scan_parsed_option \
1422 (FLOW_CFG_SET_DECL_OPT_MANUAL_name_view, \
1423 args.m_args.m_compare_parsed_vals_args.m_option_set->values().ARG_m_value); \
1425 case ::flow::cfg::Option_set_base::Declare_options_func_call_type::S_LOAD_VALS_AS_IF_PARSED: \
1426 args.m_args.m_load_val_as_if_parsed_args.m_option_set \
1427 ->load_option_value_as_if_parsed \
1428 (FLOW_CFG_SET_DECL_OPT_MANUAL_name_view, \
1429 &args.m_args.m_load_val_as_if_parsed_args.m_values_candidate->ARG_m_value, \
1430 args.m_args.m_load_val_as_if_parsed_args.m_values_to_load->ARG_m_value); \
1432 case ::flow::cfg::Option_set_base::Declare_options_func_call_type::S_VALIDATE_STORED_VALS: \
1435 using Value = decltype(args.m_args.m_validate_stored_vals_args.m_values_to_validate->ARG_m_value); \
1436 flow::Function<bool (const Value&)> FLOW_CFG_SET_DECL_OPT_MANUAL_validator_func \
1437 = [FLOW_CFG_SET_DECL_OPT_MANUAL_name_std_str = std::string(FLOW_CFG_SET_DECL_OPT_MANUAL_name_c_str)] \
1438 ([[maybe_unused]] const Value& val) -> bool { return ARG_bool_validate_expr; }; \
1440 ::flow::cfg::Option_set_base::validate_parsed_option \
1441 (FLOW_CFG_SET_DECL_OPT_MANUAL_name_view, \
1442 args.m_args.m_validate_stored_vals_args.m_values_to_validate->ARG_m_value, \
1443 ::std::move(FLOW_CFG_SET_DECL_OPT_MANUAL_validator_func), \
1444 ::flow::util::String_view(#ARG_bool_validate_expr)); \
1453template<
typename Value_set>
1457 m_nickname(nickname),
1459 m_declare_opts_func(std::move(declare_opts_func_moved)),
1463 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: Created with default values payload. Options table setup begins.");
1480 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: Options table setup finished. Null set? = [" <<
null() <<
"].");
1483template<
typename Value_set>
1489template<
typename Value_set>
1495template<
typename Value_set>
1501template<
typename Value_set>
1504 return m_parsing ? &m_values_candidate : 0;
1507template<
typename Value_set>
1512 constexpr unsigned int LINE_LENGTH = 1000;
1513 constexpr unsigned int DESC_LENGTH = LINE_LENGTH - 1;
1515 Opt_table opts_for_output(LINE_LENGTH, DESC_LENGTH);
1518 args.
m_call_type = Declare_options_func_args::Call_type::S_FILL_OUTPUT_CURRENT_ROLE_OPT_TABLE;
1520 = { &opts_for_output, &m_values_default,
1521 values_or_null ? values_or_null : &m_values };
1522 m_declare_opts_func(args);
1524 os << opts_for_output;
1527template<
typename Value_set>
1534 values_to_ostream(os.os(), values_or_null);
1536 FLOW_LOG_WITH_CHECKING(sev,
"Option_set[" << *
this <<
"]: Values payload [" << summary <<
"]:\n" << os.str());
1539template<
typename Value_set>
1542 os << m_opts_for_help;
1545template<
typename Value_set>
1552 help_to_ostream(os.os());
1557template<
typename Value_set>
1563template<
typename Value_set>
1564template<
typename Value>
1566 Value* target_value,
const Value* value_default_if_no_acc,
1567 Function<
bool (
const Value& val)>&& validator_func_moved,
1575 assert(target_value);
1576 string name(name_view);
1578 m_opt_names.insert(name);
1581 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: Options table of parsing-role: "
1582 "Declaring parsing-capable option [" << name <<
"]; raw shallow size [" <<
sizeof(Value) <<
"].");
1587 const auto val_spec = value<Value>(target_value)
1588 ->notifier(throw_on_invalid_func(name_view, std::move(validator_func_moved),
1589 validator_cond_str_view));
1594 if (value_default_if_no_acc)
1597 String_ostream default_str_os;
1599 default_str_os.os() << flush;
1601 val_spec->default_value(*value_default_if_no_acc, default_str_os.str());
1604 m_opts_for_parsing.add_options()(name.c_str(), val_spec);
1609template<
typename Value>
1612 Function<
bool (
const Value& val)>&& validator_func_moved,
1620 return [validator_func = std::move(validator_func_moved),
1621 validator_cond_str = string(validator_cond_str_view),
1622 name = string(name_view)]
1625 if (!(validator_func(val)))
1627 String_ostream msg_os;
1628 msg_os.
os() <<
"Option [" << name <<
"]: "
1629 "Validation failed; the following condition must hold: [" << validator_cond_str <<
"]. "
1630 "Option value `val` = [";
1632 msg_os.os() <<
"]." << flush;
1633 throw Runtime_error(msg_os.str());
1638template<
typename Value_set>
1639template<
typename Value>
1648 assert(!description.empty());
1654 String_ostream default_str_os;
1656 default_str_os.os() << flush;
1658 m_opts_for_help.add_options()
1659 (string(name).c_str(),
1662 ->default_value(value_default, default_str_os.str()),
1663 string(description).c_str());
1668template<
typename Value>
1670 const Value& value_default,
const Value& current_value,
1678 assert(!description.empty());
1687 String_ostream description_os;
1691 description_os.os() <<
" (";
1695 description_os.os() <<
") <==current | default==^\n"
1696 " " << description << flush;
1699 String_ostream default_str_os;
1701 default_str_os.os() << flush;
1703 target_opts->add_options()
1704 (string(name).c_str(),
1707 ->default_value(value_default, default_str_os.str()),
1708 description_os.str().c_str());
1713template<
typename Value_set>
1714template<
typename Value>
1717 using boost::any_cast;
1719 string name(name_view);
1727 const auto it = m_iterable_values_candidate.find(name);
1728 if (it == m_iterable_values_candidate.end())
1734 const auto& new_val = any_cast<const Value&>(it->second);
1735 const auto& old_val = canonical_value;
1737 if (old_val == new_val)
1739 m_iterable_values_candidate.erase(name);
1744template<
typename Value_set>
1745template<
typename Value>
1747 Value* target_value,
1748 const Value& source_value)
1751 string name(name_view);
1753 assert(target_value);
1761 *target_value = source_value;
1764 m_iterable_values_candidate[name] = source_value;
1772template<
typename Value>
1774 Function<
bool (
const Value& val)>&& validator_func_moved,
1777 const auto validate_or_throw_func =
throw_on_invalid_func(name_view, std::move(validator_func_moved),
1778 validator_cond_str_view);
1779 validate_or_throw_func(value);
1782template<
typename Value_set>
1784 (
const fs::path& cfg_path,
bool allow_unregistered,
bool* success_or_null,
1785 const boost::unordered_set<std::string>& allowed_unregistered_opts_or_empty)
1792 using opts::variables_map;
1793 using boost::system::system_category;
1795 using std::exception;
1799 if (success_or_null)
1803 parse_config_file(cfg_path, allow_unregistered, 0, allowed_unregistered_opts_or_empty);
1805 catch (
const exception& exc)
1808 *success_or_null =
false;
1811 *success_or_null =
true;
1819 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: State CANONICAL: Request to parse file [" << cfg_path <<
"]; "
1820 "entering state PARSING. Initial candidate values payload initialized from current canonical "
1821 "values payload. Details follow (TRACE log level).");
1823 assert(m_iterable_values_candidate.empty());
1827 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: State PARSING: Request to parse file [" << cfg_path <<
"]; "
1828 "continuing by parsing this next config source. "
1829 "The values payload going into it is as it was after the previous config source. "
1830 "Details follow (TRACE log level).");
1833 log_values(
"pre-parsing candidate config", &m_values_candidate,
log::Sev::S_TRACE);
1835 ifstream ifs(cfg_path);
1838 const Error_code sys_err_code(errno, system_category());
1841 throw Runtime_error(sys_err_code,
ostream_op_string(
"Could not open file [", cfg_path,
"]."));
1851 const auto values_candidate_backup = m_values_candidate;
1852 opts::parsed_options parsed_options(&m_opts_for_parsing);
1855 parsed_options = opts::parse_config_file(ifs, m_opts_for_parsing, allow_unregistered);
1857 catch (
const exception& exc)
1859 m_values_candidate = values_candidate_backup;
1863 "Parsing file [" << cfg_path <<
"]: Exception occurred; parse failed. Values payload untouched. "
1864 "Message = [" << exc.what() <<
"].");
1872 if (allow_unregistered)
1874 for (
const auto& option : parsed_options.options)
1876 if (option.unregistered)
1878 assert(!option.original_tokens.empty());
1879 const string opt_name = option.original_tokens.front();
1881 if (allowed_unregistered_opts_or_empty.empty())
1884 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: State PARSING: Ignoring unregistered option named "
1885 "[" << opt_name <<
"]. We were not given an approved-list. Perhaps this file contains "
1886 "other option sets, or it has to do with forward/backward-compatibility.");
1890 if (!
key_exists(allowed_unregistered_opts_or_empty, opt_name))
1893 m_values_candidate = values_candidate_backup;
1895 FLOW_LOG_WARNING(
"Option_set[" << *
this <<
"]: State PARSING: Unregistered option named "
1896 "[" << opt_name <<
"] is not approved; parse failed. Values payload untouched.");
1898 "] is not approved; parse failed."));
1903 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: State PARSING: Ignoring unregistered option named "
1904 "[" << opt_name <<
"]; it is in the approved-list. Perhaps this file contains "
1905 "other option sets.");
1915 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: State PARSING: Parsed general format successfully. "
1916 "Will now parse each option's value.");
1926 variables_map fresh_iterable_values;
1929 store(parsed_options, fresh_iterable_values);
1931 catch (
const exception& exc)
1934 m_values_candidate = values_candidate_backup;
1937 "Parsed file [" << cfg_path <<
"]: Exception occurred; individual option parsing failed. "
1938 "Values payload untouched. Message = [" << exc.what() <<
"].");
1942 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: State PARSING: Parsed each individual option successfully. "
1943 "Will now further validate each option value logically and store on success.");
1949 notify(fresh_iterable_values);
1951 catch (
const exception& exc)
1954 m_values_candidate = values_candidate_backup;
1957 "Parsed file [" << cfg_path <<
"]: Exception occurred; individual logical validation failed. "
1958 "Values payload untouched. Message = [" << exc.what() <<
"].");
1963 for (
const auto& pair : fresh_iterable_values)
1965 const auto& name = pair.first;
1966 const auto& var_value = pair.second.value();
1968 assert((!
key_exists(m_iterable_values_candidate, name) ||
1969 (m_iterable_values_candidate[name].type() == var_value.type())));
1971 m_iterable_values_candidate[name] = var_value;
1976 args.
m_call_type = Declare_options_func_args::Call_type::S_COMPARE_PARSED_VALS;
1978 m_declare_opts_func(args);
1986 FLOW_LOG_TRACE(
"Option_set[" << *
this <<
"]: State PARSING: Validate/store succeded. "
1987 "Further validation deferred until attempt to enter state CANONICAL. "
1988 "Updated values payload details follow.");
1989 log_values(
"post-parsing candidate config", &m_values_candidate,
log::Sev::S_TRACE);
1992template<
typename Value_set>
1998 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: State CANONICAL: Request to load values from source struct "
1999 "[" << &src_values <<
"]; entering state PARSING. "
2000 "Any preceding canonical state will be ignored. Details follow (TRACE log level).");
2002 assert(m_iterable_values_candidate.empty());
2006 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: State PARSING: Request to load values from source struct "
2007 "[" << &src_values <<
"]; continuing by parsing this next config source. "
2008 "Any current candidate values payload will be overwritten entirely. "
2009 "Details follow (TRACE log level).");
2024 args.
m_call_type = Declare_options_func_args::Call_type::S_LOAD_VALS_AS_IF_PARSED;
2026 m_declare_opts_func(args);
2034 args.
m_call_type = Declare_options_func_args::Call_type::S_COMPARE_PARSED_VALS;
2036 m_declare_opts_func(args);
2038 log_values(
"post-loading (perhaps baseline or rewound) candidate config", &m_values_candidate,
log::Sev::S_TRACE);
2041template<
typename Value_set>
2048 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: State PARSING: Entering state CANONICAL. "
2049 "Values payload finalized. Details follow (TRACE log level).");
2050 log_values(
"entering-CANONICAL-state finalized config", &m_values_candidate,
log::Sev::S_TRACE);
2056 for (
const auto& pair : m_iterable_values_candidate)
2058 const auto& name = pair.first;
2059 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: Detected change in option named [" << name <<
"].");
2062 if (change_detected)
2064 *change_detected = (!m_iterable_values_candidate.empty());
2070 m_values = m_values_candidate;
2071 m_iterable_values_candidate.clear();
2074template<
typename Value_set>
2079 FLOW_LOG_INFO(
"Option_set[" << *
this <<
"]: State PARSING: Rejecting candidate payload built; "
2080 "reverting to state CANONICAL.");
2082 m_iterable_values_candidate.clear();
2087template<
typename Value_set>
2090 validate_values(values(), success_or_null);
2093template<
typename Value_set>
2096 const auto candidate = values_candidate();
2097 assert(candidate &&
"Do not invoke validate_values_candidate() in CANONICAL state; only while PARSING.");
2098 validate_values(*candidate, success_or_null);
2101template<
typename Value_set>
2104 bool* success_or_null)
2106 using std::exception;
2109 if (success_or_null)
2113 validate_values(logger_ptr, values_to_validate, declare_opts_func);
2115 catch (
const exception& exc)
2118 *success_or_null =
false;
2121 *success_or_null =
true;
2129 args.
m_call_type = Declare_options_func_args::Call_type::S_VALIDATE_STORED_VALS;
2138 declare_opts_func(args);
2140 catch (
const exception& exc)
2142 FLOW_LOG_WARNING(
"Stand-alone validation check failed: Details: [" << exc.what() <<
"].");
2147template<
typename Value_set>
2150 validate_values(get_logger(), values_to_validate, m_declare_opts_func, success_or_null);
2153template<
typename Value_set>
2156 return os <<
'[' << val.
m_nickname <<
"]@" << &val;
2159template<
typename Value>
2165template<
typename Rep,
typename Period>
2170 using boost::chrono::ceil;
2171 using boost::chrono::nanoseconds;
2172 using boost::chrono::microseconds;
2173 using boost::chrono::milliseconds;
2174 using boost::chrono::seconds;
2175 using boost::chrono::minutes;
2176 using boost::chrono::hours;
2179 using raw_ticks_t = uint64_t;
2182 nanoseconds val_ns(val);
2185 raw_ticks_t raw_abs_ticks = (val_ns.count() < 0) ? (-val_ns.count()) : val_ns.count();
2190 if (raw_abs_ticks == 0)
2192 os << seconds::zero();
2198 const auto try_next_unit = [&](
auto pre_division_dur, raw_ticks_t divide_by) ->
bool
2200 if ((raw_abs_ticks % divide_by) == 0)
2203 raw_abs_ticks /= divide_by;
2211 if (!(try_next_unit(val_ns, 1000)
2212 || try_next_unit(ceil<microseconds>(val), 1000)
2213 || try_next_unit(ceil<milliseconds>(val), 1000)
2214 || try_next_unit(ceil<seconds>(val), 60)
2215 || try_next_unit(ceil<minutes>(val), 60)))
2217 os << ceil<hours>(val);
2221template<
typename Element>
2224 for (
size_t idx = 0; idx != val.size(); ++idx)
2227 value_to_ostream<Element>(os, val[idx]);
2229 if (idx != (val.size() - 1))
2236template<
typename Key>
2242 using boost::regex_match;
2243 using boost::smatch;
2252 smatch matched_groups;
2256 const string member_id_str(member_id);
2258 const bool matched_ok =
2261 assert(matched_ok &&
"Member identifier must look like: <longest possible stuff>[<key to replace>]<the rest>");
2263 constexpr char INDEX_SEP_BEFORE(
'.');
Un-templated base for Option_set.
static void declare_option_for_output(util::String_view name, opts::options_description *target_opts, const Value &value_default, const Value ¤t_value, util::String_view description)
Internal-through-macro helper function; the user shall not call this directly but only through FLOW_C...
static Function< void(const Value &val)> throw_on_invalid_func(util::String_view name, Function< bool(const Value &val)> &&validator_func_moved, util::String_view validator_cond_str)
Returns a function that wraps a Value->Boolean validator function, as passed to declare_option_for_pa...
Declare_options_func_call_type
Internal-use type to use with Option_set::Declare_options_func callback.
@ S_FILL_OUTPUT_HELP_ROLE_OPT_TABLE
Internal use only through macro.
@ S_FILL_PARSING_ROLE_OPT_TABLE
Internal use only through macro.
static void validate_parsed_option(util::String_view name, const Value &value, Function< bool(const Value &val)> &&validator_func_moved, util::String_view validator_cond_str)
Internal-through-macro helper function; the user shall not call this directly but only through FLOW_C...
opts::options_description Opt_table
Short-hand for boost.program_options config options description, each of which is used for parsing an...
The core config-parsing facility, which builds parsing/comparison/output capabilities on top of a giv...
typename Values::Ptr Mutable_values_ptr
Short-hand for ref-counted pointer to a mutable Values (config payload storable in an Option_set).
const boost::unordered_set< std::string > & option_names() const
Returns set of all option names declared by the option-declaring function passed to the constructor.
std::map< std::string, boost::any > Iterable_values
Similar to a boost.program_options parsing results variables_map, which conceptually mirrors the resu...
Opt_table m_opts_for_parsing
The parsing-role Opt_table (see extensive explanation in Opt_table doc header).
Iterable_values m_iterable_values_candidate
Structure mirroring m_values_candidate, where the values are the parsing-enabled members of m_values_...
Mutable_values_ptr mutable_values_copy() const
Convenience method that heap-allocates a copy of the internally stored values() and wraps in a ref-co...
void validate_values(bool *success_or_null=0) const
Validates the current contents of values() using the validators *this Option_set<Value_set> is config...
void parse_config_file(const fs::path &cfg_path, bool allow_unregistered, bool *success_or_null=0, const boost::unordered_set< std::string > &allowed_unregistered_opts_or_empty={})
Enters into (from CANONICAL state) or continues in PARSING state by parsing the config source in the ...
const std::string m_nickname
See nickname ctor arg.
boost::unordered_set< std::string > m_opt_names
See option_names().
void log_help(util::String_view summary, log::Sev sev=log::Sev::S_INFO) const
Logs a multi-line help message using help_to_ostream().
Values m_values
See values().
void load_option_value_as_if_parsed(util::String_view name, Value *target_value, const Value &source_value)
Internal-through-macro helper function; the user shall not call this directly but only through FLOW_C...
const Values & values() const
Externally immutable internally stored canonical (current) config values as last constructed or parse...
Declare_options_func m_declare_opts_func
The Opt_table-filling, or m_iterable_values_candidate-scanning, callback passed to the constructor an...
typename Values::Const_ptr Values_ptr
Short-hand for ref-counted pointer to an immutable Value_set (config payload storable in an Option_se...
void canonicalize_candidate(bool *change_detected=0)
In PARSING state enters CANONICAL state, finalizing values() from values_candidate().
void declare_option_for_parsing(util::String_view name, Value *target_value, const Value *value_default_if_no_acc, Function< bool(const Value &val)> &&validator_func_moved, util::String_view validator_cond_str)
Internal-through-macro helper function; the user shall not call this directly but only through FLOW_C...
Opt_table m_opts_for_help
The output-role Opt_table, help-text sub-role (see extensive explanation in Opt_table doc header).
Value_set Values
Short-hand for the template parameter type Value_set.
Option_set(log::Logger *logger_ptr, util::String_view nickname, Declare_options_func &&declare_opts_func_moved)
Constructs an option set in CANONICAL state with a default-valued values() payload and options declar...
bool m_parsing
See values_candidate() – true if and only if that returns non-null (PARSING state; else CANONICAL sta...
void reject_candidate()
In PARSING state, returns to CANONICAL state, as if no parse attempts have occurred.
void log_values(util::String_view summary, const Values *values_or_null=0, log::Sev sev=log::Sev::S_INFO) const
Logs the given values payload using values_to_ostream().
bool null() const
Return true if and only if the option-declaring function passed to the constructor declared no option...
void declare_option_for_help(util::String_view name, const Value &value_default, util::String_view description)
Internal-through-macro helper function; the user shall not call this directly but only through FLOW_C...
void values_to_ostream(std::ostream &os, const Values *values_or_null=0) const
Writes a multi-line user-suitable representation of the current values in a Values object,...
const Values * values_candidate() const
Returns null in CANONICAL state; or in PARSING state a pointer to the not-yet-canonical values after ...
void help_to_ostream(std::ostream &os) const
Prints a multi-line help message about the set of options that *this can parse.
Values m_values_candidate
See values_candidate(). When that returns null (m_parsing == false) this value is meaningless.
void validate_values_candidate(bool *success_or_null=0) const
Equivalent to validate_values(success_or_null) but validates *values_candidate() instead of values().
Values m_values_default
Copy of values() when it is first constructed; i.e., the defaults.
void parse_direct_values(const Values &src_values)
Enters into (from CANONICAL state) or continues in PARSING state by simply setting *values_candidate(...
void scan_parsed_option(util::String_view name, const Value &canonical_value)
Internal-through-macro helper function; the user shall not call this directly but only through FLOW_C...
An std::runtime_error (which is an std::exception) that stores an Error_code.
Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
Similar to ostringstream but allows fast read-only access directly into the std::string being written...
std::ostream & os()
Access to stream that will write to owned string.
#define FLOW_ERROR_SYS_ERROR_LOG_WARNING()
Logs a warning about the (often errno-based or from a library) error code in sys_err_code.
#define FLOW_LOG_INFO(ARG_stream_fragment)
Logs an INFO message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
#define FLOW_LOG_WARNING(ARG_stream_fragment)
Logs a WARNING message into flow::log::Logger *get_logger() with flow::log::Component get_log_compone...
#define FLOW_LOG_WITH_CHECKING(ARG_sev, ARG_stream_fragment)
Logs a message of the specified severity into flow::log::Logger *get_logger() with flow::log::Compone...
#define FLOW_LOG_SET_CONTEXT(ARG_logger_ptr, ARG_component_payload)
For the rest of the block within which this macro is instantiated, causes all FLOW_LOG_....
#define FLOW_LOG_TRACE(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
Flow module that facilitates configuring modules, such as applications and APIs, via statically and/o...
void value_to_ostream(std::ostream &os, const Value &val)
Serializes a value of type Value to the given ostream suitably for output in Option_set-related outpu...
std::string value_set_member_id_to_opt_name(util::String_view member_id)
Utility, used by FLOW_CFG_OPTION_SET_DECLARE_OPTION() internally but made available as a public API i...
std::string value_set_member_id_to_opt_name_keyed(util::String_view member_id, const Key &key)
Similar to value_set_member_id_to_opt_name() but used by FLOW_CFG_OPTION_SET_DECLARE_OPTION_KEYED() i...
const boost::regex VALUE_SET_MEMBER_ID_TO_OPT_NAME_KEYED_REGEX
An internal constant for value_set_member_id_to_opt_name_keyed().
std::ostream & operator<<(std::ostream &os, const Option_set< Value_set > &val)
Serializes (briefly) an Option_set to a standard output stream.
Sev
Enumeration containing one of several message severity levels, ordered from highest to lowest.
@ S_TRACE
Message indicates any condition that may occur with great frequency (thus verbose if logged).
@ S_INFO
Message indicates a not-"bad" condition that is not frequent enough to be of severity Sev::S_TRACE.
bool key_exists(const Container &container, const typename Container::key_type &key)
Returns true if and only if the given key is present at least once in the given associative container...
std::string ostream_op_string(T const &... ostream_args)
Equivalent to ostream_op_to_string() but returns a new string by value instead of writing to the call...
Basic_string_view< char > String_view
Commonly used char-based Basic_string_view. See its doc header.
boost::system::error_code Error_code
Short-hand for a boost.system error code (which basically encapsulates an integer/enum error code and...
Flow_log_component
The flow::log::Component payload enumeration comprising various log components used by Flow's own int...
Internal-use structure to use with Declare_options_func callback.
Option_set * m_option_set
m_option_set->m_opts_for_parsing shall be filled out.
const Values * m_values_current
The current values loaded into *m_target_opts (e.g., via description text) will originate here.
struct flow::cfg::Option_set::Declare_options_func_args::@0::@1 m_fill_parsing_role_opt_table_args
Corresponds to Call_type::S_FILL_PARSING_ROLE_OPT_TABLE.
struct flow::cfg::Option_set::Declare_options_func_args::@0::@2 m_fill_output_help_role_opt_table_args
Corresponds to Call_type::S_FILL_OUTPUT_HELP_ROLE_OPT_TABLE.
struct flow::cfg::Option_set::Declare_options_func_args::@0::@3 m_fill_output_current_role_opt_table_args
Corresponds to Call_type::S_FILL_OUTPUT_CURRENT_ROLE_OPT_TABLE.
struct flow::cfg::Option_set::Declare_options_func_args::@0::@5 m_load_val_as_if_parsed_args
Corresponds to Call_type::S_LOAD_VALS_AS_IF_PARSED.
struct flow::cfg::Option_set::Declare_options_func_args::@0::@4 m_compare_parsed_vals_args
Corresponds to Call_type::S_COMPARE_PARSED_VALS.
const Values * m_values_to_validate
Each validator-enabled (via a Declare_options_func) member in this structure shall be validated.
const Values * m_values_default
m_option_set->m_values_default: defaults loaded into Option_set::m_opts_for_help will originate here.
const Values * m_values_to_load
Values shall be copied from this external Value_set.
opts::options_description * m_target_opts
m_target_opts shall be filled out based on the defaults earlier saved into m_values_default and curre...
Call_type m_call_type
Why Declare_options_func is being called.
Values * m_values_candidate
m_option_set->m_values_candidate, the parsing-in-progress Value_set filled out whenever parsing using...
const Values * m_values_default_no_acc
m_option_set->m_values_default: the defaults loaded into m_values_candidate at the top of each parse,...
union flow::cfg::Option_set::Declare_options_func_args::@0 m_args
The args to pass in depending on m_call_type.
struct flow::cfg::Option_set::Declare_options_func_args::@0::@6 m_validate_stored_vals_args
Corresponds to Call_type::S_VALIDATE_STORED_VALS.