1 #include "hmbdc/Copyright.hpp" 5 #include <boost/property_tree/ptree.hpp> 6 #include <boost/property_tree/json_parser.hpp> 12 #include <unordered_set> 20 namespace hmbdc {
namespace app {
22 namespace config_detail {
48 using Base = boost::property_tree::ptree;
60 , section_(other.section_)
61 , fallbackConfig_(other.fallbackConfig_
62 ?new
Config(*other.fallbackConfig_)
71 section_ = other.section_;
72 fallbackConfig_.reset(other.fallbackConfig_
73 ?
new Config(*other.fallbackConfig_)
87 Config(std::istream&& is,
char const* section =
nullptr)
88 : section_(section?section:
"") {
89 read_json(is, (Base&)*
this);
102 Config(std::istream& is,
char const* section =
nullptr)
103 : section_(section?section:
"") {
104 read_json(is, (Base&)*
this);
117 Config(
char const* json,
char const* section =
nullptr)
118 :
Config(
std::istringstream(json), section)
129 Config(ptree
const& t,
char const* section =
nullptr)
131 , section_(section?section:
"") {
143 Config(ptree
const& dft, ptree
const& section)
145 , fallbackConfig_(new
Config(dft)) {
155 if (!fallbackConfig_) {
156 fallbackConfig_.reset(
new Config(c));
158 fallbackConfig_->setAdditionalFallbackConfig(c);
165 setAdditionalFallbackConfig(c);
178 if (sectionExists) get_child(section);
179 auto sec = section?section:
"";
180 if (get_child_optional(sec)) section_ = sec;
181 if (fallbackConfig_) {
182 fallbackConfig_->resetSection(section,
false);
194 template <
typename ...Args>
196 Base::put(std::forward<Args>(args)...);
212 auto res = get_child_optional(sec/=param);
214 res = get_child_optional(param);
216 if (fallbackConfig_) {
217 return fallbackConfig_->getChildExt(param);
219 throw ptree_bad_path(
"invalid param and no default user Config set", param);
237 template <
typename T>
238 T
getExt(
const path_type& param,
bool throwIfMissing =
true)
const {
240 auto res = get_optional<T>(sec/=param);
242 res = get_optional<T>(param);
244 if (fallbackConfig_) {
245 return fallbackConfig_->getExt<T>(param, throwIfMissing);
246 }
else if (throwIfMissing) {
247 throw ptree_bad_path(
"invalid param and no default user Config set", param);
267 template <
typename T>
268 std::vector<T>
getArray(
const path_type& param)
const {
271 auto children = get_child_optional(sec/=param);
272 if (!children) children = get_child_optional(param);
274 for (
auto& v : *children) {
275 if (v.first.empty()) {
276 res.push_back(v.second.get_value<T>());
278 throw ptree_bad_data(
"param not pointing to array ", param);
282 }
else if (fallbackConfig_) {
283 return fallbackConfig_->getArray<T>(param);
285 throw ptree_bad_path(
"invalid array param and no default user Config set", param);
298 template <
typename T>
299 T
getHex(ptree::path_type
const& param)
const {
300 std::istringstream iss(getExt<std::string>(param));
302 iss >> std::hex >> res;
316 template <
typename T>
317 Config const&
operator()(T& to,
const path_type& param,
bool throwIfMissing =
true)
const {
318 to = getExt<T>(param, throwIfMissing);
332 template <
typename T>
333 Config const&
operator()(std::unordered_set<T>& to,
const path_type& param,
bool throwIfMissing =
true)
const {
336 auto s = getExt<std::string>(param, throwIfMissing);
337 istringstream iss(s);
339 for (
auto iit = istream_iterator<T>(iss)
340 ; iit != istream_iterator<T>()
345 throw (ptree_bad_data(
"not space separated items in Config ", param));
361 template <
typename T>
362 Config const&
operator()(std::vector<T>& to,
const path_type& param,
bool throwIfMissing =
true)
const {
365 auto s = getExt<std::string>(param, throwIfMissing);
366 istringstream iss(s);
368 for (
auto iit = istream_iterator<T>(iss)
369 ; iit != istream_iterator<T>()
371 to.emplace_back(*iit);
374 throw (ptree_bad_data(
"not space separated items in Config ", param));
387 std::list<std::pair<std::string, std::string>>
content(
388 std::unordered_set<std::string>
const& skipThese = std::unordered_set<std::string>())
const {
390 list<pair<std::string, std::string>> res;
391 unordered_set<std::string> history(skipThese);
392 auto secTree = get_child_optional(section_);
394 for (
auto& p : *secTree) {
395 if (history.find(p.first) == history.end()) {
396 history.insert(p.first);
397 if (p.second.empty()) {
398 res.push_back(make_pair(p.first, p.second.get_value<std::string>()));
409 for (
auto& p : *
this) {
410 if (history.find(p.first) == history.end()) {
411 history.insert(p.first);
412 if (p.second.empty()) {
413 res.push_back(make_pair(p.first, p.second.get_value<std::string>()));
423 if (fallbackConfig_) {
424 auto more = fallbackConfig_->content(history);
425 res.insert(res.end(), more.begin(), more.end());
438 friend std::ostream& operator << (std::ostream& os,
Config const& cfg) {
439 for (
auto& r : cfg.
content()) {
440 os << r.first <<
'=' << r.second << std::endl;
442 if (cfg.fallbackConfig_) {
443 os <<
"next in line fallback" << std::endl;
444 os << *cfg.fallbackConfig_ << std::endl;
469 std::unique_ptr<Config> fallbackConfig_;
473 using Config = config_detail::Config;
std::vector< T > getArray(const path_type ¶m) const
get a vector of value from the json array
Definition: Config.hpp:268
T getExt(const path_type ¶m, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
Config const & operator()(std::vector< T > &to, const path_type ¶m, bool throwIfMissing=true) const
fill an list with a configured value retrieved using getExt
Definition: Config.hpp:362
Config(Config const &other)
copt ctor
Definition: Config.hpp:58
void setDefaultUserConfig(Config const &c)
depracated
Definition: Config.hpp:164
class to hold an hmbdc configuration
Definition: Config.hpp:45
void setAdditionalFallbackConfig(Config const &c)
set additional defaults
Definition: Config.hpp:154
Definition: TypedString.hpp:84
Config & resetSection(char const *section, bool sectionExists=true)
change section name
Definition: Config.hpp:177
Config const & operator()(T &to, const path_type ¶m, bool throwIfMissing=true) const
fill in a variable with a configured value retrieved using getExt
Definition: Config.hpp:317
std::list< std::pair< std::string, std::string > > content(std::unordered_set< std::string > const &skipThese=std::unordered_set< std::string >()) const
get contents of all the effective configure in the form of list of string pairs
Definition: Config.hpp:387
T getHex(ptree::path_type const ¶m) const
get a number value in hex format
Definition: Config.hpp:299
Config(char const *json, char const *section=nullptr)
construct using a string, optionally specifying the section name
Definition: Config.hpp:117
Config(ptree const &dft, ptree const §ion)
construct using a fallback ptree, and specify the section ptree
Definition: Config.hpp:143
Config(std::istream &&is, char const *section=nullptr)
construct using stream, optionally specifying the section name
Definition: Config.hpp:87
Config(std::istream &is, char const *section=nullptr)
construct using stream, optionally specifying the section name
Definition: Config.hpp:102
ptree const & getChildExt(const path_type ¶m)
Gets the child from the config.
Definition: Config.hpp:210
Config const & operator()(std::unordered_set< T > &to, const path_type ¶m, bool throwIfMissing=true) const
fill an unordered_set with a configured value retrieved using getExt
Definition: Config.hpp:333
Config & put(Args &&... args)
forward the call to ptree's put but return Configure
Definition: Config.hpp:195
Config()
empty config
Definition: Config.hpp:53
Config(ptree const &t, char const *section=nullptr)
construct using another ptree as fallbacks, optionally specifying the section name ...
Definition: Config.hpp:129