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 /** Bind a variable to configuration flag
103 * @param value Bound variable
104 * @param name Flag name
105 * @param description Option description
108 void bindFlag(T& value, const char* name, const char* description)
111 declareFlag(name, description, [&value](const char* val) {
112 value = simgrid::config::parse<T>(val);
114 xbt_cfg_setdefault_string(name, simgrid::config::to_string(value).c_str());
117 /** Bind a variable to configuration flag
121 * simgrid::config::bindFlag(a, "x", [](const char* value) {
122 * return simgrid::config::parse(value);
126 // F is a parser, F : const char* -> T
127 template<class T, class F>
128 typename std::enable_if<std::is_same<
130 typename std::remove_cv< decltype(
131 std::declval<F>()(std::declval<const char*>())
133 >::value, void>::type
134 bindFlag(T& value, const char* name, const char* description,
137 declareFlag(name, description, [&value,callback](const char* val) {
138 value = callback(val);
140 xbt_cfg_setdefault_string(name, to_string(value).c_str());
143 /** Bind a variable to configuration flag
147 * simgrid::config::bindFlag(a, "x", [](int x) {
148 * if (x < x_min || x => x_max)
149 * throw std::range_error("must be in [x_min, x_max)")
153 // F is a checker, F : T& -> ()
154 template<class T, class F>
155 typename std::enable_if<std::is_same<
157 decltype( std::declval<F>()(std::declval<const T&>()) )
158 >::value, void>::type
159 bindFlag(T& value, const char* name, const char* description,
162 declareFlag(name, description, [&value,callback](const char* val) {
163 T res = parse<T>(val);
165 value = std::move(res);
167 xbt_cfg_setdefault_string(name, to_string(value).c_str());
170 /** Bind a variable to configuration flag
174 * simgrid::config::bindFlag(a, "x", [](int x) { return return x > 0; });
177 // F is a predicate, F : T const& -> bool
178 template<class T, class F>
179 typename std::enable_if<std::is_same<
181 decltype( std::declval<F>()(std::declval<const T&>()) )
182 >::value, void>::type
183 bindFlag(T& value, const char* name, const char* description,
186 declareFlag(name, description, [&value,callback](const char* val) {
187 T res = parse<T>(val);
189 throw std::range_error("invalid value");
190 value = std::move(res);
192 xbt_cfg_setdefault_string(name, to_string(value).c_str());
195 /** A variable bound to a CLI option
198 * static simgrid::config::flag<int> answer("answer", "Expected answer", 42);
199 * static simgrid::config::flag<std::string> name("name", "Ford Prefect", "John Doe");
200 * static simgrid::config::flag<double> gamma("gamma", "Gamma factor", 1.987);
210 * @param name Flag name
211 * @param desc Flag description
212 * @param value Flag initial/default value
214 Flag(const char* name, const char* desc, T value) : value_(value)
216 simgrid::config::bindFlag(value_, name, desc);
220 Flag(const char* name, const char* desc, T value, F callback) : value_(value)
222 simgrid::config::bindFlag(value_, name, desc, std::move(callback));
226 Flag(Flag const&) = delete;
227 Flag& operator=(Flag const&) = delete;
229 // Get the underlying value:
230 T& get() { return value_; }
231 T const& get() const { return value_; }
233 // Implicit conversion to the underlying type:
234 operator T&() { return value_; }
235 operator T const&() const{ return value_; }
237 // Basic interop with T:
238 Flag& operator=(T const& that) { value_ = that; return *this; }
239 Flag& operator=(T && that) { value_ = that; return *this; }
240 bool operator==(T const& that) const { return value_ == that; }
241 bool operator!=(T const& that) const { return value_ != that; }
242 bool operator<(T const& that) const { return value_ < that; }
243 bool operator>(T const& that) const { return value_ > that; }
244 bool operator<=(T const& that) const { return value_ <= that; }
245 bool operator>=(T const& that) const { return value_ >= that; }