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
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
[aadf01e]92 map->items[map->next]->c = * identifier;
[21580dd]93 ++ identifier;
94 ++ map->next;
[3c213f6]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{
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 */
[4eca056]174void char_map_destroy(char_map_t *map)
[3c213f6]175{
176 if (char_map_is_valid(map)) {
[aadf01e]177 int index;
[21580dd]178
179 map->magic = 0;
[3c213f6]180 for (index = 0; index < map->next; ++index)
[aadf01e]181 char_map_destroy(map->items[index]);
[3c213f6]182
[aadf01e]183 free(map->items);
[21580dd]184 map->items = NULL;
185 }
186}
187
[3c213f6]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.
[1bfd3d3]198 * @return The node holding the integral value assigned to the key
[3c213f6]199 * character string.
[1bfd3d3]200 * @return NULL if the key is not assigned a node.
[3c213f6]201 */
[4eca056]202static char_map_t *
203char_map_find_node(const char_map_t *map, const char *identifier,
[3c213f6]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
[4eca056]226 return (char_map_t *) map;
[3c213f6]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.
[1bfd3d3]241 * @return The integral value assigned to the key character string.
242 * @return CHAR_MAP_NULL if the key is not assigned a value.
[3c213f6]243 */
[4eca056]244int char_map_exclude(char_map_t *map, const char *identifier, size_t length)
[3c213f6]245{
[4eca056]246 char_map_t *node;
[21580dd]247
[aadf01e]248 node = char_map_find_node(map, identifier, length);
[3c213f6]249 if (node) {
[aadf01e]250 int value;
[21580dd]251
252 value = node->value;
253 node->value = CHAR_MAP_NULL;
254 return value;
255 }
256 return CHAR_MAP_NULL;
257}
258
[3c213f6]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.
[1bfd3d3]269 * @return The integral value assigned to the key character string.
270 * @return CHAR_MAP_NULL if the key is not assigned a value.
[3c213f6]271 */
[4eca056]272int char_map_find(const char_map_t *map, const char *identifier, size_t length)
[3c213f6]273{
[4eca056]274 char_map_t *node;
[21580dd]275
[aadf01e]276 node = char_map_find_node(map, identifier, length);
[21580dd]277 return node ? node->value : CHAR_MAP_NULL;
278}
279
[3c213f6]280/** Initializes the map.
281 *
282 * @param[in,out] map The character string to integer map.
[1bfd3d3]283 * @return EOK on success.
284 * @return EINVAL if the map parameter is NULL.
285 * @return ENOMEM if there is not enough memory left.
[3c213f6]286 */
[4eca056]287int char_map_initialize(char_map_t *map)
[3c213f6]288{
289 if (!map)
[aadf01e]290 return EINVAL;
[3c213f6]291
[21580dd]292 map->c = '\0';
293 map->value = CHAR_MAP_NULL;
294 map->size = 2;
295 map->next = 0;
[3c213f6]296
[4eca056]297 map->items = malloc(sizeof(char_map_t *) * map->size);
[3c213f6]298 if (!map->items) {
[21580dd]299 map->magic = 0;
300 return ENOMEM;
301 }
[3c213f6]302
[aadf01e]303 map->items[map->next] = NULL;
[21580dd]304 map->magic = CHAR_MAP_MAGIC_VALUE;
305
[3c213f6]306 return EOK;
[21580dd]307}
308
[3c213f6]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.
[1bfd3d3]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
[3c213f6]325 * identifier parameter is an empty character string (the
326 * first character is the terminating zero ('\0) character.
[1bfd3d3]327 * @return EEXIST if the key character string is already used.
328 * @return Other error codes as defined for the char_map_add_item()
[3c213f6]329 * function.
330 */
331int
[4eca056]332char_map_update(char_map_t *map, const char *identifier, const size_t length,
[3c213f6]333 const int value)
334{
[4eca056]335 char_map_t *node;
[21580dd]336
[aadf01e]337 node = char_map_find_node(map, identifier, length);
[3c213f6]338 if (node) {
[21580dd]339 node->value = value;
340 return EOK;
341 }
[3c213f6]342
343 return char_map_add(map, identifier, length, value);
[21580dd]344}
345
346/** @}
347 */
Note: See TracBrowser for help on using the repository browser.