Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
start to fill the NEWS file
[simgrid.git] / src / xbt / dict_multi.c
1 /* dict_multi - dictionnaries of dictionnaries of ... of data               */
2
3 /* Copyright (c) 2004-2012. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #ifdef XBT_USE_DEPRECATED
10
11 #include "dict_private.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_dict_multi, xbt_dict,
14                                 "Dictionaries of multiple keys");
15
16 static void _free_dict(void *d)
17 {
18   XBT_VERB("free dict %p", d);
19   xbt_dict_free((xbt_dict_t *) & d);
20 }
21
22 /** \brief Insert \e data under all the keys contained in \e keys, providing their sizes in \e lens.
23  *
24  * \arg mdict: the multi-dict
25  * \arg keys: dynar of (char *) containing all the keys
26  * \arg lens: length of each element of \e keys
27  * \arg data: what to store in the structure
28  * \arg free_ctn: function to use to free the pushed content on need
29  *
30  * Dynars are not modified during the operation.
31  */
32
33 void
34 xbt_multidict_set_ext(xbt_dict_t mdict,
35                       xbt_dynar_t keys, xbt_dynar_t lens,
36                       void *data, void_f_pvoid_t free_ctn)
37 {
38
39   xbt_dict_t thislevel, nextlevel = NULL;
40   int i;
41
42   unsigned long int thislen;
43   char *thiskey;
44   int keys_len = xbt_dynar_length(keys);
45
46   xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens));
47   xbt_assert(keys_len, "Can't set a zero-long key set in a multidict");
48
49   XBT_DEBUG("xbt_multidict_set(%p,%d)", mdict, keys_len);
50
51   for (i = 0, thislevel = mdict; i < keys_len - 1;
52        i++, thislevel = nextlevel) {
53
54     xbt_dynar_get_cpy(keys, i, &thiskey);
55     xbt_dynar_get_cpy(lens, i, &thislen);
56
57     XBT_DEBUG("multi_set: at level %d, len=%ld, key=%p |%*s|", i, thislen,
58            thiskey, (int) thislen, thiskey);
59
60     /* search the dict of next level */
61     nextlevel = xbt_dict_get_or_null_ext(thislevel, thiskey, thislen);
62     if (nextlevel == NULL) {
63       /* make sure the dict of next level exists */
64       nextlevel = xbt_dict_new();
65       XBT_VERB("Create a dict (%p)", nextlevel);
66       xbt_dict_set_ext(thislevel, thiskey, thislen, nextlevel,
67                        &_free_dict);
68     }
69   }
70
71   xbt_dynar_get_cpy(keys, i, &thiskey);
72   xbt_dynar_get_cpy(lens, i, &thislen);
73
74   xbt_dict_set_ext(thislevel, thiskey, thislen, data, free_ctn);
75 }
76
77 /** \brief Insert \e data under all the keys contained in \e keys
78  *
79  * \arg head: the head of dict
80  * \arg keys: dynar of null-terminated strings containing all the keys
81  * \arg data: what to store in the structure
82  * \arg free_ctn: function to use to free the pushed content on need
83  */
84 void
85 xbt_multidict_set(xbt_dict_t mdict,
86                   xbt_dynar_t keys, void *data, void_f_pvoid_t free_ctn)
87 {
88   xbt_dynar_t lens = xbt_dynar_new(sizeof(unsigned long int), NULL);
89   unsigned long i;
90
91   for (i = 0; i < xbt_dynar_length(keys); i++) {
92     char *thiskey = xbt_dynar_get_as(keys, i, char *);
93     unsigned long int thislen = (unsigned long int) strlen(thiskey);
94     XBT_DEBUG("Push %ld as level %lu length", thislen, i);
95     xbt_dynar_push(lens, &thislen);
96   }
97
98   TRY {
99     xbt_multidict_set_ext(mdict, keys, lens, data, free_ctn);
100   }
101   TRY_CLEANUP {
102     xbt_dynar_free(&lens);
103   }
104   CATCH_ANONYMOUS {
105     RETHROW;
106   }
107 }
108
109 /** \brief Insert \e data under all the keys contained in \e keys, providing their sizes in \e lens.
110  *
111  * \arg mdict: the multi-dict
112  * \arg keys: dynar of (char *) containing all the keys
113  * \arg lens: length of each element of \e keys
114  * \arg data: where to put what was found in structure
115  * \arg free_ctn: function to use to free the pushed content on need
116  *
117  * Dynars are not modified during the operation.
118  */
119 void *xbt_multidict_get_ext(xbt_dict_t mdict,
120                             xbt_dynar_t keys, xbt_dynar_t lens)
121 {
122   xbt_dict_t thislevel, nextlevel;
123   int i;
124
125   unsigned long int thislen;
126   char *thiskey;
127   int keys_len = xbt_dynar_length(keys);
128
129   xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens));
130   xbt_assert(!xbt_dynar_is_empty(keys),
131               "Can't get a zero-long key set in a multidict");
132
133   XBT_DEBUG("xbt_multidict_get(%p, %ld)", mdict, xbt_dynar_length(keys));
134
135   for (i = 0, thislevel = mdict; i < keys_len - 1;
136        i++, thislevel = nextlevel) {
137
138     xbt_dynar_get_cpy(keys, i, &thiskey);
139     xbt_dynar_get_cpy(lens, i, &thislen);
140
141     XBT_DEBUG("multi_get: at level %d (%p), len=%ld, key=%p |%*s|",
142            i, thislevel, thislen, thiskey, (int) thislen, thiskey);
143
144     /* search the dict of next level: let mismatch raise if not found */
145     nextlevel = xbt_dict_get_ext(thislevel, thiskey, thislen);
146   }
147
148   xbt_dynar_get_cpy(keys, i, &thiskey);
149   xbt_dynar_get_cpy(lens, i, &thislen);
150
151   return xbt_dict_get_ext(thislevel, thiskey, thislen);
152 }
153
154 void *xbt_multidict_get(xbt_dict_t mdict, xbt_dynar_t keys)
155 {
156   xbt_dynar_t lens = xbt_dynar_new(sizeof(unsigned long int), NULL);
157   unsigned long i;
158   void *res;
159
160   for (i = 0; i < xbt_dynar_length(keys); i++) {
161     char *thiskey = xbt_dynar_get_as(keys, i, char *);
162     unsigned long int thislen = (unsigned long int) strlen(thiskey);
163     xbt_dynar_push(lens, &thislen);
164   }
165
166   res = xbt_multidict_get_ext(mdict, keys, lens), xbt_dynar_free(&lens);
167   return res;
168 }
169
170
171 /** \brief Remove the entry under all the keys contained in \e keys, providing their sizes in \e lens.
172  *
173  * \arg mdict: the multi-dict
174  * \arg keys: dynar of (char *) containing all the keys
175  * \arg lens: length of each element of \e keys
176  * \arg data: what to store in the structure
177  * \arg free_ctn: function to use to free the pushed content on need
178  *
179  * Dynars are not modified during the operation.
180  *
181  * Removing a non-existant key is ok.
182  */
183
184 void
185 xbt_multidict_remove_ext(xbt_dict_t mdict, xbt_dynar_t keys,
186                          xbt_dynar_t lens)
187 {
188   volatile xbt_dict_t thislevel;
189   volatile xbt_dict_t nextlevel = NULL;
190   volatile int i;
191   xbt_ex_t e;
192
193   unsigned long int thislen;
194   char *thiskey;
195   int keys_len = xbt_dynar_length(keys);
196
197   xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens));
198   xbt_assert(xbt_dynar_length(keys),
199               "Can't remove a zero-long key set in a multidict");
200
201   for (i = 0, thislevel = mdict; i < keys_len - 1;
202        i++, thislevel = nextlevel) {
203
204     xbt_dynar_get_cpy(keys, i, &thiskey);
205     xbt_dynar_get_cpy(lens, i, &thislen);
206
207     /* search the dict of next level */
208     TRY {
209       nextlevel = xbt_dict_get_ext(thislevel, thiskey, thislen);
210     }
211     CATCH(e) {
212       /* If non-existant entry, nothing to do */
213       if (e.category == arg_error)
214         xbt_ex_free(e);
215       else
216         RETHROW;
217     }
218   }
219
220   xbt_dynar_get_cpy(keys, i, &thiskey);
221   xbt_dynar_get_cpy(lens, i, &thislen);
222
223   xbt_dict_remove_ext(thislevel, thiskey, thislen);
224 }
225
226 void xbt_multidict_remove(xbt_dict_t mdict, xbt_dynar_t keys)
227 {
228   xbt_dynar_t lens = xbt_dynar_new(sizeof(unsigned long int), NULL);
229   unsigned long i;
230
231   for (i = 0; i < xbt_dynar_length(keys); i++) {
232     char *thiskey = xbt_dynar_get_as(keys, i, char *);
233     unsigned long int thislen = strlen(thiskey);
234     xbt_dynar_push(lens, &thislen);
235   }
236
237   TRY {
238     xbt_multidict_remove_ext(mdict, keys, lens);
239   }
240   TRY_CLEANUP {
241     xbt_dynar_free(&lens);
242   }
243   CATCH_ANONYMOUS {
244     RETHROW;
245   }
246 }
247
248 #endif