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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fe2333d was 442ebbe, checked in by Jakub Jermar <jakub@…>, 15 years ago

Cstyle fixes.

  • 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 && (length || *identifier)) {
145 int index;
146
147 for (index = 0; index < map->next; index++) {
148 if (map->items[index]->c != *identifier)
149 continue;
150
151 identifier++;
152 if((length > 1) || ((length == 0) && *identifier)) {
153 return char_map_add(map->items[index],
154 identifier, length ? length - 1 : 0, value);
155 } else {
156 if (map->items[index]->value != CHAR_MAP_NULL)
157 return EEXISTS;
158
159 map->items[index]->value = value;
160 return EOK;
161 }
162 }
163 return char_map_add_item(map, identifier, length, value);
164 }
165
166 return EINVAL;
167}
168
169/** Clears and destroys the map.
170 *
171 * @param[in,out] map The character string to integer map.
172 */
173void char_map_destroy(char_map_t *map)
174{
175 if (char_map_is_valid(map)) {
176 int index;
177
178 map->magic = 0;
179 for (index = 0; index < map->next; index++)
180 char_map_destroy(map->items[index]);
181
182 free(map->items);
183 map->items = NULL;
184 }
185}
186
187/** Returns the node assigned to the key from the map.
188 *
189 * @param[in] map The character string to integer map.
190 * @param[in] identifier The key zero ('\0') terminated character string. The
191 * key character string is processed until the first
192 * terminating zero ('\0') character after the given length
193 * is found.
194 * @param[in] length The key character string length. The parameter may be
195 * zero (0) which means that the string is processed until
196 * the terminating zero ('\0') character is found.
197 * @return The node holding the integral value assigned to the key
198 * character string.
199 * @return NULL if the key is not assigned a node.
200 */
201static char_map_t *
202char_map_find_node(const char_map_t *map, const char *identifier,
203 size_t length)
204{
205 if (!char_map_is_valid(map))
206 return NULL;
207
208 if (length || *identifier) {
209 int index;
210
211 for (index = 0; index < map->next; index++) {
212 if (map->items[index]->c == *identifier) {
213 identifier++;
214 if (length == 1)
215 return map->items[index];
216
217 return char_map_find_node(map->items[index],
218 identifier, length ? length - 1 : 0);
219 }
220 }
221
222 return NULL;
223 }
224
225 return (char_map_t *) map;
226}
227
228/** Excludes the value assigned to the key from the map.
229 *
230 * The entry is cleared from the map.
231 *
232 * @param[in,out] map The character string to integer map.
233 * @param[in] identifier The key zero ('\0') terminated character string. The
234 * key character string is processed until the first
235 * terminating zero ('\0') character after the given length
236 * is found.
237 * @param[in] length The key character string length. The parameter may be
238 * zero (0) which means that the string is processed until
239 * the terminating zero ('\0') character is found.
240 * @return The integral value assigned to the key character string.
241 * @return CHAR_MAP_NULL if the key is not assigned a value.
242 */
243int char_map_exclude(char_map_t *map, const char *identifier, size_t length)
244{
245 char_map_t *node;
246
247 node = char_map_find_node(map, identifier, length);
248 if (node) {
249 int value;
250
251 value = node->value;
252 node->value = CHAR_MAP_NULL;
253 return value;
254 }
255 return CHAR_MAP_NULL;
256}
257
258/** Returns the value assigned to the key from the map.
259 *
260 * @param[in] map The character string to integer map.
261 * @param[in] identifier The key zero ('\0') terminated character string. The
262 * key character string is processed until the first
263 * terminating zero ('\0') character after the given length
264 * is found.
265 * @param[in] length The key character string length. The parameter may be
266 * zero (0) which means that the string is processed until
267 * the terminating zero ('\0') character is found.
268 * @return The integral value assigned to the key character string.
269 * @return CHAR_MAP_NULL if the key is not assigned a value.
270 */
271int char_map_find(const char_map_t *map, const char *identifier, size_t length)
272{
273 char_map_t *node;
274
275 node = char_map_find_node(map, identifier, length);
276 return node ? node->value : CHAR_MAP_NULL;
277}
278
279/** Initializes the map.
280 *
281 * @param[in,out] map The character string to integer map.
282 * @return EOK on success.
283 * @return EINVAL if the map parameter is NULL.
284 * @return ENOMEM if there is not enough memory left.
285 */
286int char_map_initialize(char_map_t *map)
287{
288 if (!map)
289 return EINVAL;
290
291 map->c = '\0';
292 map->value = CHAR_MAP_NULL;
293 map->size = 2;
294 map->next = 0;
295
296 map->items = malloc(sizeof(char_map_t *) * map->size);
297 if (!map->items) {
298 map->magic = 0;
299 return ENOMEM;
300 }
301
302 map->items[map->next] = NULL;
303 map->magic = CHAR_MAP_MAGIC_VALUE;
304
305 return EOK;
306}
307
308/** Adds or updates the value with the key to the map.
309 *
310 * @param[in,out] map The character string to integer map.
311 * @param[in] identifier The key zero ('\0') terminated character string. The
312 * key character string is processed until the first
313 * terminating zero ('\0') character after the given length
314 * is found.
315 * @param[in] length The key character string length. The parameter may be
316 * zero (0) which means that the string is processed until
317 * the terminating zero ('\0') character is found.
318 * @param[in] value The integral value to be stored for the key character
319 * string.
320 * @return EOK on success.
321 * @return EINVAL if the map is not valid.
322 * @return EINVAL if the identifier parameter is NULL.
323 * @return EINVAL if the length parameter zero (0) and the
324 * identifier parameter is an empty character string (the
325 * first character is the terminating zero ('\0) character.
326 * @return EEXIST if the key character string is already used.
327 * @return Other error codes as defined for the char_map_add_item()
328 * function.
329 */
330int
331char_map_update(char_map_t *map, const char *identifier, const size_t length,
332 const int value)
333{
334 char_map_t *node;
335
336 node = char_map_find_node(map, identifier, length);
337 if (node) {
338 node->value = value;
339 return EOK;
340 }
341
342 return char_map_add(map, identifier, length, value);
343}
344
345/** @}
346 */
Note: See TracBrowser for help on using the repository browser.