#ifndef UTIL_H #define UTIL_H #include #include #include #include #include "dumbLog.h" #include "types.h" //----------------- // Hashing // NOTE: FNV1a hashing algorithm http://www.isthe.com/chongo/tech/comp/fnv/ #define FNV1_64_INIT ((u64) 0xcbf29ce484222325ULL) #define FNV_64_PRIME ((u64) 0x100000001b3ULL) u64 utilFNV64a_str(const char* str, u64 hval = FNV1_64_INIT); //----------------- // Memory allocation struct MemoryArena { size_t max_size; size_t free_size; void* head; void* next_free; }; #define DEFAULT_ARENA_SIZE 10 * 1024 * 1024 // 10MB MemoryArena* arenaInit(size_t initial_size = DEFAULT_ARENA_SIZE); void arenaFree(MemoryArena*& arena); u32 arenaGetFreeSize(MemoryArena* arena); #define ARENA_ALLOC(arena, type, count) \ (type*) arenaAllocateBlock(arena, sizeof(type) * count) void* arenaAllocateBlock(MemoryArena* arena, size_t block_size); void* arenaGetAddressOffset(void* address, u32 offset); #define MAX_NAME_LENGTH 256 char* arenaCopyCStr(MemoryArena* arena, const char* input, u32 max_len = MAX_NAME_LENGTH); #define UTIL_ALLOC(count, type) (type*) utilAllocate(count, sizeof(type)) void* utilAllocate(u32 count, u32 type_size); char* utilAllocateCStr(const char* str, u32 max_len = 256); void utilSafeFree(void* p); //--------------- // C string utils bool utilCStrMatch(const char* str1, const char* str2); #endif // UTIL_H #ifdef UTIL_IMPLEMENTATION //----------------- // Hashing u64 utilFNV64a_str(const char* str, u64 hval) { unsigned char* s = (unsigned char *)str; // unsigned string // FNV-1a hash each octet of the string while (*s) { // xor the bottom with the current octet hval ^= (uint64_t)*s++; // multiply by the 64 bit FNV magic prime mod 2^64 hval *= FNV_64_PRIME; } return hval; } //----------------- // Memory allocation MemoryArena* arenaInit(size_t initial_size) { u32 sz = sizeof(MemoryArena); MemoryArena* arena = (MemoryArena*) std::calloc(initial_size + sz, sizeof(u8)); arena->head = arena->next_free = (uint8_t*) arena + sz; arena->max_size = initial_size; return arena; } void arenaFree(MemoryArena*& arena) { if (arena != nullptr) { std::free(arena); arena = nullptr; } } uint arenaGetFreeSize(MemoryArena* arena) { return (uint8_t*) arena->head + arena->max_size - (uint8_t*) arena->next_free; } void* arenaAllocateBlock(MemoryArena* arena, size_t block_size) { // TODO: resizable memory arena assert(arenaGetFreeSize(arena) >= block_size); assert(block_size > 0); void* ret = arena->next_free; arena->next_free = (uint8_t*) arena->next_free + block_size; arena->free_size = arenaGetFreeSize(arena); return ret; } void* arenaGetAddressOffset(void* address, u32 offset) { return (void*) ((u8*) address + offset); } char* arenaCopyCStr(MemoryArena* arena, const char* input, u32 max_len) { u32 name_len = std::strlen(input) + 1; assert(name_len > 1 && name_len < max_len); char* out = ARENA_ALLOC(arena, char, name_len); std::strncpy(out, input, name_len); return out; } void* utilAllocate(u32 count, u32 type_size) { void* out = std::calloc(count, type_size); assert(out != nullptr); return out; } char* utilAllocateCStr(const char* str, u32 max_len) { u32 len = strlen(str) + 1; if (len > max_len) { LOGF(Error, "%s , longer than %i\n", str, max_len); return nullptr; } char* out = (char*) std::calloc(len, sizeof(u8)); strncpy(out, str, len - 1); return out; } void utilSafeFree(void* p) { if (p) free(p); else LOGF(Error, "free called on nullptr\n"); } //--------------- // C string utils bool utilCStrMatch(const char* str1, const char* str2) { if (!str1 || !str2) return false; u32 l1 = strlen(str1); u32 l2 = strlen(str2); return (l1 == l2 && strncmp(str1, str2, l1) == 0); } #endif