#ifndef UTIL_H #define UTIL_H #include #include #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 memory_arena { size_t max_size; void* head; void* next_free; }; #define DEFAULT_ARENA_SIZE 10 * 1024 * 1024 // 10MB memory_arena* arenaInit(size_t initial_size = DEFAULT_ARENA_SIZE); void arenaFree(memory_arena*& arena); uint arenaGetFreeSize(memory_arena* arena); #define ARENA_ALLOC(arena, type, count) \ (type*) arenaAllocateBlock(arena, sizeof(type) * count) void* arenaAllocateBlock(memory_arena* arena, size_t block_size); #define MAX_NAME_LENGTH 256 char* arenaCopyCStr(memory_arena* arena, const char* input, u32 max_len = MAX_NAME_LENGTH); char* utilAllocateCStr(const char* str, u32 max_len = 256); void utilSafeFree(void* p); #endif // UTIL_H #ifdef UTIL_IMPLEMENTATION //----------------- // Hashing uint64_t utilFNV64a_str(const char* str, uint64_t 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 memory_arena* arenaInit(size_t initial_size) { uint sz = sizeof(memory_arena); memory_arena* arena = (memory_arena*) 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(memory_arena*& arena) { if (arena != nullptr) { std::free(arena); arena = nullptr; } } uint arenaGetFreeSize(memory_arena* arena) { return (uint8_t*) arena->head + arena->max_size - (uint8_t*) arena->next_free; } void* arenaAllocateBlock(memory_arena* 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; return ret; } char* arenaCopyCStr(memory_arena* arena, const char* input, u32 max_len) { u32 name_len = std::strlen(input) + 1; assert(name_len < max_len); char* out = ARENA_ALLOC(arena, char, name_len); std::strncpy(out, input, name_len); return out; } char* utilAllocateCStr(const char* str, u32 max_len) { u32 len = strlen(str) + 1; if (len > max_len) { printf("%s(), %s , longer than %i\n", __FUNCTION__, str, max_len); return nullptr; } char* out = (char*) std::calloc(len, sizeof(u8)); strncpy(out, str, len - 1); return out; } void utilSafeFree(void* p) { assert(p != nullptr); free(p); } #endif