char_map.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Lukas Mejdrech
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include <adt/char_map.h>
00039 
00040 #include <errno.h>
00041 #include <malloc.h>
00042 #include <mem.h>
00043 #include <unistd.h>
00044 
00046 #define CHAR_MAP_MAGIC_VALUE    0x12345611
00047 
00066 static int
00067 char_map_add_item(char_map_t *map, const uint8_t *identifier, size_t length,
00068     const int value)
00069 {
00070         if (map->next == (map->size - 1)) {
00071                 char_map_t **tmp;
00072 
00073                 tmp = (char_map_t **) realloc(map->items,
00074                     sizeof(char_map_t *) * 2 * map->size);
00075                 if (!tmp)
00076                         return ENOMEM;
00077 
00078                 map->size *= 2;
00079                 map->items = tmp;
00080         }
00081 
00082         map->items[map->next] = (char_map_t *) malloc(sizeof(char_map_t));
00083         if (!map->items[map->next])
00084                 return ENOMEM;
00085 
00086         if (char_map_initialize(map->items[map->next]) != EOK) {
00087                 free(map->items[map->next]);
00088                 map->items[map->next] = NULL;
00089                 return ENOMEM;
00090         }
00091 
00092         map->items[map->next]->c = *identifier;
00093         identifier++;
00094         map->next++;
00095         if ((length > 1) || ((length == 0) && *identifier)) {
00096                 map->items[map->next - 1]->value = CHAR_MAP_NULL;
00097                 return char_map_add_item(map->items[map->next - 1], identifier,
00098                     length ? length - 1 : 0, value);
00099         } else {
00100                 map->items[map->next - 1]->value = value;
00101         }
00102 
00103         return EOK;
00104 }
00105 
00112 static int char_map_is_valid(const char_map_t *map)
00113 {
00114         return map && (map->magic == CHAR_MAP_MAGIC_VALUE);
00115 }
00116 
00140 int
00141 char_map_add(char_map_t *map, const uint8_t *identifier, size_t length,
00142     const int value)
00143 {
00144         if (char_map_is_valid(map) && identifier && (length || *identifier)) {
00145                 int index;
00146 
00147                 for (index = 0; index < map->next; index++) {
00148                         if (map->items[index]->c != *identifier)
00149                                 continue;
00150                                 
00151                         identifier++;
00152                         if((length > 1) || ((length == 0) && *identifier)) {
00153                                 return char_map_add(map->items[index],
00154                                     identifier, length ? length - 1 : 0, value);
00155                         } else {
00156                                 if (map->items[index]->value != CHAR_MAP_NULL)
00157                                         return EEXISTS;
00158 
00159                                 map->items[index]->value = value;
00160                                 return EOK;
00161                         }
00162                 }
00163                 return char_map_add_item(map, identifier, length, value);
00164         }
00165 
00166         return EINVAL;
00167 }
00168 
00173 void char_map_destroy(char_map_t *map)
00174 {
00175         if (char_map_is_valid(map)) {
00176                 int index;
00177 
00178                 map->magic = 0;
00179                 for (index = 0; index < map->next; index++)
00180                         char_map_destroy(map->items[index]);
00181 
00182                 free(map->items);
00183                 map->items = NULL;
00184         }
00185 }
00186 
00201 static char_map_t *
00202 char_map_find_node(const char_map_t *map, const uint8_t *identifier,
00203     size_t length)
00204 {
00205         if (!char_map_is_valid(map))
00206                 return NULL;
00207 
00208         if (length || *identifier) {
00209                 int index;
00210 
00211                 for (index = 0; index < map->next; index++) {
00212                         if (map->items[index]->c == *identifier) {
00213                                 identifier++;
00214                                 if (length == 1)
00215                                         return map->items[index];
00216 
00217                                 return char_map_find_node(map->items[index],
00218                                     identifier, length ? length - 1 : 0);
00219                         }
00220                 }
00221 
00222                 return NULL;
00223         }
00224 
00225         return (char_map_t *) map;
00226 }
00227 
00243 int char_map_exclude(char_map_t *map, const uint8_t *identifier, size_t length)
00244 {
00245         char_map_t *node;
00246 
00247         node = char_map_find_node(map, identifier, length);
00248         if (node) {
00249                 int value;
00250 
00251                 value = node->value;
00252                 node->value = CHAR_MAP_NULL;
00253                 return value;
00254         }
00255         return CHAR_MAP_NULL;
00256 }
00257 
00271 int char_map_find(const char_map_t *map, const uint8_t *identifier, size_t length)
00272 {
00273         char_map_t *node;
00274 
00275         node = char_map_find_node(map, identifier, length);
00276         return node ? node->value : CHAR_MAP_NULL;
00277 }
00278 
00286 int char_map_initialize(char_map_t *map)
00287 {
00288         if (!map)
00289                 return EINVAL;
00290 
00291         map->c = '\0';
00292         map->value = CHAR_MAP_NULL;
00293         map->size = 2;
00294         map->next = 0;
00295 
00296         map->items = malloc(sizeof(char_map_t *) * map->size);
00297         if (!map->items) {
00298                 map->magic = 0;
00299                 return ENOMEM;
00300         }
00301 
00302         map->items[map->next] = NULL;
00303         map->magic = CHAR_MAP_MAGIC_VALUE;
00304 
00305         return EOK;
00306 }
00307 
00330 int
00331 char_map_update(char_map_t *map, const uint8_t *identifier, const size_t length,
00332     const int value)
00333 {
00334         char_map_t *node;
00335 
00336         node = char_map_find_node(map, identifier, length);
00337         if (node) {
00338                 node->value = value;
00339                 return EOK;
00340         }
00341         
00342         return char_map_add(map, identifier, length, value);
00343 }
00344 

Generated on Thu Jun 2 07:45:45 2011 for HelenOS/USB by  doxygen 1.4.7