source: mainline/uspace/lib/c/generic/adt/char_map.c@ 32eceb4f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 32eceb4f was 1bfd3d3, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Replace @returns with @return.

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32
33/** @file
34 * Character string to integer map implementation.
35 * @see char_map.h
36 */
37
38#include <adt/char_map.h>
39
40#include <errno.h>
41#include <malloc.h>
42#include <mem.h>
43#include <unistd.h>
44
45/** Internal magic value for a consistency check. */
46#define CHAR_MAP_MAGIC_VALUE 0x12345611
47
48/** Adds the value with the key to the map.
49 *
50 * Creates new nodes to map the key.
51 *
52 * @param[in,out] map The character string to integer map.
53 * @param[in] identifier The key zero ('\0') terminated character string.
54 * The key character string is processed until the first
55 * terminating zero ('\0') character after the given
56 * length is found.
57 * @param[in] length The key character string length. The parameter may be
58 * zero (0) which means that the string is processed until
59 * the terminating zero ('\0') character is found.
60 * @param[in] value The integral value to be stored for the key character
61 * string.
62 * @return EOK on success.
63 * @return ENOMEM if there is not enough memory left.
64 * @return EEXIST if the key character string is already used.
65 */
66static int
67char_map_add_item(char_map_t *map, const char *identifier, size_t length,
68 const int value)
69{
70 if (map->next == (map->size - 1)) {
71 char_map_t **tmp;
72
73 tmp = (char_map_t **) realloc(map->items,
74 sizeof(char_map_t *) * 2 * map->size);
75 if (!tmp)
76 return ENOMEM;
77
78 map->size *= 2;
79 map->items = tmp;
80 }
81
82 map->items[map->next] = (char_map_t *) malloc(sizeof(char_map_t));
83 if (!map->items[map->next])
84 return ENOMEM;
85
86 if (char_map_initialize(map->items[map->next]) != EOK) {
87 free(map->items[map->next]);
88 map->items[map->next] = NULL;
89 return ENOMEM;
90 }
91
92 map->items[map->next]->c = * identifier;
93 ++ identifier;
94 ++ map->next;
95 if ((length > 1) || ((length == 0) && (*identifier))) {
96 map->items[map->next - 1]->value = CHAR_MAP_NULL;
97 return char_map_add_item(map->items[map->next - 1], identifier,
98 length ? length - 1 : 0, value);
99 } else {
100 map->items[map->next - 1]->value = value;
101 }
102
103 return EOK;
104}
105
106/** Checks if the map is valid.
107 *
108 * @param[in] map The character string to integer map.
109 * @return TRUE if the map is valid.
110 * @return FALSE otherwise.
111 */
112static int char_map_is_valid(const char_map_t *map)
113{
114 return map && (map->magic == CHAR_MAP_MAGIC_VALUE);
115}
116
117/** Adds the value with the key to the map.
118 *
119 * @param[in,out] map The character string to integer map.
120 * @param[in] identifier The key zero ('\0') terminated character string. The
121 * key character string is processed until the first
122 * terminating zero ('\0') character after the given
123 * length is found.
124 * @param[in] length The key character string length. The parameter may be
125 * zero (0) which means that the string is processed until
126 * the terminating zero ('\\0') character is found.
127 * @param[in] value The integral value to be stored for the key character
128 * string.
129 * @return EOK on success.
130 * @return EINVAL if the map is not valid.
131 * @return EINVAL if the identifier parameter is NULL.
132 * @return EINVAL if the length parameter zero (0) and the
133 * identifier parameter is an empty character string (the
134 * first character is the terminating zero ('\0')
135 * character.
136 * @return EEXIST if the key character string is already used.
137 * @return Other error codes as defined for the
138 * char_map_add_item() function.
139 */
140int
141char_map_add(char_map_t *map, const char *identifier, size_t length,
142 const int value)
143{
144 if (char_map_is_valid(map) && (identifier) &&
145 ((length) || (*identifier))) {
146 int index;
147
148 for (index = 0; index < map->next; ++ index) {
149 if (map->items[index]->c != *identifier)
150 continue;
151
152 ++ identifier;
153 if((length > 1) || ((length == 0) && (*identifier))) {
154 return char_map_add(map->items[index],
155 identifier, length ? length - 1 : 0, value);
156 } else {
157 if (map->items[index]->value != CHAR_MAP_NULL)
158 return EEXISTS;
159
160 map->items[index]->value = value;
161 return EOK;
162 }
163 }
164 return char_map_add_item(map, identifier, length, value);
165 }
166
167 return EINVAL;
168}
169
170/** Clears and destroys the map.
171 *
172 * @param[in,out] map The character string to integer map.
173 */
174void char_map_destroy(char_map_t *map)
175{
176 if (char_map_is_valid(map)) {
177 int index;
178
179 map->magic = 0;
180 for (index = 0; index < map->next; ++index)
181 char_map_destroy(map->items[index]);
182
183 free(map->items);
184 map->items = NULL;
185 }
186}
187
188/** Returns the node assigned to the key from the map.
189 *
190 * @param[in] map The character string to integer map.
191 * @param[in] identifier The key zero ('\0') terminated character string. The
192 * key character string is processed until the first
193 * terminating zero ('\0') character after the given length
194 * is found.
195 * @param[in] length The key character string length. The parameter may be
196 * zero (0) which means that the string is processed until
197 * the terminating zero ('\0') character is found.
198 * @return The node holding the integral value assigned to the key
199 * character string.
200 * @return NULL if the key is not assigned a node.
201 */
202static char_map_t *
203char_map_find_node(const char_map_t *map, const char *identifier,
204 size_t length)
205{
206 if (!char_map_is_valid(map))
207 return NULL;
208
209 if (length || (*identifier)) {
210 int index;
211
212 for (index = 0; index < map->next; ++index) {
213 if (map->items[index]->c == *identifier) {
214 ++identifier;
215 if (length == 1)
216 return map->items[index];
217
218 return char_map_find_node(map->items[index],
219 identifier, length ? length - 1 : 0);
220 }
221 }
222
223 return NULL;
224 }
225
226 return (char_map_t *) map;
227}
228
229/** Excludes the value assigned to the key from the map.
230 *
231 * The entry is cleared from the map.
232 *
233 * @param[in,out] map The character string to integer map.
234 * @param[in] identifier The key zero ('\0') terminated character string. The
235 * key character string is processed until the first
236 * terminating zero ('\0') character after the given length
237 * is found.
238 * @param[in] length The key character string length. The parameter may be
239 * zero (0) which means that the string is processed until
240 * the terminating zero ('\0') character is found.
241 * @return The integral value assigned to the key character string.
242 * @return CHAR_MAP_NULL if the key is not assigned a value.
243 */
244int char_map_exclude(char_map_t *map, const char *identifier, size_t length)
245{
246 char_map_t *node;
247
248 node = char_map_find_node(map, identifier, length);
249 if (node) {
250 int value;
251
252 value = node->value;
253 node->value = CHAR_MAP_NULL;
254 return value;
255 }
256 return CHAR_MAP_NULL;
257}
258
259/** Returns the value assigned to the key from the map.
260 *
261 * @param[in] map The character string to integer map.
262 * @param[in] identifier The key zero ('\0') terminated character string. The
263 * key character string is processed until the first
264 * terminating zero ('\0') character after the given length
265 * is found.
266 * @param[in] length The key character string length. The parameter may be
267 * zero (0) which means that the string is processed until
268 * the terminating zero ('\0') character is found.
269 * @return The integral value assigned to the key character string.
270 * @return CHAR_MAP_NULL if the key is not assigned a value.
271 */
272int char_map_find(const char_map_t *map, const char *identifier, size_t length)
273{
274 char_map_t *node;
275
276 node = char_map_find_node(map, identifier, length);
277 return node ? node->value : CHAR_MAP_NULL;
278}
279
280/** Initializes the map.
281 *
282 * @param[in,out] map The character string to integer map.
283 * @return EOK on success.
284 * @return EINVAL if the map parameter is NULL.
285 * @return ENOMEM if there is not enough memory left.
286 */
287int char_map_initialize(char_map_t *map)
288{
289 if (!map)
290 return EINVAL;
291
292 map->c = '\0';
293 map->value = CHAR_MAP_NULL;
294 map->size = 2;
295 map->next = 0;
296
297 map->items = malloc(sizeof(char_map_t *) * map->size);
298 if (!map->items) {
299 map->magic = 0;
300 return ENOMEM;
301 }
302
303 map->items[map->next] = NULL;
304 map->magic = CHAR_MAP_MAGIC_VALUE;
305
306 return EOK;
307}
308
309/** Adds or updates the value with the key to the map.
310 *
311 * @param[in,out] map The character string to integer map.
312 * @param[in] identifier The key zero ('\0') terminated character string. The
313 * key character string is processed until the first
314 * terminating zero ('\0') character after the given length
315 * is found.
316 * @param[in] length The key character string length. The parameter may be
317 * zero (0) which means that the string is processed until
318 * the terminating zero ('\0') character is found.
319 * @param[in] value The integral value to be stored for the key character
320 * string.
321 * @return EOK on success.
322 * @return EINVAL if the map is not valid.
323 * @return EINVAL if the identifier parameter is NULL.
324 * @return EINVAL if the length parameter zero (0) and the
325 * identifier parameter is an empty character string (the
326 * first character is the terminating zero ('\0) character.
327 * @return EEXIST if the key character string is already used.
328 * @return Other error codes as defined for the char_map_add_item()
329 * function.
330 */
331int
332char_map_update(char_map_t *map, const char *identifier, const size_t length,
333 const int value)
334{
335 char_map_t *node;
336
337 node = char_map_find_node(map, identifier, length);
338 if (node) {
339 node->value = value;
340 return EOK;
341 }
342
343 return char_map_add(map, identifier, length, value);
344}
345
346/** @}
347 */
Note: See TracBrowser for help on using the repository browser.