liubin | 281ac46 | 2023-07-19 14:22:54 +0800 | [diff] [blame] | 1 | /* |
| 2 | * mbtk_map.c |
| 3 | * |
| 4 | * Created on: Aug 18, 2020 |
| 5 | * Author: lb |
| 6 | */ |
| 7 | #include <stdlib.h> |
| 8 | #include <string.h> |
| 9 | #include "mbtk_map.h" |
| 10 | |
| 11 | map_node_t* map_create(uint32 capacity, map_free_func free_func) |
| 12 | { |
| 13 | if (capacity > 0) { |
| 14 | map_node_t *map = (map_node_t*) malloc(sizeof(map_node_t)); |
| 15 | if (map) { |
| 16 | memset(map, 0x0, sizeof(map_node_t)); |
| 17 | map->size = 0; |
| 18 | map->cur_index = 0; |
| 19 | map->cur_data = NULL; |
| 20 | map->capacity = (uint32) (capacity * 0.75f); // Default 0.75 |
| 21 | if(map->capacity < 1) { |
| 22 | free(map); |
| 23 | return NULL; |
| 24 | } |
| 25 | map->free_func = free_func; |
| 26 | map->map_array = (map_data_t**) malloc( |
| 27 | sizeof(map_data_t*) * map->capacity); |
| 28 | uint32 i = 0; |
| 29 | while (i < map->capacity) { |
| 30 | map->map_array[i] = NULL; |
| 31 | i++; |
| 32 | } |
| 33 | return map; |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | return NULL; |
| 38 | } |
| 39 | |
| 40 | uint32 map_size(map_node_t* map) |
| 41 | { |
| 42 | if (map) { |
| 43 | return map->size; |
| 44 | } |
| 45 | |
| 46 | return 0; |
| 47 | } |
| 48 | |
| 49 | uint32 map_hash(const char* key, uint32 capacity) |
| 50 | { |
| 51 | uint32 hash = 0; |
| 52 | const uint8 *ptr = (const uint8*) key; |
| 53 | while (*ptr) { |
| 54 | hash = 31 * hash + *ptr; |
| 55 | ptr++; |
| 56 | } |
| 57 | |
| 58 | return hash % capacity; |
| 59 | } |
| 60 | |
| 61 | void map_put(map_node_t* map, const char* key, void* value) |
| 62 | { |
| 63 | if (map && key && strlen(key) > 0 && value) { |
| 64 | uint32 index = map_hash(key, map->capacity); |
| 65 | |
| 66 | map_data_t *ptr = map->map_array[index]; |
| 67 | if (!ptr) { // Add to first position. |
| 68 | ptr = (map_data_t*) malloc(sizeof(map_data_t)); |
| 69 | ptr->key = strdup(key); |
| 70 | ptr->value = value; |
| 71 | ptr->next = NULL; |
| 72 | |
| 73 | map->size++; |
| 74 | map->map_array[index] = ptr; |
| 75 | } else { // This position has one item at least. |
| 76 | if (!memcmp(ptr->key, key, strlen(key))) { // Has this item,will change. |
| 77 | if (map->free_func) { |
| 78 | map->free_func(ptr->value); |
| 79 | } |
| 80 | |
| 81 | ptr->value = value; |
| 82 | } else { |
| 83 | while (ptr->next) { |
| 84 | if (!memcmp(ptr->next->key, key, strlen(key))) // Has this item,will change. |
| 85 | break; |
| 86 | ptr = ptr->next; |
| 87 | } |
| 88 | |
| 89 | if (!ptr->next) { // Add new item. |
| 90 | ptr->next = (map_data_t*) malloc(sizeof(map_data_t)); |
| 91 | |
| 92 | ptr->next->key = strdup(key); |
| 93 | ptr->next->value = value; |
| 94 | ptr->next->next = NULL; |
| 95 | map->size++; |
| 96 | } else { // Change item. |
| 97 | if (map->free_func) { |
| 98 | map->free_func(ptr->next->value); |
| 99 | } |
| 100 | |
| 101 | ptr->next->value = value; |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | void* map_get(map_node_t* map, char* key) |
| 109 | { |
| 110 | if (map && key && strlen(key) > 0) { |
| 111 | uint32 index = map_hash(key, map->capacity); |
| 112 | map_data_t *ptr = map->map_array[index]; |
| 113 | while (ptr) { |
| 114 | if (ptr->key && !memcmp(ptr->key, key, strlen(key))) { |
| 115 | return ptr->value; |
| 116 | } |
| 117 | ptr = ptr->next; |
| 118 | } |
| 119 | } |
| 120 | return NULL; |
| 121 | } |
| 122 | |
| 123 | void* map_remove(map_node_t* map, char* key) |
| 124 | { |
| 125 | if (map && key && strlen(key) > 0) { |
| 126 | uint32 index = map_hash(key, map->capacity); |
| 127 | map_data_t *ptr = map->map_array[index]; |
| 128 | if (!ptr) { // No items. |
| 129 | return NULL; |
| 130 | } |
| 131 | |
| 132 | if (!memcmp(ptr->key, key, strlen(key))) { // Is first item |
| 133 | map_data_t *temp = ptr; |
| 134 | void *result = temp->value; |
| 135 | map->map_array[index] = ptr->next; |
| 136 | free(temp); |
| 137 | map->size--; |
| 138 | |
| 139 | return result; |
| 140 | } else { |
| 141 | while (ptr->next) { |
| 142 | if (!memcmp(ptr->next->key, key, strlen(key))) { |
| 143 | map_data_t *temp = ptr->next; |
| 144 | void *result = temp->value; |
| 145 | ptr->next = temp->next; |
| 146 | free(temp); |
| 147 | map->size--; |
| 148 | |
| 149 | return result; |
| 150 | } |
| 151 | ptr = ptr->next; |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | return NULL; |
| 156 | } |
| 157 | |
| 158 | void map_first(map_node_t *map) |
| 159 | { |
| 160 | if (map) { |
| 161 | map->cur_index = 0; |
| 162 | map->cur_data = map->map_array[0]; |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | void* map_next(map_node_t *map) |
| 167 | { |
| 168 | if (map) { |
| 169 | while (1) { |
| 170 | if (map->cur_data) { |
| 171 | void *result = map->cur_data; |
| 172 | map->cur_data = map->cur_data->next; |
| 173 | return result; |
| 174 | } else { |
| 175 | map->cur_index++; |
| 176 | if (map->cur_index < map->capacity) { |
| 177 | map->cur_data = map->map_array[map->cur_index]; |
| 178 | } else { // Finish |
| 179 | return NULL; |
| 180 | } |
| 181 | } |
| 182 | } |
| 183 | } else { |
| 184 | return NULL; |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | void map_clear(map_node_t* map) |
| 189 | { |
| 190 | if (map) { |
| 191 | uint32 i = 0; |
| 192 | map_data_t *ptr = NULL; |
| 193 | while (i < map->capacity) { |
| 194 | ptr = map->map_array[i]; |
| 195 | while (ptr) { |
| 196 | map->map_array[i] = ptr->next; |
| 197 | |
| 198 | free(ptr->key); |
| 199 | if (map->free_func) { |
| 200 | map->free_func(ptr->value); |
| 201 | } |
| 202 | free(ptr); |
| 203 | |
| 204 | ptr = map->map_array[i]; |
| 205 | } |
| 206 | i++; |
| 207 | } |
| 208 | |
| 209 | map->size = 0; |
| 210 | map->cur_index = 0; |
| 211 | map->cur_data = NULL; |
| 212 | memset(map->map_array, 0x0, |
| 213 | sizeof(sizeof(map_data_t*) * map->capacity)); |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | void map_free(map_node_t* map) |
| 218 | { |
| 219 | if (map) { |
| 220 | uint32 i = 0; |
| 221 | map_data_t *ptr = NULL; |
| 222 | while (i < map->capacity) { |
| 223 | ptr = map->map_array[i]; |
| 224 | while (ptr) { |
| 225 | map->map_array[i] = ptr->next; |
| 226 | |
| 227 | free(ptr->key); |
| 228 | if (map->free_func) { |
| 229 | map->free_func(ptr->value); |
| 230 | } |
| 231 | free(ptr); |
| 232 | |
| 233 | ptr = map->map_array[i]; |
| 234 | } |
| 235 | i++; |
| 236 | } |
| 237 | |
| 238 | free(map->map_array); |
| 239 | free(map); |
| 240 | } |
| 241 | } |
| 242 | |