Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
move xbt_maxmin_float_t and xbt_heap_float_t here
[simgrid.git] / src / xbt / dict_cursor.c
1 /* $Id$ */
2
3 /* dict_cursor - iterators over dictionnaries                               */
4
5 /* Authors: Martin Quinson                                                  */
6 /* Copyright (C) 2003,2004 Martin Quinson.                                  */
7
8 /* This program is free software; you can redistribute it and/or modify it
9    under the terms of the license (GNU LGPL) which comes with this package. */
10
11 #include "xbt/misc.h"
12 #include "dict_private.h"
13
14 #include <string.h> /* strlen() */
15
16 XBT_LOG_EXTERNAL_CATEGORY(dict);
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(dict_cursor,dict,"To traverse dictionaries");
18
19
20 /*####[ Dict cursor functions ]#############################################*/
21 /* To traverse (simple) dicts                                               */
22 /* Don't add or remove entries to the dict while traversing !!!             */
23 /*###########################################################################*/
24 struct xbt_dict_cursor_ {
25   /* we store all level encountered until here, to backtrack on next() */
26   xbt_dynar_t   keys;
27   xbt_dynar_t   key_lens;
28   int            pos;
29   int            pos_len;
30   xbt_dictelm_t head;
31 };
32
33 static _XBT_INLINE void
34 _cursor_push_keys(xbt_dict_cursor_t p_cursor,
35                   xbt_dictelm_t     p_elm);
36
37 #undef xbt_dict_CURSOR_DEBUG
38 /*#define xbt_dict_CURSOR_DEBUG 1*/
39
40 /**
41  * xbt_dict_cursor_new:
42  *
43  * @head: the head of the dict
44  * @cursor: the curent position in the dict
45  *
46  * Structure creator
47  */
48 xbt_dict_cursor_t 
49 xbt_dict_cursor_new(const xbt_dict_t head) {
50   xbt_dict_cursor_t res = NULL;
51
52   res = xbt_new(s_xbt_dict_cursor_t,1);
53   res->keys     = xbt_dynar_new(sizeof(char **), NULL);
54   res->key_lens = xbt_dynar_new(sizeof(int  *),  NULL);
55   res->pos      = 0;
56   res->pos_len  = 0;
57   res->head     = head ? head->head : NULL;
58
59   xbt_dict_cursor_rewind(res);
60
61   return res;
62 }
63
64 /**
65  * xbt_dict_cursor_free:
66  *
67  * @cursor: poor victim
68  *
69  * Structure destructor
70  */
71 void
72 xbt_dict_cursor_free(xbt_dict_cursor_t *cursor) {
73   if (*cursor) {
74     xbt_dynar_free(&((*cursor)->keys));
75     xbt_dynar_free(&((*cursor)->key_lens));
76     xbt_free(*cursor);
77     *cursor = NULL;
78   }
79 }
80
81 /**
82  * __cursor_not_null:
83  *
84  * Sanity check to see if the head contains something
85  */
86 static _XBT_INLINE
87 xbt_error_t
88 __cursor_not_null(xbt_dict_cursor_t cursor) {
89
90   xbt_assert0(cursor, "Null cursor");
91
92   if (!cursor->head) {
93     return mismatch_error;
94   }
95
96   return no_error;
97 }
98
99
100 static _XBT_INLINE
101 void
102 _cursor_push_keys(xbt_dict_cursor_t cursor,
103                   xbt_dictelm_t     elm) {
104   xbt_dictelm_t       child = NULL;
105   int                  i       = 0;
106   static volatile int  count   = 0; /* ??? */
107
108   CDEBUG1(dict_cursor, "Push childs of %p in the cursor", (void*)elm);
109
110   if (elm->content) {
111     xbt_dynar_push(cursor->keys,     &elm->key    );
112     xbt_dynar_push(cursor->key_lens, &elm->key_len);
113     count++;
114   }
115
116   xbt_dynar_foreach(elm->sub, i, child) {
117     if (child)
118       _cursor_push_keys(cursor, child);
119   }
120
121   CDEBUG1(dict_cursor, "Count = %d", count);
122 }
123
124 /**
125  * xbt_dict_cursor_rewind:
126  * @cursor: the cursor
127  * @Returns: xbt_error_t
128  *
129  * back to the first element
130  */
131 void
132 xbt_dict_cursor_rewind(xbt_dict_cursor_t cursor) {
133
134   CDEBUG0(dict_cursor, "xbt_dict_cursor_rewind");
135   xbt_assert(cursor);
136
137   xbt_dynar_reset(cursor->keys);
138   xbt_dynar_reset(cursor->key_lens);
139
140   if (!cursor->head)
141     return ;
142
143   _cursor_push_keys(cursor, cursor->head);
144
145   xbt_dynar_cursor_first(cursor->keys,     &cursor->pos    );
146   xbt_dynar_cursor_first(cursor->key_lens, &cursor->pos_len);
147
148 }
149
150 /**
151  * xbt_dict_cursor_first:
152  * @dict: on what to let the cursor iterate
153  * @cursor: dest address
154  *
155  * Create the cursor if it does not exists. Rewind it in any case.
156  */
157 void xbt_dict_cursor_first (const xbt_dict_t   dict,
158                              xbt_dict_cursor_t *cursor){
159
160   if (!*cursor) {
161     DEBUG0("Create the cursor on first use");
162     *cursor=xbt_dict_cursor_new(dict);
163   }
164
165   xbt_dict_cursor_rewind(*cursor);
166 }
167
168
169 /**
170  * xbt_dict_cursor_step:
171  * @cursor: the cursor
172  *
173  * Move to the next element. 
174  */
175 void
176 xbt_dict_cursor_step(xbt_dict_cursor_t cursor) {
177   xbt_assert(cursor);
178
179   xbt_dynar_cursor_step(cursor->keys,     &cursor->pos);
180   xbt_dynar_cursor_step(cursor->key_lens, &cursor->pos_len);
181 }
182
183 /**
184  * xbt_dict_cursor_get_or_free:
185  * @cursor: the cursor
186  * @Returns: true if it's ok, false if there is no more data
187  *
188  * Get current data
189  */
190 int
191 xbt_dict_cursor_get_or_free(xbt_dict_cursor_t  *cursor,
192                              char               **key,
193                              void               **data) {
194   xbt_error_t  errcode = no_error;
195   int           key_len = 0;
196   
197   if (!cursor || !(*cursor))
198     return FALSE;
199
200   if (xbt_dynar_length((*cursor)->keys) <= (*cursor)->pos) {
201     xbt_dict_cursor_free(cursor);
202     return FALSE;
203   }
204     
205   *key    = xbt_dynar_get_as((*cursor)->keys,     (*cursor)->pos,     char*);
206   key_len = xbt_dynar_get_as((*cursor)->key_lens, (*cursor)->pos_len, int);
207
208   errcode = xbt_dictelm_get_ext((*cursor)->head, *key, key_len, data);
209   if (errcode == mismatch_error) {
210     xbt_dict_cursor_free(cursor);
211     return FALSE;
212   }
213
214   xbt_assert1(errcode == no_error,
215                "Unexpected problem while retrieving the content of cursor. Got %s",
216                xbt_error_name(errcode));
217
218   return TRUE;
219 }
220
221 /**
222  * xbt_dict_cursor_get_key:
223  * @cursor: the cursor
224  * @key: the current element
225  * @Returns: xbt_error_t
226  *
227  * Get current key
228  */
229 xbt_error_t
230 xbt_dict_cursor_get_key(xbt_dict_cursor_t   cursor,
231                          /*OUT*/char        **key) {
232   xbt_error_t errcode = no_error;
233
234   TRY(__cursor_not_null(cursor));
235
236   *key = xbt_dynar_get_as(cursor->keys, cursor->pos - 1, char*);
237
238   return errcode;
239 }
240
241 /**
242  * xbt_dict_cursor_get_data:
243  * @cursor: the cursor
244  *
245  * Get current data
246  */
247 xbt_error_t
248 xbt_dict_cursor_get_data(xbt_dict_cursor_t   cursor,
249                           /*OUT*/void        **data) {
250   xbt_error_t  errcode = no_error;
251   char         *key     = NULL;
252   int           key_len = 0;
253
254   TRY(__cursor_not_null(cursor));
255
256   key     = xbt_dynar_get_as(cursor->keys,     cursor->pos-1,  char *);
257   key_len = xbt_dynar_get_as(cursor->key_lens, cursor->pos_len-1, int);
258
259   TRY(xbt_dictelm_get_ext(cursor->head, key, key_len, data));
260
261   return errcode;
262 }
263
264