Logo AND Algorithmique Numérique Distribuée

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