Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
another bunch of sonar treats
[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 + 1) <= cursor->dict->table_size) {
112       line++;
113       XBT_CDEBUG(xbt_dict_cursor, "current is NULL, take the next line");
114       current = cursor->dict->table[line];
115       XBT_CDEBUG(xbt_dict_cursor, "element in the next line: %p", current);
116     }
117     XBT_CDEBUG(xbt_dict_cursor, "search finished, current = %p, line = %d", current, line);
118
119     cursor->current = current;
120     cursor->line = line;
121   }
122 }
123
124 /**
125  * @brief Get current data, or free the cursor if there is no data left
126  *
127  * @returns true if it's ok, false if there is no more data
128  */
129 inline int xbt_dict_cursor_get_or_free(xbt_dict_cursor_t * cursor, char **key, void **data)
130 {
131   xbt_dictelm_t current;
132
133   XBT_CDEBUG(xbt_dict_cursor, "xbt_dict_get_or_free");
134
135   if (!cursor || !(*cursor))
136     return FALSE;
137
138   current = (*cursor)->current;
139   if (current == NULL) {        /* no data left */
140     xbt_dict_cursor_free(cursor);
141     return FALSE;
142   }
143
144   *key = current->key;
145   *data = current->content;
146   return TRUE;
147 }
148
149 /**
150  * @brief Get current key
151  * @param cursor: the cursor
152  * @returns the current key
153  */
154 inline char *xbt_dict_cursor_get_key(xbt_dict_cursor_t cursor)
155 {
156   __cursor_not_null(cursor);
157
158   return cursor->current->key;
159 }
160
161 /**
162  * @brief Get current data
163  * @param cursor the cursor
164  * @returns the current data
165  */
166 inline void *xbt_dict_cursor_get_data(xbt_dict_cursor_t cursor)
167 {
168   __cursor_not_null(cursor);
169
170   return cursor->current->content;
171 }
172
173 /**
174  * @brief Set current data
175  * @param cursor the cursor
176  * @param data the new data
177  * @param free_ctn the function to free the new data
178  */
179 inline void xbt_dict_cursor_set_data(xbt_dict_cursor_t cursor, void *data, void_f_pvoid_t free_ctn)
180 {
181   __cursor_not_null(cursor);
182   xbt_dictelm_set_data(cursor->dict, cursor->current, data, free_ctn);
183 }