Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
make communications from an host to itself instantaneous
[simgrid.git] / src / xbt / dict_multi.c
1 /* $Id$ */
2
3 /* dict_multi - dictionnaries of dictionnaries of ... of data               */
4
5 /* Copyright (c) 2003, 2004 Martin Quinson. All rights reserved.            */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "gras_private.h"
11
12 #include <stdlib.h> /* malloc() */
13 #include <string.h> /* strlen() */
14
15 /*####[ Multi dict functions ]##############################################*/
16 /*###############################"##########################################*/
17 /**
18  * gras_mutidict_set:
19  *
20  * @head: the head of dict
21  * @keycount: the number of the key
22  * @key: the key
23  * @data: the data to set
24  * @Returns: gras_error_t
25  *
26  * set the data in the structure under the @keycount @key.
27  */
28
29 gras_error_t
30 gras_multidict_set_ext(gras_dict_t    **pp_head,
31                           int              keycount,
32                           char           **key,
33                           int             *key_len,
34                           void            *data,
35                           void_f_pvoid_t  *free_ctn) {
36   gras_error_t  errcode   = no_error;
37   gras_dictelm_t  *p_elm    =     NULL;
38   gras_dictelm_t  *p_subdict =     NULL;
39   int           i         =        0;
40
41   CDEBUG2(dict_multi, "fast_multidict_set(%p,%d). Keys:", *pp_head, keycount);
42
43   /*
44   for (i = 0; i < keycount; i++) {
45     CDEBUG1(dict_multi, "\"%s\"", key[i]);
46   }
47   */
48
49   gras_assert0(keycount >= 1, "Can't set less than one key in a multidict");
50
51   if (keycount == 1)
52     return gras_dict_set_ext(pp_head, key[0], key_len[0], data, free_ctn);
53
54   if (!*pp_head) {
55     TRY(_gras_dict_alloc(NULL, 0, 0, NULL, NULL, pp_head));
56   }
57
58   p_elm = *pp_head;
59
60   for (i = 0; i < keycount-1; i++) {
61
62     /* search the dict of next level */
63     TRYCATCH(gras_dict_get(p_elm, key[i], (void*)&p_subdict), mismatch_error);
64
65     /* make sure the dict of next level exists */
66     if (errcode == mismatch_error) {
67       TRY(_gras_dict_alloc(NULL, 0, 0, NULL, NULL, &p_subdict));
68       TRY(gras_dict_set_ext(&p_elm, key[i], key_len[i], &p_subdict,
69                                _free_dict));
70     }
71
72     p_elm = p_subdict;
73   }
74
75   return gras_dict_set_ext(&p_elm, key[i], key_len[i], data, free_ctn);
76 }
77
78 gras_error_t
79 gras_multidict_set(gras_dictelm_t    **pp_head,
80                       int              keycount,
81                       char           **key,
82                       void            *data,
83                       void_f_pvoid_t  *free_ctn) {
84   gras_error_t  errcode = no_error;
85   int          *key_len = NULL;
86   int           i       = 0;
87
88   key_len = malloc(keycount * sizeof (int));
89   if (!key_len)
90     RAISE_MALLOC;
91
92   for (i = 0; i < keycount; i++) {
93     key_len[i] = 1+strlen(key[i]);
94   }
95
96   TRYCLEAN(gras_multidict_set_ext(pp_head, keycount, key, key_len, data, free_ctn),
97            gras_free(key_len));
98
99   gras_free(key_len);
100
101   return errcode;
102 }
103
104 /**
105  * gras_mutidict_get:
106  *
107  * @head: the head of dict
108  * @keycount: the number of the key
109  * @key: the key
110  * @data: where to put the got data
111  * @Returns: gras_error_t
112  *
113  * Search the given @key. data=NULL when not found
114  */
115
116
117 gras_error_t
118 gras_multidict_get_ext(gras_dictelm_t    *p_head,
119                             int             keycount,
120                             const char    **key,
121                             int            *key_len,
122                             /* OUT */void **data) {
123   gras_error_t  errcode = no_error;
124   gras_dictelm_t  *p_elm  =   p_head;
125   int           i       =        0;
126
127   CDEBUG2(dict_multi, "fast_multidict_get(%p, %d). Keys:", p_head, keycount);
128
129   /*
130   for (i = 0; i < keycount; i++) {
131     CDEBUG1(dict_multi, "\"%s\"", key[i]);
132   }
133   */
134
135   i = 0;
136
137   while (p_elm && i < keycount-1) {
138
139     TRY(gras_dict_get_ext(p_elm, key[i], key_len[i], (void**)p_elm));
140
141     /*
142     if (p_elm) {
143       CDEBUG3(dict_multi,"Found level %d for key %s in multitree %", i, key[i], p_head);
144     } else {
145       CDEBUG3(dict_multi,"NOT found level %d for key %s in multitree %p", i, key[i], p_head);
146     }
147     */
148
149     i++;
150   }
151
152   if (p_elm) { /* Found all dicts to the data */
153
154     /*    gras_dict_dump(dict,&gras_dict_prints); */
155     return gras_dict_get_ext(p_elm, key[i], key_len[i], data);
156
157   } else {
158
159     *data = NULL;
160
161     return 1;
162   }
163
164 }
165
166 gras_error_t
167 gras_multidict_get(gras_dictelm_t    *p_head,
168                         int             keycount,
169                         const char    **key,
170                         /* OUT */void **data) {
171   gras_error_t  errcode = no_error;
172   int          *key_len = NULL;
173   int           i       = 0;
174
175   key_len = malloc(keycount * sizeof (int));
176   if (!key_len)
177     RAISE_MALLOC;
178
179   for (i = 0; i < keycount; i++) {
180     key_len[i] = 1+strlen(key[i]);
181   }
182
183   TRYCLEAN(gras_multidict_get_ext(p_head, keycount, key, key_len, data),
184            gras_free(key_len));
185   gras_free(key_len);
186
187   return errcode;
188 }
189
190
191 /**
192  *  gras_mutidict_remove:
193  *
194  *  @head: the head of dict
195  *  @keycount: the number of the key
196  *  @key: the key
197  *  @Returns: gras_error_t
198  *
199  * Remove the entry associated with the given @key
200  * Removing a non-existant key is ok.
201  */
202
203 gras_error_t
204 gras_multidict_remove_ext(gras_dictelm_t  *p_head,
205                           int           keycount,
206                           const char  **key,
207                           int          *key_len) {
208   gras_dictelm_t *p_elm = p_head;
209   int          i      =      0;
210
211   while (p_elm && i < keycount-1) {
212     if (!gras_dict_get_ext(p_elm, key[i], key_len[i], (void**)&p_elm)) {
213       return 0;
214     }
215   }
216
217   if (p_elm) {
218     /* Found all dicts to the data */
219     return gras_dict_remove_ext(p_elm, key[i], key_len[i]);
220   } else {
221     return 1;
222   }
223
224 }
225
226 gras_error_t
227 gras_multidict_remove(gras_dictelm_t  *p_head,
228                       int           keycount,
229                       const char  **key) {
230   gras_error_t  errcode = no_error;
231   int          *key_len = NULL;
232   int           i       = 0;
233
234   key_len = malloc(keycount * sizeof (int));
235   if (!key_len)
236     RAISE_MALLOC;
237
238   for (i = 0; i < keycount; i++) {
239     key_len[i] = 1+strlen(key[i]);
240   }
241
242   TRYCLEAN(gras_multidict_remove_ext(p_head, keycount, key, key_len),
243            gras_free(key_len));
244   gras_free(key_len);
245
246   return errcode;
247 }