/* Allowed type of the variable */
e_xbt_cfgelm_type_t type;
int min,max;
+
+ /* Callbacks */
+ xbt_cfg_cb_t cb_set;
+ xbt_cfg_cb_t cb_rm;
/* actual content
(cannot be an union because type host uses both str and i) */
} s_xbt_cfgelm_t,*xbt_cfgelm_t;
static const char *xbt_cfgelm_type_name[xbt_cfgelm_type_count]=
- {"int","double","string","host"};
+ {"int","double","string","host","any"};
/* Internal stuff used in cache to free a variable */
static void xbt_cfgelm_free(void *data);
e_xbt_cfgelm_type_t type,
/* OUT */ xbt_cfgelm_t *whereto);
-void xbt_cfg_str_free(void *d);
-void xbt_cfg_host_free(void *d);
-
-void xbt_cfg_str_free(void *d){
+static void xbt_cfg_str_free(void *d){
free(*(void**)d);
}
-void xbt_cfg_host_free(void *d){
+static void xbt_cfg_host_free(void *d){
xbt_host_t *h=(xbt_host_t*) *(void**)d;
if (h) {
if (h->name) free(h->name);
return (xbt_cfg_t)xbt_dict_new();
}
-/** @brief Copy an existing configuration set
+/** \brief Copy an existing configuration set
*
* \arg whereto the config set to be created
* \arg tocopy the source data
xbt_assert0(tocopy,"cannot copy NULL config");
xbt_dict_foreach((xbt_dict_t)tocopy,cursor,name,variable) {
- xbt_cfg_register(*whereto, name, variable->type, variable->min, variable->max);
+ xbt_cfg_register(*whereto, name, variable->type, variable->min, variable->max,
+ variable->cb_set, variable->cb_rm);
}
}
printf("%s %s:",indent,key);
size = xbt_dynar_length(variable->content);
- printf("%d_to_%d_%s. Actual size=%d. List of values:\n",
+ printf("%d_to_%d_%s. Actual size=%d. prerm=%p,postset=%p, List of values:\n",
variable->min,variable->max,xbt_cfgelm_type_name[variable->type],
- size);
+ size,
+ variable->cb_rm, variable->cb_set);
switch (variable->type) {
void
xbt_cfg_register(xbt_cfg_t cfg,
const char *name, e_xbt_cfgelm_type_t type,
- int min, int max){
+ int min, int max,
+ xbt_cfg_cb_t cb_set, xbt_cfg_cb_t cb_rm){
xbt_cfgelm_t res;
xbt_error_t errcode;
- DEBUG4("Register cfg elm %s (%d to %d %s)",name,min,max,xbt_cfgelm_type_name[type]);
+ xbt_assert4(type>=xbt_cfgelm_int && type<=xbt_cfgelm_host,
+ "type of %s not valid (%d should be between %d and %d)",
+ name,type,xbt_cfgelm_int, xbt_cfgelm_host);
+ DEBUG5("Register cfg elm %s (%d to %d %s (=%d))",name,min,max,xbt_cfgelm_type_name[type],type);
errcode = xbt_dict_get((xbt_dict_t)cfg,name,(void**)&res);
if (errcode == no_error) {
res->type=type;
res->min=min;
res->max=max;
+ res->cb_set = cb_set;
+ res->cb_rm = cb_rm;
switch (type) {
case xbt_cfgelm_int:
* @arg cfg the config set
* @arg entry a string describing the element to register
*
- * The string may consist in several variable description separated by a space.
+ * The string may consist in several variable descriptions separated by a space.
* Each of them must use the following syntax: \<name\>:\<min nb\>_to_\<max nb\>_\<type\>
* with type being one of 'string','int', 'host' or 'double'.
*/
xbt_abort();
}
- xbt_cfg_register(cfg,entrycpy,type,min,max);
+ xbt_cfg_register(cfg,entrycpy,type,min,max,NULL,NULL);
free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
return no_error;
return mismatch_error;
}
- if (variable->max < size) {
+ if (variable->max > 0 && variable->max < size) {
ERROR4("Config elem %s accepts at most %d %s, but there is %d values.",
name,
variable->max,
(void**)whereto);
if (errcode == mismatch_error) {
- ERROR1("No registered variable %s in this config set",
+ RAISE1(mismatch_error,
+ "No registered variable '%s' in this config set",
name);
- return mismatch_error;
}
if (errcode != no_error)
return errcode;
- xbt_assert3((*whereto)->type == type,
+ xbt_assert3(type == xbt_cfgelm_any || (*whereto)->type == type,
"You tried to access to the config element %s as an %s, but its type is %s.",
name,
xbt_cfgelm_type_name[type],
xbt_cfgelm_t variable;
xbt_error_t errcode;
- TRYCATCH(mismatch_error,xbt_dict_get((xbt_dict_t)cfg,name,(void**)&variable));
+ errcode=xbt_dict_get((xbt_dict_t)cfg,name,(void**)&variable);
if (errcode == mismatch_error) {
- ERROR1("Can't get the type of '%s' since this variable does not exist",
+ RAISE1(mismatch_error,"Can't get the type of '%s' since this variable does not exist",
name);
- return mismatch_error;
+ } else if (errcode != no_error) {
+ return errcode;
}
+ INFO1("type in variable = %d",variable->type);
*type=variable->type;
return no_error;
/** @brief va_args version of xbt_cfg_set
*
* \arg cfg config set to fill
- * \arg varargs NULL-terminated list of pairs {(const char*)key, value}
+ * \arg n variable name
+ * \arg pa variable value
*
* Add some values to the config set.
- * \warning if the list isn't NULL terminated, it will segfault.
*/
xbt_error_t
-xbt_cfg_set_vargs(xbt_cfg_t cfg, va_list pa) {
- char *str,*name;
+xbt_cfg_set_vargs(xbt_cfg_t cfg, const char *name, va_list pa) {
+ char *str;
int i;
double d;
e_xbt_cfgelm_type_t type;
xbt_error_t errcode;
- while ((name=va_arg(pa,char *))) {
-
- if (!xbt_cfg_get_type(cfg,name,&type)) {
- ERROR1("Can't set the property '%s' since it's not registered",name);
- return mismatch_error;
- }
+ errcode = xbt_cfg_get_type(cfg,name,&type);
+ if (errcode != no_error) {
+ ERROR1("Can't set the property '%s' since it's not registered",name);
+ return mismatch_error;
+ }
- switch (type) {
- case xbt_cfgelm_host:
- str = va_arg(pa, char *);
- i=va_arg(pa,int);
- TRY(xbt_cfg_set_host(cfg,name,str,i));
- break;
+ switch (type) {
+ case xbt_cfgelm_host:
+ str = va_arg(pa, char *);
+ i=va_arg(pa,int);
+ TRYOLD(xbt_cfg_set_host(cfg,name,str,i));
+ break;
- case xbt_cfgelm_string:
- str=va_arg(pa, char *);
- TRY(xbt_cfg_set_string(cfg, name, str));
- break;
+ case xbt_cfgelm_string:
+ str=va_arg(pa, char *);
+ TRYOLD(xbt_cfg_set_string(cfg, name, str));
+ break;
- case xbt_cfgelm_int:
- i=va_arg(pa,int);
- TRY(xbt_cfg_set_int(cfg,name,i));
- break;
+ case xbt_cfgelm_int:
+ i=va_arg(pa,int);
+ TRYOLD(xbt_cfg_set_int(cfg,name,i));
+ break;
- case xbt_cfgelm_double:
- d=va_arg(pa,double);
- TRY(xbt_cfg_set_double(cfg,name,d));
- break;
+ case xbt_cfgelm_double:
+ d=va_arg(pa,double);
+ TRYOLD(xbt_cfg_set_double(cfg,name,d));
+ break;
- default:
- RAISE1(unknown_error,"Config element variable %s not valid.",name);
- }
+ default:
+ xbt_assert2(0,"Config element variable %s not valid (type=%d)",name,type);
}
+
return no_error;
}
/** @brief Add a NULL-terminated list of pairs {(char*)key, value} to the set
*
* \arg cfg config set to fill
- * \arg varargs NULL-terminated list of pairs {(const char*)key, value}
+ * \arg name variable name
+ * \arg varargs variable value
*
- * \warning if the list isn't NULL terminated, it will segfault.
*/
-xbt_error_t xbt_cfg_set(xbt_cfg_t cfg, ...) {
+xbt_error_t xbt_cfg_set(xbt_cfg_t cfg, const char *name, ...) {
va_list pa;
xbt_error_t errcode;
- va_start(pa,cfg);
- errcode=xbt_cfg_set_vargs(cfg,pa);
+ va_start(pa,name);
+ errcode=xbt_cfg_set_vargs(cfg,name,pa);
va_end(pa);
return errcode;
}
/* Pass the value */
while (option-name<=(len-1) && *option != ' ' && *option != '\n' && *option != '\t') {
- DEBUG1("Take %c.\n",*option);
+ DEBUG1("Take %c.",*option);
option++;
}
if (option-name == len) {
- DEBUG0("Boundary=EOL\n");
+ DEBUG0("Boundary=EOL");
option=NULL; /* don't do next iteration */
} else {
- DEBUG3("Boundary on '%c'. len=%d;option-name=%d\n",
+ DEBUG3("Boundary on '%c'. len=%d;option-name=%d",
*option,len,option-name);
/* Pass the following blank chars */
xbt_error_t errcode;
VERB2("Configuration setting: %s=%d",name,val);
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
- if (variable->max > 1) {
- xbt_dynar_push(variable->content,&val);
- } else {
+ if (variable->max == 1) {
+ if (variable->cb_rm && xbt_dynar_length(variable->content))
+ (*variable->cb_rm)(name, 0);
+
xbt_dynar_set(variable->content,0,&val);
+ } else {
+ if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+ RAISE3(mismatch_error,
+ "Cannot add value %d to the config element %s since it's already full (size=%d)",
+ val,name,variable->max);
+
+ xbt_dynar_push(variable->content,&val);
}
+
+ if (variable->cb_set)
+ (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
return no_error;
}
xbt_error_t errcode;
VERB2("Configuration setting: %s=%f",name,val);
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
- if (variable->max > 1) {
- xbt_dynar_push(variable->content,&val);
- } else {
+ if (variable->max == 1) {
+ if (variable->cb_rm && xbt_dynar_length(variable->content))
+ (*variable->cb_rm)(name, 0);
+
xbt_dynar_set(variable->content,0,&val);
+ } else {
+ if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+ RAISE3(mismatch_error,
+ "Cannot add value %f to the config element %s since it's already full (size=%d)",
+ val,name,variable->max);
+
+ xbt_dynar_push(variable->content,&val);
}
+
+ if (variable->cb_set)
+ (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
return no_error;
}
char *newval = xbt_strdup(val);
VERB2("Configuration setting: %s=%s",name,val);
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
- if (variable->max > 1) {
- xbt_dynar_push(variable->content,&newval);
- } else {
+ if (variable->max == 1) {
+ if (variable->cb_rm && xbt_dynar_length(variable->content))
+ (*variable->cb_rm)(name, 0);
+
xbt_dynar_set(variable->content,0,&newval);
+ } else {
+ if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+ RAISE3(mismatch_error,
+ "Cannot add value %s to the config element %s since it's already full (size=%d)",
+ name,val,variable->max);
+
+ xbt_dynar_push(variable->content,&newval);
}
+
+ if (variable->cb_set)
+ (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
return no_error;
}
val->name = xbt_strdup(name);
val->port = port;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
- if (variable->max > 1) {
- xbt_dynar_push(variable->content,&val);
- } else {
+ if (variable->max == 1) {
+ if (variable->cb_rm && xbt_dynar_length(variable->content))
+ (*variable->cb_rm)(name, 0);
+
xbt_dynar_set(variable->content,0,&val);
+ } else {
+ if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+ RAISE4(mismatch_error,
+ "Cannot add value %s:%d to the config element %s since it's already full (size=%d)",
+ host,port,name,variable->max);
+
+ xbt_dynar_push(variable->content,&val);
}
+
+ if (variable->cb_set)
+ (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
return no_error;
}
int cpt,seen;
xbt_error_t errcode;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+ if (xbt_dynar_length(variable->content) == variable->min)
+ RAISE3(mismatch_error,
+ "Cannot remove value %d from the config element %s since it's already at its minimal size (=%d)",
+ val,name,variable->min);
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
xbt_dynar_foreach(variable->content,cpt,seen) {
if (seen == val) {
+ if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
xbt_dynar_cursor_rm(variable->content,&cpt);
return no_error;
}
double seen;
xbt_error_t errcode;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+ if (xbt_dynar_length(variable->content) == variable->min)
+ RAISE3(mismatch_error,
+ "Cannot remove value %f from the config element %s since it's already at its minimal size (=%d)",
+ val,name,variable->min);
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
xbt_dynar_foreach(variable->content,cpt,seen) {
if (seen == val) {
xbt_dynar_cursor_rm(variable->content,&cpt);
+ if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
return no_error;
}
}
char *seen;
xbt_error_t errcode;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+ if (xbt_dynar_length(variable->content) == variable->min)
+ RAISE3(mismatch_error,
+ "Cannot remove value %s from the config element %s since it's already at its minimal size (=%d)",
+ name,val,variable->min);
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
xbt_dynar_foreach(variable->content,cpt,seen) {
if (!strcpy(seen,val)) {
+ if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
xbt_dynar_cursor_rm(variable->content,&cpt);
return no_error;
}
xbt_host_t *seen;
xbt_error_t errcode;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
+ if (xbt_dynar_length(variable->content) == variable->min)
+ RAISE4(mismatch_error,
+ "Cannot remove value %s:%d from the config element %s since it's already at its minimal size (=%d)",
+ host,port,name,variable->min);
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
xbt_dynar_foreach(variable->content,cpt,seen) {
if (!strcpy(seen->name,host) && seen->port == port) {
+ if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
xbt_dynar_cursor_rm(variable->content,&cpt);
return no_error;
}
return mismatch_error;
}
+/** @brief Remove the \e pos th value from the provided variable */
+
+xbt_error_t xbt_cfg_rm_at (xbt_cfg_t cfg, const char *name, int pos) {
+
+ xbt_cfgelm_t variable;
+ int cpt;
+ xbt_host_t *seen;
+ xbt_error_t errcode;
+
+ if (xbt_dynar_length(variable->content) == variable->min)
+ RAISE3(mismatch_error,
+ "Cannot remove %dth value from the config element %s since it's already at its minimal size (=%d)",
+ pos,name,variable->min);
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_any,&variable));
+
+ if (variable->cb_rm) (*variable->cb_rm)(name, pos);
+ xbt_dynar_remove_at(variable->content, pos, NULL);
+
+ return mismatch_error;
+}
+
/** @brief Remove all the values from a variable
*
* \arg cfg the config set
}
if (variable) {
+ if (variable->cb_rm) {
+ int cpt;
+ void *ignored;
+ xbt_dynar_foreach(variable->content,cpt,ignored) {
+ (*variable->cb_rm)(name, cpt);
+ }
+ }
xbt_dynar_reset(variable->content);
}
return no_error;
xbt_cfgelm_t variable;
xbt_error_t errcode;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
if (xbt_dynar_length(variable->content) > 1) {
WARN2("You asked for the first value of the config element '%s', but there is %lu values",
xbt_cfgelm_t variable;
xbt_error_t errcode;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
if (xbt_dynar_length(variable->content) > 1) {
WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
*val=NULL;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
if (xbt_dynar_length(variable->content) > 1) {
WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
xbt_error_t errcode;
xbt_host_t *val;
- TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
if (xbt_dynar_length(variable->content) > 1) {
WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
return no_error;
}
+
+/** @brief Retrieve one of the integer value of a variable */
+xbt_error_t
+xbt_cfg_get_int_at(xbt_cfg_t cfg,
+ const char *name,
+ int pos,
+ int *val) {
+
+ xbt_cfgelm_t variable;
+ xbt_error_t errcode;
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+ *val = xbt_dynar_get_as(variable->content, pos, int);
+ return no_error;
+}
+
+/** @brief Retrieve one of the double value of a variable */
+xbt_error_t
+xbt_cfg_get_double_at(xbt_cfg_t cfg,
+ const char *name,
+ int pos,
+ double *val) {
+
+ xbt_cfgelm_t variable;
+ xbt_error_t errcode;
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+ *val = xbt_dynar_get_as(variable->content, pos, double);
+ return no_error;
+}
+
+
+/** @brief Retrieve one of the string value of a variable */
+xbt_error_t
+xbt_cfg_get_string_at(xbt_cfg_t cfg,
+ const char *name,
+ int pos,
+ char **val) {
+
+ xbt_cfgelm_t variable;
+ xbt_error_t errcode;
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+ *val = xbt_dynar_get_as(variable->content, pos, char*);
+ return no_error;
+}
+
+/** @brief Retrieve one of the host value of a variable */
+xbt_error_t
+xbt_cfg_get_host_at(xbt_cfg_t cfg,
+ const char *name,
+ int pos,
+ char **host,
+ int *port) {
+
+ xbt_cfgelm_t variable;
+ xbt_error_t errcode;
+ xbt_host_t *val;
+
+ TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+ val = xbt_dynar_get_ptr(variable->content, pos);
+ *port = val->port;
+ *host = val->name;
+ return no_error;
+}