From 560bd2b7f381b4fd2ce913c27333d968c1d8e2ee Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 2 Jan 2022 10:48:28 -0800 Subject: [PATCH] Adding some assertions --- src/assert/assert.h | 24 ++++++++ src/display/texturescale.h | 4 +- src/engine/CMakeLists.txt | 1 + src/engine/event.c | 81 ++++++++++++++++++++++++++ src/engine/event.h | 68 ++++++++++++++++++++++ src/file/assetmanager.c | 12 ++-- src/file/loaders/font.c | 2 +- src/file/loaders/font.h | 2 +- src/file/loaders/item.c | 10 +++- src/file/loaders/item.h | 6 +- src/file/loaders/scaledtexture.c | 3 +- src/file/loaders/scaledtexture.h | 3 +- src/file/loaders/shader.c | 2 +- src/file/loaders/shader.h | 2 +- src/file/loaders/texture.c | 2 +- src/file/loaders/texture.h | 2 +- src/file/types/common.h | 3 +- src/file/types/font.h | 2 +- src/file/types/shader.h | 4 +- src/file/types/texture.h | 2 +- src/games/poker/game.c | 17 ++++++ src/games/poker/game.h | 1 + src/libs.h | 1 + src/libs.hpp | 16 ------ src/util/array.c | 97 +++++++++++++++++++++++++++++--- src/util/array.h | 26 ++++++++- 26 files changed, 343 insertions(+), 50 deletions(-) create mode 100644 src/assert/assert.h create mode 100644 src/engine/event.c create mode 100644 src/engine/event.h delete mode 100644 src/libs.hpp diff --git a/src/assert/assert.h b/src/assert/assert.h new file mode 100644 index 00000000..6c2a2723 --- /dev/null +++ b/src/assert/assert.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "../libs.h" + +#define ASSERT_TRUE(x) assert(x) + +#define ASSERT_NOT_NULL(x) ASSERT_TRUE(x != NULL) + +#define ASSERT_IF(x, y) (x ? y : false) + +#define ASSERT_EQUAL(x, y) ASSERT_TRUE(x == y) +#define ASSERT_NOT_EQUAL(x, y) ASSERT_TRUE(x != y) + +#define ASSERT_LESS_THAN(x, y) ASSERT_TRUE(x < y) +#define ASSERT_LESS_THAN_EQUAL_TO (x, y) ASSERT_TRUE(x <= y) + +#define ASSERT_GREATER_THAN(x, y) ASSERT_TRUE(x > y) +#define ASSERT_GREATER_THAN_EQUAL_TO(x, y) ASSERT_TRUE(x >= y) \ No newline at end of file diff --git a/src/display/texturescale.h b/src/display/texturescale.h index c92d3d45..df429e09 100644 --- a/src/display/texturescale.h +++ b/src/display/texturescale.h @@ -19,8 +19,8 @@ typedef struct { typedef struct { uint8_t channels; - char *file; - char *path; + const char *file; + const char *path; int16_t baseWidth; int16_t baseHeight; diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 3e1d5dcd..8ebb8542 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -9,4 +9,5 @@ target_sources(${PROJECT_NAME} client.c engine.c thread.c + event.c ) diff --git a/src/engine/event.c b/src/engine/event.c new file mode 100644 index 00000000..15689b9c --- /dev/null +++ b/src/engine/event.c @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2022 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "event.h" + +void eventManagerInit(eventmanager_t *manager) { + uint8_t i; + + ASSERT_NOT_NULL(manager); + + for(i = 0; i < EVENT_LISTENER_COUNT_MAX; i++) { + manager->listeners[i].callback = NULL; + } +} + +bool _eventManagerFindFree(int32_t i, void *item) { + return ((eventlistener_t *) item)->callback == NULL; +} + +eventlistener_t * eventManagerSubscribe( + eventmanager_t *man, event_t event, void *user, eventcallback_t *callback +) { + int32_t first; + eventlistener_t *listener; + + ASSERT_NOT_NULL(man); + ASSERT_NOT_NULL(callback); + + // Find the first available space. + first = arrayFindCallback( + sizeof(eventmanager_t), man->listeners, + EVENT_LISTENER_COUNT_MAX, _eventManagerFindFree + ); + + ASSERT_LESS_THAN(first, EVENT_LISTENER_COUNT_MAX); + ASSERT_GREATER_THAN_EQUAL_TO(first, 0); + + // Insert + listener = man->listeners + first; + listener->callback = callback; + listener->user = user; + listener->event = event; + + return listener; +} + +void eventManagerUnsubscribe(eventmanager_t *man, eventlistener_t *listener) { + ASSERT_NOT_NULL(man); + ASSERT_NOT_NULL(listener); + + listener->callback = NULL; +} + +bool eventManagerTrigger( + eventmanager_t *manager, event_t event, void *args[], int32_t argc +) { + uint8_t i; + eventlistener_t *listener; + bool result; + + ASSERT_GREATER_THAN_EQUAL_TO(argc, 0); + ASSERT_IF( + argc > 0, + ASSERT_NOT_NULL(args) + ); + + for(i = 0; i < EVENT_LISTENER_COUNT_MAX; i++) { + listener = manager->listeners + i; + if(listener->callback == NULL) continue; + if(listener->event != event) continue; + + result = listener->callback(listener->user, event, args, argc); + if(!result) return false; + } + + return true; +} \ No newline at end of file diff --git a/src/engine/event.h b/src/engine/event.h new file mode 100644 index 00000000..977124f4 --- /dev/null +++ b/src/engine/event.h @@ -0,0 +1,68 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "../libs.h" +#include "../assert/assert.h" +#include "../util/array.h" + +#define EVENT_LISTENER_COUNT_MAX 128 + +typedef uint8_t event_t; + +typedef bool eventcallback_t( + void *user, event_t event, void *args[], int32_t argc +); + +typedef struct { + void *user; + event_t event; + eventcallback_t *callback; +} eventlistener_t; + +typedef struct { + eventlistener_t listeners[EVENT_LISTENER_COUNT_MAX]; +} eventmanager_t; + +/** + * Initialize the event manager. + * + * @param manager Event manager to initialize. + */ +void eventManagerInit(eventmanager_t *manager); + +/** + * Subscribe to an event on a given event manager. + * + * @param man Event manager to subscribe to. + * @param event Event to subscribe to. + * @param user Any custom user data to provide to the event callback. + * @param callback Callback to fire when the event is triggered. + * @return The event listener that was subscribed to. + */ +eventlistener_t * eventManagerSubscribe( + eventmanager_t *man, event_t event, void *user, eventcallback_t *callback +); + +/** + * Unsubscribe an event listener that was previously subscribed. + * + * @param listener Listener to unsubscribe. + */ +void eventManagerUnsubscribe(eventmanager_t *man, eventlistener_t *listener); + +/** + * Trigger a specific event on the event manager. + * + * @param manager Manager to trigger the event on. + * @param event Event to trigger + * @param args Array of pointers for event arguments. + * @param argc Count of event arguments. + * @return True if no events are subscribed, otherwise only returns true if all + * event listeners also return true. + */ +bool eventManagerTrigger( + eventmanager_t *manager, event_t event, void *args[], int32_t argc +); \ No newline at end of file diff --git a/src/file/assetmanager.c b/src/file/assetmanager.c index ac4d05b6..afc7fd25 100644 --- a/src/file/assetmanager.c +++ b/src/file/assetmanager.c @@ -11,22 +11,26 @@ assetmanagerloaderdefinition_t ASSET_MANAGER_LOADERS[] = { { &_assetManagerLoaderTextureAsync, &_assetManagerLoaderTextureSync, - &_assetManagerLoaderTextureDispose + &_assetManagerLoaderTextureDispose, + NULL }, { &_assetManagerLoaderFontAsync, &_assetManagerLoaderFontSync, - &_assetManagerLoaderFontDispose + &_assetManagerLoaderFontDispose, + NULL }, { &_assetManagerLoaderShaderAsync, &_assetManagerLoaderShaderSync, - &_assetManagerLoaderShaderDispose + &_assetManagerLoaderShaderDispose, + NULL }, { &_assetManagerLoaderScaledTextureAsync, &_assetManagerLoaderScaledTextureSync, - &_assetManagerLoaderScaledTextureDispose + &_assetManagerLoaderScaledTextureDispose, + NULL } }; diff --git a/src/file/loaders/font.c b/src/file/loaders/font.c index 4e6ceb63..37018028 100644 --- a/src/file/loaders/font.c +++ b/src/file/loaders/font.c @@ -8,7 +8,7 @@ #include "font.h" assetmanageritem_t * assetManagerLoadFont( - assetmanager_t *manager, assetmanagerowner_t owner, char *fileName + assetmanager_t *manager, assetmanagerowner_t owner, const char fileName[] ) { assetmanageritem_t *item; item = assetManagerItemGet(manager, fileName); diff --git a/src/file/loaders/font.h b/src/file/loaders/font.h index 51f79dd8..fc52f6cc 100644 --- a/src/file/loaders/font.h +++ b/src/file/loaders/font.h @@ -19,7 +19,7 @@ * @return A pointer to the asset manager item for tracking. */ assetmanageritem_t * assetManagerLoadFont( - assetmanager_t *manager, assetmanagerowner_t owner, char *fileName + assetmanager_t *manager, assetmanagerowner_t owner, const char fileName[] ); bool _assetManagerLoaderFontAsync(assetmanageritem_t *item); diff --git a/src/file/loaders/item.c b/src/file/loaders/item.c index d8ba68bb..44a2d3a8 100644 --- a/src/file/loaders/item.c +++ b/src/file/loaders/item.c @@ -7,7 +7,9 @@ #include "item.h" -assetmanageritem_t * assetManagerItemGet(assetmanager_t *man, char *key) { +assetmanageritem_t * assetManagerItemGet( + assetmanager_t *man, const char key[] +) { uint8_t i; assetmanageritem_t *item; @@ -19,11 +21,13 @@ assetmanageritem_t * assetManagerItemGet(assetmanager_t *man, char *key) { return NULL; } -assetmanageritem_t * assetManagerItemAdd(assetmanager_t *manager, char *key) { +assetmanageritem_t * assetManagerItemAdd( + assetmanager_t *manager, const char key[] +) { // Check if key already exists. assetmanageritem_t *item = manager->items + manager->itemCount++; item->state = ASSET_MANAGER_STATE_NOT_READY; - memcpy(item->key, key, strlen(key) + 1); + item->key = key; item->holderCount = 0x00; return item; } diff --git a/src/file/loaders/item.h b/src/file/loaders/item.h index 5327cfb4..8a0a843c 100644 --- a/src/file/loaders/item.h +++ b/src/file/loaders/item.h @@ -15,7 +15,7 @@ * @param key Key to search for. * @return The matching asset manager item, or NULL if not found. */ -assetmanageritem_t * assetManagerItemGet(assetmanager_t *man, char *key); +assetmanageritem_t * assetManagerItemGet(assetmanager_t *man, const char key[]); /** * Private method, simply adds an item to the manager and resets the state. @@ -24,7 +24,9 @@ assetmanageritem_t * assetManagerItemGet(assetmanager_t *man, char *key); * @param key Key to use when adding. * @return The added and reset item. */ -assetmanageritem_t * assetManagerItemAdd(assetmanager_t *manager, char *key); +assetmanageritem_t * assetManagerItemAdd( + assetmanager_t *manager, const char key[] +); /** * Add or get the index that a given holder has as a manager item. diff --git a/src/file/loaders/scaledtexture.c b/src/file/loaders/scaledtexture.c index 9749b321..615b093a 100644 --- a/src/file/loaders/scaledtexture.c +++ b/src/file/loaders/scaledtexture.c @@ -8,7 +8,8 @@ #include "scaledtexture.h" assetmanageritem_t * assetManagerLoadScaledTexture( - assetmanager_t *manager, assetmanagerowner_t owner, char *path, char *file + assetmanager_t *manager, assetmanagerowner_t owner, + const char path[], const char file[] ) { assetmanageritem_t *item; texturescale_t *st; diff --git a/src/file/loaders/scaledtexture.h b/src/file/loaders/scaledtexture.h index a92c4f88..7e6b6ff4 100644 --- a/src/file/loaders/scaledtexture.h +++ b/src/file/loaders/scaledtexture.h @@ -21,7 +21,8 @@ * @return A pointer to the asset manager item for tracking. */ assetmanageritem_t * assetManagerLoadScaledTexture( - assetmanager_t *manager, assetmanagerowner_t owner, char *path, char *file + assetmanager_t *manager, assetmanagerowner_t owner, + const char path[], const char file[] ); bool _assetManagerLoaderScaledTextureAsync(assetmanageritem_t *item); diff --git a/src/file/loaders/shader.c b/src/file/loaders/shader.c index 5398c16e..4b31c55e 100644 --- a/src/file/loaders/shader.c +++ b/src/file/loaders/shader.c @@ -9,7 +9,7 @@ assetmanageritem_t * assetManagerLoadShader( assetmanager_t *manager, assetmanagerowner_t owner, - char *fileVert, char *fileFrag + const char fileVert[], const char fileFrag[] ) { assetmanageritem_t *item; char buffer[ASSET_MANAGER_ITEM_NAME_MAX]; diff --git a/src/file/loaders/shader.h b/src/file/loaders/shader.h index 970948e9..a4c64a1d 100644 --- a/src/file/loaders/shader.h +++ b/src/file/loaders/shader.h @@ -21,7 +21,7 @@ */ assetmanageritem_t * assetManagerLoadShader( assetmanager_t *manager, assetmanagerowner_t owner, - char *fileVert, char *fileFrag + const char fileVert[], const char fileFrag[] ); bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item); diff --git a/src/file/loaders/texture.c b/src/file/loaders/texture.c index 3eea99b5..6f002a3d 100644 --- a/src/file/loaders/texture.c +++ b/src/file/loaders/texture.c @@ -8,7 +8,7 @@ #include "texture.h" assetmanageritem_t * assetManagerLoadTexture( - assetmanager_t *manager, assetmanagerowner_t owner, char *fileName + assetmanager_t *manager, assetmanagerowner_t owner, const char fileName[] ) { assetmanageritem_t *item; item = assetManagerItemGet(manager, fileName); diff --git a/src/file/loaders/texture.h b/src/file/loaders/texture.h index 19ffa98d..fbfba0be 100644 --- a/src/file/loaders/texture.h +++ b/src/file/loaders/texture.h @@ -19,7 +19,7 @@ * @return A pointer to the asset manager item for tracking. */ assetmanageritem_t * assetManagerLoadTexture( - assetmanager_t *manager, assetmanagerowner_t owner, char *fileName + assetmanager_t *manager, assetmanagerowner_t owner, const char fileName[] ); bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item); diff --git a/src/file/types/common.h b/src/file/types/common.h index ca21e6a8..6fdda535 100644 --- a/src/file/types/common.h +++ b/src/file/types/common.h @@ -50,7 +50,7 @@ typedef union { typedef struct { uint8_t type; uint8_t state; - char key[ASSET_MANAGER_ITEM_NAME_MAX]; + const char *key; assetmanagerassetdata_t data; assetmanagerowner_t holders[ASSET_MANAGER_HOLDERS_MAX]; uint8_t holderCount; @@ -64,6 +64,7 @@ typedef struct { assetmanagerloader_t *loadAsync; assetmanagerloader_t *loadSync; assetmanagerloader_t *dispose; + assetmanagerloader_t *update; } assetmanagerloaderdefinition_t; diff --git a/src/file/types/font.h b/src/file/types/font.h index 7f7d2203..57dc071f 100644 --- a/src/file/types/font.h +++ b/src/file/types/font.h @@ -10,6 +10,6 @@ typedef struct { font_t font; - char *fileName; + const char *fileName; char *data; } assetmanagerfont_t; \ No newline at end of file diff --git a/src/file/types/shader.h b/src/file/types/shader.h index af7f5de5..76af43ad 100644 --- a/src/file/types/shader.h +++ b/src/file/types/shader.h @@ -9,8 +9,8 @@ typedef struct { shaderprogram_t shader; - char *fileVert; - char *fileFrag; + const char *fileVert; + const char *fileFrag; char *dataVert; char *dataFrag; } assetmanagershader_t; \ No newline at end of file diff --git a/src/file/types/texture.h b/src/file/types/texture.h index 443bc482..27f1c898 100644 --- a/src/file/types/texture.h +++ b/src/file/types/texture.h @@ -9,7 +9,7 @@ typedef struct { texture_t texture; - char *fileName; + const char *fileName; int32_t width, height; pixel_t *data; } assetmanagertexture_t; \ No newline at end of file diff --git a/src/games/poker/game.c b/src/games/poker/game.c index 92ba963e..41b63294 100644 --- a/src/games/poker/game.c +++ b/src/games/poker/game.c @@ -7,7 +7,24 @@ #include "game.h" +#define EVENT_TEST 0x00 + +eventmanager_t eventManager; + +bool onEventTriggered(void *user, event_t event, void *args[], int32_t argc) { + printf("Event!\n"); + return true; +} + bool gameInit(game_t *game) { + + eventManagerInit(&eventManager); + eventManagerSubscribe(&eventManager, EVENT_TEST, NULL, onEventTriggered); + eventManagerTrigger(&eventManager, EVENT_TEST, NULL, 0); + eventManagerTrigger(&eventManager, EVENT_TEST, NULL, 0); + printf("Done.\n"); + + // Init the engine and the rendering pipeline engineInit(&game->engine); diff --git a/src/games/poker/game.h b/src/games/poker/game.h index e1f10b78..9532a275 100644 --- a/src/games/poker/game.h +++ b/src/games/poker/game.h @@ -8,6 +8,7 @@ #pragma once #include "../../libs.h" #include "../../engine/engine.h" +#include "../../engine/event.h" #include "../../display/primitive/primitive.h" #include "../../display/primitive/quad.h" #include "../../display/primitive/cube.h" diff --git a/src/libs.h b/src/libs.h index d0ac5a50..82bd9332 100644 --- a/src/libs.h +++ b/src/libs.h @@ -20,6 +20,7 @@ #include #include #include +#include #if defined(_WIN32) || defined(_WIN64) // Windows Fixes diff --git a/src/libs.hpp b/src/libs.hpp deleted file mode 100644 index c8ad5a54..00000000 --- a/src/libs.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2021 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once - -extern "C" { - #include "libs.h" -} - -#include -#include -#include -#include -#include \ No newline at end of file diff --git a/src/util/array.c b/src/util/array.c index 44ad30f3..b1b66bea 100644 --- a/src/util/array.c +++ b/src/util/array.c @@ -8,17 +8,31 @@ #include "array.h" void * arrayGet(size_t size, void *array, int32_t index) { + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(array); + ASSERT_GREATER_THAN_EQUAL_TO(index, 0); + return (char *)array + (index * (size/sizeof(char))); } void arraySet(size_t size, void *array, int32_t index, void *data) { + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(array); + ASSERT_GREATER_THAN_EQUAL_TO(index, 0); + memcpy(arrayGet(size, array, index), data, size); } void arrayShuffle(size_t size, void *array, int32_t arrayLength) { int32_t x, y; - void *itemDest, *itemSource; - void *temporary = malloc(size); + void *itemDest, *itemSource, *temporary; + + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(array); + ASSERT_GREATER_THAN_EQUAL_TO(arrayLength, 0); + + temporary = malloc(size); + ASSERT_NOT_NULL(temporary); for(x = 0; x < arrayLength-1; x++) { // Select random element from remaining elements. @@ -45,6 +59,11 @@ int32_t arrayFind(size_t size, void *array, int32_t length, void *value) { int32_t i; void *item; + ASSERT_GREATER_THAN(size, 0); + ASSERT_GREATER_THAN_EQUAL_TO(length, 0); + ASSERT_NOT_NULL(array); + ASSERT_NOT_NULL(value); + for(i = 0; i < length; i++) { // Get the item and compare. item = arrayGet(size, array, i); @@ -55,16 +74,44 @@ int32_t arrayFind(size_t size, void *array, int32_t length, void *value) { return -1; } +int32_t arrayFindCallback( + size_t size, void *array, int32_t length, arrayiterationcallback_t *callback +) { + int32_t i; + void *item; + + ASSERT_GREATER_THAN(size, 0); + ASSERT_GREATER_THAN(length, 0); + ASSERT_NOT_NULL(array); + ASSERT_NOT_NULL(callback); + + for(i = 0; i < length; i++) { + item = arrayGet(size, array, i); + if(callback(i, item)) return i; + } + return -1; +} + bool arrayContains(size_t size, void *array, int32_t length, void *value) { int32_t i = arrayFind(size, array, length, value); return i != -1; } void arrayCopy(size_t size, void *source, int32_t length, void *dest) { + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(source); + ASSERT_GREATER_THAN_EQUAL_TO(length, 0); + ASSERT_NOT_NULL(dest); + memcpy(dest, source, size * length); } void arraySort(size_t size, void *array, int32_t length, arraysort_t *sort) { + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(array); + ASSERT_GREATER_THAN_EQUAL_TO(length, 0); + ASSERT_NOT_NULL(sort); + qsort(array, length, size, sort); } @@ -86,7 +133,13 @@ int32_t _arraySorterUint8(const void* left, const void* right) { int32_t arrayFindString(char **array, int32_t arrayLength, char *value) { int32_t i; + + ASSERT_NOT_NULL(array); + ASSERT_NOT_NULL(value); + ASSERT_GREATER_THAN_EQUAL_TO(arrayLength, 0); + for(i = 0; i < arrayLength; i++) { + ASSERT_NOT_NULL(array[i]); if(strcmp(array[i], value) == 0) return i; } return -1; @@ -95,10 +148,19 @@ int32_t arrayFindString(char **array, int32_t arrayLength, char *value) { void arrayRewind(size_t size, void *source, int32_t length, int32_t start, int32_t count ) { + void *temporary; + + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(source); + ASSERT_GREATER_THAN_EQUAL_TO(length, 0); + ASSERT_GREATER_THAN_EQUAL_TO(start, 0); + ASSERT_GREATER_THAN_EQUAL_TO(count, -1); + if(count == -1) count = length - start; // Create a temporary new array to house the data. - void *temporary = malloc(size * count); + temporary = malloc(size * count); + ASSERT_NOT_NULL(temporary); // Copy the data from the source to the temporary array. arrayCopy(size, arrayGet(size, source, start), count, temporary); @@ -113,11 +175,22 @@ void arrayRewind(size_t size, void *source, int32_t length, int32_t start, void arraySplice( size_t size, void *array, int32_t start, int32_t count, int32_t length ) { - // Take the end of the array... - int32_t takeStart = start + count; - int32_t takeLength = length - takeStart; + int32_t takeStart, takeLength; + void *temporary; + + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(array); + ASSERT_GREATER_THAN_EQUAL_TO(start, 0); + ASSERT_GREATER_THAN_EQUAL_TO(count, 0); + ASSERT_GREATER_THAN_EQUAL_TO(length, 0); + + // Take the end of the array... + takeStart = start + count; + takeLength = length - takeStart; + + temporary = malloc(size * takeLength); + ASSERT_NOT_NULL(temporary); - void *temporary = malloc(size * takeLength); arrayCopy(size, arrayGet(size, array, takeStart), takeLength, temporary); // Now copy it back into the original array @@ -127,12 +200,18 @@ void arraySplice( int32_t arraySum( - size_t size, void *array, int32_t length, arraysumcallback_t *callback + size_t size, void *array, int32_t length, arrayiterationcallback_t *callback ) { int32_t i, count; + + ASSERT_GREATER_THAN(size, 0); + ASSERT_NOT_NULL(array); + ASSERT_GREATER_THAN_EQUAL_TO(length, 0); + ASSERT_NOT_NULL(callback); + count = 0; for(i = 0; i < length; i++) { - if(!callback(arrayGet(size, array, i))) continue; + if(!callback(i, arrayGet(size, array, i))) continue; count++; } return count; diff --git a/src/util/array.h b/src/util/array.h index 59024e25..000a2f03 100644 --- a/src/util/array.h +++ b/src/util/array.h @@ -7,6 +7,7 @@ #pragma once #include "../libs.h" +#include "../assert/assert.h" #include "rand.h" /** @@ -25,6 +26,15 @@ typedef int32_t arraysort_t(const void*, const void*); */ typedef bool arraysumcallback_t(void*); +/** + * Generic array iteration callback. + * + * @param i Index of the item within the array. + * @param itm Item at that index. + * @return Depending on the usage of the iteration callback. + */ +typedef bool arrayiterationcallback_t(int32_t i, void *itm); + /** * Retreive the pointer to an elment within the array of unknown type. * @@ -66,6 +76,20 @@ void arrayShuffle(size_t size, void *array, int32_t arrayLength); */ int32_t arrayFind(size_t size, void *array, int32_t length, void *value); +/** + * Find the first index within the array that matches the result of the callback + * when the callback returns true. + * + * @param size Size of each element within the array. + * @param array Array to search. + * @param length Length of the array to search. + * @param callback Callback to use when performing lookup. + * @return The first index that matches, or -1 if no match is found. + */ +int32_t arrayFindCallback( + size_t size, void *array, int32_t length, arrayiterationcallback_t *callback +); + /** * Compares each item in an array with the specified value, and returns true if * found within the array. This is a shorthand for arrayFind without an int32_t @@ -169,5 +193,5 @@ void arraySplice( * @return The count of items that matched the callback invokation. */ int32_t arraySum( - size_t size, void *array, int32_t length, arraysumcallback_t *callback + size_t size, void *array, int32_t length, arrayiterationcallback_t *callback ); \ No newline at end of file