Compare commits
No commits in common. "bb201d5085cfb2e54ebad9a0bf22347a5251f7a2" and "a72494b52a790cf9c0e4712ee1f10beea5eafd54" have entirely different histories.
bb201d5085
...
a72494b52a
16
debug.h
16
debug.h
|
@ -11,20 +11,6 @@
|
||||||
extern int g_debug_error_abort;
|
extern int g_debug_error_abort;
|
||||||
extern int g_debug_log_lvl;
|
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 {\
|
#define LOG_INFO(...) do {\
|
||||||
if(g_debug_log_lvl < 3) break;\
|
if(g_debug_log_lvl < 3) break;\
|
||||||
printf("[%s:%d] INFO | ", __FILE__, __LINE__);\
|
printf("[%s:%d] INFO | ", __FILE__, __LINE__);\
|
||||||
|
@ -85,6 +71,4 @@ extern int g_debug_log_lvl;
|
||||||
abort();\
|
abort();\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // !CUTES_DEBUG_H
|
#endif // !CUTES_DEBUG_H
|
||||||
|
|
66
hash_map.c
66
hash_map.c
|
@ -1,66 +0,0 @@
|
||||||
#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;
|
|
||||||
}
|
|
29
hash_map.h
29
hash_map.h
|
@ -1,29 +0,0 @@
|
||||||
#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
|
|
26
mirror.h
26
mirror.h
|
@ -11,7 +11,7 @@ typedef uintptr_t typeid;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* (*const get_typestring)(void* self);
|
const char* (*const get_typestring)(void* self);
|
||||||
typeid (*const get_typeid)();
|
typeid (*const get_typeid)(void* self);
|
||||||
Dictionary* (*const get_typeclasses)(void* self);
|
Dictionary* (*const get_typeclasses)(void* self);
|
||||||
} IMirror;
|
} IMirror;
|
||||||
|
|
||||||
|
@ -30,13 +30,13 @@ typedef struct {
|
||||||
} MirroredTypeclass;
|
} MirroredTypeclass;
|
||||||
|
|
||||||
static inline int mirror_is_typeid(const Mirror* mirror, typeid id) {
|
static inline int mirror_is_typeid(const Mirror* mirror, typeid id) {
|
||||||
return mirror->tc->get_typeid() == id;
|
return mirror->tc->get_typeid(mirror->data) == id;
|
||||||
}
|
}
|
||||||
static inline int mirror_is_typestring(const Mirror* mirror, const char* id) {
|
static inline int mirror_is_typestring(const Mirror* mirror, const char* id) {
|
||||||
return strcmp(id, mirror->tc->get_typestring(mirror->data)) == 0;
|
return strcmp(id, mirror->tc->get_typestring(mirror->data)) == 0;
|
||||||
}
|
}
|
||||||
static inline int mirror_eq(const Mirror* lhs, const Mirror* rhs) {
|
static inline int mirror_eq(const Mirror* lhs, const Mirror* rhs) {
|
||||||
return lhs->tc == rhs->tc;
|
return lhs->tc->get_typeid(lhs->data) == rhs->tc->get_typeid(rhs->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const void* mirror_get_typeclass(void* data, IMirror const* tc, const char* typeclass);
|
extern const void* mirror_get_typeclass(void* data, IMirror const* tc, const char* typeclass);
|
||||||
|
@ -45,8 +45,6 @@ extern const void* mirror_get_typeclass(void* data, IMirror const* tc, const cha
|
||||||
// mirror_get_function(physics_entity.data, physics_entity.mirror, "BehaviourEntity")
|
// mirror_get_function(physics_entity.data, physics_entity.mirror, "BehaviourEntity")
|
||||||
extern void* mirror_get_function(void* data, IMirror const* tc, const char* typeclass_name);
|
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
|
// macro reexport of mirror_get_function which will cast the function so it can be called immediately
|
||||||
// example:
|
// example:
|
||||||
// MIRROR_GET_WRAP_FUNC(physics_entity.data, physics_entity.mirror, BehaviourEntity)(physics_entity.data)
|
// MIRROR_GET_WRAP_FUNC(physics_entity.data, physics_entity.mirror, BehaviourEntity)(physics_entity.data)
|
||||||
|
@ -58,26 +56,26 @@ extern void* mirror_get_function(void* data, IMirror const* tc, const char* type
|
||||||
// example:
|
// example:
|
||||||
// TC_CAST(physics_entity, BehaviourEntity)
|
// TC_CAST(physics_entity, BehaviourEntity)
|
||||||
#define TC_CAST(From_, To_)\
|
#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_)\
|
#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_)do{\
|
#define MIRROR_TRY_WRAP(Into_, Mirror_, Typeclass_){\
|
||||||
MirroredTypeclassWrapFunc fn_ = mirror_get_typeclass(Mirror_, #Typeclass_);\
|
MirroredTypeclassWrapFunc fn_ = mirror_get_typeclass(Mirror_, #Typeclass_);\
|
||||||
if(fn_ != NULL) {\
|
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)\
|
#define impl_Mirror_for(T, get_typestring_f, get_typeid_f, get_typeclasses_f)\
|
||||||
Mirror T##_as_Mirror(T* x) {\
|
Mirror T##_as_Mirror(T* x) {\
|
||||||
TC_FN_TYPECHECK(const char*, get_typestring_f, T*);\
|
TC_FN_TYPECHECK(const char*, get_typestring_f, T*);\
|
||||||
TC_FN_TYPECHECK(typeid, get_typeid_f);\
|
TC_FN_TYPECHECK(typeid, get_typeid_f, T*);\
|
||||||
TC_FN_TYPECHECK(Dictionary*, get_typeclasses_f, T*);\
|
TC_FN_TYPECHECK(Dictionary*, get_typeclasses_f, T*);\
|
||||||
static IMirror const tc = {\
|
static IMirror const tc = {\
|
||||||
.get_typestring = (const char*(*const)(void*)) get_typestring_f,\
|
.get_typestring = (const char*(*const)(void*)) get_typestring_f,\
|
||||||
.get_typeid = (typeid (*const)()) get_typeid_f,\
|
.get_typeid = (typeid (*const)(void*)) get_typeid_f,\
|
||||||
.get_typeclasses = (Dictionary* (*const)(void*)) get_typeclasses_f,\
|
.get_typeclasses = (Dictionary* (*const)(void*)) get_typeclasses_f,\
|
||||||
};\
|
};\
|
||||||
return (Mirror){.tc = &tc, .data = x};\
|
return (Mirror){.tc = &tc, .data = x};\
|
||||||
|
@ -85,7 +83,7 @@ Mirror T##_as_Mirror(T* x) {\
|
||||||
|
|
||||||
#define DECL_REFLECT(T)\
|
#define DECL_REFLECT(T)\
|
||||||
extern const char* T##_get_typestring(T* self);\
|
extern const char* T##_get_typestring(T* self);\
|
||||||
extern typeid T##_get_typeid();\
|
extern typeid T##_get_typeid(T* self);\
|
||||||
extern Dictionary* T##_get_typeclasses(T* self);\
|
extern Dictionary* T##_get_typeclasses(T* self);\
|
||||||
decl_typeclass_impl(Mirror, T)
|
decl_typeclass_impl(Mirror, T)
|
||||||
|
|
||||||
|
@ -94,7 +92,7 @@ const char* T##_get_typestring(T* self) {\
|
||||||
static const char* const typestring = #T;\
|
static const char* const typestring = #T;\
|
||||||
return typestring;\
|
return typestring;\
|
||||||
}\
|
}\
|
||||||
typeid T##_get_typeid() {\
|
typeid T##_get_typeid(T* self) {\
|
||||||
static char init_flag = 0;\
|
static char init_flag = 0;\
|
||||||
static typeid id = 0;\
|
static typeid id = 0;\
|
||||||
if(!init_flag) {\
|
if(!init_flag) {\
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
uintptr_t strnhash(const char* s, size_t n) {
|
uintptr_t strnhash(const char* s, size_t n) {
|
||||||
|
static const size_t shift = sizeof(uintptr_t) * 8 - 4;
|
||||||
uintptr_t hash = 0;
|
uintptr_t hash = 0;
|
||||||
static size_t const a = 33;
|
|
||||||
for(size_t i = 0; i < n; ++i) {
|
for(size_t i = 0; i < n; ++i) {
|
||||||
hash = ((hash*a) + s[i]);
|
hash = ((hash << 4) | s[i]) ^ (((uintptr_t)0xF << shift) & hash);
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@ extern __Typeclass __Type##_as_##__Typeclass(__Type*);
|
||||||
#define new(T) (malloc(sizeof(T)))
|
#define new(T) (malloc(sizeof(T)))
|
||||||
#define new_as(T, TC) (T##_as_##TC(new(T)))
|
#define new_as(T, TC) (T##_as_##TC(new(T)))
|
||||||
#define tc_is_null(SELF) (SELF.data == NULL && SELF.tc == NULL)
|
#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
|
#endif // !CUTES_TYPECLASS_HELPERS_H
|
||||||
|
|
Loading…
Reference in a new issue