blob: 061a53834c41171e983693b9f648da7aee09b863 [file] [log] [blame]
/*
* mbtk_map.c
*
* Created on: Aug 18, 2020
* Author: lb
*/
#include <stdlib.h>
#include <string.h>
#include "mbtk_map.h"
map_node_t* map_create(uint32 capacity, map_free_func free_func)
{
if (capacity > 0) {
map_node_t *map = (map_node_t*) malloc(sizeof(map_node_t));
if (map) {
memset(map, 0x0, sizeof(map_node_t));
map->size = 0;
map->cur_index = 0;
map->cur_data = NULL;
map->capacity = (uint32) (capacity * 0.75f); // Default 0.75
if(map->capacity < 1) {
free(map);
return NULL;
}
map->free_func = free_func;
map->map_array = (map_data_t**) malloc(
sizeof(map_data_t*) * map->capacity);
uint32 i = 0;
while (i < map->capacity) {
map->map_array[i] = NULL;
i++;
}
return map;
}
}
return NULL;
}
uint32 map_size(map_node_t* map)
{
if (map) {
return map->size;
}
return 0;
}
uint32 map_hash(const char* key, uint32 capacity)
{
uint32 hash = 0;
const uint8 *ptr = (const uint8*) key;
while (*ptr) {
hash = 31 * hash + *ptr;
ptr++;
}
return hash % capacity;
}
void map_put(map_node_t* map, const char* key, void* value)
{
if (map && key && strlen(key) > 0 && value) {
uint32 index = map_hash(key, map->capacity);
map_data_t *ptr = map->map_array[index];
if (!ptr) { // Add to first position.
ptr = (map_data_t*) malloc(sizeof(map_data_t));
ptr->key = strdup(key);
ptr->value = value;
ptr->next = NULL;
map->size++;
map->map_array[index] = ptr;
} else { // This position has one item at least.
if (!memcmp(ptr->key, key, strlen(key))) { // Has this item,will change.
if (map->free_func) {
map->free_func(ptr->value);
}
ptr->value = value;
} else {
while (ptr->next) {
if (!memcmp(ptr->next->key, key, strlen(key))) // Has this item,will change.
break;
ptr = ptr->next;
}
if (!ptr->next) { // Add new item.
ptr->next = (map_data_t*) malloc(sizeof(map_data_t));
ptr->next->key = strdup(key);
ptr->next->value = value;
ptr->next->next = NULL;
map->size++;
} else { // Change item.
if (map->free_func) {
map->free_func(ptr->next->value);
}
ptr->next->value = value;
}
}
}
}
}
void* map_get(map_node_t* map, char* key)
{
if (map && key && strlen(key) > 0) {
uint32 index = map_hash(key, map->capacity);
map_data_t *ptr = map->map_array[index];
while (ptr) {
if (ptr->key && !memcmp(ptr->key, key, strlen(key))) {
return ptr->value;
}
ptr = ptr->next;
}
}
return NULL;
}
void* map_remove(map_node_t* map, char* key)
{
if (map && key && strlen(key) > 0) {
uint32 index = map_hash(key, map->capacity);
map_data_t *ptr = map->map_array[index];
if (!ptr) { // No items.
return NULL;
}
if (!memcmp(ptr->key, key, strlen(key))) { // Is first item
map_data_t *temp = ptr;
void *result = temp->value;
map->map_array[index] = ptr->next;
free(temp);
map->size--;
return result;
} else {
while (ptr->next) {
if (!memcmp(ptr->next->key, key, strlen(key))) {
map_data_t *temp = ptr->next;
void *result = temp->value;
ptr->next = temp->next;
free(temp);
map->size--;
return result;
}
ptr = ptr->next;
}
}
}
return NULL;
}
void map_first(map_node_t *map)
{
if (map) {
map->cur_index = 0;
map->cur_data = map->map_array[0];
}
}
void* map_next(map_node_t *map)
{
if (map) {
while (1) {
if (map->cur_data) {
void *result = map->cur_data;
map->cur_data = map->cur_data->next;
return result;
} else {
map->cur_index++;
if (map->cur_index < map->capacity) {
map->cur_data = map->map_array[map->cur_index];
} else { // Finish
return NULL;
}
}
}
} else {
return NULL;
}
}
void map_clear(map_node_t* map)
{
if (map) {
uint32 i = 0;
map_data_t *ptr = NULL;
while (i < map->capacity) {
ptr = map->map_array[i];
while (ptr) {
map->map_array[i] = ptr->next;
free(ptr->key);
if (map->free_func) {
map->free_func(ptr->value);
}
free(ptr);
ptr = map->map_array[i];
}
i++;
}
map->size = 0;
map->cur_index = 0;
map->cur_data = NULL;
memset(map->map_array, 0x0,
sizeof(sizeof(map_data_t*) * map->capacity));
}
}
void map_free(map_node_t* map)
{
if (map) {
uint32 i = 0;
map_data_t *ptr = NULL;
while (i < map->capacity) {
ptr = map->map_array[i];
while (ptr) {
map->map_array[i] = ptr->next;
free(ptr->key);
if (map->free_func) {
map->free_func(ptr->value);
}
free(ptr);
ptr = map->map_array[i];
}
i++;
}
free(map->map_array);
free(map);
}
}