Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Cleanup.
[simgrid.git] / src / xbt / dict_cursor.c
1 /* dict_cursor - iterators over dictionnaries                               */
2
3 /* Copyright (c) 2004-2014. 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 "xbt/misc.h"
10 #include "xbt/ex.h"
11 #include "dict_private.h"
12
13 #include <string.h>             /* strlen() */
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_dict_cursor, xbt_dict,
16                                 "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
24 #undef xbt_dict_CURSOR_DEBUG
25 /*#define xbt_dict_CURSOR_DEBUG 1*/
26
27 /** @brief Creator
28  *  @param dict the dict
29  */
30 XBT_INLINE xbt_dict_cursor_t xbt_dict_cursor_new(const xbt_dict_t dict)
31 {
32   xbt_dict_cursor_t res = NULL;
33
34   res = xbt_new(s_xbt_dict_cursor_t, 1);
35   res->dict = dict;
36
37   xbt_dict_cursor_rewind(res);
38
39   return res;
40 }
41
42 /**
43  * @brief Destructor
44  * @param cursor poor victim
45  */
46 XBT_INLINE void xbt_dict_cursor_free(xbt_dict_cursor_t * cursor)
47 {
48   xbt_free(*cursor);
49   *cursor = NULL;
50 }
51
52 /*
53  * Sanity check to see if the head contains something
54  */
55 static XBT_INLINE void __cursor_not_null(xbt_dict_cursor_t cursor)
56 {
57   xbt_assert(cursor, "Null cursor");
58 }
59
60
61 /** @brief Reinitialize the cursor. Mandatory after removal or add in dict. */
62 XBT_INLINE void xbt_dict_cursor_rewind(xbt_dict_cursor_t cursor)
63 {
64   XBT_CDEBUG(xbt_dict_cursor, "xbt_dict_cursor_rewind");
65   xbt_assert(cursor);
66
67   cursor->line = 0;
68   if (cursor->dict != NULL) {
69     cursor->current = cursor->dict->table[0];
70   } else {
71     cursor->current = NULL;
72   }
73 }
74
75 /**
76  * @brief Create the cursor if it does not exists. Rewind it in any case.
77  *
78  * @param      dict   on what to let the cursor iterate
79  * @param[out] cursor dest address
80  */
81 XBT_INLINE void xbt_dict_cursor_first(const xbt_dict_t dict,
82                                       xbt_dict_cursor_t * cursor)
83 {
84   XBT_CDEBUG(xbt_dict_cursor, "xbt_dict_cursor_first");
85   if (!*cursor) {
86     XBT_CDEBUG(xbt_dict_cursor, "Create the cursor on first use");
87     *cursor = xbt_dict_cursor_new(dict);
88   } else {
89     xbt_dict_cursor_rewind(*cursor);
90   }
91   if (dict != NULL && (*cursor)->current == NULL) {
92     xbt_dict_cursor_step(*cursor);      /* find the first element */
93   }
94 }
95
96
97 /**
98  * \brief Move to the next element.
99  */
100 XBT_INLINE void xbt_dict_cursor_step(xbt_dict_cursor_t cursor)
101 {
102   xbt_dictelm_t current;
103   int line;
104
105   XBT_CDEBUG(xbt_dict_cursor, "xbt_dict_cursor_step");
106   xbt_assert(cursor);
107
108   current = cursor->current;
109   line = cursor->line;
110
111   if (cursor->dict != NULL) {
112
113     if (current != NULL) {
114       XBT_CDEBUG(xbt_dict_cursor, "current is not null, take the next element");
115       current = current->next;
116       XBT_CDEBUG(xbt_dict_cursor, "next element: %p", current);
117     }
118
119     while (current == NULL && ++line <= cursor->dict->table_size) {
120       XBT_CDEBUG(xbt_dict_cursor, "current is NULL, take the next line");
121       current = cursor->dict->table[line];
122       XBT_CDEBUG(xbt_dict_cursor, "element in the next line: %p", current);
123     }
124     XBT_CDEBUG(xbt_dict_cursor, "search finished, current = %p, line = %d", current, line);
125
126     cursor->current = current;
127     cursor->line = line;
128   }
129 }
130
131 /**
132  * @brief Get current data, or free the cursor if there is no data left
133  *
134  * @returns true if it's ok, false if there is no more data
135  */
136 XBT_INLINE int xbt_dict_cursor_get_or_free(xbt_dict_cursor_t * cursor,
137                                            char **key, void **data)
138 {
139
140   xbt_dictelm_t current;
141
142   XBT_CDEBUG(xbt_dict_cursor, "xbt_dict_get_or_free");
143
144
145   if (!cursor || !(*cursor))
146     return FALSE;
147
148   current = (*cursor)->current;
149   if (current == NULL) {        /* no data left */
150     xbt_dict_cursor_free(cursor);
151     return FALSE;
152   }
153
154   *key = current->key;
155   *data = current->content;
156   return TRUE;
157 }
158
159 /**
160  * @brief Get current key
161  * @param cursor: the cursor
162  * @returns the current key
163  */
164 XBT_INLINE char *xbt_dict_cursor_get_key(xbt_dict_cursor_t cursor)
165 {
166   __cursor_not_null(cursor);
167
168   return cursor->current->key;
169 }
170
171 /**
172  * @brief Get current data
173  * @param cursor the cursor
174  * @returns the current data
175  */
176 XBT_INLINE void *xbt_dict_cursor_get_data(xbt_dict_cursor_t cursor)
177 {
178   __cursor_not_null(cursor);
179
180   return cursor->current->content;
181 }
182
183 /**
184  * @brief Set current data
185  * @param cursor the cursor
186  * @param data the new data
187  * @param free_ctn the function to free the new data
188  */
189 XBT_INLINE void xbt_dict_cursor_set_data(xbt_dict_cursor_t cursor,
190                                          void *data,
191                                          void_f_pvoid_t free_ctn)
192 {
193   __cursor_not_null(cursor);
194   xbt_dictelm_set_data(cursor->dict, cursor->current, data, free_ctn);
195 }