diff --git a/debug.h b/debug.h index 15dbfbe..5727347 100644 --- a/debug.h +++ b/debug.h @@ -11,6 +11,20 @@ extern int g_debug_error_abort; extern int g_debug_log_lvl; +#ifdef NDEBUG + +#define LOG_INFO(...) +#define LOG_ERROR(...) +#define LOG_WARNING(...) +#define RETURN_ERROR(...) +#define RETURN_WARNING(...) +#define ASSERT_RETURN(...) +#define CHECK(...) +#define ASSERT_RETURN_WARN(...) +#define UNREACHABLE(...) + +#else + #define LOG_INFO(...) do {\ if(g_debug_log_lvl < 3) break;\ printf("[%s:%d] INFO | ", __FILE__, __LINE__);\ @@ -71,4 +85,6 @@ extern int g_debug_log_lvl; abort();\ } while(0) +#endif + #endif // !CUTES_DEBUG_H diff --git a/hash_map.c b/hash_map.c new file mode 100644 index 0000000..b0341d5 --- /dev/null +++ b/hash_map.c @@ -0,0 +1,66 @@ +#include "hash_map.h" +#include "string.h" +#include "debug.h" + +HashMap hash_map_from_sizes(size_t key, size_t value, HashFunc hasher) { + HashMap self = { + .hasher = hasher, + .key_size = key, + .value_size = value + }; + for(size_t i = 0; i < CUTES_HASH_MAP_BUCKETS; ++i) + self.buckets[i] = list_init(sizeof(uintptr_t) + key + value); + return self; +} + +void hash_map_empty(HashMap *self) { + for(size_t i = 0; i < CUTES_HASH_MAP_BUCKETS; ++i) { + list_empty(self->buckets + i); + } +} + +void *hash_map_get_raw(HashMap *self, void *key) { + uintptr_t hash = self->hasher(key); // hash the key first + List bucket = self->buckets[hash % CUTES_HASH_MAP_BUCKETS]; // get the bucket to search + // linear search through the bucket to find the element + for(size_t i = 0; i < bucket.len; ++i) { + char *key_at = ((char*)bucket.data) + (bucket.element_size * i); + if(memcmp(&hash, key_at, sizeof(uintptr_t)) == 0) { + return key_at + sizeof(uintptr_t) + self->key_size; + } + } + return NULL; +} + +void hash_map_insert(HashMap *self, void *key, void *value) { + uintptr_t hash = self->hasher(key); + // stage key-value-pair data + char data[self->buckets[0].element_size]; + memcpy(data, &hash, sizeof(uintptr_t)); // copy key hash into start of data + memcpy(data + sizeof(uintptr_t), key, self->key_size); // copy key after hash + memcpy(data + sizeof(uintptr_t) + self->key_size, value, self->value_size); // copy value into end of data + // insert staged data into list + list_add(&self->buckets[hash % CUTES_HASH_MAP_BUCKETS], data); +} + +List hash_map_keys(HashMap *self) { + List keys = list_from_type(void*); + for(size_t bucket_index = 0; bucket_index < CUTES_HASH_MAP_BUCKETS; ++bucket_index) { + for(size_t key_index = 0; key_index < self->buckets[bucket_index].len; ++key_index) { + void *key = list_at(self->buckets + bucket_index, key_index) + sizeof(uintptr_t); + list_add(&keys, &key); + } + } + return keys; +} + +List hash_map_values(HashMap *self) { + List values = list_from_type(void*); + for(size_t bucket_index = 0; bucket_index < CUTES_HASH_MAP_BUCKETS; ++bucket_index) { + for(size_t value_index = 0; value_index < self->buckets[bucket_index].len; ++value_index) { + void *value = ((char*)list_at(self->buckets + bucket_index, value_index)) + (sizeof(uintptr_t) + self->key_size); + list_add(&values, &value); + } + } + return values; +} diff --git a/hash_map.h b/hash_map.h new file mode 100644 index 0000000..d40258d --- /dev/null +++ b/hash_map.h @@ -0,0 +1,29 @@ +#ifndef CUTES_HASH_MAP_H +#define CUTES_HASH_MAP_H + +#include "list.h" +#include "stdint.h" +#include "typeclass_helpers.h" + +#define CUTES_HASH_MAP_BUCKETS 24 + +typedef uintptr_t (*HashFunc)(void *data); + +typedef struct HashMap { + List buckets[CUTES_HASH_MAP_BUCKETS]; + HashFunc hasher; + size_t key_size; + size_t value_size; +} HashMap; + +HashMap hash_map_from_sizes(size_t key_size, size_t value_size, HashFunc hasher); +void hash_map_empty(HashMap *self); +void *hash_map_get_raw(HashMap *self, void *key); +void hash_map_insert(HashMap *self, void *key, void *value); +List hash_map_keys(HashMap *self); +List hash_map_values(HashMap *self); + +#define hash_map_from_types(TKey, TValue, KeyHasher) (hash_map_from_sizes(sizeof(TKey), sizeof(TValue), (HashFunc)KeyHasher)); TC_FN_TYPECHECK(uintptr_t, KeyHasher, TKey*) +#define hash_map_get_as(TValue, Self, Key) ((TValue*)hash_map_get_raw(Self, Key)) + +#endif // !CUTES_HASH_MAP_H diff --git a/mirror.h b/mirror.h index a9ac4cd..8816f2e 100644 --- a/mirror.h +++ b/mirror.h @@ -11,7 +11,7 @@ typedef uintptr_t typeid; typedef struct { const char* (*const get_typestring)(void* self); - typeid (*const get_typeid)(void* self); + typeid (*const get_typeid)(); Dictionary* (*const get_typeclasses)(void* self); } IMirror; @@ -30,13 +30,13 @@ typedef struct { } MirroredTypeclass; static inline int mirror_is_typeid(const Mirror* mirror, typeid id) { - return mirror->tc->get_typeid(mirror->data) == id; + return mirror->tc->get_typeid() == id; } static inline int mirror_is_typestring(const Mirror* mirror, const char* id) { return strcmp(id, mirror->tc->get_typestring(mirror->data)) == 0; } static inline int mirror_eq(const Mirror* lhs, const Mirror* rhs) { - return lhs->tc->get_typeid(lhs->data) == rhs->tc->get_typeid(rhs->data); + return lhs->tc == rhs->tc; } extern const void* mirror_get_typeclass(void* data, IMirror const* tc, const char* typeclass); @@ -45,6 +45,8 @@ extern const void* mirror_get_typeclass(void* data, IMirror const* tc, const cha // mirror_get_function(physics_entity.data, physics_entity.mirror, "BehaviourEntity") extern void* mirror_get_function(void* data, IMirror const* tc, const char* typeclass_name); +#define GET_TYPEID(Type__) (Type__##_as_Mirror(NULL).tc->get_typeid()) + // macro reexport of mirror_get_function which will cast the function so it can be called immediately // example: // MIRROR_GET_WRAP_FUNC(physics_entity.data, physics_entity.mirror, BehaviourEntity)(physics_entity.data) @@ -56,26 +58,26 @@ extern void* mirror_get_function(void* data, IMirror const* tc, const char* type // example: // TC_CAST(physics_entity, BehaviourEntity) #define TC_CAST(From_, To_)\ -MIRROR_GET_WRAP_FUNC(From_.data, From_.mirror, To_)(From_.data) +(MIRROR_GET_WRAP_FUNC(From_.data, From_.mirror, To_)(From_.data)) #define TC_MIRRORS(From_, To_)\ -MIRROR_GET_WRAP_FUNC(From_.data, From_.mirror, To_) != NULL +(MIRROR_GET_WRAP_FUNC(From_.data, From_.mirror, To_) != NULL) -#define MIRROR_TRY_WRAP(Into_, Mirror_, Typeclass_){\ +#define MIRROR_TRY_WRAP(Into_, Mirror_, Typeclass_)do{\ MirroredTypeclassWrapFunc fn_ = mirror_get_typeclass(Mirror_, #Typeclass_);\ if(fn_ != NULL) {\ - Into_ = (TypeClass_)fn(Mirror_->data);\ + Into_ = (TypeClass_)fn_(Mirror_->data);\ }\ -} +} while(0) #define impl_Mirror_for(T, get_typestring_f, get_typeid_f, get_typeclasses_f)\ Mirror T##_as_Mirror(T* x) {\ TC_FN_TYPECHECK(const char*, get_typestring_f, T*);\ - TC_FN_TYPECHECK(typeid, get_typeid_f, T*);\ + TC_FN_TYPECHECK(typeid, get_typeid_f);\ TC_FN_TYPECHECK(Dictionary*, get_typeclasses_f, T*);\ static IMirror const tc = {\ .get_typestring = (const char*(*const)(void*)) get_typestring_f,\ - .get_typeid = (typeid (*const)(void*)) get_typeid_f,\ + .get_typeid = (typeid (*const)()) get_typeid_f,\ .get_typeclasses = (Dictionary* (*const)(void*)) get_typeclasses_f,\ };\ return (Mirror){.tc = &tc, .data = x};\ @@ -83,7 +85,7 @@ Mirror T##_as_Mirror(T* x) {\ #define DECL_REFLECT(T)\ extern const char* T##_get_typestring(T* self);\ -extern typeid T##_get_typeid(T* self);\ + extern typeid T##_get_typeid();\ extern Dictionary* T##_get_typeclasses(T* self);\ decl_typeclass_impl(Mirror, T) @@ -92,7 +94,7 @@ const char* T##_get_typestring(T* self) {\ static const char* const typestring = #T;\ return typestring;\ }\ -typeid T##_get_typeid(T* self) {\ +typeid T##_get_typeid() {\ static char init_flag = 0;\ static typeid id = 0;\ if(!init_flag) {\ diff --git a/strutil.c b/strutil.c index c02490f..4c9ef4d 100644 --- a/strutil.c +++ b/strutil.c @@ -2,10 +2,10 @@ #include "string.h" uintptr_t strnhash(const char* s, size_t n) { - static const size_t shift = sizeof(uintptr_t) * 8 - 4; uintptr_t hash = 0; + static size_t const a = 33; for(size_t i = 0; i < n; ++i) { - hash = ((hash << 4) | s[i]) ^ (((uintptr_t)0xF << shift) & hash); + hash = ((hash*a) + s[i]); } return hash; } diff --git a/typeclass_helpers.h b/typeclass_helpers.h index 832fdbe..130ee43 100644 --- a/typeclass_helpers.h +++ b/typeclass_helpers.h @@ -10,6 +10,6 @@ extern __Typeclass __Type##_as_##__Typeclass(__Type*); #define new(T) (malloc(sizeof(T))) #define new_as(T, TC) (T##_as_##TC(new(T))) #define tc_is_null(SELF) (SELF.data == NULL && SELF.tc == NULL) -#define tc_null(TC) (TC){.data=NULL, .tc=NULL} +#define tc_null(TC) ((TC){.data=NULL, .tc=NULL}) #endif // !CUTES_TYPECLASS_HELPERS_H