Logo AND Algorithmique Numérique Distribuée

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