657 lines
17 KiB
C
657 lines
17 KiB
C
/* gb.h - v0.01 - public domain C89/C99 helper library - no warranty implied; use at your own risk */
|
|
/* (Experimental) A C89/99 helper library geared towards game development */
|
|
|
|
/*
|
|
* LICENSE
|
|
* This software is in the public domain. Where that dedication is not
|
|
* recognized, you are granted a perpetual, irrevocable license to copy,
|
|
* distribute, and modify this file as you see fit.
|
|
*
|
|
* WARNING
|
|
* - This library is _highly_ experimental and features may not work as expected.
|
|
* - This also means that many functions are not documented.
|
|
*
|
|
*/
|
|
|
|
#ifndef GB_INCLUDE_GB_H
|
|
#define GB_INCLUDE_GB_H
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif /* extern "C" */
|
|
|
|
/* NOTE(bill): Because static means three different things in C/C++
|
|
* Great Design(!)
|
|
*/
|
|
#ifndef global_variable
|
|
#define global_variable static
|
|
#define internal_linkage static
|
|
#define local_persist static
|
|
#endif
|
|
|
|
/* Example for static defines
|
|
|
|
global_variable const f32 TAU = 6.283185f;
|
|
global_variable void* g_memory;
|
|
|
|
internal_linkage void
|
|
some_function(...)
|
|
{
|
|
local_persist u32 count = 0;
|
|
...
|
|
count++;
|
|
...
|
|
}
|
|
*/
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
#define _ALLOW_KEYWORD_MACROS
|
|
|
|
#ifndef alignof /* Needed for MSVC 2013 'cause Microsoft "loves" standards */
|
|
#define alignof(x) __alignof(x)
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
* System OS
|
|
*/
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#ifndef GB_SYSTEM_WINDOWS
|
|
#define GB_SYSTEM_WINDOWS 1
|
|
#endif
|
|
#elif defined(__APPLE__) && defined(__MACH__)
|
|
#ifndef GB_SYSTEM_OSX
|
|
#define GB_SYSTEM_OSX 1
|
|
#endif
|
|
#elif defined(__unix__)
|
|
#ifndef GB_SYSTEM_UNIX
|
|
#define GB_SYSTEM_UNIX 1
|
|
#endif
|
|
|
|
#if defined(__linux__)
|
|
#ifndef GB_SYSTEM_LINUX
|
|
#define GB_SYSTEM_LINUX 1
|
|
#endif
|
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
#ifndef GB_SYSTEM_FREEBSD
|
|
#define GB_SYSTEM_FREEBSD 1
|
|
#endif
|
|
#else
|
|
#error This UNIX operating system is not supported by gb.hpp
|
|
#endif
|
|
#else
|
|
#error This operating system is not supported by gb.hpp
|
|
#endif
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
/* Microsoft Visual Studio */
|
|
#define GB_COMPILER_MSVC 1
|
|
#elif defined(__clang__)
|
|
/* Clang */
|
|
#define GB_COMPILER_CLANG 1
|
|
#elif defined(__GNUC__) || defined(__GNUG__) && !(defined(__clang__) || defined(__INTEL_COMPILER))
|
|
/* GNU GCC/G++ Compiler */
|
|
#define GB_COMPILER_GNU_GCC 1
|
|
#elif defined(__INTEL_COMPILER)
|
|
/* Intel C++ Compiler */
|
|
#define GB_COMPILER_INTEL 1
|
|
#endif
|
|
|
|
/* Environment Bit Size */
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#if defined(_WIN64)
|
|
#ifndef GB_ARCH_64_BIT
|
|
#define GB_ARCH_64_BIT 1
|
|
#endif
|
|
#else
|
|
#ifndef GB_ARCH_32_BIT
|
|
#define GB_ARCH_32_BIT 1
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
/* TODO(bill): Check if this works on clang */
|
|
#if defined(__GNUC__)
|
|
#if defined(__x86_64__) || defined(__ppc64__)
|
|
#ifndef GB_ARCH_64_BIT
|
|
#define GB_ARCH_64_BIT 1
|
|
#endif
|
|
#else
|
|
#ifndef GB_ARCH_32_BIT
|
|
#define GB_ARCH_32_BIT 1
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifndef GB_EDIAN_ORDER
|
|
#define GB_EDIAN_ORDER
|
|
#define GB_IS_BIG_EDIAN (!*(unsigned char *)&(unsigned short){1})
|
|
#define GB_IS_LITTLE_EDIAN (!GB_IS_BIG_EDIAN)
|
|
#endif
|
|
|
|
#define GB_IS_POWER_OF_TWO(x) ((x) != 0) && !((x) & ((x) - 1))
|
|
|
|
|
|
#if !defined(GB_HAS_NO_CONSTEXPR)
|
|
#if defined(_GNUC_VER) && _GNUC_VER < 406 /* Less than gcc 4.06 */
|
|
#define GB_HAS_NO_CONSTEXPR 1
|
|
#elif defined(_MSC_VER) && _MSC_VER < 1900 /* Less than Visual Studio 2015/MSVC++ 14.0 */
|
|
#define GB_HAS_NO_CONSTEXPR 1
|
|
#elif !defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L
|
|
#define GB_HAS_NO_CONSTEXPR 1
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(GB_HAS_NO_CONSTEXPR)
|
|
#define GB_CONSTEXPR
|
|
#else
|
|
#define GB_CONSTEXPR constexpr
|
|
#endif
|
|
|
|
#ifndef GB_FORCE_INLINE
|
|
#if defined(_MSC_VER)
|
|
#define GB_FORCE_INLINE __forceinline
|
|
#else
|
|
#define GB_FORCE_INLINE __attribute__ ((__always_inline__))
|
|
#endif
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#if defined(GB_SYSTEM_WINDOWS)
|
|
#define NOMINMAX 1
|
|
#define VC_EXTRALEAN 1
|
|
#define WIN32_EXTRA_LEAN 1
|
|
#define WIN32_LEAN_AND_MEAN 1
|
|
|
|
#include <windows.h> /* TODO(bill): Should we include only the needed headers? */
|
|
#include <mmsystem.h> /* Time functions */
|
|
|
|
#undef NOMINMAX
|
|
#undef VC_EXTRALEAN
|
|
#undef WIN32_EXTRA_LEAN
|
|
#undef WIN32_LEAN_AND_MEAN
|
|
|
|
#include <intrin.h>
|
|
#else
|
|
#include <pthread.h>
|
|
#include <sys/time.h>
|
|
#endif
|
|
|
|
#ifndef true
|
|
#define true (0==0)
|
|
#define false (0!=0)
|
|
#endif
|
|
|
|
#ifndef NULL
|
|
#define NULL ((void *)0)
|
|
#endif
|
|
|
|
#if !defined(GB_NO_DEBUG)
|
|
/* TODO(bill): Do a better assert */
|
|
#define GB_ASSERT(cond) assert(cond)
|
|
#else
|
|
#define GB_ASSERT(cond) ((void)(cond))
|
|
#endif
|
|
|
|
#define GB_STATIC_ASSERT(COND, MSG) typedef char gb__static_assertion_##MSG[(!!(COND))*2-1]
|
|
// token pasting madness:
|
|
#define GB_COMPILE_TIME_ASSERT3(cond, line) GB_STATIC_ASSERT(cond, static_assertion_at_line_##line)
|
|
#define GB_COMPILE_TIME_ASSERT2(cond, line) GB_COMPILE_TIME_ASSERT3(cond, line)
|
|
#define GB_COMPILE_TIME_ASSERT(cond) GB_COMPILE_TIME_ASSERT2(cond, __LINE__)
|
|
/* snprintf_msvc */
|
|
#if defined(_MSC_VER)
|
|
int gb__vsnprintf_compatible(char *buffer, size_t size, const char *format, va_list args)
|
|
{
|
|
int result = -1;
|
|
if (size > 0) result = _vsnprintf_s(buffer, size, _TRUNCATE, format, args);
|
|
if (result == -1) return _vscprintf(format, args);
|
|
return result;
|
|
}
|
|
|
|
int gb__snprintf_compatible(char *buffer, size_t size, const char *format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
int result = gb__vsnprintf_compatible(buffer, size, format, args);
|
|
va_end(args);
|
|
return result;
|
|
}
|
|
|
|
#if !defined(GB_DO_NOT_USE_MSVC_SPRINTF_FIX)
|
|
#define snprintf gb__snprintf_compatible
|
|
#define vsnprintf gb__vsnprintf_compatible
|
|
#endif /* GB_DO_NOT_USE_MSVC_SPRINTF_FIX */
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
typedef unsigned __int8 u8;
|
|
typedef signed __int8 s8;
|
|
typedef unsigned __int16 u16;
|
|
typedef signed __int16 s16;
|
|
typedef unsigned __int32 u32;
|
|
typedef signed __int32 s32;
|
|
typedef unsigned __int64 u64;
|
|
typedef signed __int64 s64;
|
|
#else
|
|
typedef uint8_t u8;
|
|
typedef int8_t s8;
|
|
typedef uint16_t u16;
|
|
typedef int16_t s16;
|
|
typedef uint32_t u32;
|
|
typedef int32_t s32;
|
|
typedef uint64_t u64;
|
|
typedef int64_t s64;
|
|
#endif
|
|
|
|
GB_COMPILE_TIME_ASSERT(sizeof(s8)==1);
|
|
GB_COMPILE_TIME_ASSERT(sizeof(s16)==2);
|
|
GB_COMPILE_TIME_ASSERT(sizeof(s32)==4);
|
|
GB_COMPILE_TIME_ASSERT(sizeof(s64)==8);
|
|
|
|
typedef float f32;
|
|
typedef double f64;
|
|
|
|
typedef s32 bool32;
|
|
|
|
#if defined(GB_ARCH_32_BIT)
|
|
typedef u32 usize;
|
|
typedef s32 ssize;
|
|
#elif defined(GB_ARCH_64_BIT)
|
|
typedef u64 usize;
|
|
typedef s64 ssize;
|
|
#else
|
|
#error Unknown architecture bit size
|
|
#endif
|
|
|
|
typedef uintptr_t uintptr;
|
|
typedef intptr_t intptr;
|
|
typedef ptrdiff_t ptrdiff;
|
|
|
|
#define U8_MIN 0u
|
|
#define U8_MAX 0xffu
|
|
#define S8_MIN (-0x7f - 1)
|
|
#define S8_MAX 0x7f
|
|
|
|
#define U16_MIN 0u
|
|
#define U16_MAX 0xffffu
|
|
#define S16_MIN (-0x7fff - 1)
|
|
#define S16_MAX 0x7fff
|
|
|
|
#define U32_MIN 0u
|
|
#define U32_MAX 0xffffffffu
|
|
#define S32_MIN (-0x7fffffff - 1)
|
|
#define S32_MAX 0x7fffffff
|
|
|
|
#define U64_MIN 0ull
|
|
#define U64_MAX 0xffffffffffffffffull
|
|
#define S64_MIN (-0x7fffffffffffffffll - 1)
|
|
#define S64_MAX 0x7fffffffffffffffll
|
|
|
|
#if defined(GB_ARCH_64_BIT) && !defined(GB_USIZE_MIX)
|
|
#define USIZE_MIX U64_MIN
|
|
#define USIZE_MAX U64_MAX
|
|
|
|
#define SSIZE_MIX S64_MIN
|
|
#define SSIZE_MAX S64_MAX
|
|
#elif defined(GB_ARCH_32_BIT) && !defined(GB_USIZE_MIX)
|
|
#define USIZE_MIX U32_MIN
|
|
#define USIZE_MAX U32_MAX
|
|
|
|
#define SSIZE_MIX S32_MIN
|
|
#define SSIZE_MAX S32_MAX
|
|
#endif
|
|
|
|
/* Casts */
|
|
/* NOTE(bill): Easier to grep/find for casts */
|
|
#define cast(Type, var) ((Type)(var))
|
|
|
|
/*
|
|
* Memory
|
|
*/
|
|
|
|
#define ARRAY_COUNT(x) ((sizeof(x)/sizeof(0[x])) / (cast(size_t, !(sizeof(x) % sizeof(0[x])))))
|
|
|
|
#define KILOBYTES(x) ( (x) * 1024ll)
|
|
#define MEGABYTES(x) (KILOBYTES(x) * 1024ll)
|
|
#define GIGABYTES(x) (MEGABYTES(x) * 1024ll)
|
|
#define TERABYTES(x) (GIGABYTES(x) * 1024ll)
|
|
|
|
|
|
typedef struct Mutex {
|
|
#if defined(GB_SYSTEM_WINDOWS)
|
|
HANDLE win32_mutex;
|
|
#else
|
|
pthread_mutex_t posix_mutex;
|
|
#endif
|
|
} Mutex;
|
|
|
|
Mutex mutex_make(void);
|
|
void mutex_destroy(Mutex *mutex);
|
|
void mutex_lock(Mutex *mutex);
|
|
bool32 mutex_try_lock(Mutex *mutex);
|
|
void mutex_unlock(Mutex *mutex);
|
|
|
|
|
|
typedef struct Atomic32 { u32 nonatomic; } Atomic32;
|
|
typedef struct Atomic64 { u64 nonatomic; } Atomic64;
|
|
|
|
u32 atomic32_load(const volatile Atomic32 *a);
|
|
void atomic32_store(volatile Atomic32 *a, u32 value);
|
|
u32 atomic32_compare_exchange_strong(volatile Atomic32 *a, u32 expected, u32 desired);
|
|
u32 atomic32_exchanged(volatile Atomic32 *a, u32 desired);
|
|
u32 atomic32_fetch_add(volatile Atomic32 *a, s32 desired);
|
|
u32 atomic32_fetch_and(volatile Atomic32 *a, u32 desired);
|
|
u32 atomic32_fetch_or(volatile Atomic32 *a, u32 desired);
|
|
|
|
u64 atomic64_load(const volatile Atomic64 *a);
|
|
void atomic64_store(volatile Atomic64 *a, u64 value);
|
|
u64 atomic64_compare_exchange_strong(volatile Atomic64 *a, u64 expected, u64 desired);
|
|
u64 atomic64_exchanged(volatile Atomic64 *a, u64 desired);
|
|
u64 atomic64_fetch_add(volatile Atomic64 *a, s64 desired);
|
|
u64 atomic64_fetch_and(volatile Atomic64 *a, u64 desired);
|
|
u64 atomic64_fetch_or(volatile Atomic64 *a, u64 desired);
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct Semaphore {
|
|
#if defined(GB_SYSTEM_WINDOWS)
|
|
HANDLE win32_handle;
|
|
#else
|
|
Mutex mutex;
|
|
pthread_cond_t cond;
|
|
s32 count;
|
|
#endif
|
|
} Semaphore;
|
|
|
|
Semaphore semaphore_make(void);
|
|
void semaphore_destroy(Semaphore *s);
|
|
void semaphore_post(Semaphore *s);
|
|
void semaphore_post_count(Semaphore *s, u32 count);
|
|
void semaphore_wait(Semaphore *s);
|
|
|
|
|
|
|
|
|
|
|
|
typedef void(Thread_Procedure)(void*);
|
|
|
|
typedef struct Thread {
|
|
#if defined(GB_SYSTEM_WINDOWS)
|
|
HANDLE win32_handle;
|
|
#else
|
|
pthread_t posix_handle;
|
|
#endif
|
|
|
|
Thread_Procedure *functions;
|
|
void *data;
|
|
|
|
Semaphore semaphore;
|
|
usize stack_size;
|
|
bool32 is_running;
|
|
} Thread;
|
|
|
|
Thread thread_make(void);
|
|
void thread_destroy(Thread* t);
|
|
void thread_start(Thread* t, Thread_Procedure *func, void *data);
|
|
void thread_start_with_stack(Thread* t, Thread_Procedure *func, void *data, usize stack_size);
|
|
void thread_join(Thread* t);
|
|
bool32 thread_is_running(const Thread* t); /* NOTE(bill): Can this be just pass by value? */
|
|
|
|
u32 thread_current_id(void);
|
|
|
|
|
|
|
|
|
|
|
|
/* Default aligment for memory allocations */
|
|
#ifndef GB_DEFAULT_ALIGNMENT
|
|
#define GB_DEFAULT_ALIGNMENT 8
|
|
#endif
|
|
|
|
typedef struct Allocator {
|
|
/* Allocates the specified amount of memory aligned to the specified alignment */
|
|
void *(*alloc)(struct Allocator *a, usize size, usize align);
|
|
|
|
/* Deallocates an allocation made with alloc() */
|
|
void (*dealloc)(struct Allocator *a, void *ptr);
|
|
|
|
/* Returns the amount of usuable memory allocated at `ptr`.
|
|
* If the allocator does not support tracking of the allocation size,
|
|
* the function will return -1
|
|
*/
|
|
s64 (*allocated_size)(struct Allocator *a, const void *ptr);
|
|
|
|
/* Returns the total amount of memory allocated by this allocator */
|
|
/* If the allocator does not track memory, the function will return -1 */
|
|
s64 (*total_allocated)(struct Allocator *a);
|
|
} Allocator;
|
|
|
|
void *alloc_align(Allocator *a, usize size, usize align) { GB_ASSERT(a != NULL); return a->alloc(a, size, align); }
|
|
void *alloc(Allocator *a, usize size) { GB_ASSERT(a != NULL); return alloc_align(a, size, GB_DEFAULT_ALIGNMENT); }
|
|
|
|
#define alloc_struct(allocator, Type) cast(Type *, alloc_align(allocator, sizeof(Type), alignof(Type)))
|
|
#define alloc_array(allocator, Type, count) cast(Type *, alloc_align(allocator, sizeof(Type)*(count), alignof(Type)))
|
|
|
|
void dealloc(Allocator *a, void *ptr) { GB_ASSERT(a != NULL); if (ptr) a->dealloc(a, ptr); }
|
|
|
|
s64 allocated_size(Allocator *a, const void *ptr) { GB_ASSERT(a != NULL); return a->allocated_size(a, ptr); }
|
|
s64 total_allocated(Allocator *a) { GB_ASSERT(a != NULL); return a->total_allocated(a); }
|
|
|
|
|
|
|
|
|
|
typedef struct Heap {
|
|
Allocator base; /* NOTE(bill): Must be first into order to allow for polymorphism */
|
|
|
|
Mutex mutex;
|
|
bool32 use_mutex;
|
|
s64 total_allocated_count;
|
|
s64 allocation_count;
|
|
|
|
#if defined(GB_SYSTEM_WINDOWS)
|
|
HANDLE win32_heap_handle;
|
|
#endif
|
|
} Heap;
|
|
|
|
Heap heap_make(bool32 use_mutex);
|
|
void heap_destroy(Heap *heap);
|
|
|
|
|
|
typedef struct Arena {
|
|
Allocator base; /* NOTE(bill): Must be first into order to allow for polymorphism */
|
|
|
|
Allocator *backing;
|
|
void *physical_start;
|
|
s64 total_size;
|
|
s64 total_allocated_count;
|
|
s64 temp_count;
|
|
} Arena;
|
|
|
|
|
|
Arena arena_make_from_backing(Allocator *backing, usize size);
|
|
Arena arena_make_from_pointer(void *start, usize size);
|
|
void arena_destroy(Arena *arena);
|
|
void arena_clear(Arena *arena);
|
|
|
|
|
|
typedef struct Temporary_Arena_Memory {
|
|
Arena *arena;
|
|
s64 original_count;
|
|
} Temporary_Arena_Memory;
|
|
|
|
Temporary_Arena_Memory make_temporary_arena_memory(Arena *arena);
|
|
void temporary_arena_memory_free(Temporary_Arena_Memory t);
|
|
|
|
|
|
typedef struct Pool {
|
|
Allocator base; /* NOTE(bill): Must be first into order to allow for polymorphism */
|
|
|
|
Allocator *backing;
|
|
|
|
void *physical_start;
|
|
void *free_list;
|
|
|
|
usize block_size;
|
|
usize block_align;
|
|
s64 total_size;
|
|
} Pool;
|
|
|
|
Pool pool_make(Allocator *backing, usize num_blocks, usize block_size);
|
|
Pool pool_make_align(Allocator *backing, usize num_blocks, usize block_size, usize block_align);
|
|
void pool_destroy(Pool *pool);
|
|
|
|
|
|
|
|
/*
|
|
* Memory
|
|
*/
|
|
void *align_forward(void *ptr, usize align);
|
|
|
|
#define zero_struct(element) ((void)zero_size(&(element), sizeof(element)))
|
|
#define zero_array(ptr, Type, count) cast(Type, zero_size((ptr), sizeof(Type)*(count)))
|
|
void *zero_size(void *ptr, usize bytes);
|
|
|
|
|
|
|
|
/*
|
|
* Array
|
|
*/
|
|
/*
|
|
* Array structure:
|
|
*
|
|
*
|
|
* | Allocator * | usize count | usize capacity | char * |
|
|
* |
|
|
* `-- Returned pointer
|
|
*/
|
|
|
|
typedef struct Array_Header {
|
|
Allocator *allocator;
|
|
usize count;
|
|
usize capacity;
|
|
} Array_Header;
|
|
|
|
/* TODO(bill): Implement a c style array maybe like stb/stretchy_buffer.h but with a custom allocator */
|
|
|
|
#define array_header(arr) (cast(Array_Header *, arr) - 1)
|
|
|
|
#define array_make_count(allocator, Type, count) /* TODO(bill): */
|
|
#define array_make(allocator, Type) (array_make_count(allocator, Type, 0))
|
|
#define array_free(arr) (dealloc(array_header(arr)->allocator, array_header(arr)))
|
|
|
|
#define array_allocator(arr) (array_header(arr)->allocator)
|
|
#define array_count(arr) (array_header(arr)->count)
|
|
#define array_capacity(arr) (array_header(arr)->capacity)
|
|
|
|
#define array_append(arr, item) /* TODO(bill): */
|
|
#define array_append_array(arr, items, count) /* TODO(bill): */
|
|
|
|
#define array_pop(arr) (GB_ASSERT(array_header(arr)->count > 0), array_header(arr)->count--)
|
|
|
|
#define array_clear(arr) (array_header(arr)->count = 0)
|
|
#define array_resize(arr, count) /* TODO(bill): */
|
|
#define array_reserve(arr, capacity) /* TODO(bill): */
|
|
#define array_set_capacity(arr, capacity) /* TODO(bill): */
|
|
#define array_grow(arr, min_capacity) /* TODO(bill): */
|
|
|
|
|
|
/*
|
|
* String - c compatible strings
|
|
*/
|
|
|
|
typedef char * String;
|
|
|
|
typedef u32 String_Size;
|
|
|
|
typedef struct String_Header {
|
|
Allocator *allocator;
|
|
String_Size length;
|
|
String_Size capacity;
|
|
} String_Header;
|
|
|
|
#define GB_STRING_HEADER(str) (cast(String_Header *, str) - 1)
|
|
|
|
String string_make(Allocator *a, const char* str);
|
|
String string_make_length(Allocator *a, const void* str, String_Size num_bytes);
|
|
void string_free(String str);
|
|
|
|
String string_duplicate(Allocator *a, const String str);
|
|
|
|
String_Size string_length(const String str);
|
|
String_Size string_capacity(const String str);
|
|
String_Size string_available_space(const String str);
|
|
|
|
void string_clear(String str);
|
|
|
|
String string_append_string(String *str, const String other);
|
|
String string_append_string_length(String *str, const void *other, String_Size num_bytes);
|
|
String string_append_cstring(String *str, const char *other);
|
|
|
|
String string_set(String str, const char *cstr);
|
|
|
|
String string_make_space_for(String str, String_Size add_len);
|
|
String_Size string_allocation_size(const String str);
|
|
|
|
bool32 strings_are_equal(const String lhs, const String rhs);
|
|
|
|
String string_trim(String str, const char *cut_set);
|
|
String string_trim_space(String str); /* Whitespace ` \t\r\n\v\f` */
|
|
|
|
|
|
|
|
/*
|
|
* Hash
|
|
*/
|
|
|
|
u32 hash_adler32(const void *ket, u32 num_bytes);
|
|
|
|
u32 hash_crc32(const void* key, u32 num_bytes);
|
|
u64 hash_crc64(const void* key, usize num_bytes);
|
|
|
|
u32 hash_fnv32(const void* key, usize num_bytes);
|
|
u64 hash_fnv64(const void* key, usize num_bytes);
|
|
u32 hash_fnv32a(const void* key, usize num_bytes);
|
|
u64 hash_fnv64a(const void* key, usize num_bytes);
|
|
|
|
u32 hash_murmur32(const void* key, u32 num_bytes, u32 seed);
|
|
u64 hash_murmur64(const void* key, usize num_bytes, u64 seed);
|
|
|
|
/*
|
|
* Time
|
|
*/
|
|
|
|
/* TODO(bill): How should I this */
|
|
typedef struct Time { s64 microseconds; } Time;
|
|
|
|
#define TIME_ZERO (cast(Time, {0}))
|
|
|
|
Time time_now(void);
|
|
void time_sleep(Time time);
|
|
|
|
Time time_seconds(f32 s);
|
|
Time time_milliseconsd(s32 ms);
|
|
Time time_microseconds(s64 us);
|
|
|
|
f32 time_as_seconds(Time t);
|
|
s32 time_as_milliseconds(Time t);
|
|
s64 time_as_microseconds(Time t);
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif /* extern "C" */
|
|
|
|
#if defined(GB_IMPLEMENTATION)
|
|
|
|
|
|
#endif /* GB_IMPLEMENTATION */
|
|
|
|
#endif
|