1 /* Copyright (c) 2016. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #ifndef _XBT_CONFIG_HPP_
8 #define _XBT_CONFIG_HPP_
15 #include <type_traits>
19 #include <xbt/config.h>
24 XBT_PUBLIC(bool) parseBool(const char* value);
25 XBT_PUBLIC(double) parseDouble(const char* value);
26 XBT_PUBLIC(long int) parseLong(const char* value);
28 template<class T> struct parse_option {
29 static inline T parse(const char* value)
35 template<> struct parse_option<std::string> {
36 static inline std::string parse(const char* value)
38 return std::string(value);
43 struct parse_option<double> {
44 static inline double parse(const char* value)
46 return parseDouble(value);
51 struct parse_option<int> {
52 static inline double parse(const char* value)
54 return parseLong(value);
59 struct parse_option<bool> {
60 static inline bool parse(const char* value)
62 return parseBool(value);
66 template<class T> inline
67 T parse(const char* value)
69 return parse_option<T>::parse(value);
72 template<class T> inline
73 std::string to_string(T&& value)
75 return std::to_string(std::forward<T>(value));
77 inline std::string const& to_string(std::string& value)
81 inline std::string const& to_string(std::string const& value)
85 inline std::string to_string(std::string&& value)
87 return std::move(value);
92 /** Register a configuration flag
94 * @param name name of the option
95 * @param description Description of the option
96 * @param callback called with the option value
98 XBT_PUBLIC(void) declareFlag(const char* name, const char* description,
99 std::function<void(const char* value)> callback);
101 template<class T, class F>
102 void declareFlag(const char* name, const char* description, F callback)
104 declareFlag(name, description, [callback](const char* value) {
105 callback(parse<T>(value));
109 /** Bind a variable to configuration flag
111 * @param value Bound variable
112 * @param name Flag name
113 * @param description Option description
116 void bindFlag(T& value, const char* name, const char* description)
119 declareFlag(name, description, [&value](const char* val) {
120 value = simgrid::config::parse<T>(val);
122 xbt_cfg_setdefault_string(name, simgrid::config::to_string(value).c_str());
125 /** Bind a variable to configuration flag
129 * simgrid::config::bindFlag(a, "x", [](const char* value) {
130 * return simgrid::config::parse(value);
134 // F is a parser, F : const char* -> T
135 template<class T, class F>
136 typename std::enable_if<std::is_same<
138 typename std::remove_cv< decltype(
139 std::declval<F>()(std::declval<const char*>())
141 >::value, void>::type
142 bindFlag(T& value, const char* name, const char* description,
145 declareFlag(name, description, [&value,callback](const char* val) {
146 value = callback(val);
148 xbt_cfg_setdefault_string(name, to_string(value).c_str());
151 /** Bind a variable to configuration flag
155 * simgrid::config::bindFlag(a, "x", [](int x) {
156 * if (x < x_min || x => x_max)
157 * throw std::range_error("must be in [x_min, x_max)")
161 // F is a checker, F : T& -> ()
162 template<class T, class F>
163 typename std::enable_if<std::is_same<
165 decltype( std::declval<F>()(std::declval<const T&>()) )
166 >::value, void>::type
167 bindFlag(T& value, const char* name, const char* description,
170 declareFlag(name, description, [&value,callback](const char* val) {
171 T res = parse<T>(val);
173 value = std::move(res);
175 xbt_cfg_setdefault_string(name, to_string(value).c_str());
178 /** Bind a variable to configuration flag
182 * simgrid::config::bindFlag(a, "x", [](int x) { return return x > 0; });
185 // F is a predicate, F : T const& -> bool
186 template<class T, class F>
187 typename std::enable_if<std::is_same<
189 decltype( std::declval<F>()(std::declval<const T&>()) )
190 >::value, void>::type
191 bindFlag(T& value, const char* name, const char* description,
194 declareFlag(name, description, [&value,callback](const char* val) {
195 T res = parse<T>(val);
197 throw std::range_error("invalid value");
198 value = std::move(res);
200 xbt_cfg_setdefault_string(name, to_string(value).c_str());
203 /** A variable bound to a CLI option
206 * static simgrid::config::flag<int> answer("answer", "Expected answer", 42);
207 * static simgrid::config::flag<std::string> name("name", "Ford Prefect", "John Doe");
208 * static simgrid::config::flag<double> gamma("gamma", "Gamma factor", 1.987);
218 * @param name Flag name
219 * @param desc Flag description
220 * @param value Flag initial/default value
222 Flag(const char* name, const char* desc, T value) : value_(value)
224 simgrid::config::bindFlag(value_, name, desc);
228 Flag(const char* name, const char* desc, T value, F callback) : value_(value)
230 simgrid::config::bindFlag(value_, name, desc, std::move(callback));
234 Flag(Flag const&) = delete;
235 Flag& operator=(Flag const&) = delete;
237 // Get the underlying value:
238 T& get() { return value_; }
239 T const& get() const { return value_; }
241 // Implicit conversion to the underlying type:
242 operator T&() { return value_; }
243 operator T const&() const{ return value_; }
245 // Basic interop with T:
246 Flag& operator=(T const& that) { value_ = that; return *this; }
247 Flag& operator=(T && that) { value_ = that; return *this; }
248 bool operator==(T const& that) const { return value_ == that; }
249 bool operator!=(T const& that) const { return value_ != that; }
250 bool operator<(T const& that) const { return value_ < that; }
251 bool operator>(T const& that) const { return value_ > that; }
252 bool operator<=(T const& that) const { return value_ <= that; }
253 bool operator>=(T const& that) const { return value_ >= that; }