Pogosim
Loading...
Searching...
No Matches
configuration.h
Go to the documentation of this file.
1#ifndef CONFIGURATION_H
2#define CONFIGURATION_H
3
4#include "pogosim.h"
5#include "geometry.h"
6
7#include <yaml-cpp/yaml.h>
8#include <string>
9#include <stdexcept>
10#include <sstream>
11#include <vector>
12#include <utility>
13#include <type_traits>
14
37inline std::string polygons_to_yaml(const arena_polygons_t &polygons) {
38 YAML::Node root(YAML::NodeType::Sequence);
39
40 for (const auto &poly : polygons) {
41 YAML::Node poly_node(YAML::NodeType::Sequence);
42 for (const auto &v : poly) {
43 YAML::Node vtx;
44 vtx["x"] = v.x;
45 vtx["y"] = v.y;
46 poly_node.push_back(vtx);
47 }
48 root.push_back(poly_node);
49 }
50
51 YAML::Emitter emitter;
52 emitter << root; // Default = block style, indented
53 return {emitter.c_str(), static_cast<std::size_t>(emitter.size())};
54}
55
56
65public:
68
70 explicit Configuration(const YAML::Node &node);
71
78 void load(const std::string& file_name);
79
88 Configuration operator[](const std::string& key) const;
89
91 Configuration at_path(const std::string& dotted_key) const;
92
94 template<typename T>
95 T get_path(const std::string& dotted_key, const T& default_value = T()) const;
96
106 template<typename T>
107 T get(const T& default_value = T()) const;
108
118 template<typename T>
119 void set(const std::string& key, const T& value);
120
126 bool exists() const;
127
133 std::string summary() const;
134
144 std::vector<std::pair<std::string, Configuration>> children() const;
145
146private:
147 YAML::Node node_;
148 mutable YAML::Node resolved_cache_; // Cache for resolved hierarchical default
149 mutable bool cache_valid_; // Whether the cache is valid
150
156 static YAML::Node resolve_hierarchical_default(const YAML::Node& n);
157
161 const YAML::Node& get_resolved() const;
162
163};
164
165
166namespace detail {
167
169template<typename T>
170typename std::enable_if<std::is_arithmetic<T>::value, T>::type
171numeric_fallback(const YAML::Node& n, const T& default_value) {
172 try {
173 // integral → go through double, floating-point → long double
174 typedef typename std::conditional<
175 std::is_integral<T>::value, double, long double>::type tmp_t;
176
177 tmp_t tmp = n.as<tmp_t>(); // may still throw
178 return static_cast<T>(tmp);
179 } catch (const YAML::Exception&) {
180 return default_value; // out-of-range, etc.
181 }
182}
183
185template<typename T>
186typename std::enable_if<!std::is_arithmetic<T>::value, T>::type
187numeric_fallback(const YAML::Node&, const T& default_value) {
188 return default_value;
189}
190
191} // namespace detail
192
193template<typename T>
194T Configuration::get(const T& default_value) const {
195 if (!node_) { // nothing stored here
196 return default_value;
197 }
198
199 // Get the cached resolved node at this level
200 const YAML::Node& target_ref = get_resolved();
201 YAML::Node target = target_ref; // Copy for subsequent modifications
202
203 /* honour an eventual "default_option" sub-key ---------------- */
204 if (target.IsMap()) {
205 YAML::Node opt = target["default_option"];
206 if (opt) { target = opt; }
207 }
208
209 /* -------- 1st attempt – let yaml-cpp do the conversion ------ */
210 try {
211 return target.as<T>(); // success? great, we’re done.
212 } catch (const YAML::Exception&) {
213 /* -------- 2nd attempt – only if T is numeric ------------ */
214 return detail::numeric_fallback(target, default_value);
215 }
216}
217
218template<typename T>
219void Configuration::set(const std::string& key, const T& value) {
220 // Ensure the current node is a map; if not, convert it to one.
221 if (!node_ || !node_.IsMap()) {
222 node_ = YAML::Node(YAML::NodeType::Map);
223 }
224 node_[key] = value;
225}
226
227template<typename T>
228T Configuration::get_path(const std::string& dotted_key, const T& default_value) const {
229 return at_path(dotted_key).get<T>(default_value);
230}
231
232
233#endif // CONFIGURATION_H
234
235// MODELINE "{{{1
236// vim:expandtab:softtabstop=4:shiftwidth=4:fileencoding=utf-8
237// vim:foldmethod=marker
Configuration at_path(const std::string &dotted_key) const
Access a nested sub-configuration via a dotted path (supports '.' to escape dots).
Definition configuration.cpp:65
T get(const T &default_value=T()) const
Retrieves the configuration value cast to type T.
Definition configuration.h:194
std::string summary() const
Provides a summary of the configuration.
Definition configuration.cpp:39
T get_path(const std::string &dotted_key, const T &default_value=T()) const
Read a value at a dotted path with a default (convenience wrapper around at_path(....
Definition configuration.h:228
Configuration()
Default constructor creates an empty configuration.
Definition configuration.cpp:5
void set(const std::string &key, const T &value)
Sets the configuration entry for the given key.
Definition configuration.h:219
bool exists() const
Checks if the current node is defined.
Definition configuration.cpp:35
void load(const std::string &file_name)
Loads configuration parameters from a YAML file.
Definition configuration.cpp:17
Configuration operator[](const std::string &key) const
Access a sub-configuration.
Definition configuration.cpp:25
std::vector< std::pair< std::string, Configuration > > children() const
Returns the children (sub-entries) of the current node.
Definition configuration.cpp:45
std::string polygons_to_yaml(const arena_polygons_t &polygons)
Convert an arena_polygons_t structure into a compact YAML string.
Definition configuration.h:37
std::vector< std::vector< b2Vec2 > > arena_polygons_t
Definition geometry.h:13
Definition configuration.h:166
std::enable_if< std::is_arithmetic< T >::value, T >::type numeric_fallback(const YAML::Node &n, const T &default_value)
compile-time branch for arithmetic targets
Definition configuration.h:171