Add memory and data-related implementations for handling game data.feature/data-structs
@@ -46,7 +46,7 @@ add_executable( | |||||
src/packages/game/input/IZ_keyboard.h | src/packages/game/input/IZ_keyboard.h | ||||
src/packages/game/IZ_config.c | src/packages/game/IZ_config.c | ||||
src/packages/game/IZ_config.h | src/packages/game/IZ_config.h | ||||
src/packages/game/geometry/IZ_point2d.c src/packages/game/geometry/IZ_point2d.h src/packages/game/geometry/IZ_vector2d.c src/packages/game/geometry/IZ_vector2d.h src/packages/game/geometry/IZ_rect.c src/packages/game/geometry/IZ_rect.h src/packages/game/core/IZ_object.c src/packages/game/core/IZ_object.h src/packages/game/core/IZ_creature.c src/packages/game/core/IZ_creature.h src/packages/game/core/IZ_entity.c src/packages/game/core/IZ_entity.h src/packages/game/memory/IZ_pool.c src/packages/game/memory/IZ_pool.h src/packages/game/input/IZ_input.c src/packages/game/input/IZ_input.h src/packages/game/input/IZ_midi.c src/packages/game/input/IZ_midi.h) | |||||
src/packages/game/geometry/IZ_point2d.c src/packages/game/geometry/IZ_point2d.h src/packages/game/geometry/IZ_vector2d.c src/packages/game/geometry/IZ_vector2d.h src/packages/game/geometry/IZ_rect.c src/packages/game/geometry/IZ_rect.h src/packages/game/core/IZ_object.c src/packages/game/core/IZ_object.h src/packages/game/core/IZ_creature.c src/packages/game/core/IZ_creature.h src/packages/game/core/IZ_entity.c src/packages/game/core/IZ_entity.h src/packages/game/memory/IZ_pool.c src/packages/game/memory/IZ_pool.h src/packages/game/input/IZ_input.c src/packages/game/input/IZ_input.h src/packages/game/input/IZ_midi.c src/packages/game/input/IZ_midi.h src/packages/game/data/IZ_list.c src/packages/game/data/IZ_list.h) | |||||
target_link_libraries( | target_link_libraries( | ||||
game | game | ||||
@@ -118,7 +118,17 @@ add_executable( | |||||
src/packages/game/memory/IZ_pool.h | src/packages/game/memory/IZ_pool.h | ||||
src/packages/game/memory/IZ_pool.c | src/packages/game/memory/IZ_pool.c | ||||
src/packages/game/memory/memory.test.c) | |||||
src/packages/game/memory/memory.test.c src/packages/game/data/IZ_list.c src/packages/game/data/IZ_list.h) | |||||
add_executable( | |||||
game-test-data | |||||
dependencies/bdd-for-c/bdd-for-c.h | |||||
src/packages/test/IZ_mock.h | |||||
src/packages/test/IZ_test.h | |||||
src/packages/game/data/IZ_list.h | |||||
src/packages/game/data/IZ_list.c | |||||
src/packages/game/data/data.test.c) | |||||
if (WIN32) | if (WIN32) | ||||
add_custom_command(TARGET game POST_BUILD | add_custom_command(TARGET game POST_BUILD | ||||
@@ -2,10 +2,23 @@ | |||||
#define SDL_STDINC_MOCK_H | #define SDL_STDINC_MOCK_H | ||||
#include <string.h> | #include <string.h> | ||||
#include "../src/packages/game/IZ_common.h" | |||||
#include "../src/packages/test/IZ_test.h" | #include "../src/packages/test/IZ_test.h" | ||||
mock(SDL_memcpy) void* SDL_memcpy(void* dst, const void* src, size_t len) { | mock(SDL_memcpy) void* SDL_memcpy(void* dst, const void* src, size_t len) { | ||||
mock_return(SDL_memcpy) memcpy(dst, src, len); | mock_return(SDL_memcpy) memcpy(dst, src, len); | ||||
} | } | ||||
mock(SDL_memset) void* SDL_memset(void* dst, i32 c, size_t len) { | |||||
mock_return(SDL_memset) memset(dst, c, len); | |||||
} | |||||
mock(SDL_malloc) void* SDL_malloc(size_t size) { | |||||
mock_return(SDL_malloc) malloc(size); | |||||
} | |||||
mock(SDL_free) void SDL_free(void* mem) { | |||||
mock_return(SDL_free); | |||||
} | |||||
#endif | #endif |
@@ -20,15 +20,7 @@ IZ_ProcedureResult IZ_AppInitialize(IZ_App* app) { | |||||
} | } | ||||
IZ_InputInitialize(config_path, &app->input_state); | IZ_InputInitialize(config_path, &app->input_state); | ||||
IZ_PoolInitialize(&app->pool); | |||||
// void* p1 = IZ_PoolAllocate(&app->memory_pool, sizeof(u16), 0)->pointer; | |||||
// void* p2 = IZ_PoolAllocate(&app->memory_pool, sizeof(u8), 0)->pointer; | |||||
// void* p3 = IZ_PoolAllocate(&app->memory_pool, sizeof(u64), 0)->pointer; | |||||
// void* p4 = IZ_PoolAllocate(&app->memory_pool, sizeof(u32), 0)->pointer; | |||||
// printf("\n%p %p %p %p\n", p1, p2, p3, p4); | |||||
// IZ_PoolDeallocate(p1); | |||||
// void* p5 = IZ_PoolAllocate(&app->memory_pool, sizeof(u16), 0)->pointer; | |||||
// printf("\n%p\n", p5); | |||||
IZ_PoolInitialize(&app->pool, POOL_MAX_SIZE); | |||||
// TODO put into its timer module | // TODO put into its timer module | ||||
app->ticks = 0; | app->ticks = 0; | ||||
@@ -2,6 +2,7 @@ | |||||
#define IZ_COMMON_H | #define IZ_COMMON_H | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdbool.h> | |||||
#define PLAYERS (unsigned char) 1 | #define PLAYERS (unsigned char) 1 | ||||
#define APP_NAME "SDL2" | #define APP_NAME "SDL2" | ||||
@@ -0,0 +1,77 @@ | |||||
#include "IZ_list.h" | |||||
bool IZ_ListFindFilterAlwaysTrue(IZ_ListNode* _node, u64 _index) { | |||||
return true; | |||||
} | |||||
void IZ_ListInitialize(IZ_List* list) { | |||||
list->root = NULL; | |||||
} | |||||
void IZ_ListTeardown(IZ_List* list) { | |||||
while (list->root) { | |||||
_IZ_ListDeleteFirstNode(list, IZ_ListFindFilterAlwaysTrue); | |||||
} | |||||
} | |||||
IZ_ListNode* IZ_ListAppendNode(IZ_List* list, void* node_value) { | |||||
IZ_ListNode* new_node = SDL_malloc(sizeof(IZ_ListNode)); | |||||
new_node->value = node_value; | |||||
if (!(list->root)) { | |||||
list->root = new_node; | |||||
} else { | |||||
IZ_ListNode *last_node = list->root; | |||||
while (last_node->next) { | |||||
last_node = last_node->next; | |||||
} | |||||
last_node->next = new_node; | |||||
} | |||||
new_node->next = NULL; | |||||
return new_node; | |||||
} | |||||
void _IZ_ListDeleteFirstNode(IZ_List* list, IZ_ListFindFilter filter) { | |||||
if (!(list && list->root)) { | |||||
return; | |||||
} | |||||
IZ_ListNode* iterator = list->root; | |||||
IZ_ListNode* previous_node = NULL; | |||||
u64 index = 0; | |||||
do { | |||||
if (!filter(iterator, index)) { | |||||
previous_node = iterator; | |||||
iterator = iterator->next; | |||||
index += 1; | |||||
continue; | |||||
} | |||||
if (previous_node) { | |||||
previous_node->next = iterator->next; | |||||
} else { | |||||
list->root = iterator->next; | |||||
} | |||||
SDL_free(iterator); | |||||
return; | |||||
} while (iterator); | |||||
} | |||||
IZ_ListNode* _IZ_ListFindFirstNode(IZ_List* list, IZ_ListFindFilter filter) { | |||||
if (!(list && list->root)) { | |||||
return NULL; | |||||
} | |||||
IZ_ListNode* iterator = list->root; | |||||
u64 index = 0; | |||||
do { | |||||
if (!filter(iterator, index)) { | |||||
iterator = iterator->next; | |||||
index += 1; | |||||
continue; | |||||
} | |||||
return iterator; | |||||
} while (iterator); | |||||
return NULL; | |||||
} |
@@ -0,0 +1,34 @@ | |||||
#ifndef IZ_LIST_H | |||||
#define IZ_LIST_H | |||||
#include "../IZ_common.h" | |||||
#include "SDL_stdinc.h" | |||||
typedef struct IZ_ListNode { | |||||
void* value; | |||||
struct IZ_ListNode* next; | |||||
} IZ_ListNode; | |||||
typedef struct { | |||||
IZ_ListNode* root; | |||||
} IZ_List; | |||||
typedef bool IZ_ListFindFilter(IZ_ListNode*, u64); | |||||
void IZ_ListInitialize(IZ_List*); | |||||
void IZ_ListTeardown(IZ_List*); | |||||
IZ_ListNode* IZ_ListAppendNode(IZ_List*, void*); | |||||
#define IZ_LIST_FILTER_FUNCTION(X) static IZ_PoolItem* X = NULL; | |||||
void _IZ_ListDeleteFirstNode(IZ_List*, IZ_ListFindFilter); | |||||
#define IZ_ListDeleteFirstNode(X, Y) X = Y; _IZ_ListDeleteFirstNode | |||||
IZ_ListNode* _IZ_ListFindFirstNode(IZ_List*, IZ_ListFindFilter); | |||||
#define IZ_ListFindFirstNode(X, Y) X = Y; _IZ_ListFindFirstNode | |||||
#endif |
@@ -0,0 +1,166 @@ | |||||
#include "../../test/IZ_test.h" | |||||
#include "../../game/IZ_common.h" | |||||
#include "../../../__mocks__/SDL_stdinc.mock.h" | |||||
#include "IZ_list.h" | |||||
bool NodeExists(IZ_ListNode* node, u64 _index) { | |||||
return *((u64*) node->value) == 42069; | |||||
} | |||||
bool NodeExists2(IZ_ListNode* node, u64 _index) { | |||||
return *((u64*) node->value) == 69420; | |||||
} | |||||
bool NodeDoesNotExist(IZ_ListNode* node, u64 _index) { | |||||
return *((u64*) node->value) == 55555; | |||||
} | |||||
spec("data") { | |||||
describe("list") { | |||||
describe("Initialize") { | |||||
static IZ_List list; | |||||
it("sets root to NULL") { | |||||
IZ_ListInitialize(&list); | |||||
check(list.root == NULL, "List not properly initialized."); | |||||
} | |||||
} | |||||
describe("Teardown") { | |||||
static IZ_List list; | |||||
before_each() { | |||||
static u64 value1 = 69420u; | |||||
static u64 value2 = 42069u; | |||||
static u64 value3 = 69069u; | |||||
IZ_ListInitialize(&list); | |||||
IZ_ListAppendNode(&list, &value1); | |||||
IZ_ListAppendNode(&list, &value2); | |||||
IZ_ListAppendNode(&list, &value3); | |||||
} | |||||
after_each() { | |||||
mock_reset(SDL_free); | |||||
} | |||||
it("removes all nodes from the list") { | |||||
mock_set_expected_calls(SDL_free, 3); | |||||
IZ_ListTeardown(&list); | |||||
check( | |||||
mock_get_expected_calls(SDL_free) == mock_get_actual_calls(SDL_free), | |||||
"Deallocator function call count mismatch." | |||||
); | |||||
} | |||||
} | |||||
describe("AppendNode") { | |||||
static IZ_List list; | |||||
static IZ_List list2; | |||||
before_each() { | |||||
IZ_ListInitialize(&list); | |||||
} | |||||
before_each() { | |||||
IZ_ListInitialize(&list2); | |||||
static u64 existing_value = 69420u; | |||||
static IZ_ListNode existing_node = { | |||||
.value = &existing_value, | |||||
.next = NULL, | |||||
}; | |||||
list2.root = &existing_node; | |||||
} | |||||
after_each() { | |||||
mock_reset(SDL_malloc); | |||||
} | |||||
it("appends new node to empty list and sets it as root") { | |||||
static u64 value = 69420u; | |||||
IZ_ListAppendNode(&list, &value); | |||||
check(*((u64*) list.root->value) == 69420u, "Node not properly appended."); | |||||
check( | |||||
mock_is_called(SDL_malloc), | |||||
"Allocator function not called." | |||||
); | |||||
} | |||||
it("appends new node to non-empty list") { | |||||
static u64 value1 = 42069u; | |||||
IZ_ListAppendNode(&list2, &value1); | |||||
check(*((u64*) list2.root->next->value) == 42069u, "Node not properly appended."); | |||||
check( | |||||
mock_is_called(SDL_malloc), | |||||
"Allocator function not called." | |||||
); | |||||
} | |||||
} | |||||
describe("FindFirstNode") { | |||||
static IZ_List list; | |||||
static u64 value1 = 69420u; | |||||
static u64 value2 = 42069u; | |||||
before_each() { | |||||
IZ_ListInitialize(&list); | |||||
IZ_ListAppendNode(&list, &value1); | |||||
IZ_ListAppendNode(&list, &value2); | |||||
} | |||||
it("retrieves first node satisfying the filter condition") { | |||||
static IZ_ListNode* node; | |||||
node = _IZ_ListFindFirstNode(&list, NodeExists); | |||||
check(*((u64*) node->value) == 42069u, "Existing node not found."); | |||||
} | |||||
it("returns NULL when all nodes do not satisfy the filter condition") { | |||||
static IZ_ListNode* node; | |||||
node = _IZ_ListFindFirstNode(&list, NodeDoesNotExist); | |||||
check(node == NULL, "Non-existing node found."); | |||||
} | |||||
} | |||||
describe("DeleteFirstNode") { | |||||
static IZ_List list; | |||||
before_each() { | |||||
static u64 value1 = 69420u; | |||||
static u64 value2 = 42069u; | |||||
static u64 value3 = 69069u; | |||||
IZ_ListInitialize(&list); | |||||
IZ_ListAppendNode(&list, &value1); | |||||
IZ_ListAppendNode(&list, &value2); | |||||
IZ_ListAppendNode(&list, &value3); | |||||
} | |||||
after_each() { | |||||
mock_reset(SDL_free); | |||||
} | |||||
it("removes first node satisfying the filter condition") { | |||||
_IZ_ListDeleteFirstNode(&list, NodeExists); | |||||
check( | |||||
mock_is_called(SDL_free), | |||||
"Deallocator function not called." | |||||
); | |||||
check( | |||||
_IZ_ListFindFirstNode(&list, NodeExists2), | |||||
"Node supposed to be present in list is absent." | |||||
); | |||||
check( | |||||
!_IZ_ListFindFirstNode(&list, NodeExists), | |||||
"Deleted node still present in list." | |||||
); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,6 +1,6 @@ | |||||
#include "IZ_point2d.h" | #include "IZ_point2d.h" | ||||
IZ_Point2D IZ_PointTranslate(IZ_Point2D point, IZ_GeoCoord translate_x, IZ_GeoCoord translate_y) { | |||||
IZ_Point2D IZ_Point2DTranslate(IZ_Point2D point, f32 translate_x, f32 translate_y) { | |||||
return (IZ_Point2D) { | return (IZ_Point2D) { | ||||
.x = point.x + translate_x, | .x = point.x + translate_x, | ||||
.y = point.y + translate_y, | .y = point.y + translate_y, | ||||
@@ -3,13 +3,11 @@ | |||||
#include "../IZ_common.h" | #include "../IZ_common.h" | ||||
typedef f32 IZ_GeoCoord; | |||||
typedef struct { | typedef struct { | ||||
IZ_GeoCoord x; | |||||
IZ_GeoCoord y; | |||||
f32 x; | |||||
f32 y; | |||||
} IZ_Point2D; | } IZ_Point2D; | ||||
IZ_Point2D IZ_PointTranslate(IZ_Point2D, IZ_GeoCoord, IZ_GeoCoord); | |||||
IZ_Point2D IZ_Point2DTranslate(IZ_Point2D, f32, f32); | |||||
#endif | #endif |
@@ -5,17 +5,17 @@ | |||||
#include "IZ_point2d.h" | #include "IZ_point2d.h" | ||||
typedef struct { | typedef struct { | ||||
IZ_GeoCoord left; | |||||
IZ_GeoCoord top; | |||||
IZ_GeoCoord right; | |||||
IZ_GeoCoord bottom; | |||||
f32 left; | |||||
f32 top; | |||||
f32 right; | |||||
f32 bottom; | |||||
} IZ_Bounds; | } IZ_Bounds; | ||||
typedef struct { | typedef struct { | ||||
// top left | // top left | ||||
IZ_Point2D pos; | IZ_Point2D pos; | ||||
IZ_GeoCoord width; | |||||
IZ_GeoCoord height; | |||||
f32 width; | |||||
f32 height; | |||||
} IZ_Rect; | } IZ_Rect; | ||||
IZ_Bounds IZ_RectGetBounds(IZ_Rect); | IZ_Bounds IZ_RectGetBounds(IZ_Rect); | ||||
@@ -1,20 +1,20 @@ | |||||
#include "IZ_vector2d.h" | #include "IZ_vector2d.h" | ||||
IZ_Vector2D IZ_VectorAdd(IZ_Vector2D addend, IZ_Vector2D augend) { | |||||
IZ_Vector2D IZ_Vector2DAdd(IZ_Vector2D addend, IZ_Vector2D augend) { | |||||
return (IZ_Vector2D) { | return (IZ_Vector2D) { | ||||
.right = addend.right + augend.right, | .right = addend.right + augend.right, | ||||
.up = addend.up + augend.up, | .up = addend.up + augend.up, | ||||
}; | }; | ||||
} | } | ||||
IZ_Vector2D IZ_VectorMultiply(IZ_Vector2D multiplicand, IZ_Vector2D multiplier) { | |||||
IZ_Vector2D IZ_Vector2DMultiply(IZ_Vector2D multiplicand, IZ_Vector2D multiplier) { | |||||
return (IZ_Vector2D) { | return (IZ_Vector2D) { | ||||
.right = multiplicand.right * multiplier.right, | .right = multiplicand.right * multiplier.right, | ||||
.up = multiplicand.up * multiplier.up, | .up = multiplicand.up * multiplier.up, | ||||
}; | }; | ||||
} | } | ||||
IZ_Vector2D IZ_VectorScale(IZ_Vector2D vector, IZ_GeoCoord scalar) { | |||||
IZ_Vector2D IZ_Vector2DScale(IZ_Vector2D vector, f32 scalar) { | |||||
return (IZ_Vector2D) { | return (IZ_Vector2D) { | ||||
.right = vector.right * scalar, | .right = vector.right * scalar, | ||||
.up = vector.up * scalar, | .up = vector.up * scalar, | ||||
@@ -4,14 +4,14 @@ | |||||
#include "IZ_point2d.h" | #include "IZ_point2d.h" | ||||
typedef struct { | typedef struct { | ||||
IZ_GeoCoord right; | |||||
IZ_GeoCoord up; | |||||
f32 right; | |||||
f32 up; | |||||
} IZ_Vector2D; | } IZ_Vector2D; | ||||
IZ_Vector2D IZ_VectorAdd(IZ_Vector2D, IZ_Vector2D); | |||||
IZ_Vector2D IZ_Vector2DAdd(IZ_Vector2D, IZ_Vector2D); | |||||
IZ_Vector2D IZ_VectorMultiply(IZ_Vector2D, IZ_Vector2D); | |||||
IZ_Vector2D IZ_Vector2DMultiply(IZ_Vector2D, IZ_Vector2D); | |||||
IZ_Vector2D IZ_VectorScale(IZ_Vector2D, IZ_GeoCoord); | |||||
IZ_Vector2D IZ_Vector2DScale(IZ_Vector2D, f32); | |||||
#endif | #endif |
@@ -5,7 +5,7 @@ | |||||
spec("geometry") { | spec("geometry") { | ||||
describe("point2d") { | describe("point2d") { | ||||
describe("PointTranslate") { | |||||
describe("Translate") { | |||||
it("translates coordinates of a point") { | it("translates coordinates of a point") { | ||||
static IZ_Point2D input = { | static IZ_Point2D input = { | ||||
.x = 420.f, | .x = 420.f, | ||||
@@ -18,7 +18,7 @@ spec("geometry") { | |||||
}; | }; | ||||
static IZ_Point2D actual; | static IZ_Point2D actual; | ||||
actual = IZ_PointTranslate(input, 6.f, 9.f); | |||||
actual = IZ_Point2DTranslate(input, 6.f, 9.f); | |||||
check(expected.x == actual.x, "X values do not match."); | check(expected.x == actual.x, "X values do not match."); | ||||
check(expected.y == actual.y, "Y values do not match."); | check(expected.y == actual.y, "Y values do not match."); | ||||
@@ -27,7 +27,7 @@ spec("geometry") { | |||||
} | } | ||||
describe("vector2d") { | describe("vector2d") { | ||||
describe("VectorAdd") { | |||||
describe("Add") { | |||||
it("adds two vectors") { | it("adds two vectors") { | ||||
static IZ_Vector2D addend = { | static IZ_Vector2D addend = { | ||||
.right = 420.f, | .right = 420.f, | ||||
@@ -45,14 +45,14 @@ spec("geometry") { | |||||
}; | }; | ||||
static IZ_Vector2D actual_sum; | static IZ_Vector2D actual_sum; | ||||
actual_sum = IZ_VectorAdd(addend, augend); | |||||
actual_sum = IZ_Vector2DAdd(addend, augend); | |||||
check(expected_sum.right == actual_sum.right, "Right values do not match."); | check(expected_sum.right == actual_sum.right, "Right values do not match."); | ||||
check(expected_sum.up == actual_sum.up, "Up values do not match."); | check(expected_sum.up == actual_sum.up, "Up values do not match."); | ||||
} | } | ||||
} | } | ||||
describe("VectorMultiply") { | |||||
describe("Multiply") { | |||||
it("multiplies two vectors") { | it("multiplies two vectors") { | ||||
static IZ_Vector2D multiplicand = { | static IZ_Vector2D multiplicand = { | ||||
.right = 6.f, | .right = 6.f, | ||||
@@ -70,14 +70,14 @@ spec("geometry") { | |||||
}; | }; | ||||
static IZ_Vector2D actual_product; | static IZ_Vector2D actual_product; | ||||
actual_product = IZ_VectorMultiply(multiplicand, multiplier); | |||||
actual_product = IZ_Vector2DMultiply(multiplicand, multiplier); | |||||
check(expected_product.right == actual_product.right, "Right values do not match."); | check(expected_product.right == actual_product.right, "Right values do not match."); | ||||
check(expected_product.up == actual_product.up, "Up values do not match."); | check(expected_product.up == actual_product.up, "Up values do not match."); | ||||
} | } | ||||
} | } | ||||
describe("VectorScale") { | |||||
describe("Scale") { | |||||
it("scales a vector") { | it("scales a vector") { | ||||
static IZ_Vector2D v = { | static IZ_Vector2D v = { | ||||
.right = 420.f, | .right = 420.f, | ||||
@@ -92,7 +92,7 @@ spec("geometry") { | |||||
}; | }; | ||||
static IZ_Vector2D actual; | static IZ_Vector2D actual; | ||||
actual = IZ_VectorScale(v, s); | |||||
actual = IZ_Vector2DScale(v, s); | |||||
check(expected.right == actual.right, "Right values do not match."); | check(expected.right == actual.right, "Right values do not match."); | ||||
check(expected.up == actual.up, "Up values do not match."); | check(expected.up == actual.up, "Up values do not match."); | ||||
@@ -101,7 +101,7 @@ spec("geometry") { | |||||
} | } | ||||
describe("rect") { | describe("rect") { | ||||
describe("RectGetBounds") { | |||||
describe("GetBounds") { | |||||
it("returns the bounds of a rectangle") { | it("returns the bounds of a rectangle") { | ||||
static IZ_Rect r = { | static IZ_Rect r = { | ||||
.pos = { | .pos = { | ||||
@@ -129,7 +129,7 @@ spec("geometry") { | |||||
} | } | ||||
} | } | ||||
describe("RectBoundsContainPoint") { | |||||
describe("BoundsContainPoint") { | |||||
it("returns true for points inside bounds") { | it("returns true for points inside bounds") { | ||||
static IZ_Bounds b = { | static IZ_Bounds b = { | ||||
.left = 50, | .left = 50, | ||||
@@ -185,7 +185,7 @@ spec("geometry") { | |||||
} | } | ||||
} | } | ||||
describe("RectBoundsCollide") { | |||||
describe("BoundsCollide") { | |||||
it("returns true for bounds A inside bounds B") { | it("returns true for bounds A inside bounds B") { | ||||
static IZ_Bounds a = { | static IZ_Bounds a = { | ||||
.left = 100, | .left = 100, | ||||
@@ -15,7 +15,7 @@ i16 GenerateAxisValueOutsideThreshold(u16 threshold) { | |||||
spec("input") { | spec("input") { | ||||
describe("joystick") { | describe("joystick") { | ||||
describe("JoystickHandleEvents") { | |||||
describe("HandleEvents") { | |||||
static SDL_Event e; | static SDL_Event e; | ||||
static IZ_JoystickState state[PLAYERS] = {}; | static IZ_JoystickState state[PLAYERS] = {}; | ||||
static IZ_Action action[PLAYERS] = {}; | static IZ_Action action[PLAYERS] = {}; | ||||
@@ -259,7 +259,7 @@ spec("input") { | |||||
} | } | ||||
} | } | ||||
describe("JoystickSaveConfig") { | |||||
describe("SaveConfig") { | |||||
static IZ_JoystickState state[PLAYERS]; | static IZ_JoystickState state[PLAYERS]; | ||||
after_each() { | after_each() { | ||||
@@ -290,7 +290,7 @@ spec("input") { | |||||
} | } | ||||
describe("keyboard") { | describe("keyboard") { | ||||
describe("KeyboardHandleEvents") { | |||||
describe("HandleEvents") { | |||||
static SDL_Event e; | static SDL_Event e; | ||||
static IZ_KeyboardState state[PLAYERS] = {}; | static IZ_KeyboardState state[PLAYERS] = {}; | ||||
static IZ_Action action[PLAYERS] = {}; | static IZ_Action action[PLAYERS] = {}; | ||||
@@ -326,7 +326,7 @@ spec("input") { | |||||
} | } | ||||
} | } | ||||
describe("KeyboardSaveConfig") { | |||||
describe("SaveConfig") { | |||||
static IZ_KeyboardState state[PLAYERS] = {}; | static IZ_KeyboardState state[PLAYERS] = {}; | ||||
after_each() { | after_each() { | ||||
@@ -1,14 +1,15 @@ | |||||
#include "IZ_pool.h" | #include "IZ_pool.h" | ||||
void IZ_PoolInitialize(IZ_Pool* pool) { | |||||
SDL_memset(pool->items, 0, POOL_MAX_ITEMS * sizeof(IZ_PoolItem)); | |||||
pool->top = 0; | |||||
pool->memory = SDL_malloc(POOL_MAX_SIZE); | |||||
SDL_memset(pool->memory, 0, POOL_MAX_SIZE); | |||||
void IZ_PoolInitialize(IZ_Pool* pool, size_t size) { | |||||
pool->items = &(IZ_List){ .root = NULL }; | |||||
pool->memory = SDL_malloc(size); | |||||
SDL_memset(pool->memory, 0, size); | |||||
pool->allocated_memory = 0; | |||||
pool->next_address = 0; | pool->next_address = 0; | ||||
pool->max_size = size; | |||||
} | } | ||||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, size_t size, u64 created_at) { | |||||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, size_t size, u64 priority) { | |||||
// 1. check next free allocation for size | // 1. check next free allocation for size | ||||
// 2. if 1. returns non-null, | // 2. if 1. returns non-null, | ||||
@@ -20,31 +21,29 @@ IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, size_t size, u64 created_at) { | |||||
// } | // } | ||||
// } | // } | ||||
if (pool->max_size - pool->allocated_memory < size) { | |||||
// TODO deallocate memory based from priority | |||||
} | |||||
void* pointer = &pool->memory[pool->next_address]; | void* pointer = &pool->memory[pool->next_address]; | ||||
IZ_PoolItem* next_allocation = &pool->items[pool->top]; | |||||
pool->items[pool->top] = (IZ_PoolItem) { | |||||
IZ_ListNode* new_item = IZ_ListAppendNode(pool->items, &(IZ_PoolItem) { | |||||
.pointer = pointer, | .pointer = pointer, | ||||
.size = size, | .size = size, | ||||
.created_at = created_at, | |||||
.priority = priority, | |||||
.pool = pool, | .pool = pool, | ||||
}; | |||||
pool->top = (pool->top + 1) % POOL_MAX_ITEMS; | |||||
}); | |||||
pool->next_address = (pool->next_address + size) % POOL_MAX_SIZE; | pool->next_address = (pool->next_address + size) % POOL_MAX_SIZE; | ||||
return next_allocation; | |||||
pool->allocated_memory += size; | |||||
return new_item->value; | |||||
} | |||||
IZ_LIST_FILTER_FUNCTION(__current_item) bool IZ_PoolGetSameItem(IZ_ListNode* node, u64 _index) { | |||||
return node->value == __current_item; | |||||
} | } | ||||
void IZ_PoolDeallocate(IZ_PoolItem* item) { | void IZ_PoolDeallocate(IZ_PoolItem* item) { | ||||
u64 i; | |||||
for (i = 0; i < POOL_MAX_ITEMS; i += 1) { | |||||
if (&item->pool->items[i] != item) { | |||||
continue; | |||||
} | |||||
item->pool->items[i].pool = NULL; | |||||
item->pool->items[i].size = 0; | |||||
item->pool->items[i].pointer = NULL; | |||||
item->pool->items[i].created_at = 0; | |||||
return; | |||||
} | |||||
IZ_ListDeleteFirstNode(__current_item, item)(item->pool->items, IZ_PoolGetSameItem); | |||||
} | } | ||||
void IZ_PoolTeardown(IZ_Pool* pool) { | void IZ_PoolTeardown(IZ_Pool* pool) { | ||||
@@ -3,8 +3,8 @@ | |||||
#include <SDL_stdinc.h> | #include <SDL_stdinc.h> | ||||
#include "../IZ_common.h" | #include "../IZ_common.h" | ||||
#include "../data/IZ_list.h" | |||||
#define POOL_MAX_ITEMS (1000) // 16 million allocations max | |||||
#define POOL_MAX_SIZE (1l << 23) // 16MB | #define POOL_MAX_SIZE (1l << 23) // 16MB | ||||
struct IZ_Pool; | struct IZ_Pool; | ||||
@@ -12,18 +12,19 @@ struct IZ_Pool; | |||||
typedef struct { | typedef struct { | ||||
void* pointer; | void* pointer; | ||||
size_t size; | size_t size; | ||||
u64 created_at; | |||||
u64 priority; | |||||
struct IZ_Pool* pool; | struct IZ_Pool* pool; | ||||
} IZ_PoolItem; | } IZ_PoolItem; | ||||
typedef struct IZ_Pool { | typedef struct IZ_Pool { | ||||
u16 top; | |||||
IZ_List* items; | |||||
u64 next_address; | u64 next_address; | ||||
IZ_PoolItem items[POOL_MAX_ITEMS]; | |||||
u64 allocated_memory; | |||||
size_t max_size; | |||||
void* memory; | void* memory; | ||||
} IZ_Pool; | } IZ_Pool; | ||||
void IZ_PoolInitialize(IZ_Pool*); | |||||
void IZ_PoolInitialize(IZ_Pool*, size_t); | |||||
IZ_PoolItem* IZ_PoolAllocate(IZ_Pool*, size_t, u64); | IZ_PoolItem* IZ_PoolAllocate(IZ_Pool*, size_t, u64); | ||||
@@ -1,18 +1,123 @@ | |||||
#include "../../test/IZ_test.h" | #include "../../test/IZ_test.h" | ||||
#include "../../../__mocks__/SDL_stdinc.mock.h" | |||||
#include "IZ_pool.h" | #include "IZ_pool.h" | ||||
struct DummyInnerStruct { | |||||
i8 f; | |||||
i8 g; | |||||
}; | |||||
struct DummyStruct { | |||||
i8 a; | |||||
i16 b; | |||||
i32 c; | |||||
i64 d; | |||||
struct DummyInnerStruct e; | |||||
}; | |||||
spec("memory") { | spec("memory") { | ||||
describe("pool") { | describe("pool") { | ||||
describe("PoolInitialize") { | describe("PoolInitialize") { | ||||
static IZ_Pool pool; | |||||
after_each() { | |||||
mock_reset(SDL_memset); | |||||
} | |||||
after_each() { | |||||
mock_reset(SDL_malloc); | |||||
} | |||||
after_each() { | |||||
IZ_PoolTeardown(&pool); | |||||
} | |||||
it("initializes the pool values") { | |||||
mock_set_expected_calls(SDL_memset, 1); | |||||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||||
check( | |||||
mock_get_expected_calls(SDL_memset) == mock_get_actual_calls(SDL_memset), | |||||
"Call count mismatch." | |||||
); | |||||
} | |||||
it("initializes the pool memory") { | |||||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||||
check( | |||||
mock_is_called(SDL_malloc), | |||||
"Memory not allocated." | |||||
); | |||||
} | |||||
} | } | ||||
describe("PoolAllocate") { | describe("PoolAllocate") { | ||||
static IZ_Pool pool; | |||||
after_each() { | |||||
IZ_PoolTeardown(&pool); | |||||
} | |||||
it("assigns contiguous memory") { | |||||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||||
void* p1 = IZ_PoolAllocate(&pool, sizeof(struct DummyStruct), 0)->pointer; | |||||
void* p2 = IZ_PoolAllocate(&pool, sizeof(u8), 0)->pointer; | |||||
check( | |||||
p2 - p1 == sizeof(struct DummyStruct), | |||||
"Allocated memory mismatch." | |||||
); | |||||
} | |||||
it("ignores previously deallocated items") { | |||||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||||
void* p1 = IZ_PoolAllocate(&pool, sizeof(struct DummyStruct), 0)->pointer; | |||||
void* p2 = IZ_PoolAllocate(&pool, sizeof(u8), 0)->pointer; | |||||
void* p3 = IZ_PoolAllocate(&pool, sizeof(u8), 0)->pointer; | |||||
IZ_PoolDeallocate(p2); | |||||
check( | |||||
p3 - p1 == sizeof(struct DummyStruct) + sizeof(u8), | |||||
"Allocated memory mismatch." | |||||
); | |||||
} | |||||
it("deallocates old items to make way for new ones when the memory is full") { | |||||
IZ_PoolInitialize(&pool, sizeof(u32)); | |||||
IZ_PoolAllocate(&pool, sizeof(u16), 1); | |||||
IZ_PoolAllocate(&pool, sizeof(u8), 0); | |||||
IZ_PoolAllocate(&pool, sizeof(u8), 0); | |||||
IZ_PoolAllocate(&pool, sizeof(u8), 0); | |||||
} | |||||
} | } | ||||
describe("PoolDeallocate") { | |||||
describe("PoolDeallocate") {} | |||||
describe("PoolTeardown") { | |||||
static IZ_Pool pool; | |||||
before_each() { | |||||
IZ_PoolInitialize(&pool, POOL_MAX_SIZE); | |||||
} | |||||
after_each() { | |||||
mock_reset(SDL_free); | |||||
} | |||||
it("frees memory") { | |||||
IZ_PoolTeardown(&pool); | |||||
check( | |||||
mock_is_called(SDL_free), | |||||
"Memory not freed." | |||||
); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -5,7 +5,7 @@ | |||||
spec("output") { | spec("output") { | ||||
describe("video") { | describe("video") { | ||||
describe("VideoSaveConfig") { | |||||
describe("SaveConfig") { | |||||
static IZ_VideoConfig config; | static IZ_VideoConfig config; | ||||
after_each() { | after_each() { | ||||