1 /* Copyright (c) 2004-2014,2016. The SimGrid Team.
2 * All rights reserved. */
12 #include <type_traits>
14 #include <xbt/config.h>
15 #include <xbt/config.hpp>
17 #include "xbt/sysdep.h"
20 #include "xbt/dynar.h"
25 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_cfg, xbt, "configuration support");
27 XBT_EXPORT_NO_IMPORT(xbt_cfg_t) simgrid_config = NULL;
32 void increment(e_xbt_cfgelm_type_t& type)
34 typedef std::underlying_type<e_xbt_cfgelm_type_t>::type underlying_type;
35 type = (e_xbt_cfgelm_type_t) ((underlying_type) type + 1);
43 // A configuration variable:
44 struct ConfigurationElement {
48 /* Allowed type of the variable */
49 e_xbt_cfgelm_type_t type;
50 bool isdefault = true;
53 xbt_cfg_cb_t cb_set = nullptr;
55 /* Advanced callback (for xbt_cfgelm_string only) */
56 std::function<void(const char* value)> callback;
60 double double_content;
65 ~ConfigurationElement()
67 XBT_DEBUG("Frees cfgelm %p", this);
70 case xbt_cfgelm_double:
71 case xbt_cfgelm_boolean:
73 case xbt_cfgelm_string:
74 case xbt_cfgelm_alias:
78 xbt_die("Unexpected config type");
91 Config(Config const&) = delete;
92 Config& operator=(Config const&) = delete;
95 /* Internal stuff used in cache to free a variable */
96 static void xbt_cfgelm_free(void *data)
99 delete (simgrid::config::ConfigurationElement*) data;
103 options(xbt_dict_new_homogeneous(xbt_cfgelm_free))
108 XBT_DEBUG("Frees cfg set %p", this);
109 xbt_dict_free(&this->options);
115 static const char *xbt_cfgelm_type_name[xbt_cfgelm_type_count] = { "int", "double", "string", "boolean", "any", "outofbound" };
117 const struct xbt_boolean_couple xbt_cfgelm_boolean_values[] = {
125 /* Retrieve the variable we'll modify */
126 static simgrid::config::ConfigurationElement* xbt_cfgelm_get(xbt_cfg_t cfg, const char *name, e_xbt_cfgelm_type_t type);
128 /*----[ Memory management ]-----------------------------------------------*/
129 /** @brief Constructor
131 * Initialise a config set
133 xbt_cfg_t xbt_cfg_new(void)
135 return new simgrid::config::Config();
138 /** @brief Destructor */
139 void xbt_cfg_free(xbt_cfg_t * cfg)
144 /** @brief Dump a config set for debuging purpose
146 * @param name The name to give to this config set
147 * @param indent what to write at the beginning of each line (right number of spaces)
148 * @param cfg the config set
150 void xbt_cfg_dump(const char *name, const char *indent, xbt_cfg_t cfg)
152 xbt_dict_t dict = cfg->options;
153 xbt_dict_cursor_t cursor = NULL;
154 simgrid::config::ConfigurationElement* variable = NULL;
158 printf("%s>> Dumping of the config set '%s':\n", indent, name);
160 xbt_dict_foreach(dict, cursor, key, variable) {
161 const char* type_name = xbt_cfgelm_type_name[variable->type];
162 switch (variable->type) {
164 printf("%s %s: ()%s) %i", indent, key, type_name, variable->int_content);
166 case xbt_cfgelm_double:
167 printf("%s %s: ()%s) %f", indent, key, type_name, variable->double_content);
169 case xbt_cfgelm_string:
170 printf("%s %s: ()%s) %s", indent, key, type_name, variable->string_content);
172 case xbt_cfgelm_boolean:
173 printf("%s %s: ()%s) %s", indent, key, type_name,
174 variable->boolean_content ? "true" : "false");
176 case xbt_cfgelm_alias:
180 printf("%s Invalid type!!\n", indent);
186 printf("%s<< End of the config set '%s'\n", indent, name);
189 xbt_dict_cursor_free(&cursor);
192 /*----[ Registering stuff ]-----------------------------------------------*/
193 /** @brief Register an element within a config set
195 * @param cfg the config set
196 * @param name the name of the config element
197 * @param desc a description for this item (used by xbt_cfg_help())
198 * @param type the type of the config element
199 * @param cb_set callback function called when a value is set
201 static simgrid::config::ConfigurationElement* xbt_cfg_register(
202 xbt_cfg_t * cfg, const char *name, const char *desc, e_xbt_cfgelm_type_t type, xbt_cfg_cb_t cb_set)
205 *cfg = xbt_cfg_new();
206 xbt_assert(type >= xbt_cfgelm_int && type <= xbt_cfgelm_boolean,
207 "type of %s not valid (%d should be between %d and %d)",
208 name, (int)type, xbt_cfgelm_int, xbt_cfgelm_boolean);
210 simgrid::config::ConfigurationElement* res = (simgrid::config::ConfigurationElement*) xbt_dict_get_or_null((*cfg)->options, name);
211 xbt_assert(NULL == res, "Refusing to register the config element '%s' twice.", name);
213 res = new simgrid::config::ConfigurationElement();
214 XBT_DEBUG("Register cfg elm %s (%s) (%s (=%d) @%p in set %p)",
215 name, desc, xbt_cfgelm_type_name[type], (int)type, res, *cfg);
217 res->cb_set = cb_set;
221 // Set a default default value:
224 res->int_content = 0;
226 case xbt_cfgelm_double:
227 res->double_content = 0.0;
229 case xbt_cfgelm_string:
230 res->string_content = nullptr;
232 case xbt_cfgelm_boolean:
233 res->boolean_content = false;
236 XBT_ERROR("%d is an invalid type code", (int)type);
240 xbt_dict_set((*cfg)->options, name, res, NULL);
244 void xbt_cfg_register_double(const char *name, double default_value,xbt_cfg_cb_t cb_set, const char *desc)
246 xbt_cfg_register(&simgrid_config, name, desc, xbt_cfgelm_double, cb_set);
247 xbt_cfg_setdefault_double(name, default_value);
249 void xbt_cfg_register_int(const char *name, int default_value,xbt_cfg_cb_t cb_set, const char *desc)
251 xbt_cfg_register(&simgrid_config, name, desc, xbt_cfgelm_int, cb_set);
252 xbt_cfg_setdefault_int(name, default_value);
254 void xbt_cfg_register_string(const char *name, const char *default_value, xbt_cfg_cb_t cb_set, const char *desc)
256 xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_string,cb_set);
257 xbt_cfg_setdefault_string(name, default_value);
259 void xbt_cfg_register_boolean(const char *name, const char*default_value,xbt_cfg_cb_t cb_set, const char *desc)
261 xbt_cfg_register(&simgrid_config,name,desc,xbt_cfgelm_boolean,cb_set);
262 xbt_cfg_setdefault_boolean(name, default_value);
265 void xbt_cfg_register_alias(const char *newname, const char *oldname)
267 if (simgrid_config == NULL)
268 simgrid_config = xbt_cfg_new();
270 simgrid::config::ConfigurationElement* res = (simgrid::config::ConfigurationElement*) xbt_dict_get_or_null(simgrid_config->options, oldname);
271 xbt_assert(NULL == res, "Refusing to register the option '%s' twice.", oldname);
273 res = (simgrid::config::ConfigurationElement*) xbt_dict_get_or_null(simgrid_config->options, newname);
274 xbt_assert(res, "Cannot define an alias to the non-existing option '%s'.", newname);
276 res = new simgrid::config::ConfigurationElement();
277 XBT_DEBUG("Register cfg alias %s -> %s)",oldname,newname);
279 res->desc = std::string("Deprecated alias for ")+std::string(newname);
280 res->type = xbt_cfgelm_alias;
281 res->string_content = xbt_strdup(newname);
283 xbt_dict_set(simgrid_config->options, oldname, res, NULL);
287 * @brief Parse a string and register the stuff described.
289 * @param cfg the config set
290 * @param entry a string describing the element to register
292 * The string may consist in several variable descriptions separated by a space.
293 * Each of them must use the following syntax: \<name\>:\<type\>
294 * with type being one of 'string','int','bool' or 'double'.
296 * Note that this does not allow to set the description, so you should prefer the other interface
298 void xbt_cfg_register_str(xbt_cfg_t * cfg, const char *entry)
300 char *entrycpy = xbt_strdup(entry);
303 e_xbt_cfgelm_type_t type;
304 XBT_DEBUG("Register string '%s'", entry);
306 tok = strchr(entrycpy, ':');
307 xbt_assert(tok, "Invalid config element descriptor: %s; Should be <name>:<type>", entry);
310 for (type = (e_xbt_cfgelm_type_t)0; type < xbt_cfgelm_type_count && strcmp(tok, xbt_cfgelm_type_name[type]); increment(type));
311 xbt_assert(type < xbt_cfgelm_type_count,
312 "Invalid type in config element descriptor: %s; Should be one of 'string', 'int' or 'double'.", entry);
314 xbt_cfg_register(cfg, entrycpy, NULL, type, NULL);
316 free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
319 /** @brief Displays the declared aliases and their description */
320 void xbt_cfg_aliases(void)
322 xbt_dict_cursor_t dict_cursor;
323 unsigned int dynar_cursor;
324 simgrid::config::ConfigurationElement* variable;
326 xbt_dynar_t names = xbt_dynar_new(sizeof(char *), NULL);
328 xbt_dict_foreach(simgrid_config->options, dict_cursor, name, variable)
329 xbt_dynar_push(names, &name);
330 xbt_dynar_sort_strings(names);
332 xbt_dynar_foreach(names, dynar_cursor, name) {
333 variable = (simgrid::config::ConfigurationElement*) xbt_dict_get(simgrid_config->options, name);
335 if (variable->type == xbt_cfgelm_alias)
336 printf(" %s: %s\n", name, variable->desc.c_str());
340 /** @brief Displays the declared options and their description */
341 void xbt_cfg_help(void)
343 xbt_dict_cursor_t dict_cursor;
344 unsigned int dynar_cursor;
345 simgrid::config::ConfigurationElement* variable;
347 xbt_dynar_t names = xbt_dynar_new(sizeof(char *), NULL);
349 xbt_dict_foreach(simgrid_config->options, dict_cursor, name, variable)
350 xbt_dynar_push(names, &name);
351 xbt_dynar_sort_strings(names);
353 xbt_dynar_foreach(names, dynar_cursor, name) {
354 variable = (simgrid::config::ConfigurationElement*) xbt_dict_get(simgrid_config->options, name);
355 if (variable->type == xbt_cfgelm_alias)
358 printf(" %s: %s\n", name, variable->desc.c_str());
359 printf(" Type: %s; ", xbt_cfgelm_type_name[variable->type]);
360 printf("Current value: ");
362 switch (variable->type) {
364 printf("%d\n", variable->int_content);
366 case xbt_cfgelm_double:
367 printf("%f\n", variable->double_content);
369 case xbt_cfgelm_string:
370 printf("'%s'\n", variable->string_content);
372 case xbt_cfgelm_boolean:
373 printf("'%s'\n", variable->boolean_content ? "true" : "false");
376 printf("Invalid type!!\n");
381 xbt_dynar_free(&names);
384 static simgrid::config::ConfigurationElement* xbt_cfgelm_get(xbt_cfg_t cfg, const char *name, e_xbt_cfgelm_type_t type)
386 simgrid::config::ConfigurationElement* res = (simgrid::config::ConfigurationElement*) xbt_dict_get_or_null(cfg->options, name);
388 // The user used the old name. Switch to the new one after a short warning
389 while (res && res->type == xbt_cfgelm_alias) {
390 const char* newname = res->string_content;
391 XBT_INFO("Option %s has been renamed to %s. Consider switching.", name, newname);
392 res = xbt_cfgelm_get(cfg, newname, type);
398 THROWF(not_found_error, 0, "No registered variable '%s' in this config set.", name);
401 xbt_assert(type == xbt_cfgelm_any || res->type == type,
402 "You tried to access to the config element %s as an %s, but its type is %s.",
403 name, xbt_cfgelm_type_name[type], xbt_cfgelm_type_name[res->type]);
407 /** @brief Get the type of this variable in that configuration set
409 * @param cfg the config set
410 * @param name the name of the element
412 * @return the type of the given element
414 e_xbt_cfgelm_type_t xbt_cfg_get_type(xbt_cfg_t cfg, const char *name)
416 simgrid::config::ConfigurationElement* variable = NULL;
418 variable = (simgrid::config::ConfigurationElement*) xbt_dict_get_or_null(cfg->options, name);
420 THROWF(not_found_error, 0, "Can't get the type of '%s' since this variable does not exist", name);
422 XBT_DEBUG("type in variable = %d", (int)variable->type);
423 return variable->type;
426 /*----[ Setting ]---------------------------------------------------------*/
427 /** @brief va_args version of xbt_cfg_set
429 * @param cfg config set to fill
430 * @param name variable name
431 * @param pa variable value
433 * Add some values to the config set.
435 void xbt_cfg_set_vargs(xbt_cfg_t cfg, const char *name, va_list pa)
440 e_xbt_cfgelm_type_t type = xbt_cfgelm_type_count; /* Set a dummy value to make gcc happy. It cannot get uninitialized */
445 type = xbt_cfg_get_type(cfg, name);
448 if (e.category == not_found_error) {
450 THROWF(not_found_error, 0, "Can't set the property '%s' since it's not registered", name);
456 case xbt_cfgelm_string:
457 str = va_arg(pa, char *);
458 xbt_cfg_set_string(name, str);
462 xbt_cfg_set_int(name, i);
464 case xbt_cfgelm_double:
465 d = va_arg(pa, double);
466 xbt_cfg_set_double(name, d);
468 case xbt_cfgelm_boolean:
469 str = va_arg(pa, char *);
470 xbt_cfg_set_boolean(name, str);
473 xbt_die("Config element variable %s not valid (type=%d)", name, (int)type);
477 /** @brief Add a NULL-terminated list of pairs {(char*)key, value} to the set
479 * @param cfg config set to fill
480 * @param name variable name
481 * @param ... variable value
483 void xbt_cfg_set(xbt_cfg_t cfg, const char *name, ...)
488 xbt_cfg_set_vargs(cfg, name, pa);
492 /** @brief Add values parsed from a string into a config set
494 * @param options a string containing the content to add to the config set. This is a '\\t',' ' or '\\n' or ','
495 * separated list of variables. Each individual variable is like "[name]:[value]" where [name] is the name of an
496 * already registered variable, and [value] conforms to the data type under which this variable was registered.
498 * @todo This is a crude manual parser, it should be a proper lexer.
500 void xbt_cfg_set_parse(const char *options)
502 if (!options || !strlen(options)) { /* nothing to do */
505 char *optionlist_cpy = xbt_strdup(options);
507 XBT_DEBUG("List to parse and set:'%s'", options);
508 char *option = optionlist_cpy;
509 while (1) { /* breaks in the code */
513 int len = strlen(name);
514 XBT_DEBUG("Still to parse and set: '%s'. len=%d; option-name=%ld", name, len, (long) (option - name));
517 while (option - name <= (len - 1) && *option != ' ' && *option != '\n' && *option != '\t' && *option != ',') {
518 XBT_DEBUG("Take %c.", *option);
521 if (option - name == len) {
522 XBT_DEBUG("Boundary=EOL");
523 option = NULL; /* don't do next iteration */
525 XBT_DEBUG("Boundary on '%c'. len=%d;option-name=%ld", *option, len, (long) (option - name));
526 /* Pass the following blank chars */
528 while (option - name < (len - 1) && (*option == ' ' || *option == '\n' || *option == '\t')) {
529 /* fprintf(stderr,"Ignore a blank char.\n"); */
532 if (option - name == len - 1)
533 option = NULL; /* don't do next iteration */
535 XBT_DEBUG("parse now:'%s'; parse later:'%s'", name, option);
537 if (name[0] == ' ' || name[0] == '\n' || name[0] == '\t')
542 char *val = strchr(name, ':');
543 xbt_assert(val, "Option '%s' badly formatted. Should be of the form 'name:value'", name);
544 /* don't free(optionlist_cpy) if the assert fails, 'name' points inside it */
547 if (strncmp(name, "contexts/", strlen("contexts/")) && strncmp(name, "path", strlen("path")))
548 XBT_INFO("Configuration change: Set '%s' to '%s'", name, val);
551 xbt_cfg_set_as_string(name,val);
553 free(optionlist_cpy);
557 free(optionlist_cpy);
560 /** @brief Set the value of a variable, using the string representation of that value
562 * @param key name of the variable to modify
563 * @param value string representation of the value to set
565 * @return the first char after the parsed value in val
568 void *xbt_cfg_set_as_string(const char *key, const char *value) {
572 volatile simgrid::config::ConfigurationElement* variable = NULL;
577 while (variable == NULL) {
578 variable = (simgrid::config::ConfigurationElement*) xbt_dict_get(simgrid_config->options, key);
579 if (variable->type == xbt_cfgelm_alias) {
580 const char *newname = variable->string_content;
581 XBT_INFO("Note: configuration '%s' is deprecated. Please use '%s' instead.", key, newname);
587 if (e.category == not_found_error) {
589 THROWF(not_found_error, 0, "No registered variable corresponding to '%s'.", key);
594 switch (variable->type) {
595 case xbt_cfgelm_string:
596 xbt_cfg_set_string(key, value); /* throws */
599 i = strtol(value, &ret, 0);
601 xbt_die("Value of option %s not valid. Should be an integer", key);
603 xbt_cfg_set_int(key, i); /* throws */
605 case xbt_cfgelm_double:
606 d = strtod(value, &ret);
608 xbt_die("Value of option %s not valid. Should be a double", key);
610 xbt_cfg_set_double(key, d); /* throws */
612 case xbt_cfgelm_boolean:
613 xbt_cfg_set_boolean(key, value); /* throws */
614 ret = (char *)value + strlen(value);
617 THROWF(unknown_error, 0, "Type of config element %s is not valid.", key);
623 /** @brief Set an integer value to \a name within \a cfg if it wasn't changed yet
625 * This is useful to change the default value of a variable while allowing
626 * users to override it with command line arguments
628 void xbt_cfg_setdefault_int(const char *name, int val)
630 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_int);
632 if (variable->isdefault){
633 xbt_cfg_set_int(name, val);
634 variable->isdefault = true;
636 XBT_DEBUG("Do not override configuration variable '%s' with value '%d' because it was already set.", name, val);
639 /** @brief Set an integer value to \a name within \a cfg if it wasn't changed yet
641 * This is useful to change the default value of a variable while allowing
642 * users to override it with command line arguments
644 void xbt_cfg_setdefault_double(const char *name, double val)
646 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_double);
648 if (variable->isdefault) {
649 xbt_cfg_set_double(name, val);
650 variable->isdefault = true;
652 XBT_DEBUG("Do not override configuration variable '%s' with value '%f' because it was already set.", name, val);
655 /** @brief Set a string value to \a name within \a cfg if it wasn't changed yet
657 * This is useful to change the default value of a variable while allowing
658 * users to override it with command line arguments
660 void xbt_cfg_setdefault_string(const char *name, const char *val)
662 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_string);
664 if (variable->isdefault){
665 xbt_cfg_set_string(name, val);
666 variable->isdefault = true;
668 XBT_DEBUG("Do not override configuration variable '%s' with value '%s' because it was already set.", name, val);
671 /** @brief Set an boolean value to \a name within \a cfg if it wasn't changed yet
673 * This is useful to change the default value of a variable while allowing
674 * users to override it with command line arguments
676 void xbt_cfg_setdefault_boolean(const char *name, const char *val)
678 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_boolean);
680 if (variable->isdefault){
681 xbt_cfg_set_boolean(name, val);
682 variable->isdefault = true;
685 XBT_DEBUG("Do not override configuration variable '%s' with value '%s' because it was already set.", name, val);
688 /** @brief Set an integer value to \a name within \a cfg
690 * @param name the name of the variable
691 * @param val the value of the variable
693 void xbt_cfg_set_int(const char *name, int val)
695 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_int);
696 variable->int_content = val;
697 if (variable->cb_set)
698 variable->cb_set(name);
699 variable->isdefault = false;
702 /** @brief Set or add a double value to \a name within \a cfg
704 * @param name the name of the variable
705 * @param val the double to set
707 void xbt_cfg_set_double(const char *name, double val)
709 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_double);
710 variable->double_content = val;
711 if (variable->cb_set)
712 variable->cb_set(name);
713 variable->isdefault = false;
716 /** @brief Set or add a string value to \a name within \a cfg
718 * @param cfg the config set
719 * @param name the name of the variable
720 * @param val the value to be added
723 void xbt_cfg_set_string(const char *name, const char *val)
725 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_string);
726 free(variable->string_content);
727 variable->string_content = xbt_strdup(val);
728 if (variable->cb_set)
729 variable->cb_set(name);
730 variable->isdefault = false;
732 if (variable->callback) {
734 variable->callback(val);
736 catch(std::range_error& e) {
737 xbt_die("Invalid flag %s=%s: %s", val, name, e.what());
739 catch(std::exception& e) {
740 xbt_die("Error for flag %s=%s: %s", val, name, e.what());
743 xbt_die("Error for flag %s=%s", val, name);
748 /** @brief Set or add a boolean value to \a name within \a cfg
750 * @param name the name of the variable
751 * @param val the value of the variable
753 void xbt_cfg_set_boolean(const char *name, const char *val)
756 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_boolean);
758 for (int i = 0; xbt_cfgelm_boolean_values[i].true_val != NULL; i++) {
759 if (strcmp(val, xbt_cfgelm_boolean_values[i].true_val) == 0){
763 if (strcmp(val, xbt_cfgelm_boolean_values[i].false_val) == 0){
768 xbt_assert(bval != -1, "Value of option '%s' not valid. Should be a boolean (yes,no,on,off,true,false,0,1)", val);
769 variable->boolean_content = bval;
770 if (variable->cb_set)
771 variable->cb_set(name);
772 variable->isdefault = false;
776 /* Say if the value is the default value */
777 int xbt_cfg_is_default_value(const char *name)
779 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_any);
780 return variable->isdefault;
783 /*----[ Getting ]---------------------------------------------------------*/
784 /** @brief Retrieve an integer value of a variable (get a warning if not uniq)
786 * @param name the name of the variable
788 * Returns the first value from the config set under the given name.
790 int xbt_cfg_get_int(const char *name)
792 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_int);
793 return variable->int_content;
796 /** @brief Retrieve a double value of a variable (get a warning if not uniq)
798 * @param cfg the config set
799 * @param name the name of the variable
801 * Returns the first value from the config set under the given name.
803 double xbt_cfg_get_double(const char *name)
805 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_double);
806 return variable->double_content;
809 /** @brief Retrieve a string value of a variable (get a warning if not uniq)
811 * @param cfg the config set
812 * @param name the name of the variable
814 * Returns the first value from the config set under the given name.
815 * If there is more than one value, it will issue a warning.
816 * Returns NULL if there is no value.
818 * \warning the returned value is the actual content of the config set
820 char *xbt_cfg_get_string(const char *name)
822 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_string);
823 return variable->string_content;
826 /** @brief Retrieve a boolean value of a variable (get a warning if not uniq)
828 * @param cfg the config set
829 * @param name the name of the variable
831 * Returns the first value from the config set under the given name.
832 * If there is more than one value, it will issue a warning.
834 int xbt_cfg_get_boolean(const char *name)
836 simgrid::config::ConfigurationElement* variable = xbt_cfgelm_get(simgrid_config, name, xbt_cfgelm_boolean);
837 return variable->boolean_content;
843 bool parseBool(const char* value)
845 for (int i = 0; xbt_cfgelm_boolean_values[i].true_val != NULL; i++) {
846 if (std::strcmp(value, xbt_cfgelm_boolean_values[i].true_val) == 0)
848 if (std::strcmp(value, xbt_cfgelm_boolean_values[i].false_val) == 0)
851 throw std::range_error("not a boolean");
854 double parseDouble(const char* value)
858 double res = std::strtod(value, &end);
860 throw std::range_error("out of range");
862 xbt_die("Unexpected errno");
863 if (end == value || *end != '\0')
864 throw std::range_error("invalid double");
869 long int parseLong(const char* value)
873 long int res = std::strtol(value, &end, 0);
875 if (res == LONG_MIN && errno == ERANGE)
876 throw std::range_error("underflow");
877 else if (res == LONG_MAX && errno == ERANGE)
878 throw std::range_error("overflow");
879 xbt_die("Unexpected errno");
881 if (end == value || *end != '\0')
882 throw std::range_error("invalid integer");
887 void declareFlag(const char* name, const char* description,
888 std::function<void(const char* value)> callback)
890 simgrid::config::ConfigurationElement* e = xbt_cfg_register(
891 &simgrid_config, name, description, xbt_cfgelm_string, NULL);
892 e->callback = std::move(callback);
905 #include <xbt/config.hpp>
907 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(xbt_cfg);
909 XBT_TEST_SUITE("config", "Configuration support");
911 static xbt_cfg_t make_set()
913 xbt_cfg_t set = NULL;
915 xbt_log_threshold_set(&_XBT_LOGV(xbt_cfg), xbt_log_priority_critical);
916 xbt_cfg_register_str(&set, "speed:int");
917 xbt_cfg_register_str(&set, "peername:string");
918 xbt_cfg_register_str(&set, "user:string");
921 } /* end_of_make_set */
923 XBT_PUBLIC_DATA(xbt_cfg_t) simgrid_config;
925 XBT_TEST_UNIT("memuse", test_config_memuse, "Alloc and free a config set")
927 simgrid_config = make_set();
928 xbt_test_add("Alloc and free a config set");
929 xbt_cfg_set_parse("peername:veloce user:bidule");
930 xbt_cfg_free(&simgrid_config);
933 XBT_TEST_UNIT("use", test_config_use, "Data retrieving tests")
935 simgrid_config = make_set();
936 xbt_test_add("Get a single value");
938 /* get_single_value */
941 xbt_cfg_set_parse("peername:toto:42 speed:42");
942 ival = xbt_cfg_get_int("speed");
944 xbt_test_fail("Speed value = %d, I expected 42", ival);
947 xbt_test_add("Access to a non-existant entry");
952 xbt_cfg_set_parse("color:blue");
954 if (e.category != not_found_error)
955 xbt_test_exception(e);
959 xbt_cfg_free(&simgrid_config);
962 XBT_TEST_UNIT("c++flags", test_config_cxx_flags, "C++ flags")
964 simgrid_config = make_set();
965 xbt_test_add("C++ declaration of flags");
967 simgrid::config::Flag<int> int_flag("int", "", 0);
968 simgrid::config::Flag<std::string> string_flag("string", "", "foo");
969 simgrid::config::Flag<double> double_flag("double", "", 0.32);
970 simgrid::config::Flag<bool> bool_flag1("bool1", "", false);
971 simgrid::config::Flag<bool> bool_flag2("bool2", "", true);
973 xbt_test_add("Parse values");
974 xbt_cfg_set_parse("int:42 string:bar double:8.0 bool1:true bool2:false");
975 xbt_test_assert(int_flag == 42, "Check int flag");
976 xbt_test_assert(string_flag == "bar", "Check string flag");
977 xbt_test_assert(double_flag == 8.0, "Check double flag");
978 xbt_test_assert(bool_flag1, "Check bool1 flag");
979 xbt_test_assert(!bool_flag2, "Check bool2 flag");
981 xbt_cfg_free(&simgrid_config);
984 #endif /* SIMGRID_TEST */