From 2cbb897efa1ace19993628230fe6ad3e852c1257 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Mon, 17 Apr 2017 22:48:20 +1000 Subject: [PATCH] Add pushbuffer system --- dqn.h | 166 +++++++++++++++++++++++++++++++++++++--------- dqn_unit_test.cpp | 101 +++++++++++++++++----------- 2 files changed, 197 insertions(+), 70 deletions(-) diff --git a/dqn.h b/dqn.h index 676b671..ae6c764 100644 --- a/dqn.h +++ b/dqn.h @@ -18,15 +18,13 @@ // HEADER // //////////////////////////////////////////////////////////////////////////////// -#include "stdint.h" // For standard types -#include "math.h" // For trigonometry functions (for now) -#include "stdlib.h" // For calloc, malloc, free +#include // For standard types #ifdef _WIN32 #define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK); #define DQN_WIN32 - // TODO(doyle): Our own windows.h? + // TODO(doyle): Make my own windows.h? #define WIN32_LEAN_AND_MEAN #include #endif @@ -46,11 +44,17 @@ typedef int64_t i16; typedef double f64; typedef float f32; +#define DQN_TERABYTE(val) (DQN_GIGABYTE(val) * 1024LL) +#define DQN_GIGABYTE(val) (DQN_MEGABYTE(val) * 1024LL) +#define DQN_MEGABYTE(val) (DQN_KILOBYTE(val) * 1024LL) +#define DQN_KILOBYTE(val) ((val) * 1024LL) + #define DQN_INVALID_CODE_PATH 0 #define DQN_ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) #define DQN_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; } #define DQN_PI 3.14159265359f + #define DQN_ABS(x) (((x) < 0) ? (-(x)) : (x)) #define DQN_DEGREES_TO_RADIANS(x) ((x * (DQN_PI / 180.0f))) #define DQN_RADIANS_TO_DEGREES(x) ((x * (180.0f / DQN_PI))) @@ -61,6 +65,7 @@ typedef float f32; //////////////////////////////////////////////////////////////////////////////// // DArray - Dynamic Array //////////////////////////////////////////////////////////////////////////////// +// REMINDER: Dynamic Array can be used as a stack. Don't need to create one. template struct DqnArray { @@ -69,32 +74,30 @@ struct DqnArray T *data; }; -// REMINDER: This can be used as a stack. So don't need to create a stack data -// structure. #if 0 template -bool dqn_darray_init (DqnArray *array, size_t capacity); -bool dqn_darray_grow (DqnArray *array); -T *dqn_darray_push (DqnArray *array, T item); -T *dqn_darray_pop (DqnArray *array) -T *dqn_darray_get (DqnArray *array, u64 index); -bool dqn_darray_clear (DqnArray *array); -bool dqn_darray_free (DqnArray *array); -bool dqn_darray_remove (DqnArray *array, u64 index); -bool dqn_darray_remove_stable(DqnArray *array, u64 index); +bool dqn_array_init (DqnArray *array, size_t capacity); +bool dqn_array_grow (DqnArray *array); +T *dqn_array_push (DqnArray *array, T item); +T *dqn_array_pop (DqnArray *array) +T *dqn_array_get (DqnArray *array, u64 index); +bool dqn_array_clear (DqnArray *array); +bool dqn_array_free (DqnArray *array); +bool dqn_array_remove (DqnArray *array, u64 index); +bool dqn_array_remove_stable(DqnArray *array, u64 index); #endif // Implementation taken from Milton, developed by Serge at // https://github.com/serge-rgb/milton#license template -bool dqn_darray_init(DqnArray *array, size_t capacity) +bool dqn_array_init(DqnArray *array, size_t capacity) { if (!array) return false; if (array->data) { // TODO(doyle): Logging? The array already exists - if (!dqn_darray_free(array)) return false; + if (!dqn_array_free(array)) return false; } array->data = (T *)calloc((size_t)capacity, sizeof(T)); @@ -106,7 +109,7 @@ bool dqn_darray_init(DqnArray *array, size_t capacity) } template -bool dqn_darray_grow(DqnArray *array) +bool dqn_array_grow(DqnArray *array) { if (!array || !array->data) return false; @@ -128,13 +131,13 @@ bool dqn_darray_grow(DqnArray *array) } template -T *dqn_darray_push(DqnArray *array, T item) +T *dqn_array_push(DqnArray *array, T item) { if (!array) return NULL; if (array->count >= array->capacity) { - if (!dqn_darray_grow(array)) return NULL; + if (!dqn_array_grow(array)) return NULL; } DQN_ASSERT(array->count < array->capacity); @@ -144,7 +147,7 @@ T *dqn_darray_push(DqnArray *array, T item) } template -T *dqn_darray_pop(DqnArray *array) +T *dqn_array_pop(DqnArray *array) { if (!array) return NULL; if (array->count == 0) return NULL; @@ -154,7 +157,7 @@ T *dqn_darray_pop(DqnArray *array) } template -T *dqn_darray_get(DqnArray *array, u64 index) +T *dqn_array_get(DqnArray *array, u64 index) { T *result = NULL; if (index >= 0 && index <= array->count) result = &array->data[index]; @@ -162,7 +165,7 @@ T *dqn_darray_get(DqnArray *array, u64 index) } template -bool dqn_darray_clear(DqnArray *array) +bool dqn_array_clear(DqnArray *array) { if (array) { @@ -174,7 +177,7 @@ bool dqn_darray_clear(DqnArray *array) } template -bool dqn_darray_free(DqnArray *array) +bool dqn_array_free(DqnArray *array) { if (array && array->data) { @@ -188,7 +191,7 @@ bool dqn_darray_free(DqnArray *array) } template -bool dqn_darray_remove(DqnArray *array, u64 index) +bool dqn_array_remove(DqnArray *array, u64 index) { if (!array) return false; if (index >= array->count) return false; @@ -207,7 +210,7 @@ bool dqn_darray_remove(DqnArray *array, u64 index) } template -bool dqn_darray_remove_stable(DqnArray *array, u64 index) +bool dqn_array_remove_stable(DqnArray *array, u64 index) { if (!array) return false; if (index >= array->count) return false; @@ -237,7 +240,7 @@ bool dqn_darray_remove_stable(DqnArray *array, u64 index) //////////////////////////////////////////////////////////////////////////////// // Math //////////////////////////////////////////////////////////////////////////////// -DQN_FILE_SCOPE f32 dqn_math_lerp (f32 a, f32 t, f32 b); +DQN_FILE_SCOPE f32 dqn_math_lerp(f32 a, f32 t, f32 b); DQN_FILE_SCOPE f32 dqn_math_sqrtf(f32 a); //////////////////////////////////////////////////////////////////////////////// @@ -352,6 +355,8 @@ DQN_FILE_SCOPE bool dqn_rect_contains_p (DqnRect rect, DqnV2 p); //////////////////////////////////////////////////////////////////////////////// // String Ops //////////////////////////////////////////////////////////////////////////////// +DQN_FILE_SCOPE char dqn_char_to_upper (char c); +DQN_FILE_SCOPE char dqn_char_to_lower (char c); DQN_FILE_SCOPE bool dqn_char_is_digit (char c); DQN_FILE_SCOPE bool dqn_char_is_alpha (char c); DQN_FILE_SCOPE bool dqn_char_is_alphanum(char c); @@ -381,6 +386,7 @@ DQN_FILE_SCOPE bool dqn_win32_utf8_to_wchar (const char *const in, wchar_t *cons DQN_FILE_SCOPE bool dqn_win32_wchar_to_utf8 (const wchar_t *const in, char *const out, const i32 outLen); DQN_FILE_SCOPE void dqn_win32_get_client_dim (const HWND window, LONG *width, LONG *height); +DQN_FILE_SCOPE void dqn_win32_get_rect_dim (RECT rect, LONG *width, LONG *height); DQN_FILE_SCOPE void dqn_win32_display_last_error(const char *const errorPrefix); #endif /* DQN_WIN32 */ @@ -466,6 +472,30 @@ DQN_FILE_SCOPE u32 dqn_rnd_pcg_next (DqnRandPCGState *pcg); DQN_FILE_SCOPE f32 dqn_rnd_pcg_nextf(DqnRandPCGState *pcg); // Returns a random integer N between [min, max] DQN_FILE_SCOPE i32 dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max); + +//////////////////////////////////////////////////////////////////////////////// +// PushBuffer Header +//////////////////////////////////////////////////////////////////////////////// +typedef struct PushBuffer +{ + u8 *memory; + size_t used; + size_t size; + i32 tempBufferCount; +} PushBuffer; + +typedef struct TempBuffer +{ + PushBuffer *buffer; + size_t used; +} TempBuffer; + +DQN_FILE_SCOPE bool push_buffer_init (PushBuffer *buffer, void *memory, size_t size); +DQN_FILE_SCOPE void *push_buffer_allocate(PushBuffer *buffer, size_t size); + +DQN_FILE_SCOPE TempBuffer push_buffer_begin_temp_region(PushBuffer *buffer); +DQN_FILE_SCOPE void push_buffer_end_temp_region (TempBuffer tempBuffer); + #endif /* DQN_H */ #ifndef DQN_INI_H @@ -993,6 +1023,8 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri // DQN_IMPLEMENTATION // //////////////////////////////////////////////////////////////////////////////// +#include "math.h" // TODO(doyle): For trigonometry functions (for now) +#include "stdlib.h" // For calloc, malloc, free // NOTE: STB_SPRINTF modified to be included when DQN_IMPLEMENTATION defined // #define STB_SPRINTF_IMPLEMENTATION @@ -1503,19 +1535,42 @@ DQN_FILE_SCOPE inline bool dqn_rect_contains_p(DqnRect rect, DqnV2 p) //////////////////////////////////////////////////////////////////////////////// // String Operations //////////////////////////////////////////////////////////////////////////////// -DQN_FILE_SCOPE bool dqn_char_is_digit(char c) +DQN_FILE_SCOPE inline char dqn_char_to_lower(char c) +{ + if (c >= 'A' && c <= 'Z') + { + i32 shiftOffset = 'a' - 'A'; + return (c + (char)shiftOffset); + } + + return c; +} + +DQN_FILE_SCOPE inline char dqn_char_to_upper(char c) +{ + if (c >= 'a' && c <= 'z') + { + i32 shiftOffset = 'a' - 'A'; + return (c - (char)shiftOffset); + } + + return c; +} + + +DQN_FILE_SCOPE inline bool dqn_char_is_digit(char c) { if (c >= '0' && c <= '9') return true; return false; } -DQN_FILE_SCOPE bool dqn_char_is_alpha(char c) +DQN_FILE_SCOPE inline bool dqn_char_is_alpha(char c) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return true; return false; } -DQN_FILE_SCOPE bool dqn_char_is_alphanum(char c) +DQN_FILE_SCOPE inline bool dqn_char_is_alphanum(char c) { if (dqn_char_is_alpha(c) || dqn_char_is_digit(c)) return true; return false; @@ -1851,6 +1906,12 @@ DQN_FILE_SCOPE void dqn_win32_get_client_dim(const HWND window, LONG *width, if (height) *height = rect.bottom - rect.top; } +DQN_FILE_SCOPE void dqn_win32_get_rect_dim(RECT rect, LONG *width, LONG *height) +{ + if (width) *width = rect.right - rect.left; + if (height) *height = rect.bottom - rect.top; +} + DQN_FILE_SCOPE void dqn_win32_display_last_error(const char *const errorPrefix) { DWORD error = GetLastError(); @@ -2191,6 +2252,51 @@ DQN_FILE_SCOPE i32 dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max) i32 const value = (i32)(dqn_rnd_pcg_nextf(pcg) * range); return min + value; } + +//////////////////////////////////////////////////////////////////////////////// +// PushBuffer Header +//////////////////////////////////////////////////////////////////////////////// +DQN_FILE_SCOPE bool push_buffer_init(PushBuffer *buffer, void *memory, size_t size) +{ + if (!buffer || !memory || size <= 0) return false; + + buffer->memory = (u8 *)memory; + buffer->size = size; + buffer->used = 0; + buffer->tempBufferCount = 0; + return true; +} + +DQN_FILE_SCOPE inline void *push_buffer_allocate(PushBuffer *buffer, size_t size) +{ + DQN_ASSERT((buffer->used + size) <= buffer->size); + void *result = buffer->memory + buffer->used; + buffer->used += size; + + return result; +} + +DQN_FILE_SCOPE TempBuffer push_buffer_begin_temp_region(PushBuffer *buffer) +{ + TempBuffer result = {}; + result.buffer = buffer; + result.used = buffer->used; + + buffer->tempBufferCount++; + + return result; +} + +DQN_FILE_SCOPE void push_buffer_end_temp_region(TempBuffer tempBuffer) +{ + PushBuffer *buffer = tempBuffer.buffer; + DQN_ASSERT(buffer->used > tempBuffer.used) + + buffer->used = tempBuffer.used; + buffer->tempBufferCount--; + DQN_ASSERT(buffer->tempBufferCount >= 0); +} + //////////////////////////////////////////////////////////////////////////////// // STB_Sprintf //////////////////////////////////////////////////////////////////////////////// diff --git a/dqn_unit_test.cpp b/dqn_unit_test.cpp index 55436b6..46c66d1 100644 --- a/dqn_unit_test.cpp +++ b/dqn_unit_test.cpp @@ -550,18 +550,18 @@ void dqn_vec_test() printf("dqn_vec_test(): Completed successfully\n"); } -void dqn_darray_test() +void dqn_array_test() { { DqnArray array = {}; - DQN_ASSERT(dqn_darray_init(&array, 1)); + DQN_ASSERT(dqn_array_init(&array, 1)); DQN_ASSERT(array.capacity == 1); DQN_ASSERT(array.count == 0); // Test basic insert { DqnV2 va = dqn_v2(5, 10); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DqnV2 vb = array.data[0]; DQN_ASSERT(dqn_v2_equals(va, vb)); @@ -573,7 +573,7 @@ void dqn_darray_test() // Test array resizing and freeing { DqnV2 va = dqn_v2(10, 15); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DqnV2 vb = array.data[0]; DQN_ASSERT(dqn_v2_equals(va, vb) == false); @@ -584,58 +584,58 @@ void dqn_darray_test() DQN_ASSERT(array.capacity == 2); DQN_ASSERT(array.count == 2); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 3); DQN_ASSERT(array.count == 3); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 4); DQN_ASSERT(array.count == 4); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 5); DQN_ASSERT(array.count == 5); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 6); DQN_ASSERT(array.count == 6); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 7); DQN_ASSERT(array.count == 7); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 8); DQN_ASSERT(array.count == 8); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 9); DQN_ASSERT(array.count == 9); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 10); DQN_ASSERT(array.count == 10); - DQN_ASSERT(dqn_darray_push(&array, va)); + DQN_ASSERT(dqn_array_push(&array, va)); DQN_ASSERT(array.capacity == 12); DQN_ASSERT(array.count == 11); DqnV2 vc = dqn_v2(90, 100); - DQN_ASSERT(dqn_darray_push(&array, vc)); + DQN_ASSERT(dqn_array_push(&array, vc)); DQN_ASSERT(array.capacity == 12); DQN_ASSERT(array.count == 12); DQN_ASSERT(dqn_v2_equals(vc, array.data[11])); - DQN_ASSERT(dqn_darray_free(&array) == true); + DQN_ASSERT(dqn_array_free(&array) == true); } } { DqnArray array = {}; - DQN_ASSERT(dqn_darray_init(&array, 1)); + DQN_ASSERT(dqn_array_init(&array, 1)); DQN_ASSERT(array.capacity == 1); DQN_ASSERT(array.count == 0); - dqn_darray_free(&array); + dqn_array_free(&array); } { @@ -645,46 +645,46 @@ void dqn_darray_test() DqnV2 d = dqn_v2(7, 8); DqnArray array = {}; - DQN_ASSERT(dqn_darray_init(&array, 16)); - DQN_ASSERT(dqn_darray_remove(&array, 0) == false); + DQN_ASSERT(dqn_array_init(&array, 16)); + DQN_ASSERT(dqn_array_remove(&array, 0) == false); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 0); - DQN_ASSERT(dqn_darray_clear(&array)); + DQN_ASSERT(dqn_array_clear(&array)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 0); - DQN_ASSERT(dqn_darray_push(&array, a)); - DQN_ASSERT(dqn_darray_push(&array, b)); - DQN_ASSERT(dqn_darray_push(&array, c)); - DQN_ASSERT(dqn_darray_push(&array, d)); + DQN_ASSERT(dqn_array_push(&array, a)); + DQN_ASSERT(dqn_array_push(&array, b)); + DQN_ASSERT(dqn_array_push(&array, c)); + DQN_ASSERT(dqn_array_push(&array, d)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 4); - DQN_ASSERT(dqn_darray_remove(&array, 0)); + DQN_ASSERT(dqn_array_remove(&array, 0)); DQN_ASSERT(dqn_v2_equals(array.data[0], d)); DQN_ASSERT(dqn_v2_equals(array.data[1], b)); DQN_ASSERT(dqn_v2_equals(array.data[2], c)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 3); - DQN_ASSERT(dqn_darray_remove(&array, 2)); + DQN_ASSERT(dqn_array_remove(&array, 2)); DQN_ASSERT(dqn_v2_equals(array.data[0], d)); DQN_ASSERT(dqn_v2_equals(array.data[1], b)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 2); - DQN_ASSERT(dqn_darray_remove(&array, 100) == false); + DQN_ASSERT(dqn_array_remove(&array, 100) == false); DQN_ASSERT(dqn_v2_equals(array.data[0], d)); DQN_ASSERT(dqn_v2_equals(array.data[1], b)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 2); - DQN_ASSERT(dqn_darray_clear(&array)); + DQN_ASSERT(dqn_array_clear(&array)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 0); - dqn_darray_free(&array); + dqn_array_free(&array); } { @@ -694,36 +694,36 @@ void dqn_darray_test() DqnV2 d = dqn_v2(7, 8); DqnArray array = {}; - DQN_ASSERT(dqn_darray_init(&array, 16)); + DQN_ASSERT(dqn_array_init(&array, 16)); - DQN_ASSERT(dqn_darray_push(&array, a)); - DQN_ASSERT(dqn_darray_push(&array, b)); - DQN_ASSERT(dqn_darray_push(&array, c)); - DQN_ASSERT(dqn_darray_push(&array, d)); + DQN_ASSERT(dqn_array_push(&array, a)); + DQN_ASSERT(dqn_array_push(&array, b)); + DQN_ASSERT(dqn_array_push(&array, c)); + DQN_ASSERT(dqn_array_push(&array, d)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 4); - dqn_darray_remove_stable(&array, 0); + dqn_array_remove_stable(&array, 0); DQN_ASSERT(dqn_v2_equals(array.data[0], b)); DQN_ASSERT(dqn_v2_equals(array.data[1], c)); DQN_ASSERT(dqn_v2_equals(array.data[2], d)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 3); - dqn_darray_remove_stable(&array, 1); + dqn_array_remove_stable(&array, 1); DQN_ASSERT(dqn_v2_equals(array.data[0], b)); DQN_ASSERT(dqn_v2_equals(array.data[1], d)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 2); - dqn_darray_remove_stable(&array, 1); + dqn_array_remove_stable(&array, 1); DQN_ASSERT(dqn_v2_equals(array.data[0], b)); DQN_ASSERT(array.capacity == 16); DQN_ASSERT(array.count == 1); - dqn_darray_free(&array); + dqn_array_free(&array); } - printf("dqn_darray_test(): Completed successfully\n"); + printf("dqn_array_test(): Completed successfully\n"); } void dqn_file_test() @@ -775,6 +775,26 @@ void dqn_file_test() printf("dqn_file_test(): Completed successfully\n"); } +void dqn_push_buffer_test() +{ + size_t blockSize = DQN_KILOBYTE(1); + void *block = calloc(1, blockSize); + PushBuffer buffer = {}; + push_buffer_init(&buffer, block, blockSize); + + DQN_ASSERT(buffer.memory == block); + DQN_ASSERT(buffer.size == blockSize); + DQN_ASSERT(buffer.used == 0); + + void *result = push_buffer_allocate(&buffer, (size_t)(blockSize * 0.5f)); + DQN_ASSERT(buffer.memory == block); + DQN_ASSERT(buffer.size == blockSize); + DQN_ASSERT(buffer.used == (size_t)(blockSize * 0.5f)); + DQN_ASSERT(result); + + free(block); +} + int main(void) { dqn_strings_test(); @@ -782,8 +802,9 @@ int main(void) dqn_math_test(); dqn_vec_test(); dqn_other_test(); - dqn_darray_test(); + dqn_array_test(); dqn_file_test(); + dqn_push_buffer_test(); printf("\nPress 'Enter' Key to Exit\n"); getchar();