m->capacity = (capacity > UDPC_HASHMAP_INIT_CAPACITY ? capacity : UDPC_HASHMAP_INIT_CAPACITY);
m->unitSize = unitSize;
- m->buckets = malloc(sizeof(UDPC_Deque*) * m->capacity);
+ m->buckets = malloc(sizeof(UDPC_HashMap_Node*) * m->capacity);
if(!m->buckets)
{
free(m);
m->buckets[x] = NULL;
continue;
}
- m->buckets[x] = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE * (4 + unitSize));
+ m->buckets[x] = calloc(1, sizeof(UDPC_HashMap_Node));
if(!m->buckets[x])
{
fail = 1;
{
if(m->buckets[x])
{
- UDPC_Deque_destroy(m->buckets[x]);
- }
- }
- free(m->buckets);
- free(m);
- return NULL;
- }
-
- m->overflow = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE * (4 + unitSize));
- if(!m->overflow)
- {
- for(int x = 0; x < m->capacity; ++x)
- {
- if(m->buckets[x])
- {
- UDPC_Deque_destroy(m->buckets[x]);
+ free(m->buckets[x]);
}
}
free(m->buckets);
void UDPC_HashMap_destroy(UDPC_HashMap *hashMap)
{
+ UDPC_HashMap_Node *current;
+ UDPC_HashMap_Node *next;
for(int x = 0; x < hashMap->capacity; ++x)
{
- UDPC_Deque_destroy(hashMap->buckets[x]);
+ current = hashMap->buckets[x];
+ while(current)
+ {
+ next = current->next;
+ if(current->data) { free(current->data); }
+ free(current);
+ current = next;
+ }
}
free(hashMap->buckets);
- UDPC_Deque_destroy(hashMap->overflow);
free(hashMap);
}
uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
- char *temp = malloc(4 + hm->unitSize);
- memcpy(temp, &key, 4);
- if(hm->unitSize > 0)
+ UDPC_HashMap_Node *current = hm->buckets[hash];
+ while(current->next)
{
- memcpy(temp + 4, data, hm->unitSize);
+ current = current->next;
}
-
- if(UDPC_Deque_get_available(hm->buckets[hash]) == 0)
+ current->next = malloc(sizeof(UDPC_HashMap_Node));
+ current->next->key = key;
+ if(hm->unitSize != 0)
{
- if(UDPC_Deque_get_available(hm->overflow) == 0)
- {
- free(temp);
- if(UDPC_HashMap_realloc(hm, hm->capacity * 2) != 0)
- {
- return UDPC_HashMap_INTERNAL_reinsert(hm, key, data);
- }
- else
- {
- return NULL;
- }
- }
- else if(UDPC_Deque_push_back(hm->overflow, temp, 4 + hm->unitSize) == 0)
- {
- free(temp);
- return NULL;
- }
+ current->next->data = malloc(hm->unitSize);
+ memcpy(current->next->data, data, hm->unitSize);
}
- else if(UDPC_Deque_push_back(hm->buckets[hash], temp, 4 + hm->unitSize) == 0)
+ else
{
- free(temp);
- return NULL;
+ current->next->data = NULL;
}
+ current->next->next = NULL;
+ current->next->prev = current;
- free(temp);
++hm->size;
- temp = UDPC_Deque_get_back_ptr(hm->buckets[hash], 4 + hm->unitSize);
- return temp + 4;
+ return current->next->data;
}
int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key)
uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
- for(int x = 0; x * (4 + hm->unitSize) < hm->buckets[hash]->size; ++x)
+ UDPC_HashMap_Node *current = hm->buckets[hash];
+ while(current && (current == hm->buckets[hash] || current->key != key))
{
- if(memcmp(
- UDPC_Deque_index_ptr(hm->buckets[hash], 4 + hm->unitSize, x),
- &key,
- 4) == 0)
- {
- int result = UDPC_Deque_remove(hm->buckets[hash], 4 + hm->unitSize, x);
- if(result != 0)
- {
- --hm->size;
- return 1;
- }
- else
- {
- return 0;
- }
- }
+ current = current->next;
}
- for(int x = 0; x * (4 + hm->unitSize) < hm->overflow->size; ++x)
- {
- if(memcmp(
- UDPC_Deque_index_ptr(hm->overflow, 4 + hm->unitSize, x),
- &key,
- 4) == 0)
- {
- int result = UDPC_Deque_remove(hm->overflow, 4 + hm->unitSize, x);
- if(result != 0)
- {
- --hm->size;
- return 1;
- }
- else
- {
- return 0;
- }
- }
- }
+ if(!current) { return 0; }
+
+ current->prev->next = current->next;
+ if(current->next) { current->next->prev = current->prev; }
- return 0;
+ if(current->data) { free(current->data); }
+ free(current);
+
+ return 1;
}
void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key)
uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
- for(int x = 0; x * (4 + hm->unitSize) < hm->buckets[hash]->size; ++x)
+ UDPC_HashMap_Node *current = hm->buckets[hash];
+ while(current && (current == hm->buckets[hash] || current->key != key))
{
- char *ptr = UDPC_Deque_index_ptr(hm->buckets[hash], 4 + hm->unitSize, x);
- if(memcmp(ptr, &key, 4) == 0)
- {
- if(hm->unitSize > 0)
- {
- return ptr + 4;
- }
- else
- {
- return ptr;
- }
- }
+ current = current->next;
}
- for(int x = 0; x * (4 + hm->unitSize) < hm->overflow->size; ++x)
+ if(!current) { return NULL; }
+
+ return current->data;
+}
+
+int UDPC_HashMap_has(UDPC_HashMap *hm, uint32_t key)
+{
+ if(hm->size == 0)
{
- char *ptr = UDPC_Deque_index_ptr(hm->overflow, 4 + hm->unitSize, x);
- if(memcmp(ptr, &key, 4) == 0)
- {
- if(hm->unitSize > 0)
- {
- return ptr + 4;
- }
- else
- {
- return ptr;
- }
- }
+ return 0;
+ }
+
+ uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
+
+ UDPC_HashMap_Node *current = hm->buckets[hash];
+ while(current && (current == hm->buckets[hash] || current->key != key))
+ {
+ current = current->next;
}
- return NULL;
+ return current != NULL ? 1 : 0;
}
+// TODO change to linkedList buckets up to this point
int UDPC_HashMap_realloc(UDPC_HashMap *hm, uint32_t newCapacity)
{
if(hm->size > newCapacity)
#ifndef UDPC_HASHMAP_H
#define UDPC_HASHMAP_H
+#include <stdint.h>
+
// 5 8 2 7 3 6 1
// 3 2 5 1 8 7 6
#define UDPC_HASH32(x) ( \
)
#define UDPC_HASHMAP_INIT_CAPACITY 13
-#define UDPC_HASHMAP_BUCKET_SIZE 4
#define UDPC_HASHMAP_MOD(k, m) ((UDPC_HASH32(k) % (m * 2 + 1)) % m)
-#include "UDPC_Deque.h"
+struct UDPC_HashMap_Node {
+ uint32_t key;
+ char *data;
+ struct UDPC_HashMap_Node *next;
+ struct UDPC_HashMap_Node *prev;
+};
+typedef struct UDPC_HashMap_Node UDPC_HashMap_Node;
typedef struct {
uint32_t size;
uint32_t capacity;
uint32_t unitSize;
- UDPC_Deque **buckets;
- UDPC_Deque *overflow;
+ UDPC_HashMap_Node **buckets;
} UDPC_HashMap;
/*!
* It is possible to insert items with duplicate keys. In that case, the first
* duplicate inserted will be the first returned with get() and first removed
* with remove().
- * \return Internally managed pointer to inserted data, NULL on fail
+ * \return Pointer to inserted data, NULL on fail or unitSize = 0
*/
void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data);
* Note if unitSize == 0, then the returned pointer will point to a copy of
* its integer key, which should not be changed manually (otherwise, the hash
* map would not be able to find it).
- * \return non-NULL if data was found
+ * \return non-NULL if data was found and unitSize != 0
*/
void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key);
+/*!
+ * \return non-zero if item with specified key is in the hash map
+ */
+int UDPC_HashMap_has(UDPC_HashMap *hm, uint32_t key);
+
/*!
* \brief Resizes the maximum capacity of a hash map
* Note on fail, the hash map is unchanged.