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

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

Cstyle fixes.

  • Property mode set to 100644
File size: 10.6 KB
RevLine 
[21580dd]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
[2544442]29/** @addtogroup libc
[21580dd]30 * @{
31 */
32
33/** @file
34 * Character string to integer map implementation.
35 * @see char_map.h
36 */
37
[3c213f6]38#include <adt/char_map.h>
39
[21580dd]40#include <errno.h>
41#include <malloc.h>
42#include <mem.h>
43#include <unistd.h>
44
[3c213f6]45/** Internal magic value for a consistency check. */
[21580dd]46#define CHAR_MAP_MAGIC_VALUE 0x12345611
47
48/** Adds the value with the key to the map.
[3c213f6]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.
[1bfd3d3]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.
[21580dd]65 */
[3c213f6]66static int
[4eca056]67char_map_add_item(char_map_t *map, const char *identifier, size_t length,
[3c213f6]68 const int value)
69{
70 if (map->next == (map->size - 1)) {
[4eca056]71 char_map_t **tmp;
[21580dd]72
[4eca056]73 tmp = (char_map_t **) realloc(map->items,
74 sizeof(char_map_t *) * 2 * map->size);
[3c213f6]75 if (!tmp)
[aadf01e]76 return ENOMEM;
[3c213f6]77
[21580dd]78 map->size *= 2;
79 map->items = tmp;
80 }
[3c213f6]81
[4eca056]82 map->items[map->next] = (char_map_t *) malloc(sizeof(char_map_t));
[3c213f6]83 if (!map->items[map->next])
[aadf01e]84 return ENOMEM;
[3c213f6]85
86 if (char_map_initialize(map->items[map->next]) != EOK) {
[aadf01e]87 free(map->items[map->next]);
88 map->items[map->next] = NULL;
[21580dd]89 return ENOMEM;
90 }
[3c213f6]91
[442ebbe]92 map->items[map->next]->c = *identifier;
93 identifier++;
94 map->next++;
95 if ((length > 1) || ((length == 0) && *identifier)) {
[aadf01e]96 map->items[map->next - 1]->value = CHAR_MAP_NULL;
[3c213f6]97 return char_map_add_item(map->items[map->next - 1], identifier,
98 length ? length - 1 : 0, value);
99 } else {
[aadf01e]100 map->items[map->next - 1]->value = value;
[21580dd]101 }
[3c213f6]102
[21580dd]103 return EOK;
104}
105
[3c213f6]106/** Checks if the map is valid.
107 *
108 * @param[in] map The character string to integer map.
[1bfd3d3]109 * @return TRUE if the map is valid.
110 * @return FALSE otherwise.
[3c213f6]111 */
[4eca056]112static int char_map_is_valid(const char_map_t *map)
[3c213f6]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.
[1bfd3d3]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
[3c213f6]133 * identifier parameter is an empty character string (the
134 * first character is the terminating zero ('\0')
135 * character.
[1bfd3d3]136 * @return EEXIST if the key character string is already used.
137 * @return Other error codes as defined for the
[3c213f6]138 * char_map_add_item() function.
139 */
140int
[4eca056]141char_map_add(char_map_t *map, const char *identifier, size_t length,
[3c213f6]142 const int value)
143{
[442ebbe]144 if (char_map_is_valid(map) && identifier && (length || *identifier)) {
[3c213f6]145 int index;
146
[442ebbe]147 for (index = 0; index < map->next; index++) {
[3c213f6]148 if (map->items[index]->c != *identifier)
149 continue;
150
[442ebbe]151 identifier++;
152 if((length > 1) || ((length == 0) && *identifier)) {
[3c213f6]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 */
[4eca056]173void char_map_destroy(char_map_t *map)
[3c213f6]174{
175 if (char_map_is_valid(map)) {
[aadf01e]176 int index;
[21580dd]177
178 map->magic = 0;
[442ebbe]179 for (index = 0; index < map->next; index++)
[aadf01e]180 char_map_destroy(map->items[index]);
[3c213f6]181
[aadf01e]182 free(map->items);
[21580dd]183 map->items = NULL;
184 }
185}
186
[3c213f6]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.
[1bfd3d3]197 * @return The node holding the integral value assigned to the key
[3c213f6]198 * character string.
[1bfd3d3]199 * @return NULL if the key is not assigned a node.
[3c213f6]200 */
[4eca056]201static char_map_t *
202char_map_find_node(const char_map_t *map, const char *identifier,
[3c213f6]203 size_t length)
204{
205 if (!char_map_is_valid(map))
206 return NULL;
207
[442ebbe]208 if (length || *identifier) {
[3c213f6]209 int index;
210
[442ebbe]211 for (index = 0; index < map->next; index++) {
[3c213f6]212 if (map->items[index]->c == *identifier) {
[442ebbe]213 identifier++;
[3c213f6]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
[4eca056]225 return (char_map_t *) map;
[3c213f6]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.
[1bfd3d3]240 * @return The integral value assigned to the key character string.
241 * @return CHAR_MAP_NULL if the key is not assigned a value.
[3c213f6]242 */
[4eca056]243int char_map_exclude(char_map_t *map, const char *identifier, size_t length)
[3c213f6]244{
[4eca056]245 char_map_t *node;
[21580dd]246
[aadf01e]247 node = char_map_find_node(map, identifier, length);
[3c213f6]248 if (node) {
[aadf01e]249 int value;
[21580dd]250
251 value = node->value;
252 node->value = CHAR_MAP_NULL;
253 return value;
254 }
255 return CHAR_MAP_NULL;
256}
257
[3c213f6]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.
[1bfd3d3]268 * @return The integral value assigned to the key character string.
269 * @return CHAR_MAP_NULL if the key is not assigned a value.
[3c213f6]270 */
[4eca056]271int char_map_find(const char_map_t *map, const char *identifier, size_t length)
[3c213f6]272{
[4eca056]273 char_map_t *node;
[21580dd]274
[aadf01e]275 node = char_map_find_node(map, identifier, length);
[21580dd]276 return node ? node->value : CHAR_MAP_NULL;
277}
278
[3c213f6]279/** Initializes the map.
280 *
281 * @param[in,out] map The character string to integer map.
[1bfd3d3]282 * @return EOK on success.
283 * @return EINVAL if the map parameter is NULL.
284 * @return ENOMEM if there is not enough memory left.
[3c213f6]285 */
[4eca056]286int char_map_initialize(char_map_t *map)
[3c213f6]287{
288 if (!map)
[aadf01e]289 return EINVAL;
[3c213f6]290
[21580dd]291 map->c = '\0';
292 map->value = CHAR_MAP_NULL;
293 map->size = 2;
294 map->next = 0;
[3c213f6]295
[4eca056]296 map->items = malloc(sizeof(char_map_t *) * map->size);
[3c213f6]297 if (!map->items) {
[21580dd]298 map->magic = 0;
299 return ENOMEM;
300 }
[3c213f6]301
[aadf01e]302 map->items[map->next] = NULL;
[21580dd]303 map->magic = CHAR_MAP_MAGIC_VALUE;
304
[3c213f6]305 return EOK;
[21580dd]306}
307
[3c213f6]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.
[1bfd3d3]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
[3c213f6]324 * identifier parameter is an empty character string (the
325 * first character is the terminating zero ('\0) character.
[1bfd3d3]326 * @return EEXIST if the key character string is already used.
327 * @return Other error codes as defined for the char_map_add_item()
[3c213f6]328 * function.
329 */
330int
[4eca056]331char_map_update(char_map_t *map, const char *identifier, const size_t length,
[3c213f6]332 const int value)
333{
[4eca056]334 char_map_t *node;
[21580dd]335
[aadf01e]336 node = char_map_find_node(map, identifier, length);
[3c213f6]337 if (node) {
[21580dd]338 node->value = value;
339 return EOK;
340 }
[3c213f6]341
342 return char_map_add(map, identifier, length, value);
[21580dd]343}
344
345/** @}
346 */
Note: See TracBrowser for help on using the repository browser.