Compare commits
No commits in common. "b443367f46f127d50b9dd59a3936c83c228f71bb" and "823223ffa7f820ad24b5972a5067a91bcfc91749" have entirely different histories.
b443367f46
...
823223ffa7
@ -1,24 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../std.h"
|
#include "../std.h"
|
||||||
|
|
||||||
#define Array_construct(T, DATA, LEN) ((Array_##T){ .data = DATA, .len = LEN })
|
|
||||||
|
|
||||||
/// creates Array_##T from a const array
|
|
||||||
#define ARRAY(T, A...) Array_construct(T, ((u32[])A), ARRAY_SIZE(((u32[])A)))
|
|
||||||
|
|
||||||
#define Array_declare(T)\
|
#define Array_declare(T)\
|
||||||
typedef struct Array_##T {\
|
typedef struct Array_##T {\
|
||||||
T* data;\
|
T* data;\
|
||||||
u32 len;\
|
u32 len;\
|
||||||
} Array_##T;\
|
} Array_##T;\
|
||||||
\
|
\
|
||||||
|
static inline Array_##T Array_##T##_construct(T* data_ptr, u32 len) {\
|
||||||
|
return (Array_##T){ .data = data_ptr, .len = len };\
|
||||||
|
}\
|
||||||
|
\
|
||||||
static inline Array_##T Array_##T##_alloc(u32 len){\
|
static inline Array_##T Array_##T##_alloc(u32 len){\
|
||||||
return Array_construct(T, (T*)malloc(len * sizeof(T)), len);\
|
return Array_##T##_construct((T*)malloc(len * sizeof(T)), len);\
|
||||||
}\
|
}\
|
||||||
static inline void Array_##T##_realloc(Array_##T* ptr, u32 new_len){\
|
static inline void Array_##T##_realloc(Array_##T* ptr, u32 new_len){\
|
||||||
ptr->data = (T*)realloc(ptr->data, new_len * sizeof(T));\
|
ptr->data = (T*)realloc(ptr->data, new_len * sizeof(T));\
|
||||||
ptr->len = new_len;\
|
ptr->len = new_len;\
|
||||||
}
|
}
|
||||||
|
|
||||||
Array_declare(u8)
|
|
||||||
Array_declare(u32)
|
|
||||||
|
|||||||
@ -1,139 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "../std.h"
|
|
||||||
#include "../string/str.h"
|
|
||||||
#include "Array.h"
|
|
||||||
|
|
||||||
//TODO: sorting of bucket and binary search
|
|
||||||
//TODO: delayed deletion
|
|
||||||
|
|
||||||
#define __HashMap_HASH_FUNC str_hash32
|
|
||||||
#define __HashMapBucket_MAX_LEN 16
|
|
||||||
|
|
||||||
#define HashMap_DESTROY_VALUE_FUNC_NULL ((void (*)(void*))NULL)
|
|
||||||
|
|
||||||
/// call this in a header file
|
|
||||||
///@param T Value type
|
|
||||||
#define HashMap_declare(T)\
|
|
||||||
typedef struct KeyValue_##T {\
|
|
||||||
str key;\
|
|
||||||
T value;\
|
|
||||||
u32 hash;\
|
|
||||||
} KeyValue_##T;\
|
|
||||||
\
|
|
||||||
List_declare(KeyValue_##T);\
|
|
||||||
\
|
|
||||||
typedef struct HashMapBucket_##T {\
|
|
||||||
List_KeyValue_##T kvs;\
|
|
||||||
} HashMapBucket_##T;\
|
|
||||||
\
|
|
||||||
typedef struct HashMap_##T {\
|
|
||||||
HashMapBucket_##T* table;\
|
|
||||||
u32 height;\
|
|
||||||
u16 height_n;\
|
|
||||||
} HashMap_##T;\
|
|
||||||
\
|
|
||||||
void HashMap_##T##_alloc(HashMap_##T* ptr);\
|
|
||||||
void HashMap_##T##_free(HashMap_##T* ptr);\
|
|
||||||
NULLABLE(T*) HashMap_##T##_tryGetPtr(HashMap_##T* ptr, str key);\
|
|
||||||
bool HashMap_##T##_tryPush(HashMap_##T* ptr, str key, T value);\
|
|
||||||
bool HashMap_##T##_tryDelete(HashMap_##T* ptr, str key);\
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// call this in a source code file
|
|
||||||
///@param T Value type
|
|
||||||
///@param DESTROY_VALUE_FUNC `void foo (T*)` or HashMap_DESTROY_VALUE_FUNC_NULL
|
|
||||||
#define HashMap_define(T, DESTROY_VALUE_FUNC)\
|
|
||||||
List_define(KeyValue_##T);\
|
|
||||||
\
|
|
||||||
static const Array_u32 __HashMap_##T##_heights = ARRAY(u32, {\
|
|
||||||
17, 31, 61, 127, 257, 521, 1021, 2053, 4099, 8191, 16381, 32771,\
|
|
||||||
65521, 131071, 262147, 524287, 1048583, 2097169, 4194319,\
|
|
||||||
8388617, 16777213, 33554467, 67108859, 134217757, 268435493\
|
|
||||||
});\
|
|
||||||
\
|
|
||||||
void HashMap_##T##_alloc(HashMap_##T* ptr){\
|
|
||||||
ptr->height_n = 0;\
|
|
||||||
ptr->height = __HashMap_##T##_heights.data[0];\
|
|
||||||
ptr->table = (HashMapBucket_##T*)malloc(ptr->height * sizeof(HashMapBucket_##T));\
|
|
||||||
memset(ptr->table, 0, ptr->height * sizeof(HashMapBucket_##T));\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
void HashMap_##T##_free(HashMap_##T* ptr){\
|
|
||||||
for(u32 i = 0; i < ptr->height; i++){\
|
|
||||||
for(u32 j = 0; j < ptr->table[i].kvs.len; j++){\
|
|
||||||
KeyValue_##T* kv_ptr = &ptr->table[i].kvs.data[j];\
|
|
||||||
if(DESTROY_VALUE_FUNC){\
|
|
||||||
DESTROY_VALUE_FUNC(&kv_ptr->value);\
|
|
||||||
}\
|
|
||||||
free(kv_ptr->key.data);\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
free(ptr->table[i].kvs.data);\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
free(ptr->table);\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
NULLABLE(T*) HashMap_##T##_tryGetPtr(HashMap_##T* ptr, str key){\
|
|
||||||
u32 hash = __HashMap_HASH_FUNC(key);\
|
|
||||||
HashMapBucket_##T* bu = &ptr->table[hash % ptr->height];\
|
|
||||||
for(u32 i = 0; i < bu->kvs.len; i++){\
|
|
||||||
if(bu->kvs.data[i].hash == hash && str_equals(bu->kvs.data[i].key, key)){\
|
|
||||||
return &bu->kvs.data[i].value;\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
return NULL;\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
bool HashMap_##T##_tryPush(HashMap_##T* ptr, str key, T value){\
|
|
||||||
u32 hash = __HashMap_HASH_FUNC(key);\
|
|
||||||
HashMapBucket_##T* bu = &ptr->table[hash % ptr->height];\
|
|
||||||
for(u32 i = 0; i < bu->kvs.len; i++){\
|
|
||||||
if(bu->kvs.data[i].hash == hash && str_equals(bu->kvs.data[i].key, key)){\
|
|
||||||
return false;\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
if(bu->kvs.len >= __HashMapBucket_MAX_LEN){\
|
|
||||||
u32 height_expanded_n = ptr->height_n + 1;\
|
|
||||||
if(height_expanded_n >= __HashMap_u32_heights.len){\
|
|
||||||
printf("ERROR: HashMap_" #T " IS FULL\n");\
|
|
||||||
return false;\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
u32 height_expanded = __HashMap_##T##_heights.data[height_expanded_n];\
|
|
||||||
HashMapBucket_##T* table_expanded = (HashMapBucket_##T*)malloc(height_expanded * sizeof(HashMapBucket_##T));\
|
|
||||||
memset(table_expanded, 0, height_expanded * sizeof(HashMapBucket_##T));\
|
|
||||||
for(u32 i = 0; i < height_expanded; i++){\
|
|
||||||
for(u32 j = 0; j < ptr->table[i].kvs.len; j++){\
|
|
||||||
KeyValue_##T kv = ptr->table[i].kvs.data[j];\
|
|
||||||
List_KeyValue_##T##_push(&table_expanded[kv.hash % height_expanded].kvs, kv);\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
free(ptr->table[i].kvs.data);\
|
|
||||||
}\
|
|
||||||
free(ptr->table);\
|
|
||||||
ptr->table = table_expanded;\
|
|
||||||
ptr->height = height_expanded;\
|
|
||||||
ptr->height_n = height_expanded_n;\
|
|
||||||
bu = &ptr->table[hash % ptr->height];\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
KeyValue_##T kv = { .key = str_copy(key), .value = value, .hash = hash };\
|
|
||||||
List_KeyValue_##T##_push(&bu->kvs, kv);\
|
|
||||||
return true;\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
bool HashMap_##T##_tryDelete(HashMap_##T* ptr, str key){\
|
|
||||||
u32 hash = __HashMap_HASH_FUNC(key);\
|
|
||||||
HashMapBucket_##T* bu = &ptr->table[hash % ptr->height];\
|
|
||||||
for(u32 i = 0; i < bu->kvs.len; i++){\
|
|
||||||
if(bu->kvs.data[i].hash == hash && str_equals(bu->kvs.data[i].key, key)){\
|
|
||||||
return List_KeyValue_##T##_tryRemoveAt(&bu->kvs, i);\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
return false;\
|
|
||||||
}
|
|
||||||
@ -20,7 +20,6 @@
|
|||||||
T* List_##T##_expand(List_##T* ptr, u32 count);\
|
T* List_##T##_expand(List_##T* ptr, u32 count);\
|
||||||
void List_##T##_push(List_##T* ptr, T value);\
|
void List_##T##_push(List_##T* ptr, T value);\
|
||||||
void List_##T##_pushMany(List_##T* ptr, T* values, u32 count);\
|
void List_##T##_pushMany(List_##T* ptr, T* values, u32 count);\
|
||||||
bool List_##T##_tryRemoveAt(List_##T* ptr, u32 i);\
|
|
||||||
|
|
||||||
|
|
||||||
#define List_define(T)\
|
#define List_define(T)\
|
||||||
@ -53,17 +52,6 @@
|
|||||||
T* empty_cell_ptr = List_##T##_expand(ptr, count);\
|
T* empty_cell_ptr = List_##T##_expand(ptr, count);\
|
||||||
memcpy(empty_cell_ptr, values, count * sizeof(T));\
|
memcpy(empty_cell_ptr, values, count * sizeof(T));\
|
||||||
}\
|
}\
|
||||||
\
|
|
||||||
bool List_##T##_tryRemoveAt(List_##T* ptr, u32 i){\
|
|
||||||
if(ptr->len == 0 || i >= ptr->len)\
|
|
||||||
return false;\
|
|
||||||
\
|
|
||||||
ptr->len--;\
|
|
||||||
for(; i < ptr->len; i++){\
|
|
||||||
ptr->data[i] = ptr->data[i + 1];\
|
|
||||||
}\
|
|
||||||
return true;\
|
|
||||||
}\
|
|
||||||
|
|
||||||
|
|
||||||
List_declare(u32);
|
List_declare(u32);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ typedef u8 bool;
|
|||||||
|
|
||||||
typedef const char* cstr;
|
typedef const char* cstr;
|
||||||
|
|
||||||
#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
|
#define ARRAY_SIZE(A) sizeof(A)/sizeof(A[0])
|
||||||
#define ALIGN_TO(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1))
|
#define ALIGN_TO(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1))
|
||||||
|
|
||||||
#define __count_args( \
|
#define __count_args( \
|
||||||
|
|||||||
@ -97,12 +97,3 @@ bool str_endsWith(str src, str fragment){
|
|||||||
src.len = fragment.len;
|
src.len = fragment.len;
|
||||||
return str_equals(src, fragment);
|
return str_equals(src, fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 str_hash32(str s){
|
|
||||||
u8* ubuf = (u8*)s.data;
|
|
||||||
u32 len = s.len;
|
|
||||||
u32 hash=0;
|
|
||||||
for (u32 i = 0; i < len; i++)
|
|
||||||
hash = (hash<<6) + (hash<<16) - hash + ubuf[i];
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ typedef struct str {
|
|||||||
bool isZeroTerminated;
|
bool isZeroTerminated;
|
||||||
} str;
|
} str;
|
||||||
|
|
||||||
/// creates str from a string literal
|
// creates str from a string literal
|
||||||
#define STR(LITERAL) str_construct(LITERAL, ARRAY_SIZE(LITERAL) - 1, true)
|
#define STR(LITERAL) str_construct(LITERAL, ARRAY_SIZE(LITERAL) - 1, true)
|
||||||
|
|
||||||
#define str_construct(DATA, LEN, ZERO_TERMINATED) ((str){ .data = DATA, .len = LEN, .isZeroTerminated = ZERO_TERMINATED })
|
#define str_construct(DATA, LEN, ZERO_TERMINATED) ((str){ .data = DATA, .len = LEN, .isZeroTerminated = ZERO_TERMINATED })
|
||||||
@ -32,7 +32,3 @@ i32 str_seekCharReverse(str src, char c, u32 startIndex);
|
|||||||
|
|
||||||
bool str_startsWith(str src, str fragment);
|
bool str_startsWith(str src, str fragment);
|
||||||
bool str_endsWith(str src, str fragment);
|
bool str_endsWith(str src, str fragment);
|
||||||
|
|
||||||
/// @brief calculates string hash using sdbm32 algorythm (something like lightweight crc32)
|
|
||||||
/// @return non-cryptografic hash of the string
|
|
||||||
u32 str_hash32(str s);
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user