| /* |
| * 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); |
| } |
| } |
| |