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_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
 | ||||
|  |  | |||
							
								
								
									
										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 { | ||||
|     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) {\ | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue