Logo AND Algorithmique Numérique Distribuée

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