Version: SMASH-2.0
smash::Configuration Class Reference

#include <configuration.h>

Interface to the SMASH configuration files.

The configuration is created from a YAML file and then stores a nested map of maps (normally a tree, but YAML allows it to be cyclic - even though we don't want that feature).

For the typical usage in SMASH one needs to read the value once. In that case, use the Configuration::take function:

double sigma = config.take({"General", "SIGMA"});

Note the curly braces in the function call. It is a std::initializer_list of strings. This allows an arbitrary nesting depth via the same function. But as a consequence the keys must all be given as constant strings at compile time.

If you need to access the configuration values from a run-time string you can use Configuration::operator[]. This returns a Configuration object that references the respective sub-tree.

By taking values (instead of just reading), the configuration object should be empty at the end of the initialization. If the object is not empty, SMASH will print a warning (using Configuration::unused_values_report). This can be important for the user to discover typos in his configuration file (or command line parameters).

Definition at line 464 of file configuration.h.

Collaboration diagram for smash::Configuration:
[legend]

Classes

struct  FileDoesNotExist
 
struct  IncorrectTypeInAssignment
 
struct  ParseError
 
class  Value
 Return type of Configuration::take that automatically determines the target type. More...
 

Public Member Functions

 Configuration (const bf::path &path)
 Reads config.yaml from the specified path. More...
 
 Configuration (const bf::path &path, const bf::path &filename)
 Reads a YAML config file from the specified path. More...
 
 Configuration (const char *yaml)
 
 Configuration (const Configuration &)=default
 If you want to copy this you're doing it wrong. More...
 
Configurationoperator= (const Configuration &)=default
 If you want to copy this you're doing it wrong. More...
 
 Configuration (Configuration &&)=default
 Moving is fine. More...
 
Configurationoperator= (Configuration &&)=default
 Moving is fine. More...
 
void merge_yaml (const std::string &yaml)
 Merge the configuration in yaml into the existing tree. More...
 
std::vector< std::string > list_upmost_nodes ()
 Lists all YAML::Nodes from the configuration setup. More...
 
Value take (std::initializer_list< const char * > keys)
 The default interface for SMASH to read configuration values. More...
 
template<typename T >
take (std::initializer_list< const char * > keys, T default_value)
 
Value read (std::initializer_list< const char * > keys) const
 Additional interface for SMASH to read configuration values without removing them. More...
 
template<typename T >
read (std::initializer_list< const char * > keys, T default_value)
 
void remove_all_but (const std::string &key)
 Removes all entries in the map except for key. More...
 
template<typename T >
Configuration operator[] (T &&key)
 Access to the YAML::Node behind the requested keys. More...
 
template<typename T >
Configurationoperator= (T &&value)
 Assignment overwrites the value of the current YAML node. More...
 
bool has_value_including_empty (std::initializer_list< const char * > keys) const
 Returns if there is a (maybe empty) value behind the requested keys. More...
 
bool has_value (std::initializer_list< const char * > keys) const
 Returns whether there is a non-empty value behind the requested keys. More...
 
std::string unused_values_report () const
 Returns a string listing the key/value pairs that have not been taken yet. More...
 
std::string to_string () const
 Returns a YAML string of the current tree. More...
 

Private Member Functions

 Configuration (const YAML::Node &node)
 Creates a subobject that has its root node at the given node. More...
 

Private Attributes

YAML::Node root_node_
 the general_config.yaml contents - fully parsed More...
 

Constructor & Destructor Documentation

◆ Configuration() [1/6]

smash::Configuration::Configuration ( const bf::path &  path)
explicit

Reads config.yaml from the specified path.

Parameters
[in]pathThe directory where the SMASH config files are located.

Definition at line 89 of file configuration.cc.

90  : Configuration(path, "config.yaml") {}

◆ Configuration() [2/6]

smash::Configuration::Configuration ( const bf::path &  path,
const bf::path &  filename 
)
explicit

Reads a YAML config file from the specified path.

Parameters
[in]pathThe directory where the SMASH config files are located.
[in]filenameThe filename (without path) of the YAML config file, in case you don't want the default "config.yaml".

Definition at line 93 of file configuration.cc.

93  {
94  const auto file_path = path / filename;
95  if (!bf::exists(file_path)) {
96  throw FileDoesNotExist("The configuration file was expected at '" +
97  file_path.native() +
98  "', but the file does not exist.");
99  }
100  if (has_crlf_line_ending(read_all(bf::ifstream((file_path))))) {
101  throw std::runtime_error(
102  "The configuration file has CR LF line endings. Please use LF "
103  "line endings.");
104  }
105  try {
106  root_node_ = YAML::LoadFile(file_path.native());
107  } catch (YAML::ParserException &e) {
108  if (e.msg == "illegal map value" || e.msg == "end of map not found") {
109  const auto line = std::to_string(e.mark.line + 1);
110  throw ParseError("YAML parse error at\n" + file_path.native() + ':' +
111  line + ": " + e.msg +
112  " (check that the indentation of map keys matches)");
113  }
114  throw;
115  }
116 }
Here is the call graph for this function:

◆ Configuration() [3/6]

smash::Configuration::Configuration ( const char *  yaml)
inlineexplicit
Unit tests can use this constructor to get a Configuration object from a built-in string.This function is only available to tests and should never be used/needed in actual SMASH code. The intention is to avoid creating a mock object for Configuration to test other classes of SMASH.

Definition at line 1056 of file configuration.h.

1056 : root_node_(YAML::Load(yaml)) {}

◆ Configuration() [4/6]

smash::Configuration::Configuration ( const Configuration )
default

If you want to copy this you're doing it wrong.

◆ Configuration() [5/6]

smash::Configuration::Configuration ( Configuration &&  )
default

Moving is fine.

◆ Configuration() [6/6]

smash::Configuration::Configuration ( const YAML::Node &  node)
inlineprivate

Creates a subobject that has its root node at the given node.

Note
This constructor is not explicit because it can be called only from inside Configuration and by making it explicit a return would require the copy constructor.

Definition at line 1211 of file configuration.h.

1212  : root_node_(node) {}

Member Function Documentation

◆ operator=() [1/3]

Configuration& smash::Configuration::operator= ( const Configuration )
default

If you want to copy this you're doing it wrong.

◆ operator=() [2/3]

Configuration& smash::Configuration::operator= ( Configuration &&  )
default

Moving is fine.

◆ merge_yaml()

void smash::Configuration::merge_yaml ( const std::string &  yaml)

Merge the configuration in yaml into the existing tree.

The function parses the string in yaml into its internal tree representation. Then it merges the nodes from the new tree into the existing tree. The merge resolves conflicts by taking the value from yaml.

Parameters
[in]yamlA string with YAML (or JSON) content that is to be merged.

Definition at line 118 of file configuration.cc.

118  {
119  try {
120  root_node_ |= YAML::Load(yaml);
121  } catch (YAML::ParserException &e) {
122  if (e.msg == "illegal map value" || e.msg == "end of map not found") {
123  const auto line = std::to_string(e.mark.line + 1);
124  throw ParseError("YAML parse error in:\n" + yaml + "\nat line " + line +
125  ": " + e.msg +
126  " (check that the indentation of map keys matches)");
127  }
128  throw;
129  }
130 }
Here is the caller graph for this function:

◆ list_upmost_nodes()

std::vector< std::string > smash::Configuration::list_upmost_nodes ( )

Lists all YAML::Nodes from the configuration setup.

Definition at line 132 of file configuration.cc.

132  {
133  std::vector<std::string> r;
134  for (auto i : root_node_) {
135  r.emplace_back(i.first.Scalar());
136  }
137  return r;
138 }

◆ take() [1/2]

Configuration::Value smash::Configuration::take ( std::initializer_list< const char * >  keys)

The default interface for SMASH to read configuration values.

The function returns the value at the specified keys and removes it from the Configuration object. Therefore, a subsequent call to take or has_value with the same keys returns an undefined value / false. By removing the value, the Configuration object keeps track which settings were never read.

Parameters
[in]keysYou can pass an arbitrary number of keys inside curly braces, following the nesting structure in the config file. Example:
Group:
    Key: Value
Call
string value = config.take({"Group", "Key"});
to read the value.
Returns
A proxy object that converts to the correct type automatically on assignment.

Definition at line 140 of file configuration.cc.

141  {
142  assert(keys.size() > 0);
143  auto node = root_node_;
144  auto keyIt = begin(keys);
145  std::size_t i = 0;
146  for (; i < keys.size() - 1; ++i, ++keyIt) {
147  // Node::reset does what you might expect Node::operator= to do. But
148  // operator= assigns a value to the node. So
149  // node = node[*keyIt]
150  // leads to modification of the data structure, not simple traversal.
151  node.reset(node[*keyIt]);
152  }
153  const auto r = node[*keyIt];
154  node.remove(*keyIt);
155  return {r, keys.begin()[keys.size() - 1]};
156 }
Here is the caller graph for this function:

◆ take() [2/2]

template<typename T >
T smash::Configuration::take ( std::initializer_list< const char * >  keys,
default_value 
)
inline
See also
take

Definition at line 1109 of file configuration.h.

1109  {
1110  if (has_value(keys)) {
1111  return take(keys);
1112  }
1113  return default_value;
1114  }
Here is the call graph for this function:

◆ read() [1/2]

Configuration::Value smash::Configuration::read ( std::initializer_list< const char * >  keys) const

Additional interface for SMASH to read configuration values without removing them.

The function returns the value at the specified keys but does not remove it from the Configuration object. Semantically, this means the value was not used.

Parameters
[in]keysYou can pass an arbitrary number of keys inside curly braces, following the nesting structure in the config file.
Returns
A proxy object that converts to the correct type automatically on assignment.

Definition at line 158 of file configuration.cc.

159  {
160  return {find_node_at(root_node_, keys), keys.begin()[keys.size() - 1]};
161 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read() [2/2]

template<typename T >
T smash::Configuration::read ( std::initializer_list< const char * >  keys,
default_value 
)
inline
See also
read

Definition at line 1134 of file configuration.h.

1134  {
1135  if (has_value(keys)) {
1136  return read(keys);
1137  }
1138  return default_value;
1139  }
Here is the call graph for this function:

◆ remove_all_but()

void smash::Configuration::remove_all_but ( const std::string &  key)

Removes all entries in the map except for key.

Parameters
[in]keyThe key of the map entry to keep.

Definition at line 163 of file configuration.cc.

163  {
164  std::vector<std::string> to_remove;
165  for (auto i : root_node_) {
166  if (i.first.Scalar() != key) {
167  to_remove.push_back(i.first.Scalar());
168  }
169  }
170  for (auto i : to_remove) {
171  root_node_.remove(i);
172  }
173 }
Here is the caller graph for this function:

◆ operator[]()

template<typename T >
Configuration smash::Configuration::operator[] ( T &&  key)
inline

Access to the YAML::Node behind the requested keys.

If you want to read a value use the read function above. Use the subscript operator if you want to assign a new value. The YAML::Node class will automatically convert the data you assign to a string representation suitable for the YAML file.

Parameters
[in]keyThe name of the key to be looked up
Returns
An opaque object that can be assigned to.
See also
take
read

Definition at line 1163 of file configuration.h.

1163  {
1164  return root_node_[std::forward<T>(key)];
1165  }

◆ operator=() [3/3]

template<typename T >
Configuration& smash::Configuration::operator= ( T &&  value)
inline

Assignment overwrites the value of the current YAML node.

Parameters
[in]valueAn arbitrary value that yaml-cpp can convert into YAML representation. Any builtin type, strings, maps, and vectors can be used here.

Definition at line 1175 of file configuration.h.

1175  {
1176  root_node_ = std::forward<T>(value);
1177  return *this;
1178  }

◆ has_value_including_empty()

bool smash::Configuration::has_value_including_empty ( std::initializer_list< const char * >  keys) const

Returns if there is a (maybe empty) value behind the requested keys.

Parameters
[in]keysList of keys to be checked for

Definition at line 175 of file configuration.cc.

176  {
177  const auto n = find_node_at(root_node_, keys);
178  return n.IsDefined();
179 }
Here is the call graph for this function:

◆ has_value()

bool smash::Configuration::has_value ( std::initializer_list< const char * >  keys) const

Returns whether there is a non-empty value behind the requested keys.

Parameters
[in]keysList of keys to be checked for

Definition at line 181 of file configuration.cc.

181  {
182  const auto n = find_node_at(root_node_, keys);
183  return n.IsDefined() && (!n.IsNull());
184 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unused_values_report()

std::string smash::Configuration::unused_values_report ( ) const

Returns a string listing the key/value pairs that have not been taken yet.

Definition at line 186 of file configuration.cc.

186  {
187  std::stringstream s;
189  return s.str();
190 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_string()

std::string smash::Configuration::to_string ( ) const

Returns a YAML string of the current tree.

This differs from the above in that it does not remove empty maps.

Definition at line 192 of file configuration.cc.

192  {
193  std::stringstream s;
194  s << root_node_;
195  return s.str();
196 }
Here is the caller graph for this function:

Member Data Documentation

◆ root_node_

YAML::Node smash::Configuration::root_node_
private

the general_config.yaml contents - fully parsed

Definition at line 1215 of file configuration.h.


The documentation for this class was generated from the following files:
smash::Configuration::root_node_
YAML::Node root_node_
the general_config.yaml contents - fully parsed
Definition: configuration.h:1215
smash::Configuration::read
Value read(std::initializer_list< const char * > keys) const
Additional interface for SMASH to read configuration values without removing them.
Definition: configuration.cc:158
smash::has_crlf_line_ending
bool has_crlf_line_ending(const std::string in)
Check if a line in the string ends with \r\n.
Definition: inputfunctions.h:91
smash::Configuration::has_value
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
Definition: configuration.cc:181
smash::anonymous_namespace{configuration.cc}::remove_empty_maps
YAML::Node remove_empty_maps(YAML::Node root)
Removes all empty maps of a YAML::Node.
Definition: configuration.cc:52
smash::Configuration::Configuration
Configuration(const bf::path &path)
Reads config.yaml from the specified path.
Definition: configuration.cc:89
smash::read_all
std::string read_all(std::istream &&input)
Utility function to read a complete input stream (e.g.
Definition: inputfunctions.h:80
smash::Configuration::take
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
Definition: configuration.cc:140
smash::pdg::n
constexpr int n
Neutron.
Definition: pdgcode_constants.h:30
smash::anonymous_namespace{configuration.cc}::find_node_at
YAML::Node find_node_at(YAML::Node node, std::initializer_list< const char * > keys)
Finds a node, copies its structure and replaces the previous keys by the newly provided keys.
Definition: configuration.cc:36