};
/** \brief Callback types. They get the name of the modified entry, and the position of the changed value */
-typedef void (*xbt_cfg_cb_t) (const char *);
+typedef void (*xbt_cfg_cb_t) (const char * name);
+typedef void (*xbt_cfg_cb_ext_t)(const char * name, void* cb_data);
+typedef void (*xbt_cfg_cb_free_t)(void* cb_data);
XBT_PUBLIC(xbt_cfg_t) xbt_cfg_new(void);
-XBT_PUBLIC(void) xbt_cfg_cpy(xbt_cfg_t tocopy, /* OUT */xbt_cfg_t * whereto);
XBT_PUBLIC(void) xbt_cfg_free(xbt_cfg_t * cfg);
XBT_PUBLIC(void) xbt_cfg_dump(const char *name, const char *indent, xbt_cfg_t cfg);
XBT_PUBLIC(void) xbt_cfg_register_alias(const char *newname, const char *oldname);
XBT_PUBLIC(void) xbt_cfg_register_str(xbt_cfg_t * cfg, const char *entry);
+XBT_PUBLIC(void) xbt_cfg_register_ext(
+ const char *name, const char *desc, e_xbt_cfgelm_type_t type,
+ xbt_cfg_cb_ext_t cb, void* data, xbt_cfg_cb_free_t data_free);
+
XBT_PUBLIC(void) xbt_cfg_aliases(void);
XBT_PUBLIC(void) xbt_cfg_help(void);
XBT_PUBLIC(e_xbt_cfgelm_type_t) xbt_cfg_get_type(xbt_cfg_t cfg, const char *name);
--- /dev/null
+/* Copyright (c) 2016. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef _XBT_CONFIG_HPP_
+#define _XBT_CONFIG_HPP_
+
+#include <functional>
+#include <string>
+#include <type_traits>
+
+#include <xbt/base.h>
+#include <xbt/config.h>
+
+namespace simgrid {
+namespace config {
+
+/** Get the base type of a e_xbt_cfgelm_type_t
+ *
+ * * `type` is the type used in the config framework to store
+ * the values of this type;
+ *
+ * * `get()` is used to get such a value from the configuration.
+ */
+template<e_xbt_cfgelm_type_t type>
+struct base_type;
+template<> struct base_type<xbt_cfgelm_boolean> {
+ typedef bool type;
+ static inline bool get(const char* name)
+ {
+ return xbt_cfg_get_boolean(name) ? true : false;
+ }
+};
+template<> struct base_type<xbt_cfgelm_int> {
+ typedef int type;
+ static inline int get(const char* name)
+ {
+ return xbt_cfg_get_int(name);
+ }
+};
+template<> struct base_type<xbt_cfgelm_double> {
+ typedef double type;
+ static inline double get(const char* name)
+ {
+ return xbt_cfg_get_double(name);
+ }
+};
+template<> struct base_type<xbt_cfgelm_string> {
+ typedef std::string type;
+ static inline std::string get(const char* name)
+ {
+ char* value = xbt_cfg_get_string(name);
+ return value != nullptr ? value : "";
+ }
+};
+
+/** Associate the e_xbt_cfgelm_type_t to use for a given type */
+template<class T>
+struct cfgelm_type : public std::integral_constant<e_xbt_cfgelm_type_t,
+ std::is_same<T, bool>::value ? xbt_cfgelm_boolean :
+ std::is_integral<T>::value ? xbt_cfgelm_int :
+ std::is_floating_point<T>::value ? xbt_cfgelm_double :
+ xbt_cfgelm_string>
+{};
+
+/** Get a value of a given type from the configuration */
+template<class T> inline
+T get(const char* name)
+{
+ return T(base_type<cfgelm_type<T>::value>::get(name));
+}
+template<class T> inline
+T get(std::string const& name)
+{
+ return T(base_type<cfgelm_type<T>::value>::get(name.c_str()));
+}
+
+inline void setDefault(const char* name, int value)
+{
+ xbt_cfg_setdefault_int(name, value);
+}
+inline void setDefault(const char* name, double value)
+{
+ xbt_cfg_setdefault_double(name, value);
+}
+inline void setDefault(const char* name, const char* value)
+{
+ xbt_cfg_setdefault_string(name, value);
+}
+inline void setDefault(const char* name, std::string const& value)
+{
+ xbt_cfg_setdefault_string(name, value.c_str());
+}
+inline void setDefault(const char* name, bool value)
+{
+ xbt_cfg_setdefault_boolean(name, value ? "yes" : "no");
+}
+
+/** Set the default value of a given configuration option */
+template<class T> inline
+void setDefault(const char* name, T value)
+{
+ setDefault(name, base_type<cfgelm_type<T>::value>::type(value));
+}
+
+// Register:
+
+/** Register a configuration flag
+ *
+ * @param name name of the option
+ * @param description Description of the option
+ * @param type config storage type for the option
+ * @param callback called with the option name (expected to use `simgrid::config::get`)
+ */
+XBT_PUBLIC(void) registerConfig(const char* name, const char* description,
+ e_xbt_cfgelm_type_t type,
+ std::function<void(const char*)> callback);
+
+/** Bind a variable to configuration flag
+ *
+ * @param value Bound variable
+ * @param name Flag name
+ * @param description Option description
+ */
+template<class T>
+void declareFlag(T& value, const char* name, const char* description)
+{
+ registerConfig(name, description, cfgelm_type<T>::value,
+ [&value](const char* name) {
+ value = simgrid::config::get<T>(name);
+ });
+ setDefault(name, value);
+}
+
+/** Bind a variable to configuration flag
+ *
+ * @param value Bound variable
+ * @param name Flag name
+ * @param description Option description
+ * @f Callback (called with the option name) providing the value
+ */
+template<class T, class F>
+void declareFlag(T& value, const char* name, const char* description, F f)
+{
+ registerConfig(name, description, cfgelm_type<T>::value,
+ [&value,f](const char* name) {
+ value = f(name);
+ });
+ setDefault(name, value);
+}
+
+/** A variable bound to a CLI option
+ *
+ * <pre><code>
+ * static simgrid::config::flag<int> answer("answer", "Expected answer", 42);
+ * static simgrid::config::flag<std::string> name("name", "Ford Prefect", "John Doe");
+ * static simgrid::config::flag<double> gamma("gamma", "Gamma factor", 1.987);
+ * </code></pre>
+ */
+template<class T>
+class flag {
+ T value_;
+public:
+
+ /** Constructor
+ *
+ * @param name Flag name
+ * @param desc Flag description
+ * @param value Flag initial/default value
+ */
+ flag(const char* name, const char* desc, T value) : value_(value)
+ {
+ declareFlag(value_, name, desc);
+ }
+
+ // No copy:
+ flag(flag const&) = delete;
+ flag& operator=(flag const&) = delete;
+
+ // Get the underlying value:
+ T& get() { return value_; }
+ T const& get() const { return value_; }
+
+ // Implicit conversion to the underlying type:
+ operator T&() { return value_; }
+ operator T const&() const{ return value_; }
+};
+
+}
+}
+
+#endif
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_cfg, xbt, "configuration support");
XBT_EXPORT_NO_IMPORT(xbt_cfg_t) simgrid_config = NULL;
-static void xbt_cfg_register(xbt_cfg_t * cfg, const char *name, const char *desc, e_xbt_cfgelm_type_t type, xbt_cfg_cb_t cb_set);
/* xbt_cfgelm_t: the typedef corresponding to a config variable. */
/* Callbacks */
xbt_cfg_cb_t cb_set;
+ /* Advanced callbacks */
+ xbt_cfg_cb_ext_t cb_set_ext;
+ void* cb_set_data;
+ xbt_cfg_cb_free_t cb_set_free;
+
/* actual content (could be an union or something) */
xbt_dynar_t content;
} s_xbt_cfgelm_t, *xbt_cfgelm_t;
return (xbt_cfg_t) xbt_dict_new_homogeneous(&xbt_cfgelm_free);
}
-/** \brief Copy an existing configuration set
- *
- * @param whereto the config set to be created
- * @param tocopy the source data
- *
- * This only copy the registrations, not the actual content
- */
-void xbt_cfg_cpy(xbt_cfg_t tocopy, xbt_cfg_t * whereto)
-{
- xbt_dict_cursor_t cursor = NULL;
- xbt_cfgelm_t variable = NULL;
- char *name = NULL;
-
- XBT_DEBUG("Copy cfg set %p", tocopy);
- *whereto = NULL;
- xbt_assert(tocopy, "cannot copy NULL config");
-
- xbt_dict_foreach((xbt_dict_t) tocopy, cursor, name, variable)
- xbt_cfg_register(whereto, name, variable->desc, variable->type, variable->cb_set);
-}
-
/** @brief Destructor */
void xbt_cfg_free(xbt_cfg_t * cfg)
{
printf("%s %s:", indent, key);
size = xbt_dynar_length(variable->content);
- printf ("%s. Actual size=%d. postset=%p, List of values:\n",
+ printf ("%s. Actual size=%d. postset=%p\n",
xbt_cfgelm_type_name[variable->type], size, variable->cb_set);
switch (variable->type) {
XBT_DEBUG("Frees cfgelm %p", c);
if (!c)
return;
+ if (c->cb_set_free)
+ c->cb_set_free(c->cb_set_data);
xbt_free(c->desc);
if (c->type != xbt_cfgelm_alias)
xbt_dynar_free(&(c->content));
* @param type the type of the config element
* @param cb_set callback function called when a value is set
*/
-static void xbt_cfg_register(xbt_cfg_t * cfg, const char *name, const char *desc, e_xbt_cfgelm_type_t type, xbt_cfg_cb_t cb_set)
+static void xbt_cfg_register(
+ xbt_cfg_t * cfg, const char *name, const char *desc, e_xbt_cfgelm_type_t type,
+ xbt_cfg_cb_t cb_set,
+ xbt_cfg_cb_ext_t cb_set_ext, void* cb_set_data, xbt_cfg_cb_free_t cb_set_free)
{
if (*cfg == NULL)
*cfg = xbt_cfg_new();
res->desc = xbt_strdup(desc);
res->type = type;
res->cb_set = cb_set;
+ res->cb_set_ext = cb_set_ext;
+ res->cb_set_data = cb_set_data;
+ res->cb_set_free = cb_set_free;
res->isdefault = 1;
switch (type) {
xbt_dict_set((xbt_dict_t) * cfg, name, res, NULL);
}
+
+
void xbt_cfg_register_double(const char *name, double default_value,xbt_cfg_cb_t cb_set, const char *desc){
- xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_double,cb_set);
+ xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_double,cb_set, NULL, NULL, NULL);
xbt_cfg_setdefault_double(name, default_value);
}
void xbt_cfg_register_int(const char *name, int default_value,xbt_cfg_cb_t cb_set, const char *desc) {
- xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_int,cb_set);
+ xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_int,cb_set, NULL, NULL, NULL);
xbt_cfg_setdefault_int(name, default_value);
}
void xbt_cfg_register_string(const char *name, const char *default_value, xbt_cfg_cb_t cb_set, const char *desc){
- xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_string,cb_set);
+ xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_string,cb_set, NULL, NULL, NULL);
xbt_cfg_setdefault_string(name, default_value);
}
void xbt_cfg_register_boolean(const char *name, const char*default_value,xbt_cfg_cb_t cb_set, const char *desc){
- xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_boolean,cb_set);
+ xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_boolean,cb_set, NULL, NULL, NULL);
xbt_cfg_setdefault_boolean(name, default_value);
}
+/** Register a config with an extended callback
+ *
+ * @param name Name of the flag
+ * @param desc Description of the flag
+ * @param type Type of the flag
+ * @param cb Extended callback
+ * @param data Data associated with the callback
+ * @param data_free Function used to free the callback data (or NULL)
+ */
+void xbt_cfg_register_ext(const char *name, const char *desc, e_xbt_cfgelm_type_t type,
+ xbt_cfg_cb_ext_t cb, void* data, xbt_cfg_cb_free_t data_free)
+{
+ xbt_cfg_register(&simgrid_config, name, desc, type, NULL, cb, data, data_free);
+}
+
void xbt_cfg_register_alias(const char *newname, const char *oldname)
{
if (simgrid_config == NULL)
xbt_assert(type < xbt_cfgelm_type_count,
"Invalid type in config element descriptor: %s; Should be one of 'string', 'int' or 'double'.", entry);
- xbt_cfg_register(cfg, entrycpy, NULL, type, NULL);
+ xbt_cfg_register(cfg, entrycpy, NULL, type, NULL, NULL, NULL, NULL);
free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
}
if (variable->cb_set)
variable->cb_set(name);
+ if (variable->cb_set_ext)
+ variable->cb_set_ext(name, variable->cb_set_data);
variable->isdefault = 0;
}
if (variable->cb_set)
variable->cb_set(name);
+ if (variable->cb_set_ext)
+ variable->cb_set_ext(name, variable->cb_set_data);
variable->isdefault = 0;
}
if (variable->cb_set)
variable->cb_set(name);
+ if (variable->cb_set_ext)
+ variable->cb_set_ext(name, variable->cb_set_data);
variable->isdefault = 0;
}
if (variable->cb_set)
variable->cb_set(name);
+ if (variable->cb_set_ext)
+ variable->cb_set_ext(name, variable->cb_set_data);
variable->isdefault = 0;
}
--- /dev/null
+/* Copyright (c) 2016. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <functional>
+#include <string>
+
+#include <xbt/config.h>
+#include <xbt/config.hpp>
+
+namespace simgrid {
+namespace config {
+
+static void callCallback(const char* name, void* data)
+{
+ (*(std::function<void(const char*)>*) data)(name);
+}
+
+static void freeCallback(void* data)
+{
+ delete (std::function<void(const char*)>*) data;
+}
+
+void registerConfig(const char* name, const char* description,
+ e_xbt_cfgelm_type_t type,
+ std::function<void(const char*)> callback)
+{
+ std::function<void(const char*)>* code
+ = new std::function<void(const char*)>(std::move(callback));
+ xbt_cfg_register_ext(name, description, type,
+ callCallback, code, freeCallback);
+}
+
+}
+}
\ No newline at end of file
src/xbt/automaton/automaton.c
src/xbt/automaton/automatonparse_promela.c
src/xbt/config.c
+ src/xbt/config.cpp
src/xbt/cunit.c
src/xbt/dict.c
src/xbt/dict_cursor.c
include/xbt/automaton.hpp
include/xbt/base.h
include/xbt/config.h
+ include/xbt/config.hpp
include/xbt/cunit.h
include/xbt/dict.h
include/xbt/string.hpp