Flow 1.0.2
Flow project: Full implementation reference.
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Private Types | Private Attributes | Related Functions | List of all members
flow::cfg::Option_set< Value_set > Class Template Reference

The core config-parsing facility, which builds parsing/comparison/output capabilities on top of a given simple config-holding object, of the type Value_set, a template argument to this class template. More...

#include <option_set.hpp>

Inheritance diagram for flow::cfg::Option_set< Value_set >:
[legend]
Collaboration diagram for flow::cfg::Option_set< Value_set >:
[legend]

Classes

struct  Declare_options_func_args
 Internal-use structure to use with Declare_options_func callback. More...
 

Public Types

using Values = Value_set
 Short-hand for the template parameter type Value_set. More...
 
using Values_ptr = typename Values::Const_ptr
 Short-hand for ref-counted pointer to an immutable Value_set (config payload storable in an Option_set). More...
 
using Mutable_values_ptr = typename Values::Ptr
 Short-hand for ref-counted pointer to a mutable Values (config payload storable in an Option_set). More...
 
using Declare_options_func = Function< void(const Declare_options_func_args &args)>
 Short-hand for the ever-important callback passed to the main Option_set constructor. More...
 
- Public Types inherited from flow::cfg::Option_set_base
enum class  Declare_options_func_call_type {
  S_FILL_PARSING_ROLE_OPT_TABLE , S_FILL_OUTPUT_HELP_ROLE_OPT_TABLE , S_FILL_OUTPUT_CURRENT_ROLE_OPT_TABLE , S_COMPARE_PARSED_VALS ,
  S_LOAD_VALS_AS_IF_PARSED , S_VALIDATE_STORED_VALS
}
 Internal-use type to use with Option_set::Declare_options_func callback. More...
 

Public Member Functions

 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 declared by synchronously invoking the callback declare_opts_func(). More...
 
const Valuesvalues () const
 Externally immutable internally stored canonical (current) config values as last constructed or parsed, whichever happened more recently. More...
 
Mutable_values_ptr mutable_values_copy () const
 Convenience method that heap-allocates a copy of the internally stored values() and wraps in a ref-counted handle suitable for speedy passing around the rest of the application. More...
 
const Valuesvalues_candidate () const
 Returns null in CANONICAL state; or in PARSING state a pointer to the not-yet-canonical values after the last successful parse_*() API call. More...
 
void validate_values (bool *success_or_null=0) const
 Validates the current contents of values() using the validators *this Option_set<Value_set> is configured to use via constructor. More...
 
void validate_values (const Values &values_to_validate, bool *success_or_null=0) const
 Validates an arbitrary Value_set, using the same validators *this Option_set<Value_set> is configured to use when parsing config sources. More...
 
void validate_values_candidate (bool *success_or_null=0) const
 Equivalent to validate_values(success_or_null) but validates *values_candidate() instead of values(). More...
 
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, at some point perhaps initialized or parsed by *this, to the given stream. More...
 
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(). More...
 
void help_to_ostream (std::ostream &os) const
 Prints a multi-line help message about the set of options that *this can parse. More...
 
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(). More...
 
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 form of the given file in the file-system. More...
 
void parse_direct_values (const Values &src_values)
 Enters into (from CANONICAL state) or continues in PARSING state by simply setting *values_candidate() to equal the Values payload given as an argument. More...
 
void canonicalize_candidate (bool *change_detected=0)
 In PARSING state enters CANONICAL state, finalizing values() from values_candidate(). More...
 
void reject_candidate ()
 In PARSING state, returns to CANONICAL state, as if no parse attempts have occurred. More...
 
template<typename Value >
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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header). More...
 
template<typename Value >
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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header). More...
 
template<typename Value >
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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header). More...
 
template<typename Value >
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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header). More...
 
bool null () const
 Return true if and only if the option-declaring function passed to the constructor declared no options. More...
 
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. More...
 
- Public Member Functions inherited from flow::log::Log_context
 Log_context (Logger *logger=0)
 Constructs Log_context by storing the given pointer to a Logger and a null Component. More...
 
template<typename Component_payload >
 Log_context (Logger *logger, Component_payload component_payload)
 Constructs Log_context by storing the given pointer to a Logger and a new Component storing the specified generically typed payload (an enum value). More...
 
 Log_context (const Log_context &src)
 Copy constructor that stores equal Logger* and Component values as the source. More...
 
 Log_context (Log_context &&src)
 Move constructor that makes this equal to src, while the latter becomes as-if default-constructed. More...
 
Log_contextoperator= (const Log_context &src)
 Assignment operator that behaves similarly to the copy constructor. More...
 
Log_contextoperator= (Log_context &&src)
 Move assignment operator that behaves similarly to the move constructor. More...
 
void swap (Log_context &other)
 Swaps Logger pointers and Component objects held by *this and other. More...
 
Loggerget_logger () const
 Returns the stored Logger pointer, particularly as many FLOW_LOG_*() macros expect. More...
 
const Componentget_log_component () const
 Returns reference to the stored Component object, particularly as many FLOW_LOG_*() macros expect. More...
 

Static Public Member Functions

static void validate_values (log::Logger *logger_ptr, const Values &values_to_validate, const Declare_options_func &declare_opts_func, bool *success_or_null=0)
 Validates an arbitrary Value_set, as parseable by an Option_set<Value_set>, according to the given option-registering function suitable for Option_set<Value_set> constructor. More...
 
- Static Public Member Functions inherited from flow::cfg::Option_set_base
template<typename Value >
static void declare_option_for_output (util::String_view name, opts::options_description *target_opts, const Value &value_default, const Value &current_value, util::String_view description)
 Internal-through-macro helper function; the user shall not call this directly but only through FLOW_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header). More...
 
template<typename Value >
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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header). More...
 

Public Attributes

const std::string m_nickname
 See nickname ctor arg. More...
 

Private Types

using Iterable_values = std::map< std::string, boost::any >
 Similar to a boost.program_options parsing results variables_map, which conceptually mirrors the results of a parsing operation in the target Values structure, mapping string to variable-type values. More...
 

Private Attributes

bool m_null
 See null(). More...
 
boost::unordered_set< std::string > m_opt_names
 See option_names(). More...
 
Declare_options_func m_declare_opts_func
 The Opt_table-filling, or m_iterable_values_candidate-scanning, callback passed to the constructor and invoked with various input args (see Declare_options_func doc header). More...
 
Values m_values
 See values(). More...
 
Values m_values_default
 Copy of values() when it is first constructed; i.e., the defaults. More...
 
bool m_parsing
 See values_candidate()true if and only if that returns non-null (PARSING state; else CANONICAL state). More...
 
Values m_values_candidate
 See values_candidate(). When that returns null (m_parsing == false) this value is meaningless. More...
 
Iterable_values m_iterable_values_candidate
 Structure mirroring m_values_candidate, where the values are the parsing-enabled members of m_values_candidate, and each value's key is it main config option name; if an option has not changed between m_values and m_values_candidate (according to its == operator), then that option's key is omitted. More...
 
Opt_table m_opts_for_parsing
 The parsing-role Opt_table (see extensive explanation in Opt_table doc header). More...
 
Opt_table m_opts_for_help
 The output-role Opt_table, help-text sub-role (see extensive explanation in Opt_table doc header). More...
 

Related Functions

(Note that these are not member functions.)

template<typename Value_set >
std::ostream & operator<< (std::ostream &os, const Option_set< Value_set > &val)
 Serializes (briefly) an Option_set to a standard output stream. More...
 

Additional Inherited Members

- Protected Types inherited from flow::cfg::Option_set_base
using Opt_table = opts::options_description
 Short-hand for boost.program_options config options description, each of which is used for parsing and/or describing (to humans) one or more config option/its value. More...
 
- Static Protected Member Functions inherited from flow::cfg::Option_set_base
template<typename Value >
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_parsing() and others, in code that will throw an exception with a human-useful message if that validator function indicates the Value passed to it is invalid; else will no-op. More...
 

Detailed Description

template<typename Value_set>
class flow::cfg::Option_set< Value_set >

The core config-parsing facility, which builds parsing/comparison/output capabilities on top of a given simple config-holding object, of the type Value_set, a template argument to this class template.

General use pattern

A typical expected scenario – although more complex ones can be devised – and one assumed by Config_manager – is to have 2 structs of config; one for static and one for dynamic config, the latter being something that can be parsed-into repeatedly over time, as new config is delivered to the process. In that case one would use one Option_set<Static_value_set> and one Option_set<Dynamic_value_set> and invoke their parsing at appropriate times (1+ times for the latter, once for the former). It is also possible to allow, on startup, to read both sets from the same config source(s) (e.g., a static config file); then read the dynamic Option_set<> from the dynamic config source(s) once (for any initial dynamic values overriding the initial baseline static ones); and after that accept any further updates of the latter config source(s), as they come in (e.g., if the dynamic config file is modified externally). The allow_unregistered argument to parse_*() allows 2+ Option_set<>s to share one config file.

Validation

Option validation mandatorily occurs in the following places.

However this is likely insufficient validation in at least some use cases. You should also concern yourself with the following.

Lastly, and optionally, you may validate a given Value_set object "offline," meaning outside of any Option_set<Value_set> – which need not even exist or ever parse anything; only the function fitting Option_set::Declare_options_func must exist, as-if for Option_set ctor. Simply call a validate_values() API on your object; it will yield failure given at least 1 invalid value. This can be useful, at least, when setting values manually through assignment (perhaps in a simpler program not requiring external config; or when unit-testing); just because you aren't parsing it through Option_set does not mean you don't want to sanity-check it for validity.

Change detection

For dynamic options, it may be necessary to detect whether the set of option values has changed or even individual changes (and then, in many cases, invoke config-changed hooks). Option_set is designed with this in mind, as it is able to provide such checks without forcing the user to write an operator==(Value_set, Value_set) (a laborious and error-prone procedure).

Change detection occurs at the canonicalize_candidate() stage. That is, once you've parsed all the different config sources in a parse pass, canonicalize_candidate() will scan for changes. As of this writing that method will optionally return a Boolean indicating whether at least one value changed vs. the canonical values(). It is possible to add an API for detecting individual option changes. As I write this, it doesn't exist, but it may be added after I write this. Option_set is eminently capable of it; and in fact it at least logs an INFO message for each option that has changed, at canonicalize_candidate() time.

Input/output

Input of configurable values in Value_set is required to be able to parse the corresponding options (parse_*()). Output thereof is required in:

For input (parsing), every configurable value in Value_set must have an istream>> operator.

For output (in help and current-values output), every such value must have an ostream<< operator. In addition, it is sometimes desirable to further massage output in config help/current-values output but not in a general ostream<< operator for that type. (E.g., you would not want to, or be able to usually, override stream output for std::string or chrono::duration.) To do this, provide a specialization or overload of the free function cfg::value_to_ostream<Value_set>(). Its generic implementation simply forwards to ostream<<, but you can do something different. As of this writing we already provide an overload for cfg::value_to_ostream<chrono::duration<...>>, which will automatically print the duration (which is typically stored in nanoseconds) in the coarsest possible units that would lose no precision (e.g., 60billion nanoseconds => "1 minute").

Recommended conventions

Firstly, it is recommended to store all durations in your Value_set as util::Fine_duration instead of using coarser units like chrono::seconds() or even chrono::milliseconds(). This tends to lead to more consistent and maintainable code, in the author's (ygoldfel) opinion, as util::Fine_duration can store durations expressed in essentially any units, without losing precision; does use the same underlying storage type – int64_t – and hence presents no performance or overflow difficulties (usually); and changing the desired units of a duration config value is fairly common. Simply put Fine_duration supports 99.99999999% of units and use cases without perf overhead. In addition, value_to_ostream<> is overloaded in such a way as to output Fine_duration members of Value_set in the most convenient possible units – automagically. So you're in no way forcing humans to work with nanoseconds: you can use any units in input and in code.

Note
For all duration values, config sources can specify any units (convertible without loss of precision to the specific chrono type); and indeed should specify units. E.g., "5 ms" and "5 milliseconds" will both work. Since util::Fine_duration is in nanoseconds internally, almost any conceivable units (from "hours" to "nanoseconds") are accepted equally well as inputs in config sources.

Secondly, when working with non-durations, specify units as a suffix in the member name.

Todo:
Add individual-option-changed detection API(s) in addition to the existing Option_set overall-value-set-changed detection API. This is contingent on a use case needing it. The existing code already detects this internally and logs a message for each changed option (in canonicalize_candidate()).
Template Parameters
Value_setThe value type stored inside *this, and returned by values(). Requirements on this type are at least informally explained above.

Definition at line 418 of file option_set.hpp.

Member Typedef Documentation

◆ Declare_options_func

template<typename Value_set >
using flow::cfg::Option_set< Value_set >::Declare_options_func = Function<void (const Declare_options_func_args& args)>

Short-hand for the ever-important callback passed to the main Option_set constructor.

The user of the class need not understand the meanings of the args, because the FLOW_CFG_OPTION_SET_DECLARE_OPTION() macro will take care of using them properly.

The idea is that the body of a user-provided callback of this type will consist of invoking FLOW_CFG_OPTION_SET_DECLARE_OPTION() for each parseable option, in some consistent order, and that macro (which we control) will invoke handling of that particular option – whose stored type can be anything and different from the other options', meaning we cannot iterate through them at runtime (nor is it possible at compile time without some kind of insane meta-programming). So, depending on what arguments we pass to this callback, the macro will – upon performing an operation only a macro can do (namely #ARG_whatever and the like) – forward those args to a function templated on the type of the option's stored value, namely one of declare_option_*(), scan_parsed_option(), load_option_value_as_if_parsed(), or validate_parsed_option(). That function will then perform the needed handling for that particular option.

See Declare_options_func_args for the possible args' meanings.

Definition at line 573 of file option_set.hpp.

◆ Iterable_values

template<typename Value_set >
using flow::cfg::Option_set< Value_set >::Iterable_values = std::map<std::string, boost::any>
private

Similar to a boost.program_options parsing results variables_map, which conceptually mirrors the results of a parsing operation in the target Values structure, mapping string to variable-type values.

As explained in the doc header for Option_set::Opt_table, a parsing operation takes in a config source (config file, etc.) and a parsing-role Opt_table; and outputs a Values and an object of the present type. Values is the main point Option_set exists; it's what the application accesses, via simple ->m_* access of various values, to observe the parsed config – so why do we need Iterable_values?

The reason we use this is: we need to be able to iterate through all the options that were found in a parsing pass, at least to detect changes as needed at least for dynamic option features (triggering on-changed hooks, etc.). (Requiring a manual operator==(Value_set, Value_set) or similar is too onerous and error-prone for the implementor of the Value_set, as every ->m_ would require manual mention.)

A variables_map is classically filled via the aforementioned parsing operation opts::store(); and is itself an std::map. Hence one can copy all the pairs from that into an Iterable_values; and an Iterable_values can be manually pre-filled with pre-parse values from Values for easy comparison after the store() (and other such algorithms). Note, also, it is deep-copyable, as long as all types stored within are deep-copyable.

Rationale

  • Why not simply use opts::variables_map? It is after all very close to what this is. Answer: I (ygoldfel) started that way, but its API is a bit hairy, and it's scary to have to depend on how boost.program_options will act when variables_map isn't empty before the parsing begins, for example (e.g., store() docs say it will NOT overwrite any "non-defaulted" value – having to rely on such nuances doesn't seem great). It is safer, if slower (but we don't care), to treat a fresh variables_map that's store()d into as an intermediary.
  • Why not unordered_map? It's faster after all. Answer: An alphabetical iteration order seems nice when (e.g.) iterating over the keys to show differences in values to humans.

Definition at line 1062 of file option_set.hpp.

◆ Mutable_values_ptr

template<typename Value_set >
using flow::cfg::Option_set< Value_set >::Mutable_values_ptr = typename Values::Ptr

Short-hand for ref-counted pointer to a mutable Values (config payload storable in an Option_set).

Definition at line 442 of file option_set.hpp.

◆ Values

template<typename Value_set >
using flow::cfg::Option_set< Value_set >::Values = Value_set

Short-hand for the template parameter type Value_set.

E.g.: Cool_option_set::Values, where one aliased Cool_option_set to Option_set<Cool_value_set>.

Definition at line 430 of file option_set.hpp.

◆ Values_ptr

template<typename Value_set >
using flow::cfg::Option_set< Value_set >::Values_ptr = typename Values::Const_ptr

Short-hand for ref-counted pointer to an immutable Value_set (config payload storable in an Option_set).

The name is not, say, Const_values_ptr, because we would expect such objects to be passed around in const form most of the time, including when made accessible from within a config-holding API. When a mutable Values is desired, one would typically create it from an Option_set by using mutable_values_copy().

Definition at line 439 of file option_set.hpp.

Constructor & Destructor Documentation

◆ Option_set()

template<typename Value_set >
flow::cfg::Option_set< Value_set >::Option_set ( log::Logger logger_ptr,
util::String_view  nickname,
Declare_options_func &&  declare_opts_func_moved 
)
explicit

Constructs an option set in CANONICAL state with a default-valued values() payload and options declared by synchronously invoking the callback declare_opts_func().

See below for details on the latter.

Post-condition: values() is equal to Values(); values_candidate() is null (so the state is initially CANONICAL). (Therefore Value_set no-args ctor must by definition be written so as to initialize all its relevant members to their defaults. Recall Value_set is a template parameter type with certain requirements.)

Use parse_*() (once per config source) and canonicalize_candidate() (once) to move to PARSING state and back to CANONICAL state respectively.

Declaring options via declare_opts_func() callback

declare_opts_func above denotes an internally saved callback move()d from the corresponding arg declare_opts_func_moved. declare_opts_func() is also invoked synchronously from within various relevant output APIs; their doc headers mention it. (E.g., invoking stream output os << *this will call declare_opts_func().)

Informally, the callback must declare every parseable (and therefore stream-printable-semantic-description-having) option, linking it to some data member within a target Values whose address is passed to the callback as an arg; in a consistent order; and as many times through the lifetime of *this (including during this ctor) as *this deems necessary. Use FLOW_CFG_OPTION_SET_DECLARE_OPTION() to describe all the options. Formally, it must follow the following exact rules:

  • Its signature right above the { body } must name its args exactly as shown in the value of the Declare_options_func alias.
  • Its body must execute N>=1 invocations of the macro FLOW_CFG_OPTION_SET_DECLARE_OPTION() – see its doc header – each corresponding to a distinct data member of Values, always in the same order and the same N. Clues as to how this works:
    • The naming of the args is so specific in order to make the macro minimally concise to use.
    • Macro machinery will auto-determine the main name of the option (as seen in config sources like files) based on the naming of the m_ member.
    • The macro will call a public API that is not to be called directly, passing in various data just mentioned, plus the text description passed to it (if relevant) and the option name passed to it.
Parameters
logger_ptrLogger to use for subsequently logging.
nicknameBrief string used for logging subsequently.
declare_opts_func_movedSee above.

Definition at line 1454 of file option_set.hpp.

References FLOW_LOG_TRACE, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_call_type, flow::cfg::Option_set< Value_set >::m_declare_opts_func, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_fill_output_help_role_opt_table_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_fill_parsing_role_opt_table_args, flow::cfg::Option_set< Value_set >::m_values_candidate, flow::cfg::Option_set< Value_set >::m_values_default, flow::cfg::Option_set< Value_set >::null(), flow::cfg::Option_set_base::S_FILL_OUTPUT_HELP_ROLE_OPT_TABLE, and flow::cfg::Option_set_base::S_FILL_PARSING_ROLE_OPT_TABLE.

Here is the call graph for this function:

Member Function Documentation

◆ canonicalize_candidate()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::canonicalize_candidate ( bool change_detected = 0)

In PARSING state enters CANONICAL state, finalizing values() from values_candidate().

Any cumulative changes are INFO-logged on a per-changed-option basis; and if at least one option's value indeed changed then *change_detected is set to true (else false). (Leave the arg null, if you do not care.)

Note
Individual option validation should be done via the validation condition argument to FLOW_CFG_OPTION_SET_DECLARE_OPTION(). However, it may be necessary to perform a check for internal consistency among the final values. The proper time to do this is just before calling canonicalize_candidate(). If the final check fails, typically one would instead call reject_candidate().
Parameters
change_detectedIf null, ignored; otherwise *change_detected is set to true if a setting changed; else false.

Definition at line 2042 of file option_set.hpp.

References FLOW_LOG_INFO, flow::util::key_exists(), and flow::log::S_TRACE.

Referenced by flow::cfg::Config_manager< S_d_value_set >::option_set_canonicalize_or_reject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ declare_option_for_help()

template<typename Value_set >
template<typename Value >
void flow::cfg::Option_set< Value_set >::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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header).

Loads an entry into m_opts_for_help which will enable the proper help text to appear for that option in help_to_ostream() or log_help().

Template Parameters
ValueType of the value inside a Values object. It must be reasonably copyable; and it must be supported by some version (including specialization(s) and overload(s)) of value_to_ostream().
Parameters
nameSee declare_option_for_parsing().
value_defaultDefault value to show to the user.
descriptionThe description text to show to the user.

Definition at line 1640 of file option_set.hpp.

References flow::cfg::value_to_ostream().

Here is the call graph for this function:

◆ declare_option_for_parsing()

template<typename Value_set >
template<typename Value >
void flow::cfg::Option_set< Value_set >::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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header).

Loads an entry into m_opts_for_parsing which will enable the parsing into *target_value from config sources such as config files.

Template Parameters
ValueType of the value inside a Values object. It must be reasonably copyable.
Parameters
nameMain option name: as specified by the user in a config source. As of this writing FLOW_CFG_OPTION_SET_DECLARE_OPTION() uses macro magic to automatically form this from the identifier name within a Values object (e.g., Value_set::m_cool_option => "cool-option").
target_valueWhen deserializing a value from a config source, the bits shall be written there. This must point inside m_values_candidate.
value_default_if_no_accUsually – with regular (accumulating) options – null; otherwise pointer to the default value for *target_value (as from Values()), inside m_values_default. In the latter case (non-null) this indicates this is an option marked by the user as non-accumulating (see FLOW_CFG_OPTION_SET_DECLARE_OPTION_NO_ACC() and similar), meaning each time a config source (e.g., a file) is parsed *target_value is first reset to this default; then overwritten with the value in the config source if, else left at the default. An accumulating option in the latter case would instead keep its existing value already in *target_value.
validator_func_movedFunction F, such that F(V) shall be called from parse_*() when this option's successfully parsed value V is being validated before final storage in m_values_candidate. Return false if the validation shall fail; otherwise return true.
validator_cond_strString containing the Boolean code that validator_func_moved() would need to evaluate to true to pass validation. As of this writing FLOW_CFG_OPTION_SET_DECLARE_OPTION() uses macro magic to automatically form this from a Boolean expression fragment.

Definition at line 1565 of file option_set.hpp.

References FLOW_LOG_TRACE, and flow::cfg::value_to_ostream().

Here is the call graph for this function:

◆ help_to_ostream()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::help_to_ostream ( std::ostream &  os) const

Prints a multi-line help message about the set of options that *this can parse.

This should typically be preceded by a newline but not followed by one, unless one desires a blank line there.

Parameters
osStream to which to serialize.

Definition at line 1540 of file option_set.hpp.

◆ load_option_value_as_if_parsed()

template<typename Value_set >
template<typename Value >
void flow::cfg::Option_set< Value_set >::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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header).

To be called only when m_parsing is true, sets a value in m_values_candidate to equal one in an external Values object; and mirrors this in m_iterable_values_candidate to maintain its invariant. As a result, it is as-if that value was parsed from some config source such as a file. Note that, as with parsing from actual config sources like files, one must still scan_parsed_option() at some point to slim down m_iterable_values_candidate to store merely the changed options.

Template Parameters
ValueType of the value inside a Values object. It must have a meaningful = operation.
Parameters
nameSee declare_option_for_parsing().
target_valueTarget value inside m_values_candidate.
source_valueValue to load into *target_value (as-if it was parsed from a config source).

Definition at line 1746 of file option_set.hpp.

◆ log_help()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::log_help ( util::String_view  summary,
log::Sev  sev = log::Sev::S_INFO 
) const

Logs a multi-line help message using help_to_ostream().

Parameters
summaryBrief summary of the help message.
sevSeverity to use for the log message.

Definition at line 1546 of file option_set.hpp.

References FLOW_LOG_WITH_CHECKING.

◆ log_values()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::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().

Parameters
values_or_nullSee values_to_ostream().
summaryBrief summary of what this payload represents.
sevSeverity to use for the log message.

Definition at line 1528 of file option_set.hpp.

References FLOW_LOG_WITH_CHECKING.

◆ mutable_values_copy()

template<typename Value_set >
Option_set< Value_set >::Mutable_values_ptr flow::cfg::Option_set< Value_set >::mutable_values_copy

Convenience method that heap-allocates a copy of the internally stored values() and wraps in a ref-counted handle suitable for speedy passing around the rest of the application.

Returns
See above.

Definition at line 1496 of file option_set.hpp.

◆ null()

template<typename Value_set >
bool flow::cfg::Option_set< Value_set >::null

Return true if and only if the option-declaring function passed to the constructor declared no options.

This value is always the same for a given *this.

Rationale

While likely of little value when the user instantiates an Option_set directly, this can be useful in generic meta-programming, wherein multiple Option_sets might be instantiated at compile time, but the coder doesn't know how many while coding. For example Config_manager uses null() to bypass confusingly-logging parse_config_file() calls on empty Option_set objects, such as if a static config set has no dynamic config counterpart.

Returns
See above.

Definition at line 1484 of file option_set.hpp.

Referenced by flow::cfg::Option_set< Value_set >::Option_set(), and flow::cfg::Config_manager< S_d_value_set >::option_set_canonicalize_or_reject().

Here is the caller graph for this function:

◆ option_names()

template<typename Value_set >
const boost::unordered_set< std::string > & flow::cfg::Option_set< Value_set >::option_names

Returns set of all option names declared by the option-declaring function passed to the constructor.

This can be useful to supply to parse_config_file(), for example, when parsing another Option_set from the same file: then other options can be passed to that function as not causing a parse error if encountered; hence 2 or more Option_sets can parse_config_file() the same file despite having disjoint option name sets – yet totally extraneous options in none of the Option_sets would cause an error as desired.

This returns the same value (and reference) each time it is called.

Returns
See above.

Definition at line 1558 of file option_set.hpp.

◆ parse_config_file()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::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 form of the given file in the file-system.

On success values_candidate() is updated; on failure it is untouched.

On failure throws an exception, if success_or_null is null; otherwise set *success_or_null to false. On success simply returns or sets *success_or_null to true respectively. Information is logged regardless.

A failure may occur due to invalid contents in the config source. A failure may occur due to a validator condition failed (see FLOW_CFG_OPTION_SET_DECLARE_OPTION()).

However: the latter applies only to settings actually specified in cfg_path file. Any default or baseline or otherwise-previously-set, but not overridden in cfg_path, values are not validated – neither before nor after scanning cfg_path. You are, however, free to do so by next (or previously, or both) invoking validate_values_candidate(). (If "previously," and not yet in PARSING state, then use validate_values().) See Validation in class doc header for discussion.

See also
canonicalize_candidate() which will finalize the values_candidate() constructed so far.
reject_candidate() which will snap back to CANONICAL state rejecting any successful parsing done. In particular it would make sense in many cases to do this if parse_config_file() indicates failure.
Parameters
cfg_pathPath to parse.
allow_unregisteredIf true, if an unknown option is encountered it may be allowed (not considered a failure), subject to allowed_unregistered_opts_or_empty, though an INFO message is still logged for each; if false it is an error like any other illegal config setting. One reason for true is if another Option_set<> will be parsed from the same config source. Another is if there could be forward- or backward-compatibility concerns.
allowed_unregistered_opts_or_emptyMeaningful only if allow_unregistered == true, this is the list of all option names (compared case-sensitively) that will not cause a validation error; or empty to allow all unknown options.
success_or_nullIf null exceptions mark failure; otherwise the pointed-to value shall indicate success or failure.

Definition at line 1783 of file option_set.hpp.

References FLOW_ERROR_SYS_ERROR_LOG_WARNING, FLOW_LOG_INFO, FLOW_LOG_TRACE, FLOW_LOG_WARNING, flow::util::key_exists(), flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_call_type, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_compare_parsed_vals_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_option_set, flow::util::ostream_op_string(), and flow::log::S_TRACE.

Here is the call graph for this function:

◆ parse_direct_values()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::parse_direct_values ( const Values src_values)

Enters into (from CANONICAL state) or continues in PARSING state by simply setting *values_candidate() to equal the Values payload given as an argument.

Typically precedes other parse_*() calls such as parse_config_file(). If already in PARSING state, note that any changes accumulated in *values_candidate() so far will be overwritten entirely.

The values in src_values are not checked for validity according to the validators configured in the FLOW_CFG_OPTION_SET_DECLARE_OPTION() invocations in declare_opts_func() passed to ctor. You are, however, free to do so by next invoking validate_values_candidate(). See Validation in class doc header for discussion.

Rationale

This is useful, particularly, when one plans to repeatedly apply updates to one *this, but a certain baseline state is desired before each update. Consider the example of an Option_set that stores dynamically changeable values. Suppose each update consists only of a single parse_config_file(F) call, where F is some file that might get changed at various times to deliver dynamic updates. Then consider this series:

  1. Initial Option_set construction. End state: values() == Values() (default).
  2. First update occurs: parse_config_file(F), followed by canonicalize_candidate(). End state: values() == defaults + changes in file F at time 1.
  3. Second update occurs: parse_config_file(F), followed by canonicalize_candidate(). End state: values() == defaults + changes in file F at time 1 + changes in file F at time 2.
  4. (etc.)

In this case values() is incrementally changed by each dynamic update, as the file F keeps changing. E.g., if at time 1 it contained only option A, and at time 2 it contained only option B, then values() would contain both time-1 option A value and time-2 option B value – even though the file F at time 2 contains only the latter. This might be what you want, but since it's fully incremental, there are some usability landmines. Mainly: If one looks at F contents at any given time, they can't know what the resulting state would be; it depends on what updates preceded it.

To resolve this, one can save a baseline state of values() by copy; and then apply it via this parse_direct_values() call before parsing the file in each dynamic update. The baseline state could just be defaults (Values()), or it could come from some special "baseline" config file that is not F which one knows to never change. (Such a file could also typically store static config managed by a separate Option_set.)

So then the sequence might become not parse_config_file(), canonicalize_candidate(), parse_config_file(), canonicalize_candidate(), ...; but rather:

  1. Baseline parse: parse_config_file(B), canonicalize_candidate().
  2. Save values() copy into Values baseline.
  3. Update 0: parse_direct_values(baseline), parse_config_file(F), canonicalize_candidate().
  4. Update 1: parse_direct_values(baseline), parse_config_file(F), canonicalize_candidate().
  5. Update 2: parse_direct_values(baseline), parse_config_file(F), canonicalize_candidate().
  6. ... (The first parse_direct_values(baseline) here is a no-op but included for clarity/symmetry, as usually one would just do the same thing for each update.)

It is also sometimes desirable to "rewind" the state of values_candidate() (by first memorizing it, then parse_config_file() or similar, then if some value in the resulting value set indicates the file should not apply after all, parse_direct_values() to "undo." Config_manager uses it when its multi-source feature is engaged – commit = false.)

Parameters
src_valuesThe values set loaded into *values_candidate(), as-if parsed from some config source.

Definition at line 1993 of file option_set.hpp.

References FLOW_LOG_INFO, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_call_type, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_compare_parsed_vals_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_load_val_as_if_parsed_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_option_set, and flow::log::S_TRACE.

Referenced by flow::cfg::Config_manager< S_d_value_set >::apply_impl().

Here is the caller graph for this function:

◆ reject_candidate()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::reject_candidate

In PARSING state, returns to CANONICAL state, as if no parse attempts have occurred.

In CANONICAL state, a no-op. Calling this is typically a good idea when a parse_*() attempt indicates failure.

Definition at line 2075 of file option_set.hpp.

References FLOW_LOG_INFO.

Referenced by flow::cfg::Config_manager< S_d_value_set >::option_set_canonicalize_or_reject().

Here is the caller graph for this function:

◆ scan_parsed_option()

template<typename Value_set >
template<typename Value >
void flow::cfg::Option_set< Value_set >::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_CFG_OPTION_SET_DECLARE_OPTION() (see Option_set main constructor doc header).

Scans a canonical (current) value in m_values, comparing it to the (possibly) parsed one in m_iterable_values_candidate, erasing it from the latter if and only if it is unchanged.

Template Parameters
ValueType of the value inside a Values object. It must have a meaningful == operation.
Parameters
nameSee declare_option_for_parsing().
canonical_valueCurrent value in m_values.

Definition at line 1715 of file option_set.hpp.

◆ validate_values() [1/3]

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::validate_values ( bool success_or_null = 0) const

Validates the current contents of values() using the validators *this Option_set<Value_set> is configured to use via constructor.

If at least one option is invalid according to a validator declared by a FLOW_CFG_OPTION_SET_DECLARE_OPTION() invocation in declare_opts_func(), then this function shall indicate failure; else success.

On failure throws an exception, if success_or_null is null; otherwise set *success_or_null to false. On success simply returns or sets *success_or_null to true respectively. In the exception case the message will indicate every reasonable detail about the option value that went wrong. This info is logged regardless.

Informally, the use case driving the presence of this overload is discussed in the Validation section of our class doc header; see that. To restate: If you want to stringently ensure the defaults are themselves valid, simply invoke this right after construction, at which point values() are by definition at their defaults.

Parameters
success_or_nullIf null exceptions mark failure; otherwise the pointed-to value shall indicate success or failure.

Definition at line 2088 of file option_set.hpp.

◆ validate_values() [2/3]

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::validate_values ( const Values values_to_validate,
bool success_or_null = 0 
) const

Validates an arbitrary Value_set, using the same validators *this Option_set<Value_set> is configured to use when parsing config sources.

This essentially means using the static overload and passing to it declare_opts_func equal to the one earlier passed by the user to *this constructor. The success/failure semantics are identical to the other overload's (see that doc header).

You can also use the static overload, if you aren't at all parsing from config sources but still want to validate.

Parameters
values_to_validateThe values in this structure shall be validated in the same way as they are upon this->parse_*()ing from a config source.
success_or_nullIf null exceptions mark failure; otherwise the pointed-to value shall indicate success or failure.

Definition at line 2148 of file option_set.hpp.

◆ validate_values() [3/3]

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::validate_values ( log::Logger logger_ptr,
const Values values_to_validate,
const Declare_options_func declare_opts_func,
bool success_or_null = 0 
)
static

Validates an arbitrary Value_set, as parseable by an Option_set<Value_set>, according to the given option-registering function suitable for Option_set<Value_set> constructor.

If at least one option is invalid according to a validator declared by a FLOW_CFG_OPTION_SET_DECLARE_OPTION() invocation in declare_opts_func(), then this function shall indicate failure; else success.

On failure throws an exception, if success_or_null is null; otherwise set *success_or_null to false. On success simply returns or sets *success_or_null to true respectively. In the exception case the message will indicate every reasonable detail about the option value that went wrong. This info is logged regardless.

Use this, at least, if you've filled out a Value_set through manual assignment or some other source, rather than parsing through an Option_set – and don't even use an Option_set, as you don't parse from config – but still want to check it for validity.

You can also use the non-static overload to reuse the Declare_options_func passed to an existing parsing-capable Option_set<Value_set>.

Parameters
logger_ptrLogger to use for subsequently logging.
values_to_validateThe values in this structure shall be validated in the same way as they are upon parsing by a hypothetical Option_set<Value_set> into whose ctor the same declare_opts_func were passed.
declare_opts_funcSee Option_set constructor.
success_or_nullIf null exceptions mark failure; otherwise the pointed-to value shall indicate success or failure.

Definition at line 2102 of file option_set.hpp.

References FLOW_LOG_SET_CONTEXT, FLOW_LOG_WARNING, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_call_type, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_validate_stored_vals_args, and flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_values_to_validate.

◆ validate_values_candidate()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::validate_values_candidate ( bool success_or_null = 0) const

Equivalent to validate_values(success_or_null) but validates *values_candidate() instead of values().

Behavior is undefined (assertion may trip) if not in PARSING mode currently (i.e., values_candidate() is null).

Informally, the use case driving the presence of this overload is discussed in the Validation section of our class doc header; see that. To restate: If you want to ensure no invalid defaults or baseline values have "gotten through" in the current PARSING state, then invoke this – particularly just ahead of the decision to either canonicalize_candidate() or reject_candidate().

Parameters
success_or_nullIf null exceptions mark failure; otherwise the pointed-to value shall indicate success or failure.

Definition at line 2094 of file option_set.hpp.

◆ values()

template<typename Value_set >
const Value_set & flow::cfg::Option_set< Value_set >::values

Externally immutable internally stored canonical (current) config values as last constructed or parsed, whichever happened more recently.

See also
mutable_values_copy() to get a copy.
Returns
See above.

Definition at line 1490 of file option_set.hpp.

Referenced by flow::cfg::Config_manager< S_d_value_set >::apply_impl().

Here is the caller graph for this function:

◆ values_candidate()

template<typename Value_set >
const Value_set * flow::cfg::Option_set< Value_set >::values_candidate

Returns null in CANONICAL state; or in PARSING state a pointer to the not-yet-canonical values after the last successful parse_*() API call.

Rationale: It is supplied publicly in case the caller wans to log it or something; or perhaps to check for current state (CANONICAL if and only it returns null).

Returns
See above.

Definition at line 1502 of file option_set.hpp.

Referenced by flow::cfg::Config_manager< S_d_value_set >::apply_impl().

Here is the caller graph for this function:

◆ values_to_ostream()

template<typename Value_set >
void flow::cfg::Option_set< Value_set >::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, at some point perhaps initialized or parsed by *this, to the given stream.

This should typically be preceded by a newline but not followed by one, unless one desires a blank line there.

Parameters
osStream to which to serialize.
values_or_nullValues to serialize; if null then we act as-if it's &(values()).

Definition at line 1508 of file option_set.hpp.

References flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_args, flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_call_type, and flow::cfg::Option_set< Value_set >::Declare_options_func_args::m_fill_output_current_role_opt_table_args.

Friends And Related Function Documentation

◆ operator<<()

template<typename Value_set >
std::ostream & operator<< ( std::ostream &  os,
const Option_set< Value_set > &  val 
)
related

Serializes (briefly) an Option_set to a standard output stream.

Template Parameters
Value_setSee Option_set doc header.
Parameters
osStream to which to serialize.
valValue to serialize.
Returns
os.

Definition at line 2154 of file option_set.hpp.

References flow::cfg::Option_set< Value_set >::m_nickname.

Member Data Documentation

◆ m_declare_opts_func

template<typename Value_set >
Declare_options_func flow::cfg::Option_set< Value_set >::m_declare_opts_func
private

The Opt_table-filling, or m_iterable_values_candidate-scanning, callback passed to the constructor and invoked with various input args (see Declare_options_func doc header).

Depending on those args it will either fill Opt_table in various roles (see Opt_table doc header), or it will scan the values just loaded into m_iterable_values_candidate (e.g., for equality to the values in canonical m_values).

Definition at line 1078 of file option_set.hpp.

Referenced by flow::cfg::Option_set< Value_set >::Option_set().

◆ m_iterable_values_candidate

template<typename Value_set >
Iterable_values flow::cfg::Option_set< Value_set >::m_iterable_values_candidate
private

Structure mirroring m_values_candidate, where the values are the parsing-enabled members of m_values_candidate, and each value's key is it main config option name; if an option has not changed between m_values and m_values_candidate (according to its == operator), then that option's key is omitted.

In particular it is .empty() == true when in CANONICAL mode (m_parsing == false).

Definition at line 1098 of file option_set.hpp.

◆ m_nickname

template<typename Value_set >
const std::string flow::cfg::Option_set< Value_set >::m_nickname

See nickname ctor arg.

Definition at line 1027 of file option_set.hpp.

Referenced by flow::cfg::Option_set< Value_set >::operator<<().

◆ m_null

template<typename Value_set >
bool flow::cfg::Option_set< Value_set >::m_null
private

See null().

Definition at line 1067 of file option_set.hpp.

◆ m_opt_names

template<typename Value_set >
boost::unordered_set<std::string> flow::cfg::Option_set< Value_set >::m_opt_names
private

See option_names().

Definition at line 1070 of file option_set.hpp.

◆ m_opts_for_help

template<typename Value_set >
Opt_table flow::cfg::Option_set< Value_set >::m_opts_for_help
private

The output-role Opt_table, help-text sub-role (see extensive explanation in Opt_table doc header).

Briefly: it's used to output help text to output streams for user's convenience, in fact simply by piping it to an ostream via <<. This should not change after the first parse_*() API begins execution (lest the user become confused).

Definition at line 1113 of file option_set.hpp.

◆ m_opts_for_parsing

template<typename Value_set >
Opt_table flow::cfg::Option_set< Value_set >::m_opts_for_parsing
private

The parsing-role Opt_table (see extensive explanation in Opt_table doc header).

Briefly: it's used to actually load *m_values_candidate – and ultimately m_values – with values parsed from config sources such as files. This must not change after the first parse_*() API begins execution.

Definition at line 1105 of file option_set.hpp.

◆ m_parsing

template<typename Value_set >
bool flow::cfg::Option_set< Value_set >::m_parsing
private

See values_candidate()true if and only if that returns non-null (PARSING state; else CANONICAL state).

Definition at line 1087 of file option_set.hpp.

◆ m_values

template<typename Value_set >
Values flow::cfg::Option_set< Value_set >::m_values
private

See values().

Definition at line 1081 of file option_set.hpp.

◆ m_values_candidate

template<typename Value_set >
Values flow::cfg::Option_set< Value_set >::m_values_candidate
private

See values_candidate(). When that returns null (m_parsing == false) this value is meaningless.

Definition at line 1090 of file option_set.hpp.

Referenced by flow::cfg::Option_set< Value_set >::Option_set().

◆ m_values_default

template<typename Value_set >
Values flow::cfg::Option_set< Value_set >::m_values_default
private

Copy of values() when it is first constructed; i.e., the defaults.

Definition at line 1084 of file option_set.hpp.

Referenced by flow::cfg::Option_set< Value_set >::Option_set().


The documentation for this class was generated from the following files: