Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use new/delete for s_xbt_cfgelm_t
[simgrid.git] / include / xbt / config.hpp
1 /* Copyright (c) 2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 #ifndef _XBT_CONFIG_HPP_
8 #define _XBT_CONFIG_HPP_
9
10 #include <functional>
11 #include <string>
12 #include <type_traits>
13
14 #include <xbt/base.h>
15 #include <xbt/config.h>
16
17 namespace simgrid {
18 namespace config {
19
20 /** Get the base type of a e_xbt_cfgelm_type_t
21  *
22  *  * `type` is the type used in the config framework to store
23  *     the values of this type;
24  *
25  *  * `get()` is used to get such a value from the configuration.
26  */
27 template<e_xbt_cfgelm_type_t type>
28 struct base_type;
29 template<> struct base_type<xbt_cfgelm_boolean> {
30   typedef bool type;
31   static inline bool get(const char* name)
32   {
33     return xbt_cfg_get_boolean(name) ? true : false;
34   }
35 };
36 template<> struct base_type<xbt_cfgelm_int> {
37   typedef int type;
38   static inline int get(const char* name)
39   {
40     return xbt_cfg_get_int(name);
41   }
42 };
43 template<> struct base_type<xbt_cfgelm_double> {
44   typedef double type;
45   static inline double get(const char* name)
46   {
47     return xbt_cfg_get_double(name);
48   }
49 };
50 template<> struct base_type<xbt_cfgelm_string> {
51   typedef std::string type;
52   static inline std::string get(const char* name)
53   {
54     char* value = xbt_cfg_get_string(name);
55     return value != nullptr ? value : "";
56   }
57 };
58
59 /** Associate the e_xbt_cfgelm_type_t to use for a given type */
60 template<class T>
61 struct cfgelm_type : public std::integral_constant<e_xbt_cfgelm_type_t,
62   std::is_same<T, bool>::value ? xbt_cfgelm_boolean :
63   std::is_integral<T>::value ? xbt_cfgelm_int :
64   std::is_floating_point<T>::value ? xbt_cfgelm_double :
65   xbt_cfgelm_string>
66 {};
67
68 /** Get a value of a given type from the configuration */
69 template<class T> inline
70 T get(const char* name)
71 {
72   return T(base_type<cfgelm_type<T>::value>::get(name));
73 }
74 template<class T> inline
75 T get(std::string const& name)
76 {
77   return T(base_type<cfgelm_type<T>::value>::get(name.c_str()));
78 }
79
80 inline void setDefault(const char* name, int value)
81 {
82   xbt_cfg_setdefault_int(name, value);
83 }
84 inline void setDefault(const char* name, double value)
85 {
86   xbt_cfg_setdefault_double(name, value);
87 }
88 inline void setDefault(const char* name, const char* value)
89 {
90   xbt_cfg_setdefault_string(name, value);
91 }
92 inline void setDefault(const char* name, std::string const& value)
93 {
94   xbt_cfg_setdefault_string(name, value.c_str());
95 }
96 inline void setDefault(const char* name, bool value)
97 {
98   xbt_cfg_setdefault_boolean(name, value ? "yes" : "no");
99 }
100
101 /** Set the default value of a given configuration option */
102 template<class T> inline
103 void setDefault(const char* name, T value)
104 {
105   setDefault(name, base_type<cfgelm_type<T>::value>::type(value));
106 }
107
108 // Register:
109
110 /** Register a configuration flag
111  *
112  *  @param name        name of the option
113  *  @param description Description of the option
114  *  @param type        config storage type for the option
115  *  @param callback    called with the option name (expected to use `simgrid::config::get`)
116  */
117 XBT_PUBLIC(void) registerConfig(const char* name, const char* description,
118   e_xbt_cfgelm_type_t type,
119   std::function<void(const char*)> callback);
120
121 /** Bind a variable to configuration flag
122  *
123  *  @param value Bound variable
124  *  @param name  Flag name
125  *  @param description Option description
126  */
127 template<class T>
128 void declareFlag(T& value, const char* name, const char* description)
129 {
130   registerConfig(name, description, cfgelm_type<T>::value,
131     [&value](const char* name) {
132       value = simgrid::config::get<T>(name);
133     });
134   setDefault(name, value);
135 }
136
137 /** Bind a variable to configuration flag
138  *
139  *  @param value Bound variable
140  *  @param name  Flag name
141  *  @param description Option description
142  *  @f     Callback (called with the option name) providing the value
143  */
144 template<class T, class F>
145 void declareFlag(T& value, const char* name, const char* description, F f)
146 {
147   registerConfig(name, description, cfgelm_type<T>::value,
148     [&value,f](const char* name) {
149       value = f(name);
150     });
151   setDefault(name, value);
152 }
153
154 /** A variable bound to a CLI option
155  *
156  *  <pre><code>
157  *  static simgrid::config::flag<int> answer("answer", "Expected answer", 42);
158  *  static simgrid::config::flag<std::string> name("name", "Ford Prefect", "John Doe");
159  *  static simgrid::config::flag<double> gamma("gamma", "Gamma factor", 1.987);
160  *  </code></pre>
161  */
162 template<class T>
163 class flag {
164   T value_;
165 public:
166
167   /** Constructor
168    *
169    *  @param name  Flag name
170    *  @param desc  Flag description
171    *  @param value Flag initial/default value
172    */
173   flag(const char* name, const char* desc, T value) : value_(value)
174   {
175     declareFlag(value_, name, desc);
176   }
177
178   // No copy:
179   flag(flag const&) = delete;
180   flag& operator=(flag const&) = delete;
181
182   // Get the underlying value:
183   T& get() { return value_; }
184   T const& get() const { return value_; }
185
186   // Implicit conversion to the underlying type:
187   operator T&() { return value_; }
188   operator T const&() const{ return value_; }
189 };
190
191 }
192 }
193
194 #endif