X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/c9f0b6f33ed2290b8f99ca0d34646e6418dcd0ba..78b7ddcea041887aed58f1c80e4838f1fe5d4728:/src/xbt/config.c diff --git a/src/xbt/config.c b/src/xbt/config.c index 571a57081c..aade80293a 100644 --- a/src/xbt/config.c +++ b/src/xbt/config.c @@ -29,6 +29,10 @@ typedef struct { /* 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) */ @@ -36,7 +40,7 @@ typedef struct { } 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); @@ -46,17 +50,14 @@ static xbt_error_t xbt_cfgelm_get(xbt_cfg_t cfg, const char *name, 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){ - xbt_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) xbt_free(h->name); - xbt_free(h); + if (h->name) free(h->name); + free(h); } } @@ -72,7 +73,7 @@ xbt_cfg_t xbt_cfg_new(void) { 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 @@ -90,7 +91,8 @@ xbt_cfg_cpy(xbt_cfg_t tocopy,xbt_cfg_t *whereto) { 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); } } @@ -124,9 +126,10 @@ void xbt_cfg_dump(const char *name,const char *indent,xbt_cfg_t cfg) { 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) { @@ -180,7 +183,7 @@ void xbt_cfgelm_free(void *data) { if (!c) return; xbt_dynar_free(&(c->content)); - xbt_free(c); + free(c); } /*----[ Registering stuff ]-----------------------------------------------*/ @@ -196,11 +199,15 @@ void xbt_cfgelm_free(void *data) { 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) { @@ -214,6 +221,8 @@ xbt_cfg_register(xbt_cfg_t cfg, 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: @@ -258,7 +267,7 @@ xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) { * @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: \:\_to_\_\ * with type being one of 'string','int', 'host' or 'double'. */ @@ -276,7 +285,7 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) { ERROR3("%s%s%s", "Invalid config element descriptor: ",entry, "; Should be :_to__"); - xbt_free(entrycpy); + free(entrycpy); xbt_abort(); } *(tok++)='\0'; @@ -284,7 +293,7 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) { min=strtol(tok, &tok, 10); if (!tok) { ERROR1("Invalid minimum in config element descriptor %s",entry); - xbt_free(entrycpy); + free(entrycpy); xbt_abort(); } @@ -292,7 +301,7 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) { ERROR3("%s%s%s", "Invalid config element descriptor: ",entry, "; Should be :_to__"); - xbt_free(entrycpy); + free(entrycpy); xbt_abort(); } tok += strlen("_to_"); @@ -300,7 +309,7 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) { max=strtol(tok, &tok, 10); if (!tok) { ERROR1("Invalid maximum in config element descriptor %s",entry); - xbt_free(entrycpy); + free(entrycpy); xbt_abort(); } @@ -308,7 +317,7 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) { ERROR3("%s%s%s", "Invalid config element descriptor: ",entry, "; Should be :_to__"); - xbt_free(entrycpy); + free(entrycpy); xbt_abort(); } @@ -319,13 +328,13 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) { ERROR3("%s%s%s", "Invalid type in config element descriptor: ",entry, "; Should be one of 'string', 'int', 'host' or 'double'."); - xbt_free(entrycpy); + free(entrycpy); xbt_abort(); } - xbt_cfg_register(cfg,entrycpy,type,min,max); + xbt_cfg_register(cfg,entrycpy,type,min,max,NULL,NULL); - xbt_free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */ + free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */ return no_error; } @@ -352,7 +361,7 @@ xbt_cfg_check(xbt_cfg_t cfg) { 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, @@ -377,14 +386,14 @@ static xbt_error_t xbt_cfgelm_get(xbt_cfg_t cfg, (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], @@ -408,14 +417,16 @@ xbt_cfg_get_type(xbt_cfg_t cfg, const char *name, 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; @@ -425,69 +436,68 @@ xbt_cfg_get_type(xbt_cfg_t cfg, const char *name, /** @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); + TRY(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 *); + TRY(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); + TRY(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); + TRY(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; } @@ -536,15 +546,15 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { /* 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 */ @@ -566,7 +576,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { val=strchr(name,':'); if (!val) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); xbt_assert1(FALSE, "Malformated option: '%s'; Should be of the form 'name:value'", name); @@ -581,11 +591,11 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { break; case mismatch_error: ERROR1("No registrated variable corresponding to '%s'.",name); - xbt_free(optionlist_cpy); + free(optionlist_cpy); return mismatch_error; break; default: - xbt_free(optionlist_cpy); + free(optionlist_cpy); return errcode; } @@ -593,7 +603,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { case xbt_cfgelm_string: errcode = xbt_cfg_set_string(cfg, name, val); if (errcode != no_error) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); return errcode; } break; @@ -601,7 +611,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { case xbt_cfgelm_int: i=strtol(val, &val, 0); if (val==NULL) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); xbt_assert1(FALSE, "Value of option %s not valid. Should be an integer", name); @@ -609,7 +619,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { errcode = xbt_cfg_set_int(cfg,name,i); if (errcode != no_error) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); return errcode; } break; @@ -617,7 +627,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { case xbt_cfgelm_double: d=strtod(val, &val); if (val==NULL) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); xbt_assert1(FALSE, "Value of option %s not valid. Should be a double", name); @@ -625,7 +635,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { errcode = xbt_cfg_set_double(cfg,name,d); if (errcode != no_error) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); return errcode; } break; @@ -634,7 +644,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { str=val; val=strchr(val,':'); if (!val) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); xbt_assert1(FALSE, "Value of option %s not valid. Should be an host (machine:port)", name); @@ -643,7 +653,7 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { *(val++)='\0'; i=strtol(val, &val, 0); if (val==NULL) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); xbt_assert1(FALSE, "Value of option %s not valid. Should be an host (machine:port)", name); @@ -651,18 +661,18 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) { errcode = xbt_cfg_set_host(cfg,name,str,i); if (errcode != no_error) { - xbt_free(optionlist_cpy); + free(optionlist_cpy); return errcode; } break; default: - xbt_free(optionlist_cpy); + free(optionlist_cpy); RAISE1(unknown_error,"Type of config element %s is not valid.",name); } } - xbt_free(optionlist_cpy); + free(optionlist_cpy); return no_error; } @@ -680,11 +690,22 @@ xbt_cfg_set_int(xbt_cfg_t cfg,const char*name, int val) { VERB2("Configuration setting: %s=%d",name,val); TRY (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; } @@ -703,11 +724,22 @@ xbt_cfg_set_double(xbt_cfg_t cfg,const char*name, double val) { VERB2("Configuration setting: %s=%f",name,val); TRY (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; } @@ -728,11 +760,22 @@ xbt_cfg_set_string(xbt_cfg_t cfg,const char*name, const char*val) { VERB2("Configuration setting: %s=%s",name,val); TRY (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; } @@ -760,11 +803,22 @@ xbt_cfg_set_host(xbt_cfg_t cfg,const char*name, TRY (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; } @@ -782,10 +836,16 @@ xbt_error_t xbt_cfg_rm_int(xbt_cfg_t cfg,const char*name, int val) { int cpt,seen; xbt_error_t errcode; + 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); + TRY (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; } @@ -809,11 +869,17 @@ xbt_error_t xbt_cfg_rm_double(xbt_cfg_t cfg,const char*name, double val) { double seen; xbt_error_t errcode; + 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); + TRY (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; } } @@ -836,10 +902,16 @@ xbt_cfg_rm_string(xbt_cfg_t cfg,const char*name, const char *val) { char *seen; xbt_error_t errcode; + 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); + TRY (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; } @@ -865,10 +937,16 @@ xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) { xbt_host_t *seen; xbt_error_t errcode; + 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); + TRY (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; } @@ -879,6 +957,28 @@ xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) { 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); + + TRY (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 @@ -900,6 +1000,13 @@ xbt_cfg_empty(xbt_cfg_t cfg,const char*name) { } 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; @@ -1065,3 +1172,68 @@ xbt_error_t xbt_cfg_get_dynar (xbt_cfg_t cfg, 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; + + TRY (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; + + TRY (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; + + TRY (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; + + TRY (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; +}