/*
* Copyright (c) 2010 Jiri Svoboda
* 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.
*/
/** @file Integer map.
*
* Maps integers to pointers (void *). Current implementation is trivial
* (linked list of key-value pairs).
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"
#include "mytypes.h"
#include "intmap.h"
/** Initialize map.
*
* @param intmap Map to initialize.
*/
void intmap_init(intmap_t *intmap)
{
list_init(&intmap->elem);
}
/** Deinitialize map.
*
* The map must be already empty.
*
* @param intmap Map to initialize.
*/
void intmap_fini(intmap_t *intmap)
{
list_fini(&intmap->elem);
}
/** Set value corresponding to a key.
*
* If there already exists a mapping for @a key in the map, it is
* silently replaced. If @a value is @c NULL, the mapping for @a key
* is removed from the map.
*
* @param intmap Map
* @param key Key (integer)
* @param value Value (must be a pointer) or @c NULL
*/
void intmap_set(intmap_t *intmap, int key, void *value)
{
list_node_t *node;
map_elem_t *elem;
node = list_first(&intmap->elem);
while (node != NULL) {
elem = list_node_data(node, map_elem_t *);
if (elem->key == key) {
if (value != NULL) {
/* Replace existing value. */
elem->value = value;
} else {
/* Remove map element. */
list_remove(&intmap->elem, node);
free(elem);
}
return;
}
node = list_next(&intmap->elem, node);
}
/* Allocate new map element and add it to the list. */
elem = calloc(1, sizeof(map_elem_t));
if (elem == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
elem->key = key;
elem->value = value;
list_append(&intmap->elem, elem);
}
/** Get value corresponding to a key.
*
* @param intmap Map
* @param key Key for which to retrieve mapping
*
* @return Value correspoding to @a key or @c NULL if no mapping
* exists.
*/
void *intmap_get(intmap_t *intmap, int key)
{
list_node_t *node;
map_elem_t *elem;
node = list_first(&intmap->elem);
while (node != NULL) {
elem = list_node_data(node, map_elem_t *);
if (elem->key == key) {
return elem->value;
}
node = list_next(&intmap->elem, node);
}
/* Not found */
return NULL;
}
/** Get first element in the map.
*
* For iterating over the map, this returns the first element (in no
* particular order).
*
* @param intmap Map
* @return Map element or NULL if the map is empty
*/
map_elem_t *intmap_first(intmap_t *intmap)
{
list_node_t *node;
node = list_first(&intmap->elem);
if (node == NULL)
return NULL;
return list_node_data(node, map_elem_t *);
}
/** Get element key.
*
* Giver a map element, return the key.
*
* @param elem Map element
* @return Key
*/
int intmap_elem_get_key(map_elem_t *elem)
{
return elem->key;
}
/** Get element value.
*
* Giver a map element, return the value.
*
* @param elem Map element
* @return Value
*/
void *intmap_elem_get_value(map_elem_t *elem)
{
return elem->value;
}