Compare commits
	
		
			10 commits
		
	
	
		
			a72494b52a
			...
			bb201d5085
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | bb201d5085 | ||
|   | 96323d7abc | ||
|   | faf0463e37 | ||
|   | e99e391ffa | ||
|   | 2021092a17 | ||
|   | bb6dcbeabe | ||
|   | af50174b71 | ||
|   | c4ec92fa82 | ||
|   | 172d1ee10e | ||
|   | eab5961989 | 
							
								
								
									
										16
									
								
								debug.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								debug.h
									
									
									
									
									
								
							|  | @ -11,6 +11,20 @@ | ||||||
| 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__);\ | ||||||
|  | @ -71,4 +85,6 @@ 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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								hash_map.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								hash_map.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								hash_map.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -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
 | ||||||
							
								
								
									
										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)(void* self); |     typeid (*const get_typeid)(); | ||||||
|     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(mirror->data) == id; |     return mirror->tc->get_typeid() == 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->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); | 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")
 | // 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)
 | ||||||
|  | @ -56,26 +58,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_){\ | #define MIRROR_TRY_WRAP(Into_, Mirror_, Typeclass_)do{\ | ||||||
|     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, T*);\ |     TC_FN_TYPECHECK(typeid, get_typeid_f);\ | ||||||
|     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)(void*)) get_typeid_f,\ |         .get_typeid = (typeid (*const)()) 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};\ | ||||||
|  | @ -83,7 +85,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(T* self);\ |     extern typeid T##_get_typeid();\ | ||||||
| extern Dictionary* T##_get_typeclasses(T* self);\ | extern Dictionary* T##_get_typeclasses(T* self);\ | ||||||
| decl_typeclass_impl(Mirror, T) | decl_typeclass_impl(Mirror, T) | ||||||
| 
 | 
 | ||||||
|  | @ -92,7 +94,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(T* self) {\ | typeid T##_get_typeid() {\ | ||||||
|     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 << 4) | s[i]) ^ (((uintptr_t)0xF << shift) & hash); |         hash = ((hash*a) + s[i]); | ||||||
|     } |     } | ||||||
|     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