A small OpenGL 3+ renderer and game engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

197 lines
4.2 KiB

#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include "dumbLog.h"
#include "util.h"
const uint MAX_FILESIZE = 2 * 1024 * 1024; // 2MB
const uint MAX_STRING_LENGTH = 1024;
//-----------------
// C Strings
const char*
utilBaseName(const char* path_str)
{
assert(std::strlen(path_str) < MAX_STRING_LENGTH);
const char* output = std::strrchr(path_str, '/');
if (output)
return output;
else
return path_str;
}
bool
utilCopyCStr(char* dest, const char* src, uint max_len)
{
assert(std::strlen(src) < MAX_STRING_LENGTH && max_len <= MAX_STRING_LENGTH);
if (std::strlen(src) + 1 > max_len)
return false;
std::memcpy(dest, src, std::strlen(src) + 1);
return true;
}
char*
utilConcatPath(char* out, const char* base_dir, const char* file_name, uint max_len)
{
size_t l1 = std::strlen(base_dir);
size_t l2 = std::strlen(file_name);
size_t padded = l1 + l2 + 2; // NOTE: null term + '/'
assert(padded <= MAX_STRING_LENGTH && padded <= max_len);
int c = std::snprintf(out, padded, "%s/%s", base_dir, file_name);
assert(c > 0);
return out;
}
bool
utilMatchPrefix(const char* lhs, const char* rhs, int sz)
{
int rc = strncmp(lhs, rhs, sz);
return (rc >= 0);
}
//-----------------
// 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
void *
utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line)
{
assert(item_count > 0); // that was a fun bug
void* mem = std::calloc(item_count, type_size);
if (mem == nullptr) {
LOG(Error) << "Memory allocation failed, called from "
<< file_name << ":" << line;
}
assert(mem != nullptr); // might as well stop execution here
return mem;
}
void
utilSafeFree(const void* mem)
{
if (mem != nullptr) std::free((void *) mem);
}
memory_arena*
arenaInit(size_t initial_size)
{
uint sz = sizeof(memory_arena);
memory_arena* arena =
(memory_arena*) UTIL_ALLOC(initial_size + sz, uint8_t);
arena->head = arena->next_free = (uint8_t*) arena + sz;
arena->max_size = initial_size;
return arena;
}
void
arenaFree(memory_arena*& arena)
{
utilSafeFree(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);
void* ret = arena->next_free;
arena->next_free = (uint8_t*) arena->next_free + block_size;
return ret;
}
//-----------------
// File I/O
// TODO: don't use ftell() to get filesize
// https://wiki.sei.cmu.edu/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file
char *
utilDumpTextFile(const char* filename)
{
LOG(Info) << "loading filename, " << filename << "\n";
std::FILE* fp = std::fopen(filename, "rt");
assert(fp);
std::fseek(fp, 0, SEEK_END);
uint length = std::ftell(fp);
std::fseek(fp, 0, SEEK_SET);
assert(length < MAX_FILESIZE);
// TODO: check error codes for fseek and ftell
char* buf = UTIL_ALLOC(length, char);
assert(buf);
std::fread(buf, sizeof(char), length, fp);
// TODO: check fp w/ ferror() here
return buf;
}
// TODO: might want to do the base_dir concat in this function to prevent clobbering
// user files on accident
bool
utilWriteTextFile(const char* filename, const char* text)
{
size_t text_len = std::strlen(text);
if (text_len >= MAX_FILESIZE) {
LOG(Error) << "that string is too big\n";
return false;
}
std::FILE* fp = fopen(filename, "wt");
if (fp) {
size_t written = fwrite(text, sizeof(char), text_len, fp);
fclose(fp);
if (written == text_len) {
LOG(Debug) << "successfuly wrote " << written << " bytes\n";
return true;
} else {
LOG(Error) << "error writing to file: " << filename << "\n";
return false;
}
}
LOG(Debug) << text << "\n";
return false;
}