/* * Copyright (c) 2009 Lukas Mejdrech * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup net * @{ */ /** @file * Character string to integer map implementation. * @see char_map.h */ #include #include #include #include #include "char_map.h" /** Internal magic value for a consistency check. */ #define CHAR_MAP_MAGIC_VALUE 0x12345611 /** Adds the value with the key to the map. * Creates new nodes to map the key. * @param[in,out] map The character string to integer map. * @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found. * @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found. * @param[in] value The integral value to be stored for the key character string. * @returns EOK on success. * @returns ENOMEM if there is not enough memory left. * @returns EEXIST if the key character string is already used. */ int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value ); /** Returns the node assigned to the key from the map. * @param[in] map The character string to integer map. * @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found. * @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found. * @returns The node holding the integral value assigned to the key character string. * @returns NULL if the key is not assigned a node. */ char_map_ref char_map_find_node( const char_map_ref map, const char * identifier, const size_t length ); /** Returns the value assigned to the map. * @param[in] map The character string to integer map. * @returns The integral value assigned to the map. * @returns CHAR_MAP_NULL if the map is not assigned a value. */ int char_map_get_value( const char_map_ref map ); /** Checks if the map is valid. * @param[in] map The character string to integer map. * @returns TRUE if the map is valid. * @returns FALSE otherwise. */ int char_map_is_valid( const char_map_ref map ); int char_map_add( char_map_ref map, const char * identifier, size_t length, const int value ){ if( char_map_is_valid( map ) && ( identifier ) && (( length ) || ( * identifier ))){ int index; for( index = 0; index < map->next; ++ index ){ if( map->items[ index ]->c == * identifier ){ ++ identifier; if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){ return char_map_add( map->items[ index ], identifier, length ? length - 1 : 0, value ); }else{ if( map->items[ index ]->value != CHAR_MAP_NULL ) return EEXISTS; map->items[ index ]->value = value; return EOK; } } } return char_map_add_item( map, identifier, length, value ); } return EINVAL; } int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value ){ if( map->next == ( map->size - 1 )){ char_map_ref * tmp; tmp = ( char_map_ref * ) realloc( map->items, sizeof( char_map_ref ) * 2 * map->size ); if( ! tmp ) return ENOMEM; map->size *= 2; map->items = tmp; } map->items[ map->next ] = ( char_map_ref ) malloc( sizeof( char_map_t )); if( ! map->items[ map->next ] ) return ENOMEM; if( char_map_initialize( map->items[ map->next ] ) != EOK ){ free( map->items[ map->next ] ); map->items[ map->next ] = NULL; return ENOMEM; } map->items[ map->next ]->c = * identifier; ++ identifier; ++ map->next; if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){ map->items[ map->next - 1 ]->value = CHAR_MAP_NULL; return char_map_add_item( map->items[ map->next - 1 ], identifier, length ? length - 1 : 0, value ); }else{ map->items[ map->next - 1 ]->value = value; } return EOK; } void char_map_destroy( char_map_ref map ){ if( char_map_is_valid( map )){ int index; map->magic = 0; for( index = 0; index < map->next; ++ index ){ char_map_destroy( map->items[ index ] ); } free( map->items ); map->items = NULL; } } int char_map_exclude( char_map_ref map, const char * identifier, size_t length ){ char_map_ref node; node = char_map_find_node( map, identifier, length ); if( node ){ int value; value = node->value; node->value = CHAR_MAP_NULL; return value; } return CHAR_MAP_NULL; } int char_map_find( const char_map_ref map, const char * identifier, size_t length ){ char_map_ref node; node = char_map_find_node( map, identifier, length ); return node ? node->value : CHAR_MAP_NULL; } char_map_ref char_map_find_node( const char_map_ref map, const char * identifier, size_t length ){ if( ! char_map_is_valid( map )) return NULL; if( length || ( * identifier )){ int index; for( index = 0; index < map->next; ++ index ){ if( map->items[ index ]->c == * identifier ){ ++ identifier; if( length == 1 ) return map->items[ index ]; return char_map_find_node( map->items[ index ], identifier, length ? length - 1 : 0 ); } } return NULL; } return map; } int char_map_get_value( const char_map_ref map ){ return char_map_is_valid( map ) ? map->value : CHAR_MAP_NULL; } int char_map_initialize( char_map_ref map ){ if( ! map ) return EINVAL; map->c = '\0'; map->value = CHAR_MAP_NULL; map->size = 2; map->next = 0; map->items = malloc( sizeof( char_map_ref ) * map->size ); if( ! map->items ){ map->magic = 0; return ENOMEM; } map->items[ map->next ] = NULL; map->magic = CHAR_MAP_MAGIC_VALUE; return EOK; } int char_map_is_valid( const char_map_ref map ){ return map && ( map->magic == CHAR_MAP_MAGIC_VALUE ); } int char_map_update( char_map_ref map, const char * identifier, const size_t length, const int value ){ char_map_ref node; // if( ! char_map_is_valid( map )) return EINVAL; node = char_map_find_node( map, identifier, length ); if( node ){ node->value = value; return EOK; }else{ return char_map_add( map, identifier, length, value ); } } /** @} */