Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Importing the documentation !!! :)
[simgrid.git] / src / xbt / config.c
1 /* $Id$ */
2
3 /* config - Dictionnary where the type of each cell is provided.            */
4
5 /* This is useful to build named structs, like option or property sets.     */
6
7 /* Copyright (c) 2001,2002,2003,2004 Martin Quinson. All rights reserved.   */
8
9 /* This program is free software; you can redistribute it and/or modify it
10  * under the terms of the license (GNU LGPL) which comes with this package. */
11
12 #include "xbt/misc.h"
13 #include "xbt/sysdep.h"
14 #include "xbt/log.h"
15 #include "xbt/error.h"
16 #include "xbt/dynar.h"
17 #include "xbt/dict.h"
18
19 #include "xbt/config.h" /* prototypes of this module */
20
21 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(config,xbt,"configuration support");
22
23 /* xbt_cfgelm_t: the typedef corresponding to a config cell. 
24
25    Both data and DTD are mixed, but fixing it now would prevent me to ever
26    defend my thesis. */
27
28 typedef struct {
29   /* Allowed type of the cell */
30   e_xbt_cfgelm_type_t type;
31   int min,max;
32
33   /* actual content 
34      (cannot be an union because type host uses both str and i) */
35   xbt_dynar_t content;
36 } s_xbt_cfgelm_t,*xbt_cfgelm_t;
37
38 static const char *xbt_cfgelm_type_name[xbt_cfgelm_type_count]=
39   {"int","double","string","host"};
40
41 /* Internal stuff used in cache to free a cell */
42 static void xbt_cfgelm_free(void *data);
43
44 /* Retrieve the cell we'll modify */
45 static xbt_error_t xbt_cfgelm_get(xbt_cfg_t cfg, const char *name,
46                                     e_xbt_cfgelm_type_t type,
47                                     /* OUT */ xbt_cfgelm_t *whereto);
48
49 void xbt_cfg_str_free(void *d);
50 void xbt_cfg_host_free(void *d);
51
52 void xbt_cfg_str_free(void *d){
53   xbt_free(*(void**)d);
54 }
55 void xbt_cfg_host_free(void *d){
56   xbt_host_t *h=(xbt_host_t*) *(void**)d; 
57   if (h) {
58     if (h->name) xbt_free(h->name);
59     xbt_free(h);
60   }
61 }
62
63 /*----[ Memory management ]-----------------------------------------------*/
64
65 /**
66  * xbt_cfg_new:
67  *
68  * @whereto: 
69  *
70  * Initialise an config set
71  */
72
73
74 xbt_cfg_t xbt_cfg_new(void) {
75   return (xbt_cfg_t)xbt_dict_new();
76 }
77
78 /**
79  * xbt_cfg_cpy:
80  *
81  * @whereto: the config set to be created
82  * @tocopy: the source data
83  *
84  */
85
86 void
87 xbt_cfg_cpy(xbt_cfg_t tocopy,xbt_cfg_t *whereto) {
88   xbt_dict_cursor_t cursor=NULL; 
89   xbt_cfgelm_t cell=NULL;
90   char *name=NULL;
91   
92   *whereto=NULL;
93   xbt_assert0(tocopy,"cannot copy NULL config");
94
95   xbt_dict_foreach((xbt_dict_t)tocopy,cursor,name,cell) {
96     xbt_cfg_register(*whereto, name, cell->type, cell->min, cell->max);
97   }
98 }
99
100 void xbt_cfg_free(xbt_cfg_t *cfg) {
101   xbt_dict_free((xbt_dict_t*)cfg);
102 }
103
104 /**
105  * xbt_cfg_dump:
106  * @name: The name to give to this config set
107  * @indent: what to write at the begining of each line (right number of spaces)
108  * @cfg: the config set
109  *
110  * Dumps a config set for debuging purpose
111  */
112 void
113 xbt_cfg_dump(const char *name,const char *indent,xbt_cfg_t cfg) {
114   xbt_dict_t dict = (xbt_dict_t) cfg;
115   xbt_dict_cursor_t cursor=NULL; 
116   xbt_cfgelm_t cell=NULL;
117   char *key=NULL;
118   int i; 
119   int size;
120   int ival;
121   char *sval;
122   double dval;
123   xbt_host_t *hval;
124
125   if (name)
126     printf("%s>> Dumping of the config set '%s':\n",indent,name);
127   xbt_dict_foreach(dict,cursor,key,cell) {
128
129     printf("%s  %s:",indent,key);
130
131     size = xbt_dynar_length(cell->content);
132     printf("%d_to_%d_%s. Actual size=%d. List of values:\n",
133            cell->min,cell->max,xbt_cfgelm_type_name[cell->type],
134            size);
135
136     switch (cell->type) {
137        
138     case xbt_cfgelm_int:
139       for (i=0; i<size; i++) {
140         ival = xbt_dynar_get_as(cell->content,i,int);
141         printf ("%s    %d\n",indent,ival);
142       }
143       break;
144
145     case xbt_cfgelm_double:
146       for (i=0; i<size; i++) {
147         dval = xbt_dynar_get_as(cell->content,i,double);
148         printf ("%s    %f\n",indent,dval);
149       }
150       break;
151
152     case xbt_cfgelm_string:
153       for (i=0; i<size; i++) {
154         sval = xbt_dynar_get_as(cell->content,i,char*);
155         printf ("%s    %s\n",indent,sval);
156       }
157       break;
158
159     case xbt_cfgelm_host:
160       for (i=0; i<size; i++) {
161         hval = xbt_dynar_get_as(cell->content,i,xbt_host_t*);
162         printf ("%s    %s:%d\n",indent,hval->name,hval->port);
163       }
164       break;
165
166     default:
167       printf("%s    Invalid type!!\n",indent);
168     }
169
170   }
171
172   if (name) printf("%s<< End of the config set '%s'\n",indent,name);
173   fflush(stdout);
174
175   xbt_dict_cursor_free(&cursor);
176   return;
177 }
178
179 /**
180  * xbt_cfgelm_free:
181  *
182  * @data: the data to be freed (typed as void* to be usable as free funct in dict)
183  *
184  * free an config element
185  */
186
187 void xbt_cfgelm_free(void *data) {
188   xbt_cfgelm_t c=(xbt_cfgelm_t)data;
189
190   if (!c) return;
191   xbt_dynar_free(&(c->content));
192   xbt_free(c);
193 }
194
195 /*----[ Registering stuff ]-----------------------------------------------*/
196
197 /**
198  * xbt_cfg_register:
199  * @cfg: the config set
200  * @type: the type of the config element
201  * @min: the minimum
202  * @max: the maximum
203  *
204  * register an element within a config set
205  */
206
207 void
208 xbt_cfg_register(xbt_cfg_t cfg,
209                   const char *name, e_xbt_cfgelm_type_t type,
210                   int min, int max){
211   xbt_cfgelm_t res;
212   xbt_error_t errcode;
213
214   DEBUG4("Register cfg elm %s (%d to %d %s)",name,min,max,xbt_cfgelm_type_name[type]);
215   errcode = xbt_dict_get((xbt_dict_t)cfg,name,(void**)&res);
216
217   if (errcode == no_error) {
218     WARN1("Config elem %s registered twice.",name);
219     /* Will be removed by the insertion of the new one */
220   } 
221   xbt_assert_error(mismatch_error);
222
223   res=xbt_new(s_xbt_cfgelm_t,1);
224
225   res->type=type;
226   res->min=min;
227   res->max=max;
228
229   switch (type) {
230   case xbt_cfgelm_int:
231     res->content = xbt_dynar_new(sizeof(int), NULL);
232     break;
233
234   case xbt_cfgelm_double:
235     res->content = xbt_dynar_new(sizeof(double), NULL);
236     break;
237
238   case xbt_cfgelm_string:
239    res->content = xbt_dynar_new(sizeof(char*),&xbt_cfg_str_free);
240    break;
241
242   case xbt_cfgelm_host:
243    res->content = xbt_dynar_new(sizeof(xbt_host_t*),&xbt_cfg_host_free);
244    break;
245
246   default:
247     ERROR1("%d is an invalide type code",type);
248   }
249     
250   xbt_dict_set((xbt_dict_t)cfg,name,res,&xbt_cfgelm_free);
251 }
252
253 /**
254  * xbt_cfg_unregister:
255  * 
256  * @cfg: the config set
257  * @name: the name of the elem to be freed
258  * 
259  * unregister an element from a config set. 
260  * Note that it removes both the DTD and the actual content.
261  */
262
263 xbt_error_t
264 xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
265   return xbt_dict_remove((xbt_dict_t)cfg,name);
266 }
267
268 /**
269  * xbt_cfg_register_str:
270  *
271  * @cfg: the config set
272  * @entry: a string describing the element to register
273  *
274  * Parse a string and register the stuff described.
275  */
276
277 xbt_error_t
278 xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
279   char *entrycpy=xbt_strdup(entry);
280   char *tok;
281
282   int min,max;
283   e_xbt_cfgelm_type_t type;
284
285   tok=strchr(entrycpy, ':');
286   if (!tok) {
287     ERROR3("%s%s%s",
288           "Invalid config element descriptor: ",entry,
289           "; Should be <name>:<min nb>_to_<max nb>_<type>");
290     xbt_free(entrycpy);
291     xbt_abort();
292   }
293   *(tok++)='\0';
294
295   min=strtol(tok, &tok, 10);
296   if (!tok) {
297     ERROR1("Invalid minimum in config element descriptor %s",entry);
298     xbt_free(entrycpy);
299     xbt_abort();
300   }
301
302   if (!strcmp(tok,"_to_")){
303     ERROR3("%s%s%s",
304           "Invalid config element descriptor: ",entry,
305           "; Should be <name>:<min nb>_to_<max nb>_<type>");
306     xbt_free(entrycpy);
307     xbt_abort();
308   }
309   tok += strlen("_to_");
310
311   max=strtol(tok, &tok, 10);
312   if (!tok) {
313     ERROR1("Invalid maximum in config element descriptor %s",entry);
314     xbt_free(entrycpy);
315     xbt_abort();
316   }
317
318   if (*(tok++)!='_') {
319     ERROR3("%s%s%s",
320           "Invalid config element descriptor: ",entry,
321           "; Should be <name>:<min nb>_to_<max nb>_<type>");
322     xbt_free(entrycpy);
323     xbt_abort();
324   }
325
326   for (type=0; 
327        type<xbt_cfgelm_type_count && strcmp(tok,xbt_cfgelm_type_name[type]); 
328        type++);
329   if (type == xbt_cfgelm_type_count) {
330     ERROR3("%s%s%s",
331           "Invalid type in config element descriptor: ",entry,
332           "; Should be one of 'string', 'int', 'host' or 'double'.");
333     xbt_free(entrycpy);
334     xbt_abort();
335   }
336
337   xbt_cfg_register(cfg,entrycpy,type,min,max);
338
339   xbt_free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
340   return no_error;
341 }
342
343 /**
344  * xbt_cfg_check:
345  *
346  * @cfg: the config set
347  * 
348  * Check the config set
349  */
350
351 xbt_error_t
352 xbt_cfg_check(xbt_cfg_t cfg) {
353   xbt_dict_cursor_t cursor; 
354   xbt_cfgelm_t cell;
355   char *name;
356   int size;
357
358   xbt_assert0(cfg,"NULL config set.");
359
360   xbt_dict_foreach((xbt_dict_t)cfg,cursor,name,cell) {
361     size = xbt_dynar_length(cell->content);
362     if (cell->min > size) { 
363       ERROR4("Config elem %s needs at least %d %s, but there is only %d values.",
364              name,
365              cell->min,
366              xbt_cfgelm_type_name[cell->type],
367              size); 
368       xbt_dict_cursor_free(&cursor);
369       return mismatch_error;
370     }
371
372     if (cell->max < size) {
373       ERROR4("Config elem %s accepts at most %d %s, but there is %d values.",
374              name,
375              cell->max,
376              xbt_cfgelm_type_name[cell->type],
377              size);
378       xbt_dict_cursor_free(&cursor);
379       return mismatch_error;
380     }
381
382   }
383
384   xbt_dict_cursor_free(&cursor);
385   return no_error;
386 }
387
388 static xbt_error_t xbt_cfgelm_get(xbt_cfg_t  cfg,
389                                     const char *name,
390                                     e_xbt_cfgelm_type_t type,
391                                     /* OUT */ xbt_cfgelm_t *whereto){
392    
393   xbt_error_t errcode = xbt_dict_get((xbt_dict_t)cfg,name,
394                                        (void**)whereto);
395
396   if (errcode == mismatch_error) {
397     ERROR1("No registered cell %s in this config set",
398            name);
399     return mismatch_error;
400   }
401   if (errcode != no_error)
402      return errcode;
403
404   xbt_assert3((*whereto)->type == type,
405                "You tried to access to the config element %s as an %s, but its type is %s.",
406                name,
407                xbt_cfgelm_type_name[type],
408                xbt_cfgelm_type_name[(*whereto)->type]);
409
410   return no_error;
411 }
412
413 /**
414  * xbt_cfg_get_type:
415  *
416  * @cfg: the config set
417  * @name: the name of the element 
418  * @type: the result
419  *
420  * Give the type of the config element
421  */
422
423 xbt_error_t
424 xbt_cfg_get_type(xbt_cfg_t cfg, const char *name, 
425                       /* OUT */e_xbt_cfgelm_type_t *type) {
426
427   xbt_cfgelm_t cell;
428   xbt_error_t errcode;
429
430   TRYCATCH(mismatch_error,xbt_dict_get((xbt_dict_t)cfg,name,(void**)&cell));
431
432   if (errcode == mismatch_error) {
433     ERROR1("Can't get the type of '%s' since this cell does not exist",
434            name);
435     return mismatch_error;
436   }
437
438   *type=cell->type;
439
440   return no_error;
441 }
442
443 /*----[ Setting ]---------------------------------------------------------*/
444 /** 
445  * xbt_cfg_set_vargs(): 
446  * @cfg: config set to fill
447  * @varargs: NULL-terminated list of pairs {(const char*)key, value}
448  *
449  * Add some values to the config set.
450  * @warning: if the list isn't NULL terminated, it will segfault. 
451  */
452 xbt_error_t
453 xbt_cfg_set_vargs(xbt_cfg_t cfg, va_list pa) {
454   char *str,*name;
455   int i;
456   double d;
457   e_xbt_cfgelm_type_t type;
458
459   xbt_error_t errcode;
460   
461   while ((name=va_arg(pa,char *))) {
462
463     if (!xbt_cfg_get_type(cfg,name,&type)) {
464       ERROR1("Can't set the property '%s' since it's not registered",name);
465       return mismatch_error;
466     }
467
468     switch (type) {
469     case xbt_cfgelm_host:
470       str = va_arg(pa, char *);
471       i=va_arg(pa,int);
472       TRY(xbt_cfg_set_host(cfg,name,str,i));
473       break;
474       
475     case xbt_cfgelm_string:
476       str=va_arg(pa, char *);
477       TRY(xbt_cfg_set_string(cfg, name, str));
478       break;
479
480     case xbt_cfgelm_int:
481       i=va_arg(pa,int);
482       TRY(xbt_cfg_set_int(cfg,name,i));
483       break;
484
485     case xbt_cfgelm_double:
486       d=va_arg(pa,double);
487       TRY(xbt_cfg_set_double(cfg,name,d));
488       break;
489
490     default: 
491       RAISE1(unknown_error,"Config element cell %s not valid.",name);
492     }
493   }
494   return no_error;
495 }
496
497 /** 
498  * xbt_cfg_set():
499  * @cfg: config set to fill
500  * @varargs: NULL-terminated list of pairs {(const char*)key, value}
501  *
502  * Add some values to the config set.
503  * @warning: if the list isn't NULL terminated, it will segfault. 
504  */
505 xbt_error_t xbt_cfg_set(xbt_cfg_t cfg, ...) {
506   va_list pa;
507   xbt_error_t errcode;
508
509   va_start(pa,cfg);
510   errcode=xbt_cfg_set_vargs(cfg,pa);
511   va_end(pa);
512   return errcode;
513 }
514
515 /**
516  * xbt_cfg_set_parse():
517  * @cfg: config set to fill
518  * @options: a string containing the content to add to the config set. This
519  * is a '\t',' ' or '\n' separated list of cells. Each individual cell is
520  * like "[name]:[value]" where [name] is the name of an already registred 
521  * cell, and [value] conforms to the data type under which this cell was
522  * registred.
523  *
524  * Add the cells described in a string to a config set.
525  */
526
527 xbt_error_t
528 xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
529   int i;
530   double d;
531   char *str;
532
533   xbt_cfgelm_t cell;
534   char *optionlist_cpy;
535   char *option,  *name,*val;
536
537   int len;
538   xbt_error_t errcode;
539
540   XBT_IN;
541   if (!options || !strlen(options)) { /* nothing to do */
542     return no_error;
543   }
544   optionlist_cpy=xbt_strdup(options);
545
546   DEBUG1("List to parse and set:'%s'",options);
547   option=optionlist_cpy;
548   while (1) { /* breaks in the code */
549
550     if (!option) 
551       break;
552     name=option;
553     len=strlen(name);
554     DEBUG3("Still to parse and set: '%s'. len=%d; option-name=%ld",
555            name,len,(long)(option-name));
556
557     /* Pass the value */
558     while (option-name<=(len-1) && *option != ' ' && *option != '\n' && *option != '\t') {
559       /*fprintf(stderr,"Take %c.\n",*option);*/
560       option++;
561     }
562     if (option-name == len) {
563       /*fprintf(stderr,"Boundary=EOL\n");*/
564       option=NULL; /* don't do next iteration */
565
566     } else {
567       /*fprintf(stderr,"Boundary on '%c'. len=%d;option-name=%d\n",*option,len,option-name);*/
568
569       /* Pass the following blank chars */
570       *(option++)='\0';
571       while (option-name<(len-1) && (*option == ' ' || *option == '\n' || *option == '\t')) {
572         /*      fprintf(stderr,"Ignore a blank char.\n");*/
573         option++;
574       }
575       if (option-name == len-1)
576         option=NULL; /* don't do next iteration */
577     }
578     DEBUG2("parse now:'%s'; parse later:'%s'",name,option);
579
580     if (name[0] == ' ' || name[0] == '\n' || name[0] == '\t')
581       continue;
582     if (!strlen(name))
583       break;
584     
585     val=strchr(name,':');
586     if (!val) {
587       xbt_free(optionlist_cpy);
588       xbt_assert1(FALSE,
589                    "Malformated option: '%s'; Should be of the form 'name:value'",
590                    name);
591     }
592     *(val++)='\0';
593
594     DEBUG2("name='%s';val='%s'",name,val);
595
596     errcode=xbt_dict_get((xbt_dict_t)cfg,name,(void**)&cell);
597     switch (errcode) {
598     case no_error:
599       break;
600     case mismatch_error:
601       ERROR1("No registrated cell corresponding to '%s'.",name);
602       xbt_free(optionlist_cpy);
603       return mismatch_error;
604       break;
605     default:
606       xbt_free(optionlist_cpy);
607       return errcode;
608     }
609
610     switch (cell->type) {
611     case xbt_cfgelm_string:
612       TRYCLEAN(xbt_cfg_set_string(cfg, name, val),
613                xbt_free(optionlist_cpy));
614       break;
615
616     case xbt_cfgelm_int:
617       i=strtol(val, &val, 0);
618       if (val==NULL) {
619         xbt_free(optionlist_cpy);       
620         xbt_assert1(FALSE,
621                      "Value of option %s not valid. Should be an integer",
622                      name);
623       }
624
625       TRYCLEAN(xbt_cfg_set_int(cfg,name,i),
626                xbt_free(optionlist_cpy));
627       break;
628
629     case xbt_cfgelm_double:
630       d=strtod(val, &val);
631       if (val==NULL) {
632         xbt_free(optionlist_cpy);       
633         xbt_assert1(FALSE,
634                "Value of option %s not valid. Should be a double",
635                name);
636       }
637
638       TRYCLEAN(xbt_cfg_set_double(cfg,name,d),
639                xbt_free(optionlist_cpy));
640       break;
641
642     case xbt_cfgelm_host:
643       str=val;
644       val=strchr(val,':');
645       if (!val) {
646         xbt_free(optionlist_cpy);       
647         xbt_assert1(FALSE,
648                "Value of option %s not valid. Should be an host (machine:port)",
649                name);
650       }
651
652       *(val++)='\0';
653       i=strtol(val, &val, 0);
654       if (val==NULL) {
655         xbt_free(optionlist_cpy);       
656         xbt_assert1(FALSE,
657                "Value of option %s not valid. Should be an host (machine:port)",
658                name);
659       }
660
661       TRYCLEAN(xbt_cfg_set_host(cfg,name,str,i),
662                xbt_free(optionlist_cpy));
663       break;      
664
665     default: 
666       xbt_free(optionlist_cpy);
667       RAISE1(unknown_error,"Type of config element %s is not valid.",name);
668     }
669     
670   }
671   xbt_free(optionlist_cpy);
672   return no_error;
673 }
674
675 /**
676  * xbt_cfg_set_int:
677  *
678  * @cfg: the config set
679  * @name: the name of the cell
680  * @val: the value of the cell
681  *
682  * Set the value of the cell @name in @cfg with the provided value.
683  */ 
684 xbt_error_t
685 xbt_cfg_set_int(xbt_cfg_t cfg,const char*name, int val) {
686   xbt_cfgelm_t cell;
687   xbt_error_t errcode;
688
689   VERB2("Configuration setting: %s=%d",name,val);
690   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&cell));
691
692   if (cell->max > 1) {
693     xbt_dynar_push(cell->content,&val);
694   } else {
695     xbt_dynar_set(cell->content,0,&val);
696   }
697   return no_error;
698 }
699
700 /**
701  * xbt_cfg_set_double:
702  * @cfg: the config set
703  * @name: the name of the cell
704  * @val: the doule to set
705  * 
706  * Set the value of the cell @name in @cfg with the provided value.
707  */ 
708
709 xbt_error_t
710 xbt_cfg_set_double(xbt_cfg_t cfg,const char*name, double val) {
711   xbt_cfgelm_t cell;
712   xbt_error_t errcode;
713
714   VERB2("Configuration setting: %s=%f",name,val);
715   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&cell));
716
717   if (cell->max > 1) {
718     xbt_dynar_push(cell->content,&val);
719   } else {
720     xbt_dynar_set(cell->content,0,&val);
721   }
722   return no_error;
723 }
724
725 /**
726  * xbt_cfg_set_string:
727  * 
728  * @cfg: the config set
729  * @name: the name of the cell
730  * @val: the value to be added
731  *
732  * Set the value of the cell @name in @cfg with the provided value.
733  */ 
734
735 xbt_error_t
736 xbt_cfg_set_string(xbt_cfg_t cfg,const char*name, const char*val) { 
737   xbt_cfgelm_t cell;
738   xbt_error_t errcode;
739   char *newval = xbt_strdup(val);
740
741   VERB2("Configuration setting: %s=%s",name,val);
742   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&cell));
743
744   if (cell->max > 1) {
745     xbt_dynar_push(cell->content,&newval);
746   } else {
747     xbt_dynar_set(cell->content,0,&newval);
748   }
749   return no_error;
750 }
751
752 /**
753  * xbt_cfg_set_host:
754  * 
755  * @cfg: the config set
756  * @name: the name of the cell
757  * @host: the host
758  * @port: the port number
759  *
760  * Set the value of the cell @name in @cfg with the provided value 
761  * on the given @host to the given @port
762  */ 
763
764 xbt_error_t 
765 xbt_cfg_set_host(xbt_cfg_t cfg,const char*name, 
766                   const char *host,int port) {
767   xbt_cfgelm_t cell;
768   xbt_error_t errcode;
769   xbt_host_t *val=xbt_new(xbt_host_t,1);
770
771   VERB3("Configuration setting: %s=%s:%d",name,host,port);
772
773   val->name = xbt_strdup(name);
774   val->port = port;
775
776   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&cell));
777
778   if (cell->max > 1) {
779     xbt_dynar_push(cell->content,&val);
780   } else {
781     xbt_dynar_set(cell->content,0,&val);
782   }
783   return no_error;
784 }
785
786 /* ---- [ Removing ] ---- */
787
788 /**
789  * xbt_cfg_rm_int:
790  *
791  * @cfg: the config set
792  * @name: the name of the cell
793  * @val: the value to be removed
794  *
795  * Remove the provided @val from the cell @name in @cfg.
796  */
797 xbt_error_t xbt_cfg_rm_int(xbt_cfg_t cfg,const char*name, int val) {
798
799   xbt_cfgelm_t cell;
800   int cpt,seen;
801   xbt_error_t errcode;
802
803   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&cell));
804   
805   xbt_dynar_foreach(cell->content,cpt,seen) {
806     if (seen == val) {
807       xbt_dynar_cursor_rm(cell->content,&cpt);
808       return no_error;
809     }
810   }
811
812   ERROR2("Can't remove the value %d of config element %s: value not found.",
813          val,name);
814   return mismatch_error;
815 }
816
817 /**
818  * xbt_cfg_rm_double:
819  *
820  * @cfg: the config set
821  * @name: the name of the cell
822  * @val: the value to be removed
823  *
824  * Remove the provided @val from the cell @name in @cfg.
825  */
826
827 xbt_error_t xbt_cfg_rm_double(xbt_cfg_t cfg,const char*name, double val) {
828   xbt_cfgelm_t cell;
829   int cpt;
830   double seen;
831   xbt_error_t errcode;
832
833   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&cell));
834   
835   xbt_dynar_foreach(cell->content,cpt,seen) {
836     if (seen == val) {
837       xbt_dynar_cursor_rm(cell->content,&cpt);
838       return no_error;
839     }
840   }
841
842   ERROR2("Can't remove the value %f of config element %s: value not found.",
843          val,name);
844   return mismatch_error;
845 }
846
847 /**
848  * xbt_cfg_rm_string:
849  *
850  * @cfg: the config set
851  * @name: the name of the cell
852  * @val: the value of the string which will be removed
853  *
854  * Remove the provided @val from the cell @name in @cfg.
855  */
856 xbt_error_t
857 xbt_cfg_rm_string(xbt_cfg_t cfg,const char*name, const char *val) {
858   xbt_cfgelm_t cell;
859   int cpt;
860   char *seen;
861   xbt_error_t errcode;
862
863   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&cell));
864   
865   xbt_dynar_foreach(cell->content,cpt,seen) {
866     if (!strcpy(seen,val)) {
867       xbt_dynar_cursor_rm(cell->content,&cpt);
868       return no_error;
869     }
870   }
871
872   ERROR2("Can't remove the value %s of config element %s: value not found.",
873          val,name);
874   return mismatch_error;
875 }
876
877 /**
878  * xbt_cfg_rm_host:
879  * 
880  * @cfg: the config set
881  * @name: the name of the cell
882  * @host: the hostname
883  * @port: the port number
884  *
885  * Remove the provided @host:@port from the cell @name in @cfg.
886  */
887
888 xbt_error_t
889 xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
890   xbt_cfgelm_t cell;
891   int cpt;
892   xbt_host_t *seen;
893   xbt_error_t errcode;
894
895   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&cell));
896   
897   xbt_dynar_foreach(cell->content,cpt,seen) {
898     if (!strcpy(seen->name,host) && seen->port == port) {
899       xbt_dynar_cursor_rm(cell->content,&cpt);
900       return no_error;
901     }
902   }
903
904   ERROR3("Can't remove the value %s:%d of config element %s: value not found.",
905          host,port,name);
906   return mismatch_error;
907 }
908
909 /* rm everything */
910
911 /**
912  * xbt_cfg_empty:
913  * 
914  * @cfg: the config set
915  * @name: the name of the cell
916  *
917  * rm evenything
918  */
919
920 xbt_error_t 
921 xbt_cfg_empty(xbt_cfg_t cfg,const char*name) {
922   xbt_cfgelm_t cell;
923
924   xbt_error_t errcode;
925
926   TRYCATCH(mismatch_error,
927            xbt_dict_get((xbt_dict_t)cfg,name,(void**)&cell));
928   if (errcode == mismatch_error) {
929     ERROR1("Can't empty  '%s' since this config element does not exist",
930            name);
931     return mismatch_error;
932   }
933
934   if (cell) {
935     xbt_dynar_reset(cell->content);
936   }
937   return no_error;
938 }
939
940 /*----[ Getting ]---------------------------------------------------------*/
941
942 /**
943  * xbt_cfg_get_int:
944  * @cfg: the config set
945  * @name: the name of the cell
946  * @val: the wanted value
947  *
948  * Returns the first value from the config set under the given name.
949  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
950  * instead.
951  *
952  * @warning the returned value is the actual content of the config set
953  */
954 xbt_error_t
955 xbt_cfg_get_int   (xbt_cfg_t  cfg,
956                     const char *name,
957                     int        *val) {
958   xbt_cfgelm_t cell;
959   xbt_error_t errcode;
960
961   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&cell));
962
963   if (xbt_dynar_length(cell->content) > 1) {
964     WARN2("You asked for the first value of the config element '%s', but there is %lu values",
965              name, xbt_dynar_length(cell->content));
966   }
967
968   *val = xbt_dynar_get_as(cell->content, 0, int);
969   return no_error;
970 }
971
972 /**
973  * xbt_cfg_get_double:
974  * @cfg: the config set
975  * @name: the name of the cell
976  * @val: the wanted value
977  *
978  * Returns the first value from the config set under the given name.
979  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
980  * instead.
981  *
982  * @warning the returned value is the actual content of the config set
983  */
984
985 xbt_error_t
986 xbt_cfg_get_double(xbt_cfg_t  cfg,
987                     const char *name,
988                     double     *val) {
989   xbt_cfgelm_t cell;
990   xbt_error_t  errcode;
991
992   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&cell));
993
994   if (xbt_dynar_length(cell->content) > 1) {
995     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
996              name, xbt_dynar_length(cell->content));
997   }
998
999   *val = xbt_dynar_get_as(cell->content, 0, double);
1000   return no_error;
1001 }
1002
1003 /**
1004  * xbt_cfg_get_string:
1005  *
1006  * @th: the config set
1007  * @name: the name of the cell
1008  * @val: the wanted value
1009  *
1010  * Returns the first value from the config set under the given name.
1011  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
1012  * instead.
1013  *
1014  * @warning the returned value is the actual content of the config set
1015  */
1016
1017 xbt_error_t xbt_cfg_get_string(xbt_cfg_t  cfg,
1018                                  const char *name,
1019                                  char      **val) {
1020   xbt_cfgelm_t  cell;
1021   xbt_error_t errcode;
1022
1023   *val=NULL;
1024
1025   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&cell));
1026
1027   if (xbt_dynar_length(cell->content) > 1) {
1028     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
1029              name, xbt_dynar_length(cell->content));
1030   }
1031
1032   *val = xbt_dynar_get_as(cell->content, 0, char *);
1033   return no_error;
1034 }
1035
1036 /**
1037  * xbt_cfg_get_host:
1038  *
1039  * @cfg: the config set
1040  * @name: the name of the cell
1041  * @host: the host
1042  * @port: the port number
1043  *
1044  * Returns the first value from the config set under the given name.
1045  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
1046  * instead.
1047  *
1048  * @warning the returned value is the actual content of the config set
1049  */
1050
1051 xbt_error_t xbt_cfg_get_host  (xbt_cfg_t  cfg,
1052                                  const char *name,
1053                                  char      **host,
1054                                  int        *port) {
1055   xbt_cfgelm_t cell;
1056   xbt_error_t  errcode;
1057   xbt_host_t  *val;
1058
1059   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&cell));
1060
1061   if (xbt_dynar_length(cell->content) > 1) {
1062     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
1063              name, xbt_dynar_length(cell->content));
1064   }
1065
1066   val = xbt_dynar_get_as(cell->content, 0, xbt_host_t*);
1067   *host=val->name;
1068   *port=val->port;
1069   
1070   return no_error;
1071 }
1072
1073 /**
1074  * xbt_cfg_get_dynar:
1075  * @cfg: where to search in
1076  * @name: what to search for
1077  * @dynar: result
1078  *
1079  * Get the data stored in the config bag. 
1080  *
1081  * @warning the returned value is the actual content of the config set
1082  */
1083 xbt_error_t xbt_cfg_get_dynar (xbt_cfg_t    cfg,
1084                                  const char   *name,
1085                                  xbt_dynar_t *dynar) {
1086   xbt_cfgelm_t cell;
1087   xbt_error_t  errcode = xbt_dict_get((xbt_dict_t)cfg,name,
1088                                         (void**)&cell);
1089
1090   if (errcode == mismatch_error) {
1091     ERROR1("No registered cell %s in this config set",
1092            name);
1093     return mismatch_error;
1094   }
1095   if (errcode != no_error)
1096      return errcode;
1097
1098   *dynar = cell->content;
1099   return no_error;
1100 }
1101