werkzeugkiste::config namespace

Utilities to handle configurations in a unified manner via the werkzeugkiste::config::Configuration class.

#include <werkzeugkiste/config/configuration.h>
namespace wkc = werkzeugkiste::config;
// Load a configuration from a file ...
wkc::Configuration cfg = wkc::LoadTOMLFile("path/to/config.toml");
// ... or a string:
wkc::Configuration cfg = wkc::LoadTOMLString(R"toml(
    my-double = 42.17
    my-long = 2147483648
    labels = ["lbl1", "lbl2"]
    day = 2023-10-09

    camera-matrix = [
      [800,   0, 400],
      [  0, 750, 300],
      [  0,   0,   1]
    ]

    polyline = [
      [ 1, 2],            # Points can be specified as lists...
      { x = -1, y = -2},  # ... or as groups (key/value pairs).
    ]
    )toml");

// Basic parameter queries:
using namespace std::string_view_literals;
double val_dbl = cfg.GetDouble("my-double"sv);
int64_t val_long = cfg.GetInt64("my-long"sv);
std::vector<std::string> strings = cfg.GetStringList("labels"sv);
wkc::date day = cfg.GetDate("day"sv);

// If a parameter does not exist:
cfg.GetString("unknown"sv);                 // Throws a wkc::KeyError.
cfg.GetStringOr("unknown"sv, "fallback"sv); // Returns "fallback".
cfg.GetOptionalString("unknown"sv);         // Returns std::nullopt.

// A wkc::TypeError will be thrown if the parameter is of a different type:
cfg.GetString("my-long"sv);

// Type conversion between numeric types is supported if the parameter
// can be exactly represented by the requested type:
val_dbl = cfg.GetDouble("my-long"sv);  // Implicit conversion.
cfg.GetInt64("my-double"sv); // Value can't be represented by an integer.
cfg.GetInt32("my-long"sv);   // Value exceeds int32 range.

// Usage convenience for geometric types:
wkc::Matrix<double> intrinsics = cfg.GetMatrixDouble("camera-matrix"sv);
// Note that matrices will use row-major storage order.

// TODO not yet available
// namespace wkg = werkzeugkiste::geometry;
// const std::vector<wkg::Vec2i> polyline = cfg.GetVec2iList("polyline"sv);
// Type conversion
// const std::vector<wkg::Vec2d> polyline = cfg.GetVec2dList("polyline"sv);

Namespaces

namespace detail
Internal implementation namespace.

Classes

template<class A, class B>
struct are_integral
Checks whether both types are integral.
template<class A, class B>
struct are_floating_point
Checks whether both types are floating point types.
class Configuration
Encapsulates configuration data.
class KeyMatcher
Matches keys (fully qualified parameter names) against user-defined patterns.
class ParseError
Indicates a failure during parsing a configuration string/file.
class KeyError
Indicates that an invalid key was provided to access a parameter.
class TypeError
Indicates that an invalid type was used to query or set a parameter.
class ValueError
Indicates invalid input values.
struct date
Represents a local date.
struct time
Represents a local time.
struct time_offset
Represents a time zone offset.
struct date_time
A date-time specification following RFC 3339.
template<typename Tp>
struct point2d
A point in 2D Euclidean space.
template<typename Tp>
struct point3d
A point in 3D Euclidean space.

Enums

enum class ConfigType: unsigned char { Boolean, Integer, FloatingPoint, String, Date, Time, DateTime, List, Group }
Available configuration parameters.
enum class NullValuePolicy: unsigned char { Skip, NullString, EmptyList, Fail }
How to handle Null/None values (e.g. when loading JSON).

Typedefs

template<typename Tp>
using Matrix = Eigen::Matrix<Tp, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
Alias for a dynamic-size row-major matrix.

Functions

template<typename S, typename T>
auto is_promotable() -> bool constexpr
Checks whether source type S is promotable to target type T, i.e. if a type conversion without loss of precision is feasible.
template<typename T, typename S>
auto safe_numcast(const S value) -> std::optional<T> noexcept
Returns the value as type T if it can be exactly represented in the target type, or std::nullopt otherwise.
template<typename T, typename S, typename E = std::domain_error>
auto checked_numcast(const S value) -> T
Returns the value as type T iff it can be exactly represented in the target type.
auto IsValidKey(std::string_view key, bool allow_dots) -> WERKZEUGKISTE_CONFIG_EXPORT bool noexcept
Checks if the given key is a valid parameter name.
auto ConfigTypeToString(const ConfigType& ct) -> WERKZEUGKISTE_CONFIG_EXPORT std::string
Returns the string representation.
auto operator<<(std::ostream& os, const ConfigType& ct) -> WERKZEUGKISTE_CONFIG_EXPORT std::ostream&
Prints the string representation of a ConfigType out to the stream.
template<typename T>
auto TypeName() -> const char* constexpr

Variables

template<class A, class B>
bool are_integral_v constexpr
Helper variable template to check whether both types are integral.
template<class A, class B>
bool are_floating_point_v constexpr
Helper variable template to check whether both types are floating point types.

Loading a configuration

@desc Utilities to load a configuration from files or strings.

auto LoadFile(std::string_view filename) -> Configuration
Loads a configuration file.
auto LoadTOMLFile(std::string_view filename) -> Configuration
Loads a TOML configuration from the given file.
auto LoadTOMLString(std::string_view toml_string) -> Configuration
Loads a TOML configuration from a string.
auto LoadLibconfigFile(std::string_view filename) -> WERKZEUGKISTE_CONFIG_EXPORT Configuration
Loads a libconfig configuration from the given file.
auto LoadLibconfigString(std::string_view lcfg_string) -> WERKZEUGKISTE_CONFIG_EXPORT Configuration
Loads a libconfig configuration from a string.
auto LoadJSONFile(std::string_view filename, NullValuePolicy none_policy = NullValuePolicy::Skip) -> WERKZEUGKISTE_CONFIG_EXPORT Configuration
Loads a JSON configuration from a string.
auto LoadJSONString(std::string_view json_string, NullValuePolicy none_policy = NullValuePolicy::Skip) -> WERKZEUGKISTE_CONFIG_EXPORT Configuration
Loads a JSON configuration from a string.
auto LoadYAMLFile(std::string_view filename, NullValuePolicy none_policy = NullValuePolicy::Skip) -> WERKZEUGKISTE_CONFIG_EXPORT Configuration
Loads a YAML configuration from a file.
auto LoadYAMLString(const std::string& yaml_string, NullValuePolicy none_policy = NullValuePolicy::Skip) -> WERKZEUGKISTE_CONFIG_EXPORT Configuration
Loads a YAML configuration from a string.

String Representation

@desc Represent a configuration as a string in a specific format.

auto DumpLibconfigString(const Configuration& cfg) -> WERKZEUGKISTE_CONFIG_EXPORT std::string
Returns a libconfig-formatted string.
auto DumpTOMLString(const Configuration& cfg) -> std::string
Returns a TOML-formatted string.
auto DumpJSONString(const Configuration& cfg) -> std::string
Returns a JSON-formatted string.
auto DumpYAMLString(const Configuration& cfg) -> std::string
Returns a YAML-formatted string.

Enum documentation

enum class werkzeugkiste::config::ConfigType: unsigned char

Available configuration parameters.

Enumerators
Boolean

A boolean flag.

Integer

A 32- or 64-bit integer.

Internally, integers are represented by 64-bit.

FloatingPoint

A single- or double-precision floating point number.

Internally, floating point numbers are always represented by a double.

String

A string.

Date

A local date.

Time

A local time.

DateTime

A date-time following RFC 3339.

List

A list/array of unnamed parameters.

Group

A group/collection of named parameters.

enum class werkzeugkiste::config::NullValuePolicy: unsigned char

How to handle Null/None values (e.g. when loading JSON).

Enumerators
Skip

Null values will be skipped, i.e. not loaded into the configuration.

NullString

Null values will be replaced by the string "null".

EmptyList

Null values will be replaced by an empty list.

Fail

A werkzeugkiste::config::ParseError will be thrown.

Typedef documentation

template<typename Tp>
using werkzeugkiste::config::Matrix = Eigen::Matrix<Tp, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>

Alias for a dynamic-size row-major matrix.

Template parameters
Tp Scalar type of the matrix.

Function documentation

template<typename S, typename T>
bool werkzeugkiste::config::is_promotable() constexpr

Checks whether source type S is promotable to target type T, i.e. if a type conversion without loss of precision is feasible.

See implicit conversion rules: https://en.cppreference.com/w/c/language/conversion

template<typename T, typename S>
std::optional<T> werkzeugkiste::config::safe_numcast(const S value) noexcept

Returns the value as type T if it can be exactly represented in the target type, or std::nullopt otherwise.

Template parameters
T The target type.
S The input type.
Parameters
value The value to be casted.

template<typename T, typename S, typename E = std::domain_error>
T werkzeugkiste::config::checked_numcast(const S value)

Returns the value as type T iff it can be exactly represented in the target type.

Template parameters
T The target type.
S The input type.
E Exception which will be thrown if the cast is not feasible.
Parameters
value The value to be casted.

If the value is not exactly representable in the target type (i.e. the cast is not possible without losing precision/information), an exception of type E will be thrown.

WERKZEUGKISTE_CONFIG_EXPORT bool werkzeugkiste::config::IsValidKey(std::string_view key, bool allow_dots) noexcept

Checks if the given key is a valid parameter name.

Parameters
key The key to be checked.
allow_dots If true, dots (as in a key path / fully qualified parameter name) are also allowed.

A valid parameter name consists of alpha-numeric characters, dashes and underscores. Optionally, dots are also allowed (if )

WERKZEUGKISTE_CONFIG_EXPORT std::string werkzeugkiste::config::ConfigTypeToString(const ConfigType& ct)

Returns the string representation.

WERKZEUGKISTE_CONFIG_EXPORT std::ostream& werkzeugkiste::config::operator<<(std::ostream& os, const ConfigType& ct)

Prints the string representation of a ConfigType out to the stream.

template<typename T>
const char* werkzeugkiste::config::TypeName() constexpr

Configuration werkzeugkiste::config::LoadFile(std::string_view filename)

Loads a configuration file.

Parameters
filename Path to the configuration file.

The configuration type will be deduced from the file extension, i.e. .toml, .json, .yml/.yaml or .cfg. For JSON and YAML files, the default NullValuePolicy will be used, see LoadJSONFile or LoadYAMLFile.

Configuration werkzeugkiste::config::LoadTOMLFile(std::string_view filename)

Loads a TOML configuration from the given file.

Parameters
filename Path to the .toml file.

Configuration werkzeugkiste::config::LoadTOMLString(std::string_view toml_string)

Loads a TOML configuration from a string.

Parameters
toml_string String representation of the TOML config.

WERKZEUGKISTE_CONFIG_EXPORT Configuration werkzeugkiste::config::LoadLibconfigFile(std::string_view filename)

Loads a libconfig configuration from the given file.

Parameters
filename Path to the .cfg file.

WERKZEUGKISTE_CONFIG_EXPORT Configuration werkzeugkiste::config::LoadLibconfigString(std::string_view lcfg_string)

Loads a libconfig configuration from a string.

Parameters
lcfg_string String representation of the libconfig configuration.

WERKZEUGKISTE_CONFIG_EXPORT Configuration werkzeugkiste::config::LoadJSONFile(std::string_view filename, NullValuePolicy none_policy = NullValuePolicy::Skip)

Loads a JSON configuration from a string.

Parameters
filename Path to the .json file.
none_policy How to deal with None values.

Because a Configuration must consist of key/value pairs, a plain JSON array (e.g. "[1, 2, 3]") will be loaded into the key list. Thus, the (root) configuration would have 1 element, and it must be accessed via this key, for example, cfg.Size("list"), cfg.GetDouble("list[0]"), etc.

WERKZEUGKISTE_CONFIG_EXPORT Configuration werkzeugkiste::config::LoadJSONString(std::string_view json_string, NullValuePolicy none_policy = NullValuePolicy::Skip)

Loads a JSON configuration from a string.

Parameters
json_string String representation of the JSON configuration.
none_policy How to deal with None values.

Because a Configuration must consist of key/value pairs, a plain JSON array (e.g. "[1, 2, 3]") will be loaded into the key list. Thus, the (root) configuration would have 1 element, and it must be accessed via this key, for example, cfg.Size("list"), cfg.GetDouble("list[0]"), etc.

WERKZEUGKISTE_CONFIG_EXPORT Configuration werkzeugkiste::config::LoadYAMLFile(std::string_view filename, NullValuePolicy none_policy = NullValuePolicy::Skip)

Loads a YAML configuration from a file.

Parameters
filename Path to the YAML file.
none_policy How to deal with None values.

Because a Configuration must consist of key/value pairs, a plain YAML sequence (e.g. "[1, 2, 3]") will be loaded into the key list. Thus, the (root) configuration would have 1 element, and it must be accessed via this key, for example, cfg.Size("list"), cfg.GetDouble("list[0]"), etc.

WERKZEUGKISTE_CONFIG_EXPORT Configuration werkzeugkiste::config::LoadYAMLString(const std::string& yaml_string, NullValuePolicy none_policy = NullValuePolicy::Skip)

Loads a YAML configuration from a string.

Parameters
yaml_string String representation of the YAML configuration.
none_policy How to deal with None values.

Because a Configuration must consist of key/value pairs, a plain YAML sequence (e.g. "[1, 2, 3]") will be loaded into the key list. Thus, the (root) configuration would have 1 element, and it must be accessed via this key, for example, cfg.Size("list"), cfg.GetDouble("list[0]"), etc.

WERKZEUGKISTE_CONFIG_EXPORT std::string werkzeugkiste::config::DumpLibconfigString(const Configuration& cfg)

Returns a libconfig-formatted string.

std::string werkzeugkiste::config::DumpTOMLString(const Configuration& cfg)

Returns a TOML-formatted string.

std::string werkzeugkiste::config::DumpJSONString(const Configuration& cfg)

Returns a JSON-formatted string.

std::string werkzeugkiste::config::DumpYAMLString(const Configuration& cfg)

Returns a YAML-formatted string.

Variable documentation

template<class A, class B>
bool werkzeugkiste::config::are_integral_v constexpr

Helper variable template to check whether both types are integral.

template<class A, class B>
bool werkzeugkiste::config::are_floating_point_v constexpr

Helper variable template to check whether both types are floating point types.