Logo AND Algorithmique Numérique Distribuée

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