From 1480e1bda90d1c52e5ad44a994409eccf5dacec9 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Fri, 19 Sep 2025 08:32:22 -0500 Subject: [PATCH 01/34] :sparkles: Fix juno juno --- include/juno/macros.h | 2 +- src/juno_hash.c | 2 +- src/juno_map.c | 2 +- src/juno_memory_block.c | 2 +- templates/template_app/src/template_app.cpp | 2 +- templates/template_impl/src/template_impl.c | 2 +- templates/template_lib/src/template_impl.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/juno/macros.h b/include/juno/macros.h index 3088880a..e33d62a3 100644 --- a/include/juno/macros.h +++ b/include/juno/macros.h @@ -38,7 +38,7 @@ if(!(ptr)) \ @param ptMod The module @param str The error message if `ptr` fails assertion */ -#define JUNO_JUNO_ASSERT_EXISTS_MODULE(ptr, ptMod, str) if(!(ptr)) \ +#define JUNO_ASSERT_EXISTS_MODULE(ptr, ptMod, str) if(!(ptr)) \ { \ JUNO_FAIL_MODULE(JUNO_STATUS_NULLPTR_ERROR, ptMod, str); \ return JUNO_STATUS_NULLPTR_ERROR; \ diff --git a/src/juno_hash.c b/src/juno_hash.c index eb8c66e9..6c6ff733 100644 --- a/src/juno_hash.c +++ b/src/juno_hash.c @@ -24,7 +24,7 @@ static inline JUNO_STATUS_T Verify(JUNO_HASH_T *ptJunoHash) { JUNO_ASSERT_EXISTS(ptJunoHash); JUNO_HASH_DJB2_T *ptJunoHashDjb2 = (JUNO_HASH_DJB2_T *)(ptJunoHash); - JUNO_JUNO_ASSERT_EXISTS_MODULE( + JUNO_ASSERT_EXISTS_MODULE( ptJunoHash && ptJunoHashDjb2->JUNO_MODULE_SUPER.ptApi /* TODO: Assert other dependencies and members here using &&*/, ptJunoHashDjb2, diff --git a/src/juno_map.c b/src/juno_map.c index 455c5d54..1d35ac67 100644 --- a/src/juno_map.c +++ b/src/juno_map.c @@ -30,7 +30,7 @@ static inline JUNO_STATUS_T Verify(JUNO_MAP_T *ptJunoMap) { JUNO_ASSERT_EXISTS(ptJunoMap); JUNO_MAP_IMPL_T *ptJunoMapImpl = (JUNO_MAP_IMPL_T *)(ptJunoMap); - JUNO_JUNO_ASSERT_EXISTS_MODULE( + JUNO_ASSERT_EXISTS_MODULE( ptJunoMap && ptJunoMapImpl->JUNO_MODULE_SUPER.ptApi && ptJunoMapImpl->JUNO_MODULE_SUPER.ptMapKeys && diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index 2145f056..c275f115 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -27,7 +27,7 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_T *ptJunoMemory) { JUNO_ASSERT_EXISTS(ptJunoMemory); JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); - JUNO_JUNO_ASSERT_EXISTS_MODULE( + JUNO_ASSERT_EXISTS_MODULE( ptJunoMemory && ptJunoMemoryBlock->JUNO_MODULE_SUPER.ptApi && ptJunoMemoryBlock->pvMemory && diff --git a/templates/template_app/src/template_app.cpp b/templates/template_app/src/template_app.cpp index 859d2f14..68681174 100644 --- a/templates/template_app/src/template_app.cpp +++ b/templates/template_app/src/template_app.cpp @@ -85,7 +85,7 @@ static inline JUNO_STATUS_T Verify(JUNO_APP_T *ptJunoApp) // Cast to the template app TEMPLATE_APP_T *ptTemplateApp = (TEMPLATE_APP_T *)(ptJunoApp); // Assert the module dependencies are present - JUNO_JUNO_ASSERT_EXISTS_MODULE( + JUNO_ASSERT_EXISTS_MODULE( /* TODO: Assert other dependencies and members here using &&*/ ptTemplateApp && ptTemplateApp->tRoot.ptApi, diff --git a/templates/template_impl/src/template_impl.c b/templates/template_impl/src/template_impl.c index 4dcb2c4d..d432dc11 100644 --- a/templates/template_impl/src/template_impl.c +++ b/templates/template_impl/src/template_impl.c @@ -50,7 +50,7 @@ static inline JUNO_STATUS_T Verify(TEMPLATE_T *ptTemplate) { JUNO_ASSERT_EXISTS(ptTemplate); TEMPLATE_IMPL_T *ptTemplateImpl = (TEMPLATE_IMPL_T *)(ptTemplate); - JUNO_JUNO_ASSERT_EXISTS_MODULE( + JUNO_ASSERT_EXISTS_MODULE( ptTemplate && ptTemplateImpl->JUNO_MODULE_SUPER.ptApi /* TODO: Assert other dependencies and members here using &&*/, ptTemplateImpl, diff --git a/templates/template_lib/src/template_impl.c b/templates/template_lib/src/template_impl.c index e6145059..07de3464 100644 --- a/templates/template_lib/src/template_impl.c +++ b/templates/template_lib/src/template_impl.c @@ -50,7 +50,7 @@ static inline JUNO_STATUS_T Verify(TEMPLATE_T *ptTemplate) { JUNO_ASSERT_EXISTS(ptTemplate); TEMPLATE_IMPL_T *ptTemplateImpl = (TEMPLATE_IMPL_T *)(ptTemplate); - JUNO_JUNO_ASSERT_EXISTS_MODULE( + JUNO_ASSERT_EXISTS_MODULE( ptTemplate && ptTemplateImpl->tRoot.ptApi /* TODO: Assert other dependencies and members here using &&*/, ptTemplateImpl, From 4144d89509153c2561d79983df08d4ffca9cc59b Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Fri, 19 Sep 2025 13:29:05 -0500 Subject: [PATCH 02/34] :sparkles: Fix map --- CMakeLists.txt | 2 - include/juno/map/map_api.h | 124 +++++-- include/juno/map/map_impl.h | 77 ---- include/juno/sb/broker_api.h | 70 ++++ include/juno/sb/msg_api.h | 4 +- include/juno/types.h | 1 + src/juno_map.c | 162 ++------- tests/test_map.c | 664 ++++++++++++++++++++--------------- 8 files changed, 570 insertions(+), 534 deletions(-) delete mode 100644 include/juno/map/map_impl.h create mode 100644 include/juno/sb/broker_api.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ecbca97..0a52c033 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,8 +52,6 @@ set(JUNO_COMPILE_CXX_OPTIONS ) set(JUNO_COMPILE_C_OPTIONS - -Wstrict-prototypes # Warn if a function is declared without specifying argument types - -Wmissing-prototypes # Warn if a global function is defined without a previous prototype declaration ) if(JUNO_PIC) diff --git a/include/juno/map/map_api.h b/include/juno/map/map_api.h index 96fbb9d2..559fb9f1 100644 --- a/include/juno/map/map_api.h +++ b/include/juno/map/map_api.h @@ -26,55 +26,121 @@ */ #ifndef JUNO_MAP_API_H #define JUNO_MAP_API_H -#include "juno/hash/hash_api.h" -#include "juno/memory/memory_api.h" -#include "juno/status.h" +#include "juno/macros.h" #include "juno/module.h" #include +#include +#include "juno/status.h" +#include "juno/types.h" #ifdef __cplusplus extern "C" { #endif typedef struct JUNO_MAP_API_TAG JUNO_MAP_API_T; -typedef bool (*JUNO_MAP_KEY_EQUAL_FCN_T)(JUNO_MEMORY_T ptKey1, JUNO_MEMORY_T ptKey2); typedef union JUNO_MAP_TAG JUNO_MAP_T; typedef struct JUNO_MAP_ROOT_TAG JUNO_MAP_ROOT_T; struct JUNO_MAP_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MAP_API_T, - JUNO_HASH_T *ptHash; - JUNO_MEMORY_T *ptMapKeys; - JUNO_MEMORY_T *ptMapValues; size_t zCapacity; - size_t zLenHashTable; - JUNO_MAP_KEY_EQUAL_FCN_T pfcnIsEqual; ); + struct JUNO_MAP_API_TAG { - /// Add a key,value pair to the map - /// @param ptMap A pointer to the map - /// @param ptKey A key to add - /// @param pvValue A value to add - /// @return Status of operation - JUNO_STATUS_T (*Set)(JUNO_MAP_T *ptMap, JUNO_MEMORY_T tKey, JUNO_MEMORY_T tValue); - - /// Remove a key,value pair from the map - /// @param ptMap A pointer to the map - /// @param tKey The key to remove - /// @return Status of operation - JUNO_STATUS_T (*Remove)(JUNO_MAP_T *ptMap, JUNO_MEMORY_T tKey); - - /// Get a value from the map using the key - /// @param ptMap A pointer to the map - /// @param tKey The key to use - /// @param ptRetVal The return value retrieved using the key - /// @return Status of operation - /// Returns `JUNO_STATUS_DNE_ERROR` if the key is not in the map - JUNO_STATUS_T (*Get)(JUNO_MAP_T *ptMap, JUNO_MEMORY_T tKey, JUNO_MEMORY_T *ptRetValue); + JUNO_RESULT_SIZE_T (*Hash)(void *ptKey); + JUNO_RESULT_BOOL_T (*KeyIsEqual)(void *ptLeft, void *ptRight); + JUNO_RESULT_VOID_PTR_T (*GetValue)(size_t iIndex); + JUNO_RESULT_VOID_PTR_T (*GetKey)(size_t iIndex); + JUNO_STATUS_T (*SetValue)(size_t iIndex, void *ptValue); + JUNO_STATUS_T (*SetKey)(size_t iIndex, void *ptKey); + JUNO_STATUS_T (*Remove)(size_t iIndex); + JUNO_RESULT_BOOL_T (*IsEmpty)(size_t zIndex); }; +static inline JUNO_STATUS_T JunoMap_VerifyApi(const JUNO_MAP_API_T *ptApi) +{ + JUNO_ASSERT_EXISTS( + ptApi && + ptApi->Hash && + ptApi->KeyIsEqual && + ptApi->GetValue && + ptApi->GetKey && + ptApi->SetValue && + ptApi->SetKey && + ptApi->Remove && + ptApi->IsEmpty + ); + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T JunoMap_Verify(JUNO_MAP_ROOT_T *ptMap) +{ + JUNO_ASSERT_EXISTS(ptMap); + JUNO_STATUS_T tStatus = JunoMap_VerifyApi(ptMap->ptApi); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_EXISTS(ptMap->zCapacity); + return tStatus; +} + +JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey); + +static inline JUNO_STATUS_T JunoMap_Set(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey, void *ptValue) +{ + JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); + tStatus = tSizeResult.tStatus; + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = ptJunoMap->ptApi->SetKey(tSizeResult.tOk, ptKey); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = ptJunoMap->ptApi->SetValue(tSizeResult.tOk, ptValue); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + return tStatus; +} + +static inline JUNO_RESULT_VOID_PTR_T JunoMap_Get(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) +{ + JUNO_RESULT_VOID_PTR_T tResult = {0, NULL}; + tResult.tStatus = JunoMap_Verify(ptJunoMap); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); + tResult.tStatus = tSizeResult.tStatus; + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); + tResult.tStatus = tBoolResult.tStatus; + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + bool bIsEmpty = tBoolResult.tOk; + if(bIsEmpty) + { + tResult.tStatus = JUNO_STATUS_DNE_ERROR; + return tResult; + } + return ptJunoMap->ptApi->GetValue(tSizeResult.tOk); +} + +static inline JUNO_STATUS_T JunoMap_Remove(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) +{ + JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); + tStatus = tSizeResult.tStatus; + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); + tStatus = tBoolResult.tStatus; + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + bool bIsEmpty = tBoolResult.tOk; + if(bIsEmpty) + { + tStatus = JUNO_STATUS_DNE_ERROR; + return tStatus; + } + tStatus = ptJunoMap->ptApi->Remove(tSizeResult.tOk); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + return tStatus; +} + #ifdef __cplusplus } #endif diff --git a/include/juno/map/map_impl.h b/include/juno/map/map_impl.h deleted file mode 100644 index 45a0aa00..00000000 --- a/include/juno/map/map_impl.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_map impl implementation - @author Robin Onsay -*/ -#ifndef JUNO_MAP_IMPL_H -#define JUNO_MAP_IMPL_H -#include "juno/module.h" -#include "juno/status.h" -#include "juno/map/map_api.h" -#ifdef __cplusplus -extern "C" -{ -#endif - - -typedef struct JUNO_MAP_IMPL_TAG JUNO_MAP_IMPL_T; - -struct JUNO_MAP_IMPL_TAG JUNO_MODULE_DERIVE(JUNO_MAP_ROOT_T, - /* - - TODO: Include implementation specific members here - - */ -); - -#ifdef JUNO_MAP_DEFAULT -/** - This is the default implementation for `JUNO_MAP_T`. - If you want to use the default implementation for `JUNO_MAP_T` - use `#define JUNO_MAP_DEFAULT` prior to including - `#include "juno_map_impl.h"` - - Note: If you are implementing a derived module you will need - to implement `JUNO_MAP_IMPL`. -*/ -union JUNO_MAP_TAG JUNO_MODULE(JUNO_MAP_API_T, JUNO_MAP_ROOT_T, - JUNO_MAP_IMPL_T tJunoMapImpl; -); -#endif - -JUNO_STATUS_T JunoMap_ImplApi( - JUNO_MAP_T *ptJunoMap, - JUNO_HASH_T *ptHash, - JUNO_MEMORY_T *ptKeyTable, - JUNO_MEMORY_T *ptValueTable, - size_t zCapacity, - JUNO_MAP_KEY_EQUAL_FCN_T pfcnIsEqual, - JUNO_FAILURE_HANDLER_T pfcnFailureHandler, - JUNO_USER_DATA_T *pvFailureUserData -); -#ifdef __cplusplus -} -#endif -#endif // JUNO_MAP_IMPL_H - diff --git a/include/juno/sb/broker_api.h b/include/juno/sb/broker_api.h new file mode 100644 index 00000000..c7c91005 --- /dev/null +++ b/include/juno/sb/broker_api.h @@ -0,0 +1,70 @@ +/* + MIT License + + Copyright (c) 2025 Robin A. Onsay + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. +*/ + +/** + This API has been generated by LibJuno: + https://www.robinonsay.com/libjuno/ +*/ + +/** + This header contains the juno_msg library API + @author Robin Onsay +*/ +#ifndef JUNO_BROKER_API_H +#define JUNO_BROKER_API_H +#include "juno/memory/memory_api.h" +#include "juno/status.h" +#include "juno/module.h" +#include +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct JUNO_BROKER_API_TAG JUNO_BROKER_API_T; +typedef struct JUNO_MSG_BUFFER_HDR_TAG JUNO_MSG_BUFFER_HDR_T; + +typedef union JUNO_MSG_TAG JUNO_MSG_T; +typedef struct JUNO_MSG_ROOT_TAG JUNO_MSG_ROOT_T; + +struct JUNO_MSG_BUFFER_HDR_TAG +{ + JUNO_MSG_BUFFER_HDR_T *ptNext; + size_t zBufferSize; +}; + +/// Creates a new buffer +#define JunoMsg_NewBuffer(BUFFER_T, ...) {{NULL, sizeof(BUFFER_T)}, __VA_ARGS__} + +struct JUNO_MSG_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BROKER_API_T, + JUNO_MEMORY_ALLOC_T *ptAlloc; +); + +struct JUNO_BROKER_API_TAG +{ + /// Verify the message + JUNO_STATUS_T (*VerifyMsg)(JUNO_MSG_T *ptJunoMsg); + /// Get the message buffer + JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_HDR_T *ptRetBuffer); + /// Set the message buffer + JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_HDR_T tRetBuffer); +}; + +#ifdef __cplusplus +} +#endif +#endif // JUNO_BROKER_API_H diff --git a/include/juno/sb/msg_api.h b/include/juno/sb/msg_api.h index 4aa37b10..08a5ff9a 100644 --- a/include/juno/sb/msg_api.h +++ b/include/juno/sb/msg_api.h @@ -35,12 +35,12 @@ extern "C" #endif typedef struct JUNO_MSG_API_TAG JUNO_MSG_API_T; -typedef struct JUNO_MSG_BUFFER_TAG JUNO_MSG_BUFFER_T; +typedef struct JUNO_MSG_BUFFER_HDR_TAG JUNO_MSG_BUFFER_T; typedef union JUNO_MSG_TAG JUNO_MSG_T; typedef struct JUNO_MSG_ROOT_TAG JUNO_MSG_ROOT_T; -struct JUNO_MSG_BUFFER_TAG +struct JUNO_MSG_BUFFER_HDR_TAG { void *pvBuffer; size_t zBufferSize; diff --git a/include/juno/types.h b/include/juno/types.h index 8706c32d..f4e721be 100644 --- a/include/juno/types.h +++ b/include/juno/types.h @@ -30,6 +30,7 @@ JUNO_MODULE_RESULT(JUNO_RESULT_BOOL_T, bool); JUNO_MODULE_RESULT(JUNO_RESULT_UINT32_T, uint32_t); JUNO_MODULE_RESULT(JUNO_RESULT_F64_T, double); JUNO_MODULE_RESULT(JUNO_RESULT_SIZE_T, size_t); +JUNO_MODULE_RESULT(JUNO_RESULT_VOID_PTR_T, void *); #ifdef __cplusplus } diff --git a/src/juno_map.c b/src/juno_map.c index 1d35ac67..3e0fcc32 100644 --- a/src/juno_map.c +++ b/src/juno_map.c @@ -14,159 +14,55 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. */ -#include "juno/hash/hash_api.h" #include "juno/macros.h" -#include "juno/map/map_impl.h" -#include "juno/memory/memory_api.h" +#include "juno/map/map_api.h" #include "juno/status.h" #include "juno/macros.h" #include #include #include -static const JUNO_MAP_API_T tJunoMapImplApi; - -static inline JUNO_STATUS_T Verify(JUNO_MAP_T *ptJunoMap) +JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { - JUNO_ASSERT_EXISTS(ptJunoMap); - JUNO_MAP_IMPL_T *ptJunoMapImpl = (JUNO_MAP_IMPL_T *)(ptJunoMap); - JUNO_ASSERT_EXISTS_MODULE( - ptJunoMap && - ptJunoMapImpl->JUNO_MODULE_SUPER.ptApi && - ptJunoMapImpl->JUNO_MODULE_SUPER.ptMapKeys && - ptJunoMapImpl->JUNO_MODULE_SUPER.ptHash && - ptJunoMapImpl->JUNO_MODULE_SUPER.ptMapValues && - ptJunoMapImpl->JUNO_MODULE_SUPER.zCapacity && - ptJunoMapImpl->JUNO_MODULE_SUPER.pfcnIsEqual, - ptJunoMapImpl, - "Module does not have all dependencies" - ); - if(ptJunoMapImpl->JUNO_MODULE_SUPER.ptApi != &tJunoMapImplApi) - { - JUNO_FAIL_MODULE(JUNO_STATUS_INVALID_TYPE_ERROR, ptJunoMapImpl, "Module has invalid API"); - return JUNO_STATUS_INVALID_TYPE_ERROR; - } - return JUNO_STATUS_SUCCESS; -} - -static inline JUNO_STATUS_T Juno_MapGetIndex(JUNO_MAP_T *ptJunoMap, JUNO_MEMORY_T tKey, size_t *pzRetSize, bool bShallEqual) -{ - - JUNO_MAP_IMPL_T *ptMap = (JUNO_MAP_IMPL_T *)(ptJunoMap); - size_t zHash = 0; - JUNO_HASH_ROOT_T *ptHash = (JUNO_HASH_ROOT_T *)(ptMap->tRoot.ptHash); - JUNO_STATUS_T tStatus = ptHash->ptApi->Hash(ptMap->tRoot.ptHash, (const uint8_t *)(tKey.pvAddr), tKey.zSize, &zHash); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_RESULT_SIZE_T tResult = {0, 0}; + tResult.tStatus = JunoMap_Verify(ptJunoMap); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + const JUNO_MAP_API_T *ptApi = ptJunoMap->ptApi; + tResult = ptApi->Hash(ptKey); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + size_t iHash = tResult.tOk; // Get the capacity - size_t zCapacity = ptMap->tRoot.zCapacity; - tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + size_t zCapacity = ptJunoMap->zCapacity; + tResult.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; // Calculate the index - size_t zIndex = zHash % zCapacity; // Set the initial status // Iterate over the table for (size_t i = 0; i < zCapacity; i++) { + size_t zIndex = (iHash + i) % zCapacity; // Get a pointer to the current key - JUNO_MEMORY_T tCurKey = ptMap->tRoot.ptMapKeys[zIndex]; + JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetKey(zIndex); + tResult.tStatus = tPtrResult.tStatus; + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + void *pvAddr = tPtrResult.tOk; + JUNO_RESULT_BOOL_T tBoolResult = ptApi->IsEmpty( zIndex); + tResult.tStatus = tBoolResult.tStatus; + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + bool bIsEmpty = tBoolResult.tOk; + tBoolResult = ptApi->KeyIsEqual(ptKey, pvAddr); + tResult.tStatus = tBoolResult.tStatus; + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + bool bIsEqual = tBoolResult.tOk; // Check if the spot is empty or the key is equal - if((!tCurKey.pvAddr && !bShallEqual) || (tCurKey.pvAddr && tKey.pvAddr && ptMap->tRoot.pfcnIsEqual(tCurKey, tKey))) + if(bIsEmpty || bIsEqual) { // Return the index - *pzRetSize = zIndex; - tStatus = JUNO_STATUS_SUCCESS; - ptMap->tRoot.zLenHashTable += 1; + tResult.tOk = zIndex; + tResult.tStatus = JUNO_STATUS_SUCCESS; break; } - zIndex = (zHash + i) % zCapacity; - } - if(tStatus != JUNO_STATUS_SUCCESS) - { - JUNO_FAIL_MODULE(tStatus, ptMap, "Map is full"); + tResult.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; } // Return the status - return tStatus; -} - -static JUNO_STATUS_T Juno_MapSet(JUNO_MAP_T *ptJunoMap, JUNO_MEMORY_T tKey, JUNO_MEMORY_T tValue) -{ - JUNO_MAP_IMPL_T *ptMap = (JUNO_MAP_IMPL_T *)(ptJunoMap); - JUNO_STATUS_T tStatus = Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - size_t zIndex = 0; - tStatus = Juno_MapGetIndex(ptJunoMap, tKey, &zIndex, false); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptMap->tRoot.ptMapKeys[zIndex] = tKey; - ptMap->tRoot.ptMapValues[zIndex] = tValue; - return tStatus; -} - -static JUNO_STATUS_T Juno_MapRemove(JUNO_MAP_T *ptJunoMap, JUNO_MEMORY_T tKey) -{ - JUNO_MAP_IMPL_T *ptMap = (JUNO_MAP_IMPL_T *)(ptJunoMap); - JUNO_STATUS_T tStatus = Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - size_t zIndex = 0; - tStatus = Juno_MapGetIndex(ptJunoMap, tKey, &zIndex, true); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptMap->tRoot.ptMapKeys[zIndex] = (JUNO_MEMORY_T){0}; - ptMap->tRoot.ptMapValues[zIndex] = (JUNO_MEMORY_T){0}; - return tStatus; -} - - -static JUNO_STATUS_T Juno_MapGet(JUNO_MAP_T *ptJunoMap, JUNO_MEMORY_T tKey, JUNO_MEMORY_T *ptRetValue) -{ - JUNO_MAP_IMPL_T *ptMap = (JUNO_MAP_IMPL_T *)(ptJunoMap); - JUNO_STATUS_T tStatus = Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - size_t zIndex = 0; - tStatus = Juno_MapGetIndex(ptJunoMap, tKey, &zIndex, true); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - if(!ptMap->tRoot.ptMapKeys[zIndex].pvAddr) - { - tStatus = JUNO_STATUS_DNE_ERROR; - JUNO_FAIL_MODULE(tStatus, ptMap, "Key Does not exist"); - return tStatus; - } - *ptRetValue = ptMap->tRoot.ptMapValues[zIndex]; - return tStatus; -} - -static const JUNO_MAP_API_T tJunoMapImplApi = -{ - .Set = Juno_MapSet, - .Remove = Juno_MapRemove, - .Get = Juno_MapGet -}; - -JUNO_STATUS_T JunoMap_ImplApi( - JUNO_MAP_T *ptJunoMap, - JUNO_HASH_T *ptHash, - JUNO_MEMORY_T *ptKeyTable, - JUNO_MEMORY_T *ptValueTable, - size_t zCapacity, - JUNO_MAP_KEY_EQUAL_FCN_T pfcnIsEqual, - JUNO_FAILURE_HANDLER_T pfcnFailureHandler, - JUNO_USER_DATA_T *pvFailureUserData -) -{ - JUNO_ASSERT_EXISTS(ptJunoMap); - JUNO_MAP_IMPL_T *ptJunoMapImpl = (JUNO_MAP_IMPL_T *)(ptJunoMap); - ptJunoMapImpl->JUNO_MODULE_SUPER.ptApi = &tJunoMapImplApi; - ptJunoMapImpl->JUNO_MODULE_SUPER.JUNO_FAILURE_HANDLER = pfcnFailureHandler; - ptJunoMapImpl->JUNO_MODULE_SUPER.JUNO_FAILURE_USER_DATA = pvFailureUserData; - ptJunoMapImpl->JUNO_MODULE_SUPER.ptHash = ptHash; - ptJunoMapImpl->JUNO_MODULE_SUPER.ptMapKeys = ptKeyTable; - ptJunoMapImpl->JUNO_MODULE_SUPER.ptMapValues = ptValueTable; - ptJunoMapImpl->JUNO_MODULE_SUPER.zCapacity = zCapacity; - ptJunoMapImpl->JUNO_MODULE_SUPER.zLenHashTable = 0; - ptJunoMapImpl->JUNO_MODULE_SUPER.pfcnIsEqual = pfcnIsEqual; - JUNO_STATUS_T tStatus = Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - for(size_t i = 0; i < zCapacity; i++) - { - ptKeyTable[i] = (JUNO_MEMORY_T){0}; - ptValueTable[i] = (JUNO_MEMORY_T){0}; - } - return tStatus; + return tResult; } diff --git a/tests/test_map.c b/tests/test_map.c index 297db171..48bf8663 100644 --- a/tests/test_map.c +++ b/tests/test_map.c @@ -1,344 +1,424 @@ -#include "juno/hash/hash_api.h" -#include "juno/map/map_api.h" -#define JUNO_HASH_DEFAULT -#include "juno/hash/hash_djb2.h" -#define JUNO_MAP_DEFAULT -#include "juno/map/map_impl.h" -#include "juno/status.h" #include "unity.h" #include #include #include +#include "juno/map/map_api.h" + +#ifndef TEST_MAP_CAPACITY +#define TEST_MAP_CAPACITY 16 +#endif -static JUNO_HASH_T gtHash = {0}; +// Storage for test map +static void *gKeys[TEST_MAP_CAPACITY]; +static void *gValues[TEST_MAP_CAPACITY]; +static bool gOccupied[TEST_MAP_CAPACITY]; -static const JUNO_MAP_API_T *gptMapApi = {0}; +// Forward-declared API and root +static JUNO_MAP_API_T gApi; +static JUNO_MAP_ROOT_T gRoot; -typedef struct +// Helpers +static void TestMap_Reset(void) { - char key[32]; -} TEST_KEY; + memset(gKeys, 0, sizeof(gKeys)); + memset(gValues, 0, sizeof(gValues)); + memset(gOccupied, 0, sizeof(gOccupied)); +} -typedef struct +// Simple digit parser +static size_t parse_digits(const char *s) { - int value; -} TEST_VALUE; + size_t v = 0; + while (*s >= '0' && *s <= '9') + { + v = (v * 10) + (size_t)(*s - '0'); + s++; + } + return v; +} +// Hash function: +// - If key starts with '#' or 'C', parse the following digits as the hash seed. +// - Else, use a simple sum to avoid dependence on external functions. +static JUNO_RESULT_SIZE_T TestHash(void *ptKey) +{ + JUNO_RESULT_SIZE_T r = {0}; + if (!ptKey) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; // any non-success code works for tests + return r; + } + const char *s = (const char *)ptKey; + size_t v = 0; + if (s[0] == '#' || s[0] == 'C') + { + v = parse_digits(s + 1); + } + else + { + for (int i = 0; s[i] && i < 8; i++) v += (unsigned char)s[i]; + } + r.tOk = v; + r.tStatus = JUNO_STATUS_SUCCESS; + return r; +} -void setUp(void) +static JUNO_RESULT_BOOL_T TestKeyIsEqual(void *ptLeft, void *ptRight) { - JunoHash_Djb2Api(>Hash, NULL, NULL); + JUNO_RESULT_BOOL_T r = {0}; + const char *l = (const char *)ptLeft; + const char *p = (const char *)ptRight; + if (!l || !p) + { + r.tOk = (l == p); + r.tStatus = JUNO_STATUS_SUCCESS; + return r; + } + r.tOk = (strcmp(l, p) == 0); + r.tStatus = JUNO_STATUS_SUCCESS; + return r; } -void tearDown(void) + +static JUNO_RESULT_VOID_PTR_T TestGetValue(size_t iIndex) { + JUNO_RESULT_VOID_PTR_T r = {0}; + if (iIndex >= TEST_MAP_CAPACITY) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + return r; + } + r.tOk = gValues[iIndex]; + r.tStatus = JUNO_STATUS_SUCCESS; + return r; +} + +static JUNO_RESULT_VOID_PTR_T TestGetKey(size_t iIndex) +{ + JUNO_RESULT_VOID_PTR_T r = {0}; + if (iIndex >= TEST_MAP_CAPACITY) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + return r; + } + r.tOk = gKeys[iIndex]; + r.tStatus = JUNO_STATUS_SUCCESS; + return r; +} + +static JUNO_STATUS_T TestSetValue(size_t iIndex, void *ptValue) +{ + if (iIndex >= TEST_MAP_CAPACITY) return JUNO_STATUS_TABLE_FULL_ERROR; + gValues[iIndex] = ptValue; + return JUNO_STATUS_SUCCESS; +} +static JUNO_STATUS_T TestSetKey(size_t iIndex, void *ptKey) +{ + if (iIndex >= TEST_MAP_CAPACITY) return JUNO_STATUS_TABLE_FULL_ERROR; + gKeys[iIndex] = ptKey; + gOccupied[iIndex] = (ptKey != NULL); + return JUNO_STATUS_SUCCESS; } -static bool IsKeyEqual(JUNO_MEMORY_T tKey1, JUNO_MEMORY_T tKey2) +static JUNO_STATUS_T TestRemove(size_t iIndex) { - TEST_KEY *ptKey1 = (TEST_KEY*)(tKey1.pvAddr); - TEST_KEY *ptKey2 = (TEST_KEY*)(tKey2.pvAddr); - return strcmp(ptKey1->key, ptKey2->key) == 0; + if (iIndex >= TEST_MAP_CAPACITY) return JUNO_STATUS_TABLE_FULL_ERROR; + if (!gOccupied[iIndex]) return JUNO_STATUS_TABLE_FULL_ERROR; + gKeys[iIndex] = NULL; + gValues[iIndex] = NULL; + gOccupied[iIndex] = false; + return JUNO_STATUS_SUCCESS; } +static JUNO_RESULT_BOOL_T TestIsEmpty(size_t zIndex) +{ + JUNO_RESULT_BOOL_T r = {0}; + if (zIndex >= TEST_MAP_CAPACITY) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + return r; + } + r.tOk = !gOccupied[zIndex]; + r.tStatus = JUNO_STATUS_SUCCESS; + return r; +} + +// Count occupied slots +static size_t TestMap_CountOccupied(void) +{ + size_t c = 0; + for (size_t i = 0; i < TEST_MAP_CAPACITY; i++) + if (gOccupied[i]) c++; + return c; +} + +// Injection helpers for error-path testing +static bool gInjectGetKeyError = false; +static size_t gInjectGetKeyErrorIndex = 0; + +static JUNO_RESULT_VOID_PTR_T TestGetKey_WithInjectedError(size_t iIndex) +{ + JUNO_RESULT_VOID_PTR_T r = {0}; + if (gInjectGetKeyError && iIndex == gInjectGetKeyErrorIndex) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + return r; + } + return TestGetKey(iIndex); +} + +static bool gInjectIsEmptyError = false; +static size_t gInjectIsEmptyErrorIndex = 0; + +static JUNO_RESULT_BOOL_T TestIsEmpty_WithInjectedError(size_t zIndex) +{ + JUNO_RESULT_BOOL_T r = {0}; + if (gInjectIsEmptyError && zIndex == gInjectIsEmptyErrorIndex) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + return r; + } + return TestIsEmpty(zIndex); +} + +static int gInjectKeyEqErrorCount = 0; + +static const char *gInjectHashErrorKey = NULL; + +static JUNO_RESULT_SIZE_T TestHash_WithInjectedError(void *ptKey) +{ + JUNO_RESULT_SIZE_T r = {0}; + if (gInjectHashErrorKey && ptKey && strcmp((const char *)ptKey, gInjectHashErrorKey) == 0) + { + r.tStatus = JUNO_STATUS_TABLE_FULL_ERROR; + return r; + } + return TestHash(ptKey); +} + +// Unity fixtures +void setUp(void) +{ + TestMap_Reset(); + gApi.Hash = TestHash; + gApi.KeyIsEqual = TestKeyIsEqual; + gApi.GetValue = TestGetValue; + gApi.GetKey = TestGetKey; + gApi.SetValue = TestSetValue; + gApi.SetKey = TestSetKey; + gApi.Remove = TestRemove; + gApi.IsEmpty = TestIsEmpty; + + gRoot.ptApi = &gApi; + gRoot.zCapacity = TEST_MAP_CAPACITY; + + gInjectGetKeyError = false; + gInjectIsEmptyError = false; + gInjectKeyEqErrorCount = 0; + gInjectHashErrorKey = NULL; +} + +void tearDown(void) +{ +} + +// Tests static void test_nominal_map(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[10] = {0}; - JUNO_MEMORY_T tValTbl[10] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - 10, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - gptMapApi = tMap.ptApi; - TEST_KEY tTestKeys[10] = {0}; - TEST_VALUE tTestValues[10] = {0}; - for(int i = 0; i < 10; i++) - { - sprintf(tTestKeys[i].key, "Hello_%i", i+1); - tTestValues[i].value = i+1; - tStatus = gptMapApi->Set( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestKeys[i], .zSize = sizeof(*tTestKeys)}, - (JUNO_MEMORY_T){.pvAddr = &tTestValues[i], .zSize = sizeof(*tTestValues)} - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - TEST_KEY tTestExtra = {.key = "Hello"}; - TEST_VALUE tTestExtraV = {.value = 10}; - tStatus = gptMapApi->Set( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestExtra, .zSize = sizeof(TEST_KEY)}, - (JUNO_MEMORY_T){.pvAddr = &tTestExtraV, .zSize = sizeof(TEST_VALUE)} - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(int i = 0; i < 10; i++) - { - JUNO_MEMORY_T tValue = {0}; - tStatus = gptMapApi->Get( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestKeys[i], .zSize = sizeof(TEST_KEY)}, - &tValue - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_VALUE *ptValue = (TEST_VALUE *)(tValue.pvAddr); - TEST_ASSERT_EQUAL(i+1, ptValue->value); - } - for(int i = 0; i < 10; i++) - { - tStatus = gptMapApi->Remove( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestKeys[i], .zSize = sizeof(TEST_KEY)} - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - JUNO_MEMORY_T tValue = {0}; - tStatus = gptMapApi->Get( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestKeys[i], .zSize = sizeof(TEST_KEY)}, - &tValue - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } + const char *k1 = "#1"; + int v1 = 42; + + JUNO_STATUS_T s = JunoMap_Set(&gRoot, (void *)k1, &v1); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, s); + + JUNO_RESULT_VOID_PTR_T r = JunoMap_Get(&gRoot, (void *)k1); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, r.tStatus); + TEST_ASSERT_EQUAL_PTR(&v1, r.tOk); + + s = JunoMap_Remove(&gRoot, (void *)k1); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, s); + + r = JunoMap_Get(&gRoot, (void *)k1); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, r.tStatus); + TEST_ASSERT_NULL(r.tOk); + + const char *ka = "C3a"; + const char *kb = "C4b"; + int va = 11, vb = 22; + + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)ka, &va)); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)kb, &vb)); + + JUNO_RESULT_VOID_PTR_T ra = JunoMap_Get(&gRoot, (void *)ka); + JUNO_RESULT_VOID_PTR_T rb = JunoMap_Get(&gRoot, (void *)kb); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, ra.tStatus); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, rb.tStatus); + TEST_ASSERT_EQUAL_PTR(&va, ra.tOk); + TEST_ASSERT_EQUAL_PTR(&vb, rb.tOk); + + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)ka)); + ra = JunoMap_Get(&gRoot, (void *)ka); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, ra.tStatus); + TEST_ASSERT_NULL(ra.tOk); + rb = JunoMap_Get(&gRoot, (void *)kb); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, rb.tStatus); + TEST_ASSERT_EQUAL_PTR(&vb, rb.tOk); } -/* Test: Initialize map with null pointer arguments */ + static void test_null_init(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[5] = {0}; - JUNO_MEMORY_T tValTbl[5] = {0}; - /* Passing NULL for key table */ - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - NULL, - tValTbl, - 5, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - gptMapApi = tMap.ptApi; - - /* Reset and pass NULL for value table */ - tMap = (JUNO_MAP_T){0}; - tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - NULL, - 5, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_VerifyApi(NULL)); + + JUNO_MAP_ROOT_T badRoot1 = {0}; + badRoot1.ptApi = NULL; + badRoot1.zCapacity = TEST_MAP_CAPACITY; + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Verify(&badRoot1)); + + JUNO_MAP_ROOT_T badRoot2 = {0}; + badRoot2.ptApi = &gApi; + badRoot2.zCapacity = 0; + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Verify(&badRoot2)); } -/* Test: Set operation with null map pointer */ static void test_null_set(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[10] = {0}; - JUNO_MEMORY_T tValTbl[10] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - 10, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - gptMapApi = tMap.ptApi; - TEST_KEY tKey = {.key = "Test"}; - TEST_VALUE tValue = {.value = 123}; - /* Call Set with null map pointer */ - tStatus = gptMapApi->Set( - NULL, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)}, - (JUNO_MEMORY_T){.pvAddr = &tValue, .zSize = sizeof(TEST_VALUE)} - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + int v = 1; + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(NULL, (void *)"#1", &v)); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, NULL, &v)); } -/* Test: Get operation with null map pointer */ static void test_null_get(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[10] = {0}; - JUNO_MEMORY_T tValTbl[10] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - 10, - IsKeyEqual, - NULL, - NULL - ); - gptMapApi = tMap.ptApi; - TEST_KEY tKey = {.key = "Test"}; - JUNO_MEMORY_T tValue = {0}; - tStatus = gptMapApi->Get( - NULL, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)}, - &tValue - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + JUNO_RESULT_VOID_PTR_T r = JunoMap_Get(NULL, (void *)"#2"); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, r.tStatus); + + r = JunoMap_Get(&gRoot, NULL); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, r.tStatus); } -/* Test: Remove operation with null map pointer */ static void test_null_remove(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[10] = {0}; - JUNO_MEMORY_T tValTbl[10] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - 10, - IsKeyEqual, - NULL, - NULL - ); - gptMapApi = tMap.ptApi; - TEST_KEY tKey = {.key = "Test"}; - tStatus = gptMapApi->Remove( - NULL, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)} - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(NULL, (void *)"#3")); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, NULL)); } -/* Test: Remove a key that was never inserted */ static void test_remove_nonexistent_key(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[5] = {0}; - JUNO_MEMORY_T tValTbl[5] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - 5, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - gptMapApi = tMap.ptApi; - TEST_KEY tKey = {.key = "Nonexistent"}; - tStatus = gptMapApi->Remove( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)} - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)"#7")); + + int vals[4] = {10, 20, 30, 40}; + const char *k0 = "C7a"; + const char *k1 = "C7b"; + const char *k2 = "C7c"; + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k0, &vals[0])); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k1, &vals[1])); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k2, &vals[2])); + + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)"C7x")); } -/* Test: Insert duplicate keys, expecting error/duplicate rejection */ static void test_duplicate_key_insertion(void) { - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[5] = {0}; - JUNO_MEMORY_T tValTbl[5] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - 5, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - gptMapApi = tMap.ptApi; - TEST_KEY tKey = {.key = "Duplicate"}; - TEST_VALUE tValue1 = {.value = 1}; - TEST_VALUE tValue2 = {.value = 2}; - - /* First insertion should succeed */ - tStatus = gptMapApi->Set( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)}, - (JUNO_MEMORY_T){.pvAddr = &tValue1, .zSize = sizeof(TEST_VALUE)} - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - - /* Second insertion with same key expected to fail */ - tStatus = gptMapApi->Set( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)}, - (JUNO_MEMORY_T){.pvAddr = &tValue2, .zSize = sizeof(TEST_VALUE)} - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - JUNO_MEMORY_T tRetVal = {0}; - tStatus = gptMapApi->Get( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tKey, .zSize = sizeof(TEST_KEY)}, - &tRetVal - ); - TEST_VALUE *ptRetVal = (TEST_VALUE *)(tRetVal.pvAddr); - TEST_ASSERT_EQUAL(tValue2.value, ptRetVal->value); + const char *k = "#5"; + int a = 100, b = 200; + + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k, &a)); + size_t before = TestMap_CountOccupied(); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k, &b)); + size_t after = TestMap_CountOccupied(); + + TEST_ASSERT_EQUAL(before, after); + + JUNO_RESULT_VOID_PTR_T r = JunoMap_Get(&gRoot, (void *)k); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, r.tStatus); + TEST_ASSERT_EQUAL_PTR(&b, r.tOk); } -/* Test: Overflow the map capacity by inserting more keys than allowed */ static void test_overflow_map(void) { - const int capacity = 3; - JUNO_MAP_T tMap = {0}; - JUNO_MEMORY_T tKeyTbl[3] = {0}; - JUNO_MEMORY_T tValTbl[3] = {0}; - JUNO_STATUS_T tStatus = JunoMap_ImplApi( - &tMap, - >Hash, - tKeyTbl, - tValTbl, - capacity, - IsKeyEqual, - NULL, - NULL - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - gptMapApi = tMap.ptApi; - TEST_KEY tTestKeys[4] = {0}; - TEST_VALUE tTestValues[4] = {0}; - - /* Insert keys equal to capacity */ - for(int i = 0; i < capacity; i++) - { - sprintf(tTestKeys[i].key, "Key_%i", i); - tTestValues[i].value = i; - tStatus = gptMapApi->Set( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestKeys[i], .zSize = sizeof(*tTestKeys)}, - (JUNO_MEMORY_T){.pvAddr = &tTestValues[i], .zSize = sizeof(*tTestValues)} - ); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - /* Attempt to insert one more key beyond capacity */ - sprintf(tTestKeys[3].key, "Key_%i", 3); - tTestValues[3].value = 3; - tStatus = gptMapApi->Set( - &tMap, - (JUNO_MEMORY_T){.pvAddr = &tTestKeys[3], .zSize = sizeof(*tTestKeys)}, - (JUNO_MEMORY_T){.pvAddr = &tTestValues[3], .zSize = sizeof(*tTestValues)} - ); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + int vals[TEST_MAP_CAPACITY]; + char keybuf[32]; + for (size_t i = 0; i < TEST_MAP_CAPACITY; i++) + { + vals[i] = (int)i + 1; + snprintf(keybuf, sizeof(keybuf), "#%u", (unsigned)i); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, keybuf, &vals[i])); + } + TEST_ASSERT_EQUAL(TEST_MAP_CAPACITY, TestMap_CountOccupied()); + + JUNO_STATUS_T s = JunoMap_Set(&gRoot, (void *)"C0_overflow", &vals[0]); + TEST_ASSERT_EQUAL(JUNO_STATUS_TABLE_FULL_ERROR, s); +} + +#include + +static void test_fill_map(void) +{ + int baseVals[TEST_MAP_CAPACITY * 2]; + char tmp[32]; + // Store stable pointers for all keys we touch in this test + const char *keys[TEST_MAP_CAPACITY] = {0}; + + // Insert: allocate and store unique key strings "C" + for (size_t i = 0; i < TEST_MAP_CAPACITY; i++) + { + baseVals[i] = 1000 + (int)i; + snprintf(tmp, sizeof(tmp), "C%u", (unsigned)i); + + // Duplicate key into heap so the map stores a stable pointer + size_t len = strlen(tmp) + 1; + char *k = (char *)malloc(len); + TEST_ASSERT_NOT_NULL(k); + memcpy(k, tmp, len); + keys[i] = k; + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)keys[i], &baseVals[i])); + } + + // Remove every other entry using the exact same pointer used for insert + for (size_t i = 0; i < TEST_MAP_CAPACITY / 2; i += 2) + { + TEST_ASSERT_NOT_NULL(keys[i]); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)keys[i])); + } + + // Reinsert the same keys (same pointers) for those removed, with new values + for (size_t i = 0; i < TEST_MAP_CAPACITY / 2; i++) + { + if ((i % 2) == 0) + { + baseVals[TEST_MAP_CAPACITY + i] = 2000 + (int)i; + TEST_ASSERT_NOT_NULL(keys[i]); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)keys[i], &baseVals[TEST_MAP_CAPACITY + i])); + } + } + + // 1) GetKey error path + gApi.GetKey = TestGetKey_WithInjectedError; + gInjectGetKeyErrorIndex = 2; + gInjectGetKeyError = true; + JUNO_RESULT_SIZE_T gi = JunoMap_GetIndex(&gRoot, (void *)"#2"); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, gi.tStatus); + gInjectGetKeyError = false; + gApi.GetKey = TestGetKey; + + // 2) IsEmpty error path + gApi.IsEmpty = TestIsEmpty_WithInjectedError; + gInjectIsEmptyErrorIndex = 3; + gInjectIsEmptyError = true; + gi = JunoMap_GetIndex(&gRoot, (void *)"#3"); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, gi.tStatus); + gInjectIsEmptyError = false; + gApi.IsEmpty = TestIsEmpty; + // 4) Hash error path + gApi.Hash = TestHash_WithInjectedError; + gInjectHashErrorKey = "BADHASH"; + gi = JunoMap_GetIndex(&gRoot, (void *)"BADHASH"); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, gi.tStatus); + gInjectHashErrorKey = NULL; + gApi.Hash = TestHash; + + // Note: keys[] are intentionally not freed to avoid dangling pointers + // inside the map; tests exit shortly after. } int main(void) @@ -352,5 +432,7 @@ int main(void) RUN_TEST(test_remove_nonexistent_key); RUN_TEST(test_duplicate_key_insertion); RUN_TEST(test_overflow_map); + RUN_TEST(test_fill_map); return UNITY_END(); } + From 1aec23a4722841abe29f4188c559c260df50c20a Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Sat, 20 Sep 2025 08:20:23 -0500 Subject: [PATCH 03/34] :sparkles: Refactor hash --- include/juno/hash/hash_api.h | 54 --------------------------- include/juno/hash/hash_djb2.h | 41 +++++++++----------- src/juno_hash.c | 70 ----------------------------------- tests/test_cpp.cpp | 1 - tests/test_hash.c | 41 -------------------- 5 files changed, 18 insertions(+), 189 deletions(-) delete mode 100644 include/juno/hash/hash_api.h delete mode 100644 src/juno_hash.c delete mode 100644 tests/test_hash.c diff --git a/include/juno/hash/hash_api.h b/include/juno/hash/hash_api.h deleted file mode 100644 index ffd81a53..00000000 --- a/include/juno/hash/hash_api.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_hash library API - @author Robin Onsay -*/ -#ifndef JUNO_HASH_API_H -#define JUNO_HASH_API_H -#include "juno/status.h" -#include "juno/module.h" -#include -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct JUNO_HASH_API_TAG JUNO_HASH_API_T; - -typedef union JUNO_HASH_TAG JUNO_HASH_T; -typedef struct JUNO_HASH_ROOT_TAG JUNO_HASH_ROOT_T; - -struct JUNO_HASH_ROOT_TAG JUNO_MODULE_ROOT(JUNO_HASH_API_T, JUNO_MODULE_EMPTY); - -struct JUNO_HASH_API_TAG -{ - - JUNO_STATUS_T (*Hash)(JUNO_HASH_T *ptHash, const uint8_t *pcBuff, size_t zBuffSize, size_t *pzRetHash); - -}; - -#ifdef __cplusplus -} -#endif -#endif // JUNO_HASH_API_H diff --git a/include/juno/hash/hash_djb2.h b/include/juno/hash/hash_djb2.h index a2ed096b..e0b6999e 100644 --- a/include/juno/hash/hash_djb2.h +++ b/include/juno/hash/hash_djb2.h @@ -26,36 +26,31 @@ */ #ifndef JUNO_HASH_DJB2_H #define JUNO_HASH_DJB2_H -#include "juno/module.h" #include "juno/status.h" -#include "juno/hash/hash_api.h" +#include "juno/types.h" #ifdef __cplusplus extern "C" { #endif -typedef struct JUNO_HASH_DJB2_TAG JUNO_HASH_DJB2_T; - -struct JUNO_HASH_DJB2_TAG JUNO_MODULE_DERIVE(JUNO_HASH_ROOT_T, JUNO_MODULE_EMPTY); - -#ifdef JUNO_HASH_DEFAULT -/** - This is the default djb2ementation for `JUNO_HASH_T`. - If you want to use the default djb2ementation for `JUNO_HASH_T` - use `#define JUNO_HASH_DEFAULT` prior to including - `#include "juno_hash_djb2.h"` - - Note: If you are djb2ementing a derived module you will need - to djb2ement `JUNO_HASH_DJB2`. -*/ -union JUNO_HASH_TAG JUNO_MODULE(JUNO_HASH_API_T, JUNO_HASH_ROOT_T, - JUNO_HASH_DJB2_T tJunoHashDjb2; -); -#endif - -/* TODO: Insert initialization arguments for module members here*/ -JUNO_STATUS_T JunoHash_Djb2Api(JUNO_HASH_T *ptJunoHash, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData); +static inline JUNO_RESULT_SIZE_T JunoHash_Djb2(const uint8_t *pcBuff, size_t zBuffSize) +{ + JUNO_RESULT_SIZE_T tResult = {0, 0}; + if(!(pcBuff)) + { + tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; + return tResult; + } + size_t zHash = 5381; + for(size_t i = 0; i < zBuffSize; i++) + { + zHash = ((zHash << 5) + zHash) + pcBuff[i]; + } + tResult.tStatus = JUNO_STATUS_SUCCESS; + tResult.tOk = zHash; + return tResult; +} #ifdef __cplusplus } #endif diff --git a/src/juno_hash.c b/src/juno_hash.c deleted file mode 100644 index 6c6ff733..00000000 --- a/src/juno_hash.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ -#include "juno/hash/hash_api.h" -#include "juno/hash/hash_djb2.h" -#include "juno/macros.h" - -static const JUNO_HASH_API_T tJunoHashDjb2Api; - -static inline JUNO_STATUS_T Verify(JUNO_HASH_T *ptJunoHash) -{ - JUNO_ASSERT_EXISTS(ptJunoHash); - JUNO_HASH_DJB2_T *ptJunoHashDjb2 = (JUNO_HASH_DJB2_T *)(ptJunoHash); - JUNO_ASSERT_EXISTS_MODULE( - ptJunoHash && ptJunoHashDjb2->JUNO_MODULE_SUPER.ptApi - /* TODO: Assert other dependencies and members here using &&*/, - ptJunoHashDjb2, - "Module does not have all dependencies" - ); - if(ptJunoHashDjb2->JUNO_MODULE_SUPER.ptApi != &tJunoHashDjb2Api) - { - JUNO_FAIL_MODULE(JUNO_STATUS_INVALID_TYPE_ERROR, ptJunoHashDjb2, "Module has invalid API"); - return JUNO_STATUS_INVALID_TYPE_ERROR; - } - return JUNO_STATUS_SUCCESS; -} - -static JUNO_STATUS_T Hash(JUNO_HASH_T *ptJunoHash, const uint8_t *pcBuff, size_t zBuffSize, size_t *pzRetHash) -{ - JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS; - tStatus = Verify(ptJunoHash); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus) - size_t zHash = 5381; - for(size_t i = 0; i < zBuffSize; i++) - { - zHash = ((zHash << 5) + zHash) + pcBuff[i]; - } - *pzRetHash = zHash; - return JUNO_STATUS_SUCCESS; -} - - -static const JUNO_HASH_API_T tJunoHashDjb2Api = { - .Hash = Hash -}; - -JUNO_STATUS_T JunoHash_Djb2Api(JUNO_HASH_T *ptJunoHash, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) -{ - JUNO_ASSERT_EXISTS(ptJunoHash); - JUNO_HASH_DJB2_T *ptJunoHashDjb2 = (JUNO_HASH_DJB2_T *)(ptJunoHash); - ptJunoHashDjb2->JUNO_MODULE_SUPER.ptApi = &tJunoHashDjb2Api; - ptJunoHashDjb2->JUNO_MODULE_SUPER.JUNO_FAILURE_HANDLER = pfcnFailureHandler; - ptJunoHashDjb2->JUNO_MODULE_SUPER.JUNO_FAILURE_USER_DATA = pvFailureUserData; - JUNO_STATUS_T tStatus = Verify(ptJunoHash); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - return tStatus; -} diff --git a/tests/test_cpp.cpp b/tests/test_cpp.cpp index 63a23305..75df130d 100644 --- a/tests/test_cpp.cpp +++ b/tests/test_cpp.cpp @@ -3,7 +3,6 @@ #include "juno/ds/buff_stack_api.h" #include "juno/ds/heap_api.h" #include "juno/crc/crc.h" -#include "juno/hash/hash_api.h" #include "juno/io/async_io_api.h" #include "juno/io/i2c_io_api.h" #include "juno/io/spi_io_api.h" diff --git a/tests/test_hash.c b/tests/test_hash.c deleted file mode 100644 index 7243ad17..00000000 --- a/tests/test_hash.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "juno/hash/hash_api.h" -#include "juno/status.h" -#include "unity.h" -#include "unity_internals.h" -#include -#include -#define JUNO_HASH_DEFAULT -#include "juno/hash/hash_djb2.h" - -void setUp(void) -{ -} -void tearDown(void) -{ - -} - -static void test_djb2_hash(void) -{ - JUNO_HASH_T tHash = {0}; - JUNO_STATUS_T tStatus = JunoHash_Djb2Api(&tHash, NULL, NULL); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_HASH_API_T *ptHashApi = tHash.ptApi; - const char pcTestString[16] = "Hello World!"; - size_t zRetHash = 0; - tStatus = ptHashApi->Hash(&tHash, (const uint8_t *)(pcTestString), sizeof(pcTestString), &zRetHash); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const char pcTestString2[16] = "Test World!"; - size_t zRetHash2 = 0; - tStatus = ptHashApi->Hash(&tHash, (const uint8_t *)(pcTestString2), sizeof(pcTestString2), &zRetHash2); - TEST_ASSERT_NOT_EQUAL(zRetHash, zRetHash2); - - -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_djb2_hash); - return UNITY_END(); -} From ca843805478db29d10f77374256ff206c341d913 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Sat, 20 Sep 2025 08:29:38 -0500 Subject: [PATCH 04/34] :sparkles: Add comments to hash map --- include/juno/map/map_api.h | 28 +++++++++++++++++++++++++++- tests/test_map.c | 4 ++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/juno/map/map_api.h b/include/juno/map/map_api.h index 559fb9f1..4580f7ad 100644 --- a/include/juno/map/map_api.h +++ b/include/juno/map/map_api.h @@ -43,22 +43,32 @@ typedef union JUNO_MAP_TAG JUNO_MAP_T; typedef struct JUNO_MAP_ROOT_TAG JUNO_MAP_ROOT_T; struct JUNO_MAP_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MAP_API_T, + /// The capacity of the hash map size_t zCapacity; ); struct JUNO_MAP_API_TAG { + /// Calculate the hash for the given key JUNO_RESULT_SIZE_T (*Hash)(void *ptKey); + /// Return true if the left and right are equal JUNO_RESULT_BOOL_T (*KeyIsEqual)(void *ptLeft, void *ptRight); + /// Get the value at the given index JUNO_RESULT_VOID_PTR_T (*GetValue)(size_t iIndex); + /// Get the key at the given index JUNO_RESULT_VOID_PTR_T (*GetKey)(size_t iIndex); + /// Set the value at the given index JUNO_STATUS_T (*SetValue)(size_t iIndex, void *ptValue); + /// Set the key at the given index JUNO_STATUS_T (*SetKey)(size_t iIndex, void *ptKey); + /// Remove the key and value at the given index JUNO_STATUS_T (*Remove)(size_t iIndex); + /// Check if the given index is empty JUNO_RESULT_BOOL_T (*IsEmpty)(size_t zIndex); }; +/// Check if the api has all members static inline JUNO_STATUS_T JunoMap_VerifyApi(const JUNO_MAP_API_T *ptApi) { JUNO_ASSERT_EXISTS( @@ -75,6 +85,7 @@ static inline JUNO_STATUS_T JunoMap_VerifyApi(const JUNO_MAP_API_T *ptApi) return JUNO_STATUS_SUCCESS; } +/// Verify the map has all members static inline JUNO_STATUS_T JunoMap_Verify(JUNO_MAP_ROOT_T *ptMap) { JUNO_ASSERT_EXISTS(ptMap); @@ -84,58 +95,73 @@ static inline JUNO_STATUS_T JunoMap_Verify(JUNO_MAP_ROOT_T *ptMap) return tStatus; } +/// Get the index for a given key JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey); +/// Set the value at a given key static inline JUNO_STATUS_T JunoMap_Set(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey, void *ptValue) { + // verify the map JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + // Get the index for the key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tStatus = tSizeResult.tStatus; JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + // Set the key for the index tStatus = ptJunoMap->ptApi->SetKey(tSizeResult.tOk, ptKey); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + // Set the value for the index tStatus = ptJunoMap->ptApi->SetValue(tSizeResult.tOk, ptValue); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; } +/// Get the value for a given key static inline JUNO_RESULT_VOID_PTR_T JunoMap_Get(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { JUNO_RESULT_VOID_PTR_T tResult = {0, NULL}; tResult.tStatus = JunoMap_Verify(ptJunoMap); JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + // Get the index for the key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tResult.tStatus = tSizeResult.tStatus; JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + // Check if the value at the index is empty JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); tResult.tStatus = tBoolResult.tStatus; JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); bool bIsEmpty = tBoolResult.tOk; if(bIsEmpty) { + // Its empty so return DNE error tResult.tStatus = JUNO_STATUS_DNE_ERROR; return tResult; } + // Get the value return ptJunoMap->ptApi->GetValue(tSizeResult.tOk); } +/// Remove the key and value ata given key static inline JUNO_STATUS_T JunoMap_Remove(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + // Get the index for the given key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tStatus = tSizeResult.tStatus; JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + // Check if the key is empty JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); tStatus = tBoolResult.tStatus; JUNO_ASSERT_SUCCESS(tStatus, return tStatus); bool bIsEmpty = tBoolResult.tOk; if(bIsEmpty) { - tStatus = JUNO_STATUS_DNE_ERROR; + // Its empty so fail silently return tStatus; } + // Remove the key, value at the index tStatus = ptJunoMap->ptApi->Remove(tSizeResult.tOk); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; diff --git a/tests/test_map.c b/tests/test_map.c index 48bf8663..71e43ec4 100644 --- a/tests/test_map.c +++ b/tests/test_map.c @@ -304,7 +304,7 @@ static void test_null_remove(void) static void test_remove_nonexistent_key(void) { - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)"#7")); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)"#7")); int vals[4] = {10, 20, 30, 40}; const char *k0 = "C7a"; @@ -314,7 +314,7 @@ static void test_remove_nonexistent_key(void) TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k1, &vals[1])); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, (void *)k2, &vals[2])); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)"C7x")); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Remove(&gRoot, (void *)"C7x")); } static void test_duplicate_key_insertion(void) From 94d2f36db8b60a7a3232e0137857f6ee2fe85f3b Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Sat, 20 Sep 2025 12:24:43 -0500 Subject: [PATCH 05/34] :sparkles: Make consitency changes --- CMakeLists.txt | 34 ++++++++++++++++++--- examples/example_state_machine.c | 6 ++-- include/juno/ds/buff_queue_api.h | 2 +- include/juno/ds/heap_api.h | 28 +++++++++-------- include/juno/hash/hash_djb2.h | 2 +- include/juno/macros.h | 4 +-- include/juno/map/map_api.h | 24 +++++++-------- include/juno/memory/memory_block.h | 6 ++-- include/juno/module.h | 23 +++++++------- include/juno/sm/sm_api.h | 15 ++++++--- include/juno/types.h | 2 +- src/{crc => }/juno_arc.c | 2 +- src/{crc => }/juno_binhex.c | 2 +- src/{crc => }/juno_ccitt.c | 2 +- src/{crc => }/juno_ccitt32.c | 2 +- src/juno_crc.c | 22 ------------- src/juno_heap.c | 20 ++++++------ src/{crc => }/juno_kermit.c | 2 +- src/juno_map.c | 28 +++++++++++------ src/juno_memory_block.c | 8 ++--- src/juno_time.c | 2 +- src/{crc => }/juno_zip.c | 2 +- templates/template_app/src/template_app.cpp | 2 +- templates/template_impl/src/template_impl.c | 2 +- templates/template_lib/src/template_impl.c | 2 +- tests/test_cpp.cpp | 1 + tests/test_heap.c | 3 +- 27 files changed, 134 insertions(+), 114 deletions(-) rename src/{crc => }/juno_arc.c (97%) rename src/{crc => }/juno_binhex.c (97%) rename src/{crc => }/juno_ccitt.c (97%) rename src/{crc => }/juno_ccitt32.c (97%) delete mode 100644 src/juno_crc.c rename src/{crc => }/juno_kermit.c (97%) rename src/{crc => }/juno_zip.c (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a52c033..6b3451fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,9 @@ option(JUNO_COVERAGE "Compile Juno with code coverage" OFF) option(JUNO_DOCS "Enable doxygen docs" OFF) option(JUNO_PIC "Compile Juno with Position Independent Code" ON) option(JUNO_SHARED "Compile the juno shared library" OFF) +option(JUNO_FREESTANDING "Compile as a freestanding library" OFF) +option(JUNO_ASAN "Compile ASAN" OFF) +option(JUNO_UBSAN "Compile with UBSAN" OFF) message("Compiler: ${CMAKE_C_COMPILER}") message("Testing: ${JUNO_TESTS}") @@ -83,17 +86,38 @@ foreach(lib ${JUNO_LIBS}) PRIVATE ${PROJECT_SOURCE_DIR}/src ) + if(JUNO_FREESTANDING) + list(APPEND JUNO_COMPILE_C_OPTIONS + -nostdlib + -ffreestanding + ) + target_link_options(${lib} PRIVATE + -nostdlib + ) + endif() + if(JUNO_ASAN) + add_compile_options( + -fsanitize=address + ) + add_link_options( + -fsanitize=address + ) + endif() + if(JUNO_UBSAN) + add_compile_options( + -fsanitize=undefined + ) + add_link_options( + -fsanitize=undefined + ) + endif() # Enable a comprehensive set of warnings target_compile_options(${lib} PRIVATE ${JUNO_COMPILE_OPTIONS} $<$:${JUNO_COMPILE_C_OPTIONS}> $<$:${JUNO_COMPILE_CXX_OPTIONS}> - -nostdlib - -ffreestanding # Disable the hosted environment - ) - target_link_options(${lib} PRIVATE - -nostdlib ) + endforeach() if(JUNO_SHARED) diff --git a/examples/example_state_machine.c b/examples/example_state_machine.c index 3fc85fa6..671b3e8d 100644 --- a/examples/example_state_machine.c +++ b/examples/example_state_machine.c @@ -27,7 +27,7 @@ union JUNO_SM_STATE_T JUNO_MODULE(JUNO_SM_STATE_API_T, JUNO_SM_STATE_ROOT_T, static JUNO_STATUS_T StateAction(JUNO_SM_STATE_T *ptJunoSm) { JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; printf("Current State: %u\n", ptTrafficLightState->tThisLight); sleep(1); @@ -41,7 +41,7 @@ static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm) JUNO_RESULT_BOOL_T tResult = {0}; TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; tResult.tStatus = tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tStatus, return tResult;) tResult.tOk = ptTrafficLightState->iCounter == 10; return tResult; } @@ -50,7 +50,7 @@ static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm) static JUNO_STATUS_T ResetState(JUNO_SM_STATE_T *ptJunoSm) { JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; ptTrafficLightState->iCounter = 0; return JUNO_STATUS_SUCCESS; diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index 3cd656a7..e8f40d17 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -125,7 +125,7 @@ static inline JUNO_RESULT_SIZE_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_T *ptQueue) if(ptQueueRoot->zLength == 0) { tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tResult.tStatus, ptQueueRoot->_pfcnFailureHandler, ptQueueRoot->_pvFailureUserData, "Failed to enqueue data"); + JUNO_FAIL(tResult.tStatus, ptQueueRoot->_pfcnFailureHandler, ptQueueRoot->_pvFailureUserData, "Queue is empty"); return tResult; } tResult.tOk = ptQueueRoot->iStartIndex; diff --git a/include/juno/ds/heap_api.h b/include/juno/ds/heap_api.h index b7bc283f..900ab802 100644 --- a/include/juno/ds/heap_api.h +++ b/include/juno/ds/heap_api.h @@ -246,7 +246,7 @@ static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetLeft(JUNO_D { JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) iIndex = 2 * iIndex + 1; if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity) { @@ -273,7 +273,7 @@ static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetRight(JUNO_ { JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) iIndex = 2 * iIndex + 2; if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity) { @@ -300,7 +300,7 @@ static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetParent(JUNO { JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) iIndex = (iIndex - 1)/2; if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity) { @@ -333,7 +333,7 @@ static inline JUNO_DS_HEAP_INDEX_RESULT_T JunoDs_Heap_Insert(JUNO_DS_HEAP_ROOT_T { JUNO_DS_HEAP_INDEX_RESULT_T tResult = {JUNO_STATUS_SUCCESS, 0}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) if(ptHeap->zLength >= ptHeap->zCapacity) { tResult.tStatus = JUNO_STATUS_ERR; @@ -356,14 +356,18 @@ static inline JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap) { JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - if(ptHeap->zLength <= 0) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + if(ptHeap->zLength < 0) { tStatus = JUNO_STATUS_ERR; return tStatus; } + if(ptHeap->zLength < 0) + { + return tStatus; + } JUNO_DS_HEAP_INDEX_OPTION_RESULT_T iIndexResult = JunoDs_Heap_ChildGetParent(ptHeap, ptHeap->zLength); - JUNO_ASSERT_SUCCESS(iIndexResult.tStatus, return iIndexResult.tStatus); + JUNO_ASSERT_SUCCESS(iIndexResult.tStatus, return iIndexResult.tStatus;) if(!iIndexResult.tOk.bIsSome) { return tStatus; @@ -373,7 +377,7 @@ static inline JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap) { size_t iCurrentIndex = iIndex - i; tStatus = JunoDs_Heap_SiftDown(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tStatus, continue); + JUNO_ASSERT_SUCCESS(tStatus, continue;) } return tStatus; } @@ -393,16 +397,16 @@ static inline JUNO_STATUS_T JunoDs_Heap_Delete(JUNO_DS_HEAP_ROOT_T *ptHeap) { JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS;; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) if(ptHeap->zLength <= 0) { tStatus = JUNO_STATUS_ERR; return tStatus; } tStatus = ptHeap->ptApi->Swap(ptHeap, ptHeap->zLength-1, 0); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptHeap->ptApi->Reset(ptHeap, ptHeap->zLength-1); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + tStatus = ptHeap->ptApi->Reset(ptHeap, ptHeap->zLength-1); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) ptHeap->zLength -= 1; return JunoDs_Heap_SiftDown(ptHeap, 0); } diff --git a/include/juno/hash/hash_djb2.h b/include/juno/hash/hash_djb2.h index e0b6999e..80d8ee54 100644 --- a/include/juno/hash/hash_djb2.h +++ b/include/juno/hash/hash_djb2.h @@ -21,7 +21,7 @@ */ /** - This header contains the juno_hash djb2 djb2ementation + This header contains the juno_hash djb2 implementation @author Robin Onsay */ #ifndef JUNO_HASH_DJB2_H diff --git a/include/juno/macros.h b/include/juno/macros.h index e33d62a3..1da420eb 100644 --- a/include/juno/macros.h +++ b/include/juno/macros.h @@ -49,9 +49,9 @@ if(!(ptr)) \ @param tStatus The status to assert @param failOp The failure operation */ -#define JUNO_ASSERT_SUCCESS(tStatus, failOp) if(tStatus != JUNO_STATUS_SUCCESS) \ +#define JUNO_ASSERT_SUCCESS(tStatus, ...) if(tStatus != JUNO_STATUS_SUCCESS) \ { \ - failOp; \ + __VA_ARGS__ \ } diff --git a/include/juno/map/map_api.h b/include/juno/map/map_api.h index 4580f7ad..957884ce 100644 --- a/include/juno/map/map_api.h +++ b/include/juno/map/map_api.h @@ -90,7 +90,7 @@ static inline JUNO_STATUS_T JunoMap_Verify(JUNO_MAP_ROOT_T *ptMap) { JUNO_ASSERT_EXISTS(ptMap); JUNO_STATUS_T tStatus = JunoMap_VerifyApi(ptMap->ptApi); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) JUNO_ASSERT_EXISTS(ptMap->zCapacity); return tStatus; } @@ -103,17 +103,17 @@ static inline JUNO_STATUS_T JunoMap_Set(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey, { // verify the map JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) // Get the index for the key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tStatus = tSizeResult.tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) // Set the key for the index tStatus = ptJunoMap->ptApi->SetKey(tSizeResult.tOk, ptKey); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) // Set the value for the index tStatus = ptJunoMap->ptApi->SetValue(tSizeResult.tOk, ptValue); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) return tStatus; } @@ -122,15 +122,15 @@ static inline JUNO_RESULT_VOID_PTR_T JunoMap_Get(JUNO_MAP_ROOT_T *ptJunoMap, voi { JUNO_RESULT_VOID_PTR_T tResult = {0, NULL}; tResult.tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) // Get the index for the key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tResult.tStatus = tSizeResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) // Check if the value at the index is empty JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); tResult.tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) bool bIsEmpty = tBoolResult.tOk; if(bIsEmpty) { @@ -146,15 +146,15 @@ static inline JUNO_RESULT_VOID_PTR_T JunoMap_Get(JUNO_MAP_ROOT_T *ptJunoMap, voi static inline JUNO_STATUS_T JunoMap_Remove(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) // Get the index for the given key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tStatus = tSizeResult.tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) // Check if the key is empty JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) bool bIsEmpty = tBoolResult.tOk; if(bIsEmpty) { @@ -163,7 +163,7 @@ static inline JUNO_STATUS_T JunoMap_Remove(JUNO_MAP_ROOT_T *ptJunoMap, void *ptK } // Remove the key, value at the index tStatus = ptJunoMap->ptApi->Remove(tSizeResult.tOk); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) return tStatus; } diff --git a/include/juno/memory/memory_block.h b/include/juno/memory/memory_block.h index e7da3814..586321ff 100644 --- a/include/juno/memory/memory_block.h +++ b/include/juno/memory/memory_block.h @@ -21,7 +21,7 @@ */ /** - This header contains the juno_memory block blockementation + This header contains the juno_memory block implementation @author Robin Onsay */ #ifndef JUNO_MEMORY_BLOCK_H @@ -70,8 +70,8 @@ struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MODULE_DERIVE(JUNO_MEMORY_ALLOC_ROOT_T, #ifndef JUNO_MEMORY_CUSTOM /** - This is the default blockementation for `JUNO_MEMORY_T`. - If you want to derive new blockementations for `JUNO_MEMORY_T` + This is the default implementation for `JUNO_MEMORY_T`. + If you want to derive new implementations for `JUNO_MEMORY_T` use `#define JUNO_MEMORY_DERIVED` prior to including `#include "juno_memory_block.h"` diff --git a/include/juno/module.h b/include/juno/module.h index 7a8bc6a6..98bb3fd9 100644 --- a/include/juno/module.h +++ b/include/juno/module.h @@ -17,9 +17,9 @@ #ifndef JUNO_MODULE_H #define JUNO_MODULE_H -#include "status.h" +#include "juno/status.h" #include - +#include /**DOC ## Overview LibJuno implements dependency injection through modules @@ -227,12 +227,10 @@ typedef struct NAME_T \ OK_T tOk; \ } NAME_T -#define JUNO_RESULT(OK_T) \ -{ \ - JUNO_STATUS_T tStatus; \ - OK_T tOk; \ -} - +#define JUNO_OK(result, ...) result.tOk +#define JUNO_ASSERT_OK(result, ...) JUNO_ASSERT_SUCCESS(result.tStatus, __VA_ARGS__) +#define JUNO_OK_RESULT(value) {JUNO_STATUS_SUCCESS, value} +#define JUNO_ERR_RESULT(err, value) {err, value} /** * @def JUNO_MODULE_OPTION(NAME_T, OK_T) * @brief Defines an option type combining a flag to indicate some and a success payload. @@ -246,10 +244,11 @@ typedef struct NAME_T \ SOME_T tSome; \ } NAME_T -#define JUNO_OPTION(SOME_T) \ -{ \ - bool bIsSome; \ - SOME_T tSome; \ +#define JUNO_SOME(result, ...) result.tSome +#define JUNO_ASSERT_SOME(result, ...) if(!result.bIsSome){ \ + __VA_ARGS__ \ } +#define JUNO_SOME_OPTION(value) {true, value} +#define JUNO_NONE_OPTION(default_value) {false, default_value} #endif // JUNO_MODULE_H diff --git a/include/juno/sm/sm_api.h b/include/juno/sm/sm_api.h index 189bd53e..c539fc1f 100644 --- a/include/juno/sm/sm_api.h +++ b/include/juno/sm/sm_api.h @@ -104,6 +104,11 @@ static inline JUNO_STATUS_T JunoSm_StateInit(JUNO_SM_ROOT_T *ptSm, JUNO_SM_STATE ptStateRoot->tOptionNextState.bIsSome = true; ptStateRoot->tOptionNextState.tSome = (JUNO_SM_STATE_T *) ptNextState; } + else + { + ptStateRoot->tOptionNextState.bIsSome = false; + ptStateRoot->tOptionNextState.tSome = NULL; + } return JunoSm_StateVerify(ptStateRoot); } @@ -114,7 +119,7 @@ static inline JUNO_STATUS_T JunoSm_Init(JUNO_SM_ROOT_T *ptSmRoot, JUNO_SM_STATE_ ptSmRoot->_pfcnFailureHandler = pfcnFailureHandler; ptSmRoot->_pvFailureUserData = pvFailureUserData; JUNO_STATUS_T tStatus = JunoSm_Verify(ptSmRoot); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) return tStatus; } @@ -122,7 +127,7 @@ static inline JUNO_SM_RESULT_STATE_T JunoSm_GetCurrentState(JUNO_SM_ROOT_T *ptSm { JUNO_SM_RESULT_STATE_T tResult = {JUNO_STATUS_ERR, NULL}; tResult.tStatus = JunoSm_Verify(ptSmRoot); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) tResult.tStatus = JUNO_STATUS_SUCCESS; tResult.tOk = ptSmRoot->ptCurrentState; return tResult; @@ -130,9 +135,11 @@ static inline JUNO_SM_RESULT_STATE_T JunoSm_GetCurrentState(JUNO_SM_ROOT_T *ptSm static inline JUNO_SM_RESULT_OPTION_STATE_T JunoSm_TransitionState(JUNO_SM_ROOT_T *ptSmRoot) { - JUNO_SM_RESULT_OPTION_STATE_T tResult = {JUNO_STATUS_ERR, {}}; + JUNO_SM_RESULT_OPTION_STATE_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, + JUNO_NONE_OPTION(NULL) + ); tResult.tStatus = JunoSm_Verify(ptSmRoot); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) tResult.tStatus = JUNO_STATUS_SUCCESS; JUNO_SM_STATE_ROOT_T *ptCurrentStateRoot = (JUNO_SM_STATE_ROOT_T*) ptSmRoot->ptCurrentState; if(ptCurrentStateRoot->tOptionNextState.bIsSome) diff --git a/include/juno/types.h b/include/juno/types.h index f4e721be..f14bce5c 100644 --- a/include/juno/types.h +++ b/include/juno/types.h @@ -17,7 +17,7 @@ #ifndef JUNO_TYPES_H #define JUNO_TYPES_H -#include "module.h" +#include "juno/module.h" #ifdef __cplusplus extern "C" { diff --git a/src/crc/juno_arc.c b/src/juno_arc.c similarity index 97% rename from src/crc/juno_arc.c rename to src/juno_arc.c index 7e3e4d24..0e3d14fe 100644 --- a/src/crc/juno_arc.c +++ b/src/juno_arc.c @@ -16,7 +16,7 @@ */ #include "juno/crc/crc.h" #include -#include "arc.h" +#include "crc/arc.h" uint16_t Juno_CrcArcUpdate(uint16_t iCrc, const void *pcData, size_t zDataSize) { diff --git a/src/crc/juno_binhex.c b/src/juno_binhex.c similarity index 97% rename from src/crc/juno_binhex.c rename to src/juno_binhex.c index 4db6cd7e..1ca73726 100644 --- a/src/crc/juno_binhex.c +++ b/src/juno_binhex.c @@ -16,7 +16,7 @@ */ #include "juno/crc/crc.h" #include -#include "binhex.h" +#include "crc/binhex.h" uint16_t Juno_CrcBinhexUpdate(uint16_t iCrc, const void *pcData, size_t zDataSize) { diff --git a/src/crc/juno_ccitt.c b/src/juno_ccitt.c similarity index 97% rename from src/crc/juno_ccitt.c rename to src/juno_ccitt.c index 2fea36f3..fbaca716 100644 --- a/src/crc/juno_ccitt.c +++ b/src/juno_ccitt.c @@ -16,7 +16,7 @@ */ #include "juno/crc/crc.h" #include -#include "ccitt.h" +#include "crc/ccitt.h" uint16_t Juno_CrcCcittUpdate(uint16_t iCrc, const void *pcData, size_t zDataSize) { diff --git a/src/crc/juno_ccitt32.c b/src/juno_ccitt32.c similarity index 97% rename from src/crc/juno_ccitt32.c rename to src/juno_ccitt32.c index fe446683..bf9b5f64 100644 --- a/src/crc/juno_ccitt32.c +++ b/src/juno_ccitt32.c @@ -15,7 +15,7 @@ included in all copies or substantial portions of the Software. */ #include "juno/crc/crc.h" -#include "ccitt32.h" +#include "crc/ccitt32.h" uint32_t Juno_CrcCcitt32Update(uint32_t iCrc, const void *pcData, size_t zDataSize) { diff --git a/src/juno_crc.c b/src/juno_crc.c deleted file mode 100644 index f0d33767..00000000 --- a/src/juno_crc.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ -#include "crc/juno_arc.c" -#include "crc/juno_binhex.c" -#include "crc/juno_ccitt.c" -#include "crc/juno_ccitt32.c" -#include "crc/juno_kermit.c" -#include "crc/juno_zip.c" diff --git a/src/juno_heap.c b/src/juno_heap.c index a7a69f48..8aed1c0e 100644 --- a/src/juno_heap.c +++ b/src/juno_heap.c @@ -6,7 +6,7 @@ JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap) { JUNO_STATUS_T tStatus = {0}; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) if(ptHeap->zLength == 0) { tStatus = JUNO_STATUS_ERR; @@ -24,7 +24,7 @@ JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap) for(size_t i = 0; i < ptHeap->zLength; ++i) { tIndexResult = JunoDs_Heap_ChildGetParent(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus); + JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus;) if(!tIndexResult.tOk.bIsSome) { return tStatus; @@ -33,11 +33,11 @@ JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap) iParentIndex = tIndexResult.tOk.tSome; // Assign to the parent metrix JUNO_DS_HEAP_COMPARE_RESULT_T tCompareResult = ptHeap->ptApi->Compare(ptHeap, iParentIndex, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus); + JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus;) if(!tCompareResult.tOk) { tStatus = ptHeap->ptApi->Swap(ptHeap, iCurrentIndex, iParentIndex); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) } if(iParentIndex == 0) { @@ -52,7 +52,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) { JUNO_STATUS_T tStatus = {0}; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) if(ptHeap->zLength <= 0) { tStatus = JUNO_STATUS_ERR; @@ -65,7 +65,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) iCurrentIndex = iRoot; JUNO_DS_HEAP_COMPARE_RESULT_T tCompareResult = {0}; JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tIndexResult = JunoDs_Heap_ChildGetLeft(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus); + JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus;) size_t iLeft = 0; bool bLeftSome = tIndexResult.tOk.bIsSome; if(tIndexResult.tOk.bIsSome) @@ -73,7 +73,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) iLeft = tIndexResult.tOk.tSome; } tIndexResult = JunoDs_Heap_ChildGetRight(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus); + JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus;) size_t iRight = 0; bool bRightSome = tIndexResult.tOk.bIsSome; if(tIndexResult.tOk.bIsSome) @@ -83,7 +83,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) if(bLeftSome) { tCompareResult = ptHeap->ptApi->Compare(ptHeap, iCurrentIndex, iLeft); - JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus); + JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus;) if(!tCompareResult.tOk) { iCurrentIndex = iLeft; @@ -92,7 +92,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) if(bRightSome) { tCompareResult = ptHeap->ptApi->Compare(ptHeap, iCurrentIndex, iRight); - JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus); + JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus;) if(!tCompareResult.tOk) { iCurrentIndex = iRight; @@ -101,7 +101,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) if(iCurrentIndex != iRoot) { tStatus = ptHeap->ptApi->Swap(ptHeap, iRoot, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) iRoot = iCurrentIndex; } else diff --git a/src/crc/juno_kermit.c b/src/juno_kermit.c similarity index 97% rename from src/crc/juno_kermit.c rename to src/juno_kermit.c index 3d4c06b6..d399f115 100644 --- a/src/crc/juno_kermit.c +++ b/src/juno_kermit.c @@ -16,7 +16,7 @@ */ #include "juno/crc/crc.h" #include -#include "kermit.h" +#include "crc/kermit.h" uint32_t Juno_CrcKermitUpdate(uint32_t iCrc, const void *pcData, size_t zDataSize) { diff --git a/src/juno_map.c b/src/juno_map.c index 3e0fcc32..50369356 100644 --- a/src/juno_map.c +++ b/src/juno_map.c @@ -26,10 +26,10 @@ JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { JUNO_RESULT_SIZE_T tResult = {0, 0}; tResult.tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) const JUNO_MAP_API_T *ptApi = ptJunoMap->ptApi; tResult = ptApi->Hash(ptKey); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) size_t iHash = tResult.tOk; // Get the capacity size_t zCapacity = ptJunoMap->zCapacity; @@ -41,20 +41,28 @@ JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { size_t zIndex = (iHash + i) % zCapacity; // Get a pointer to the current key - JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetKey(zIndex); - tResult.tStatus = tPtrResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); - void *pvAddr = tPtrResult.tOk; + JUNO_RESULT_BOOL_T tBoolResult = ptApi->IsEmpty( zIndex); tResult.tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) bool bIsEmpty = tBoolResult.tOk; + // Check if the spot is empty or the key is equal + if(bIsEmpty) + { + // Return the index + tResult.tOk = zIndex; + tResult.tStatus = JUNO_STATUS_SUCCESS; + break; + } + JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetKey(zIndex); + tResult.tStatus = tPtrResult.tStatus; + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + void *pvAddr = tPtrResult.tOk; tBoolResult = ptApi->KeyIsEqual(ptKey, pvAddr); tResult.tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) bool bIsEqual = tBoolResult.tOk; - // Check if the spot is empty or the key is equal - if(bIsEmpty || bIsEqual) + if(bIsEqual) { // Return the index tResult.tOk = zIndex; diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index c275f115..fb379ac5 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -49,7 +49,7 @@ static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_M { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) JUNO_MEMORY_ALLOC_BLOCK_T *ptMemBlk = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); if(!zSize) { @@ -105,7 +105,7 @@ static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUN { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) JUNO_MEMORY_ALLOC_BLOCK_T *ptMem = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); if(zNewSize > ptMem->zTypeSize) { @@ -122,7 +122,7 @@ static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_M { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) JUNO_MEMORY_ALLOC_BLOCK_T *ptMemBlk = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); JUNO_ASSERT_EXISTS(ptMemory && ptMemory->pvAddr); JUNO_MEMORY_T tMemory = *ptMemory; @@ -227,6 +227,6 @@ JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_T *ptJunoMemory, // Initially, no freed blocks are available ptJunoMemoryBlock->zFreed = 0; JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) return tStatus; } diff --git a/src/juno_time.c b/src/juno_time.c index ffbb0a62..0e8c0ca3 100644 --- a/src/juno_time.c +++ b/src/juno_time.c @@ -3,7 +3,7 @@ #include "juno/time/time_api.h" #include -static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = -1; +static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = ((JUNO_TIME_SUBSECONDS_T)~0ull); JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd) { diff --git a/src/crc/juno_zip.c b/src/juno_zip.c similarity index 97% rename from src/crc/juno_zip.c rename to src/juno_zip.c index dbf1f571..8373b334 100644 --- a/src/crc/juno_zip.c +++ b/src/juno_zip.c @@ -15,7 +15,7 @@ included in all copies or substantial portions of the Software. */ #include "juno/crc/crc.h" -#include "zip.h" +#include "crc/zip.h" uint32_t Juno_CrcZipUpdate(uint32_t iCrc, const void *pcData, size_t zDataSize) { diff --git a/templates/template_app/src/template_app.cpp b/templates/template_app/src/template_app.cpp index 68681174..b447ded3 100644 --- a/templates/template_app/src/template_app.cpp +++ b/templates/template_app/src/template_app.cpp @@ -115,7 +115,7 @@ JUNO_STATUS_T TemplateApp( ptTemplateApp->tRoot.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptTemplateApp->tRoot.JUNO_FAILURE_USER_DATA = pvFailureUserData; JUNO_STATUS_T tStatus = Verify(ptJunoApp); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) ptTemplateApp->ptLogger = ptLogger; return tStatus; } diff --git a/templates/template_impl/src/template_impl.c b/templates/template_impl/src/template_impl.c index d432dc11..96a869d9 100644 --- a/templates/template_impl/src/template_impl.c +++ b/templates/template_impl/src/template_impl.c @@ -73,7 +73,7 @@ JUNO_STATUS_T Template_ImplApi(TEMPLATE_T *ptTemplate, JUNO_FAILURE_HANDLER_T pf ptTemplateImpl->JUNO_MODULE_SUPER.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptTemplateImpl->JUNO_MODULE_SUPER.JUNO_FAILURE_USER_DATA = pvFailureUserData; JUNO_STATUS_T tStatus = Verify(ptTemplate); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) /* TODO: Assign private members here diff --git a/templates/template_lib/src/template_impl.c b/templates/template_lib/src/template_impl.c index 07de3464..3f37bf68 100644 --- a/templates/template_lib/src/template_impl.c +++ b/templates/template_lib/src/template_impl.c @@ -73,7 +73,7 @@ JUNO_STATUS_T Template_ImplApi(TEMPLATE_T *ptTemplate, JUNO_FAILURE_HANDLER_T pf ptTemplateImpl->tRoot.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptTemplateImpl->tRoot.JUNO_FAILURE_USER_DATA = pvFailureUserData; JUNO_STATUS_T tStatus = Verify(ptTemplate); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) /* TODO: Assign private members here diff --git a/tests/test_cpp.cpp b/tests/test_cpp.cpp index 75df130d..f65827a7 100644 --- a/tests/test_cpp.cpp +++ b/tests/test_cpp.cpp @@ -15,6 +15,7 @@ #include "juno/sb/publisher_api.h" #include "juno/sb/subscriber_api.h" #include "juno/string/string_api.h" +#include "juno/sm/sm_api.h" int main() { diff --git a/tests/test_heap.c b/tests/test_heap.c index cbd17673..be0f1880 100644 --- a/tests/test_heap.c +++ b/tests/test_heap.c @@ -380,8 +380,7 @@ static void test_delete_on_empty_and_delete_reset_behaviour(void) last_index_before = h.tRoot.zLength - 1; h.fail_reset = true; // Reset will return error, but Delete shouldn't propagate it - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoDs_Heap_Delete(&h.tRoot)); - TEST_ASSERT_EQUAL(1u, h.tRoot.zLength); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, JunoDs_Heap_Delete(&h.tRoot)); // Because Reset failed, the last slot should *not* be zeroed TEST_ASSERT_NOT_EQUAL(0, h.data[last_index_before]); h.fail_reset = false; From 242ae768ab5ab8818909d12f2ac282123edb53d1 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Sat, 20 Sep 2025 13:13:13 -0500 Subject: [PATCH 06/34] :sparkles: Make documentation changes --- .github/copilot-instructions.md | 205 ++++++++++++++++++++++++++++ include/juno/ds/heap_api.h | 17 ++- include/juno/io/i2c_io_api.h | 19 ++- include/juno/memory/README.md | 60 +++----- include/juno/sb/broker_api.h | 28 ++-- include/juno/sb/msg_api.h | 23 +++- include/juno/string/string_api.h | 64 --------- include/juno/string/string_direct.h | 50 ------- include/juno/string/string_impl.h | 69 ---------- include/juno/time/time_api.h | 65 ++++++++- src/juno_time.c | 18 +-- tests/test_cpp.cpp | 1 - tests/test_heap.c | 2 +- 13 files changed, 349 insertions(+), 272 deletions(-) create mode 100644 .github/copilot-instructions.md delete mode 100644 include/juno/string/string_api.h delete mode 100644 include/juno/string/string_direct.h delete mode 100644 include/juno/string/string_impl.h diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..63e0c52e --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,205 @@ +# .github/copilot-instructions.md + +> **Purpose:** Onboard a coding agent to perform **thorough merge-request code reviews** for a **freestanding embedded C library**, with an emphasis on **memory safety, reliability, developer experience, and deployability on new systems**. +> **Scope:** General, repo-agnostic playbook (≤2 pages). Use these steps first; only search the repo when information here is incomplete or wrong. + +--- + +## 1) High-Level Overview (for the agent) + +* **What this repository is (expected):** A C library intended for **embedded/freestanding** targets that helps developers **build quickly and test easily**. Likely provides headers in `include/`, sources in `src/`, examples in `examples/`, tests in `tests/` or `test/`. +* **Project type & languages:** C (C99/C11 typical), optional C++ shims, build via **CMake** or **Make** (sometimes **Meson**, **Zephyr/West**, or **PlatformIO**). Host tests run on Linux/macOS/Windows; cross builds for ARM/RISC-V etc. +* **Repo size (estimate at review time):** Run a quick inventory (see §4) and note line counts, dependency weight, and key dirs. Record any large test assets or submodules. + +> **Rule:** Trust this playbook. Prefer the commands and checklists here before ad-hoc greps or trial-and-error. Search only when a step is missing or fails. + +--- + +## 2) Build, Test, Lint, Run — Standard Sequences + +> **Preconditions (always do):** +> +> * Ensure a clean tree: `git submodule update --init --recursive` (if `.gitmodules` exists). +> * If present: `scripts/bootstrap.*` or `tools/bootstrap.*` (read & run first). +> * Prefer out-of-tree builds (`build/` dir). Avoid root pollution. + +### A) CMake (most common) + +```bash +# Configure (host) +cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo +# Or add sanitizers for review +cmake -S . -B build-asan -DCMAKE_BUILD_TYPE=Debug -DSANITIZE=Address,Undefined + +# Build +cmake --build build -j + +# Tests (ctest is typical) +ctest --test-dir build --output-on-failure + +# Lint/format (if defined) +cmake --build build --target clang-format-check || true +cmake --build build --target clang-tidy || true +``` + +**Cross-compile (example ARM GCC):** + +```bash +cmake -S . -B build-arm -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm-gcc.cmake -DCMAKE_BUILD_TYPE=Release +cmake --build build-arm -j +``` + +### B) Makefile + +```bash +make clean || true +make -j +make test # if defined +make format lint # if defined +``` + +### C) Meson (if `meson.build` exists) + +```bash +meson setup build +meson compile -C build +meson test -C build --print-errorlogs +``` + +### D) Zephyr / West (if `west.yml` or `zephyr/` present) + +```bash +west update +west build -b samples/ # verify library links cleanly +``` + +### E) PlatformIO (if `platformio.ini` exists) + +```bash +pio run +pio test +``` + +> **If commands fail:** +> +> * Re-run from a clean out-of-tree dir. +> * Check required tool versions in `CMakeLists.txt`, `toolchain.cmake`, `Makefile`, or CI workflow. +> * Prefer `-DCMAKE_C_STANDARD=11` (or repo’s declared standard) for consistency. + +--- + +## 3) Validation Pipeline (replicate CI locally) + +1. **Discover checks:** Open `.github/workflows/*.yml` (and any other CI config). List jobs: **format**, **lint**, **build (host & cross)**, **unit/integration tests**, **coverage**, **package/install**. +2. **Replicate locally** in this order: + + * **Format**: `clang-format -i` or run provided target. + * **Lint**: `clang-tidy` / `cppcheck` using project config. + * **Build (Debug+ASan/UBSan)**, then **run all tests** with verbose failures. + * **Build (Release)** for size/perf checks. + * **Coverage** (if enabled): `gcov`/`lcov/genhtml`. + * **Install/package** (CMake: `cmake --install build --prefix `). +3. **Record deviations:** If CI runs extra scripts (e.g., `scripts/ci/*.sh`), run them locally and note required env vars. + +> **Time-outs:** Note any step that routinely exceeds 10 minutes; capture mitigation (e.g., `-j`, ccache). + +--- + +## 4) Fast Inventory & Layout Hints + +* **Root files to find quickly:** `README.md`, `CONTRIBUTING.md`, `LICENSE`, `CMakeLists.txt` or `Makefile`, `meson.build`, `.clang-format`, `.clang-tidy`, `.editorconfig`, `Doxyfile`, `.github/workflows/`. +* **Key dirs:** `include/` (public headers), `src/` (lib sources), `tests?/` (unit), `examples?/`, `cmake/` (toolchains/macros), `ports/` or `platform/` (HAL/MCU), `scripts/` or `tools/` (dev utilities). +* **Config locations:** Lint (.clang-\*), compilation options (CMake toolchain or top-level), test config (CTest/Meson), preferences (.editorconfig), package metadata (`pkgconfig/`, `cmake/.cmake`). +* **Dependencies not obvious:** Submodules in `third_party/`, codegen scripts (Python/Lua), optional RTOS shims, platform drivers. + +--- + +## 5) Expert Embedded C Code-Review Checklist (use for every MR) + +### Memory Safety & Undefined Behavior + +* **Bounds/overflow:** Array indices validated; no off-by-one; careful `memcpy/memmove/str*` lengths; avoid `strcpy/sprintf` (prefer length-bounded variants). +* **Integer issues:** Signed/unsigned mixing, shifts by width, overflow/underflow, implicit narrowing (`-Wconversion`), sentinel `size_t` vs `int`. +* **Pointer hygiene:** Null checks, lifetime/aliasing, alignment, strict aliasing violations, double-free, use-after-free, dangling pointers after realloc. +* **Ownership & API contracts:** Who allocates/frees? Clarify in docstrings. Avoid hidden allocations in hot paths and **never in ISRs**. +* **UB hotspots:** Uninitialized reads, out-of-range enums, `volatile` misuse, data races, order of evaluation assumptions. + +### Concurrency, ISR, and Real-Time + +* **ISR-safety:** No blocking or heap; atomicity around shared state; minimal critical sections; correct `volatile` and memory barriers. +* **Reentrancy/thread-safety:** No shared mutable statics unless guarded; documented guarantees. +* **Timing:** O(1) where required; avoid unpredictable latency (I/O, locks, malloc). + +### Portability & Freestanding Constraints + +* Builds with `-ffreestanding` (if applicable) and without hosted headers; no forbidden syscalls; guarded `#ifdef` per platform; endianness and word-size handling; alignment assumptions explicit. +* **C standard:** Consistent (C11/C99). Don’t rely on compiler extensions unless wrapped. +* **Toolchains:** GCC/Clang/ARM-GCC flags sane; warnings as errors (`-Wall -Wextra -Werror -Wshadow -Wstrict-prototypes -Wcast-align -Wconversion -Wdouble-promotion -Wformat=2`, plus `-fanalyzer` where possible). + +### API & Developer Experience (DX) + +* **Ease of use:** Simple init/deinit; clear error codes; consistent naming & prefixes; **zero-config sensible defaults** with optional advanced config via macros. +* **Docs:** Public headers self-documenting; examples compile; README quick-start works; Doxygen (if present) builds clean; change log updated. +* **Testing strategy:** Unit tests cover edge cases; fuzz targets (if any) run; deterministic behavior; host tests do not accidentally require target hardware. + +### Deployment & Packaging + +* **Installability:** `make install` or `cmake --install` installs headers+static/dynamic libs and `pkg-config`/CMake package files. +* **Cross builds:** Toolchain files provided; example commands documented; no hard-coded host paths. +* **ABI/semver:** Public symbols gated; no accidental API breaks; visibility flags set on shared libs. + +--- + +## 6) Automated & Manual Analyses to Run (prefer host first) + +* **Static:** `clang-tidy` with project config; `cppcheck --enable=warning,performance,portability,unusedFunction`; compiler with max warnings + `-Werror`; optional `-fanalyzer`. +* **Dynamic (host):** AddressSanitizer + UndefinedBehaviorSanitizer builds; run all tests with `ASAN_OPTIONS=halt_on_error=1` etc. Valgrind Memcheck on non-ASan builds. +* **Coverage:** Build with `--coverage` or `-fprofile-arcs -ftest-coverage`; generate with `lcov/genhtml`. +* **Fuzz (if available):** libFuzzer/AFL targets; ensure no timeouts/oom. +* **Emulation (if applicable):** QEMU for target ISA; smoke test examples. + +--- + +## 7) MR Review Flow (step-by-step) + +1. **Bootstrap quickly** using §2 for the detected build system. If both CMake and Make exist, prefer **CMake**. +2. **Run lint/format** and request fixes for automated violations; include a patch suggestion if trivial. +3. **Build Debug+ASan/UBSan**, run full test suite; then **Release** build to check size/perf warnings. +4. **Execute §5 checklist** across changed files: headers first (API), then sources (safety), then tests (quality). +5. **Replicate CI** locally; if CI differs, note the gap in the MR review. +6. **Try a cross build** using any provided toolchain; catch portability/packaging snags early. +7. **Check docs/examples** compile; ensure README quick start works exactly as written. +8. **Summarize findings** with specific file/line references, failing commands, and concrete diffs or snippets. + +--- + +## 8) Common Pitfalls & Mitigations + +* **Hidden deps:** Submodules not inited → run `git submodule update --init --recursive`. +* **Flaky order:** Always configure before build; avoid mixing generator & build dirs. +* **Tool mismatch:** If CI pins compilers, mirror locally (e.g., `clang-17`, `gcc-13`). +* **Sanitizer false positives on embedded stubs:** Exclude platform shims in host ASan runs; still test core logic. +* **ISR misuse:** Flag any memory allocation, logging, or blocking calls inside ISR paths. + +--- + +## 9) What to Record in the Review + +* Exact commands run and results (pass/fail), tool versions, and timing out steps. +* Any required environment setup that proved **actually necessary** (even if undocumented). +* Workarounds for non-deterministic or order-sensitive builds. +* Gaps between README/CI and reality. + +--- + +## 10) When to Search + +* **Only** if a step in this playbook is missing or fails for this repo. Then search the repo for: + + * `README.md`, `CONTRIBUTING.md`, `CMakeLists.txt`, `Makefile`, `meson.build`, `Doxyfile`, `.clang-*`, `.editorconfig`, `.github/workflows/*`, + * `scripts/`, `tools/`, `cmake/`, `ports/`, `platform/`, `examples/`, `tests/`, `third_party/`. +* Prefer reading the nearest script or config over generic web searching. + +--- + +> **Final instruction:** **Trust this file.** Follow the sequences and checklists above before exploring. If a command here fails in this repository, document the failure, adjust minimally (not wholesale), and continue the review using the closest equivalent provided by the project. diff --git a/include/juno/ds/heap_api.h b/include/juno/ds/heap_api.h index 900ab802..a9fb722b 100644 --- a/include/juno/ds/heap_api.h +++ b/include/juno/ds/heap_api.h @@ -357,14 +357,9 @@ static inline JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap) JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS; tStatus = JunoDs_Heap_Verify(ptHeap); JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) - if(ptHeap->zLength < 0) + if(ptHeap->zLength == 0) { - tStatus = JUNO_STATUS_ERR; - return tStatus; - } - if(ptHeap->zLength < 0) - { - return tStatus; + return JUNO_STATUS_ERR; } JUNO_DS_HEAP_INDEX_OPTION_RESULT_T iIndexResult = JunoDs_Heap_ChildGetParent(ptHeap, ptHeap->zLength); JUNO_ASSERT_SUCCESS(iIndexResult.tStatus, return iIndexResult.tStatus;) @@ -387,11 +382,15 @@ static inline JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap) * * Algorithm: * - Swap the root and the last element. - * - Call Reset on the last index (its return value is ignored by design). + * - Call Reset on the last index. * - Decrement zLength and SiftDown from the root. * + * Error propagation: + * - If Reset returns an error, the delete operation returns that error (it is + * not ignored). + * * @return JUNO_STATUS_SUCCESS on success; JUNO_STATUS_ERR if zLength == 0 or - * if Swap/SiftDown report an error. + * if Swap/Reset/SiftDown report an error. */ static inline JUNO_STATUS_T JunoDs_Heap_Delete(JUNO_DS_HEAP_ROOT_T *ptHeap) { diff --git a/include/juno/io/i2c_io_api.h b/include/juno/io/i2c_io_api.h index 6723b8ad..6f376a78 100644 --- a/include/juno/io/i2c_io_api.h +++ b/include/juno/io/i2c_io_api.h @@ -110,12 +110,23 @@ struct JUNO_I2C_IO_API_TAG Perform an I2C transfer. A typical call would look like: - ``` - ptApi->Transfer(ptI2c, JUNO_I2C_IO_TRANSFER{WriteMsg(0xFF, ptMyWriteBuff, sizeof(ptMyWriteBuff))}, 1) - // OR - JUNO_I2C_IO_MSG_T ptArrTransfer[] = JUNO_I2C_IO_TRANSFER{WriteMsg(0xFF, ptMyWriteBuff, sizeof(ptMyWriteBuff))}; + ```c + // Single message + ptApi->Transfer(ptI2c, JUNO_I2C_IO_TRANSFER(WriteMsg(0xFF, ptMyWriteBuff, sizeof(ptMyWriteBuff))), 1); + + // OR, create an array of messages + JUNO_I2C_IO_MSG_T ptArrTransfer[] = JUNO_I2C_IO_TRANSFER( + WriteMsg(0xFF, ptMyWriteBuff, sizeof(ptMyWriteBuff)), + ReadMsg(0xFF, ptMyReadBuff, sizeof(ptMyReadBuff)) + ); ptApi->Transfer(ptI2c, ptArrTransfer, sizeof(ptArrTransfer) / sizeof(ptArrTransfer[0])); ``` + + @param ptI2c The I2C module instance. + @param ptArrMsgs Pointer to an array of I2C messages created with + JUNO_I2C_IO_TRANSFER(...). + @param zMsgArrLen Number of messages in the array. + @return JUNO_STATUS_SUCCESS on success, error code otherwise. */ JUNO_STATUS_T (*Transfer)(JUNO_I2C_IO_T *ptI2c, const JUNO_I2C_IO_MSG_T *ptArrMsgs, size_t zMsgArrLen); }; diff --git a/include/juno/memory/README.md b/include/juno/memory/README.md index be0cc710..c1a783c9 100644 --- a/include/juno/memory/README.md +++ b/include/juno/memory/README.md @@ -159,10 +159,14 @@ if(tStatus != JUNO_STATUS_SUCCESS) { For a more dynamic approach, you can use the Memory API interface: ```c +#include "juno/memory/memory_api.h" +#include "juno/memory/memory_block.h" + +// Access the allocator API vtable through the union's ptApi field +const JUNO_MEMORY_ALLOC_API_T *ptMemApi = tMemAlloc.ptApi; -// Use the API for operations JUNO_MEMORY_T tMemory = {0}; -tStatus = ptMemApi->Get(&tMemAlloc, &tMemory, sizeof(MY_DATA_T)); +JUNO_STATUS_T tStatus = ptMemApi->Get(&tMemAlloc, &tMemory, sizeof(MY_DATA_T)); // ... use the memory ... @@ -282,13 +286,13 @@ union JUNO_MEMORY_ALLOC_TAG ```c JUNO_STATUS_T JunoMemory_BlockApi( - JUNO_MEMORY_BLOCK_T *ptMemBlk, + JUNO_MEMORY_ALLOC_T *ptJunoMemory, void *pvMemory, - JUNO_MEMORY_BLOCK_METADATA_T *pvMetadata, + JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, size_t zLength, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, - JUNO_USER_DATA_T *pvUserData + JUNO_USER_DATA_T *pvFailureUserData ); ``` @@ -301,44 +305,21 @@ Initializes a memory block for allocation. Parameters: - `pfcnFailureHandler`: Optional callback function to handle failures - `pvUserData`: Optional user data passed to the failure handler -### Memory Operations +### Memory Operations (via API vtable) ```c -JUNO_STATUS_T Juno_MemoryGet( - JUNO_MEMORY_ALLOC_T *ptMem, - JUNO_MEMORY_T *ptMemory, - size_t zSize -); -``` +// Allocate +JUNO_STATUS_T (*Get)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zSize); -Allocates memory from the specified allocator. Parameters: -- `ptMem`: Pointer to the memory allocation structure -- `ptMemory`: Pointer to store allocation details -- `zSize`: Size of memory to allocate in bytes +// Resize (cannot exceed element size in block allocator) +JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zNewSize); -```c -JUNO_STATUS_T Juno_MemoryUpdate( - JUNO_MEMORY_ALLOC_T *ptMem, - JUNO_MEMORY_T *ptMemory, - size_t zNewSize -); -``` - -Updates an existing memory allocation to a new size. Parameters: -- `ptMem`: Pointer to the memory allocator -- `ptMemory`: The memory to update -- `zNewSize`: The new size for the memory - -```c -JUNO_STATUS_T Juno_MemoryPut( - JUNO_MEMORY_ALLOC_T *ptMem, - JUNO_MEMORY_T *ptMemory -); +// Free +JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory); ``` -Releases memory back to the allocator. Parameters: -- `ptMem`: Pointer to the memory allocation structure -- `ptMemory`: Pointer to the memory to free +Access these through `const JUNO_MEMORY_ALLOC_API_T *ptApi = tMemAlloc.ptApi;` then +call `ptApi->Get(...)`, etc. ### Reference Management @@ -362,9 +343,8 @@ Releases a reference to memory, decrementing its reference count. Parameters: The following example demonstrates how to use the Juno Memory Module to implement a simple single linked list with reference counting: ```c -#include "juno/memory/memory.h" #include "juno/memory/memory_api.h" -#include "juno/memory/memory_types.h" +#include "juno/memory/memory_block.h" #include "juno/status.h" #include @@ -410,7 +390,7 @@ int main() { if(tStatus != JUNO_STATUS_SUCCESS) { return -1; } - const JUNO_MEMORY_API_T *ptMemApi = tMemAlloc.tBase.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptMemApi = tMemAlloc.ptApi; // Create a linked list SINGLE_LINKED_LIST_T tList = { diff --git a/include/juno/sb/broker_api.h b/include/juno/sb/broker_api.h index c7c91005..d50ed8ae 100644 --- a/include/juno/sb/broker_api.h +++ b/include/juno/sb/broker_api.h @@ -21,9 +21,15 @@ */ /** - This header contains the juno_msg library API - @author Robin Onsay -*/ + * @file include/juno/sb/broker_api.h + * @brief Juno broker API. + * + * Defines a broker interface that may work with JUNO_MSG_T messages. + * Note: This header intentionally uses a broker-specific buffer header + * type (JUNO_BROKER_BUFFER_HDR_T) to avoid conflicts with msg_api.h. + * + * @author Robin Onsay + */ #ifndef JUNO_BROKER_API_H #define JUNO_BROKER_API_H #include "juno/memory/memory_api.h" @@ -36,19 +42,19 @@ extern "C" #endif typedef struct JUNO_BROKER_API_TAG JUNO_BROKER_API_T; -typedef struct JUNO_MSG_BUFFER_HDR_TAG JUNO_MSG_BUFFER_HDR_T; +typedef struct JUNO_BROKER_BUFFER_HDR_TAG JUNO_BROKER_BUFFER_HDR_T; typedef union JUNO_MSG_TAG JUNO_MSG_T; typedef struct JUNO_MSG_ROOT_TAG JUNO_MSG_ROOT_T; -struct JUNO_MSG_BUFFER_HDR_TAG +struct JUNO_BROKER_BUFFER_HDR_TAG { - JUNO_MSG_BUFFER_HDR_T *ptNext; + JUNO_BROKER_BUFFER_HDR_T *ptNext; size_t zBufferSize; }; /// Creates a new buffer -#define JunoMsg_NewBuffer(BUFFER_T, ...) {{NULL, sizeof(BUFFER_T)}, __VA_ARGS__} +#define JunoBroker_NewBuffer(BUFFER_T, ...) {{NULL, sizeof(BUFFER_T)}, __VA_ARGS__} struct JUNO_MSG_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BROKER_API_T, JUNO_MEMORY_ALLOC_T *ptAlloc; @@ -58,10 +64,10 @@ struct JUNO_BROKER_API_TAG { /// Verify the message JUNO_STATUS_T (*VerifyMsg)(JUNO_MSG_T *ptJunoMsg); - /// Get the message buffer - JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_HDR_T *ptRetBuffer); - /// Set the message buffer - JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_HDR_T tRetBuffer); + /// Get the message buffer header (out parameter) + JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, JUNO_BROKER_BUFFER_HDR_T *ptRetBuffer); + /// Set the message buffer header (by value) + JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_BROKER_BUFFER_HDR_T tBuffer); }; #ifdef __cplusplus diff --git a/include/juno/sb/msg_api.h b/include/juno/sb/msg_api.h index 08a5ff9a..f7809289 100644 --- a/include/juno/sb/msg_api.h +++ b/include/juno/sb/msg_api.h @@ -21,9 +21,18 @@ */ /** - This header contains the juno_msg library API - @author Robin Onsay -*/ + * @file include/juno/sb/msg_api.h + * @brief Juno message abstraction API. + * + * Provides a generic message type (JUNO_MSG_T) and buffer accessor API. The + * buffer is described by a pointer and a size. Implementations should set the + * buffer using SetBuffer and return it via GetBuffer. + * + * GetBuffer uses an out-parameter (non-const) to return the current buffer + * descriptor. SetBuffer accepts a buffer descriptor by value. + * + * @author Robin Onsay + */ #ifndef JUNO_MSG_API_H #define JUNO_MSG_API_H #include "juno/status.h" @@ -54,10 +63,10 @@ struct JUNO_MSG_API_TAG { /// Verify the message JUNO_STATUS_T (*VerifyMsg)(JUNO_MSG_T *ptJunoMsg); - /// Get the message buffer - JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_T *ptRetBuffer); - /// Set the message buffer - JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_T tRetBuffer); + /// Get the message buffer (out parameter) + JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, JUNO_MSG_BUFFER_T *ptRetBuffer); + /// Set the message buffer (by value) + JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_T tBuffer); }; #ifdef __cplusplus diff --git a/include/juno/string/string_api.h b/include/juno/string/string_api.h deleted file mode 100644 index b46f6689..00000000 --- a/include/juno/string/string_api.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_string library API - @author Robin Onsay -*/ -#ifndef JUNO_STRING_API_H -#define JUNO_STRING_API_H -#include "juno/memory/memory_api.h" -#include "juno/status.h" -#include "juno/module.h" -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct JUNO_STRING_API_TAG JUNO_STRING_API_T; -typedef struct JUNO_STRING_BUFFER_TAG JUNO_STRING_BUFFER_T; - -typedef union JUNO_STRING_TAG JUNO_STRING_T; -typedef struct JUNO_STRING_ROOT_TAG JUNO_STRING_ROOT_T; - - -struct JUNO_STRING_ROOT_TAG JUNO_MODULE_ROOT(JUNO_STRING_API_T, - JUNO_MEMORY_ALLOC_T *ptAlloc; - JUNO_MEMORY_T tMemory; - size_t zSize; -); - -struct JUNO_STRING_API_TAG -{ - /// Initializes the module and resources for juno_string - JUNO_STATUS_T (*Init)(JUNO_STRING_T *ptJunoString, JUNO_MEMORY_ALLOC_T *ptAlloc, const char *pcCStr, size_t zCStrSize); - JUNO_STATUS_T (*Append)(JUNO_STRING_T *ptJunoString, JUNO_STRING_T *ptNewJunoString); - JUNO_STATUS_T (*AppendCStr)(JUNO_STRING_T *ptJunoString, const char *pcCStr, size_t zCStrSize); - JUNO_STATUS_T (*GetSize)(JUNO_STRING_T *ptJunoString, size_t *pzSize); - /// Frees resources allocated by juno_string - JUNO_STATUS_T (*Free)(JUNO_STRING_T *ptJunoString); -}; - -#ifdef __cplusplus -} -#endif -#endif // JUNO_STRING_API_H diff --git a/include/juno/string/string_direct.h b/include/juno/string/string_direct.h deleted file mode 100644 index b807cc22..00000000 --- a/include/juno/string/string_direct.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_string library API - @author Robin Onsay -*/ -#ifndef JUNO_STRING_DIRECT_H -#define JUNO_STRING_DIRECT_H -#include "juno/memory/memory_api.h" -#include "juno/status.h" -#include "juno/string/string_api.h" -#ifdef __cplusplus -extern "C" -{ -#endif - - -/// Initializes the module and resources for juno_string -JUNO_STATUS_T JunoString_Init(JUNO_STRING_T *ptJunoString, JUNO_MEMORY_ALLOC_T *ptAlloc, const char *pcCStr, size_t zCStrSize); -JUNO_STATUS_T JunoString_Append(JUNO_STRING_T *ptJunoString, JUNO_STRING_T *ptNewJunoString); -JUNO_STATUS_T JunoString_AppendCStr(JUNO_STRING_T *ptJunoString, const char *pcCStr, size_t zCStrSize); -JUNO_STATUS_T JunoString_GetSize(JUNO_STRING_T *ptJunoString, size_t *pzSize); -/// Frees resources allocated by juno_string -JUNO_STATUS_T JunoString_Free(JUNO_STRING_T *ptJunoString); - -#ifdef __cplusplus -} -#endif -#endif // JUNO_STRING_DIRECT_H - diff --git a/include/juno/string/string_impl.h b/include/juno/string/string_impl.h deleted file mode 100644 index 22c55a6e..00000000 --- a/include/juno/string/string_impl.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_string impl implementation - @author Robin Onsay -*/ -#ifndef JUNO_STRING_IMPL_H -#define JUNO_STRING_IMPL_H -#include "juno/module.h" -#include "juno/status.h" -#include "juno/string/string_api.h" -#ifdef __cplusplus -extern "C" -{ -#endif - - -typedef struct JUNO_STRING_IMPL_TAG JUNO_STRING_IMPL_T; - -struct JUNO_STRING_IMPL_TAG JUNO_MODULE_DERIVE(JUNO_STRING_ROOT_T, - /* - - TODO: Include implementation specific members here - - */ -); - -#ifdef JUNO_STRING_DEFAULT -/** - This is the default implementation for `JUNO_STRING_T`. - If you want to use the default implementation for `JUNO_STRING_T` - use `#define JUNO_STRING_DEFAULT` prior to including - `#include "juno_string_impl.h"` - - Note: If you are implementing a derived module you will need - to implement `JUNO_STRING_IMPL`. -*/ -union JUNO_STRING_TAG JUNO_MODULE(JUNO_STRING_API_T, JUNO_STRING_ROOT_T, - JUNO_STRING_IMPL_T tJunoStringImpl; -); -#endif - -/* TODO: Insert initialization arguments for module members here*/ -JUNO_STATUS_T JunoString_ImplApi(JUNO_STRING_T *ptJunoString, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData); -#ifdef __cplusplus -} -#endif -#endif // JUNO_STRING_IMPL_H - diff --git a/include/juno/time/time_api.h b/include/juno/time/time_api.h index bd340f21..dab0a259 100644 --- a/include/juno/time/time_api.h +++ b/include/juno/time/time_api.h @@ -15,9 +15,40 @@ included in all copies or substantial portions of the Software. */ /** - This header contains the time library API - @author Robin Onsay -*/ + * @file include/juno/time/time_api.h + * @brief Juno Time module API and common time math helpers. + * + * This header declares the Juno Time module interface (JUNO_TIME_API_T) and + * provides reference implementations for common time math and conversions + * (add/subtract timestamps; convert between timestamp and nanos/micros/millis + * and double). + * + * Notes on timestamp representation: + * - JUNO_TIMESTAMP_T uses an integer seconds field (iSeconds) and an + * unsigned fractional field (iSubSeconds). + * - The fractional field is interpreted as a fixed-point fraction of a second + * over the full-scale value giSUBSECS_MAX (all-ones of the type). That is, + * fraction = (double)iSubSeconds / giSUBSECS_MAX. + * - Representations are not normalized: iSubSeconds == giSUBSECS_MAX is + * equivalent to adding 1 to iSeconds and setting iSubSeconds to 0. Callers + * should avoid constructing such non-canonical values unless they plan to + * normalize. + * + * Conversion/rounding behavior: + * - Conversions from timestamp to integer nanos/micros/millis truncate the + * fractional part toward zero (flooring). Conversions from double to + * timestamp also truncate the integer seconds and fractional part (no + * rounding). Negative inputs are not supported. + * + * Error handling: + * - Subtraction that would result in negative time returns + * JUNO_STATUS_INVALID_DATA_ERROR and saturates the result to 0 seconds and + * 0 subseconds. + * - Conversion functions detect overflow and return + * JUNO_STATUS_INVALID_DATA_ERROR. + * + * @author Robin Onsay + */ #ifndef JUNO_TIME_API_H #define JUNO_TIME_API_H #include "juno/status.h" @@ -61,10 +92,10 @@ struct JUNO_TIME_ROOT_TAG JUNO_MODULE_ROOT(JUNO_TIME_API_T, JUNO_MODULE_EMPTY); struct JUNO_TIMESTAMP_TAG { - /// Seconds component of time + /// Whole seconds component of time JUNO_TIME_SECONDS_T iSeconds; - /// Subseconds componenet of time. - /// `1 Second == 1 << sizeof(JUNO_TIME_SUBSECONDS_T) - 1 Subseconds` + /// Fractional component of time represented over full-scale giSUBSECS_MAX + /// i.e., fractional_seconds = (double)iSubSeconds / giSUBSECS_MAX JUNO_TIME_SUBSECONDS_T iSubSeconds; }; @@ -89,7 +120,7 @@ struct JUNO_TIME_API_TAG JUNO_STATUS_T (*Sleep)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tDuration); /// Convert a timestamp to nanoseconds JUNO_TIME_NANOS_RESULT_T (*TimestampToNanos)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); - /// Convert a timestamp to microsconds + /// Convert a timestamp to microseconds JUNO_TIME_MICROS_RESULT_T (*TimestampToMicros)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); /// Convert a timestamp to milliseconds JUNO_TIME_MILLIS_RESULT_T (*TimestampToMillis)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); @@ -106,14 +137,34 @@ struct JUNO_TIME_API_TAG }; +/** + * @brief Add a duration to a timestamp in-place. + * @param ptTime Module pointer (used for error reporting). + * @param ptRetTime In/out timestamp to be updated. + * @param tTimeToAdd Duration to add. + * @return JUNO_STATUS_SUCCESS on success. + */ JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd); + +/** + * @brief Subtract a duration from a timestamp in-place. + * If the subtraction would underflow (negative time), the result is saturated + * to 0 seconds and 0 subseconds, and JUNO_STATUS_INVALID_DATA_ERROR is + * returned. + */ JUNO_STATUS_T JunoTime_SubtractTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract); + +/** Conversions from timestamp to integer durations (truncates fractional) */ JUNO_TIME_NANOS_RESULT_T JunoTime_TimestampToNanos(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); + +/** Conversions from integer durations to timestamp */ JUNO_TIMESTAMP_RESULT_T JunoTime_NanosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_NANOS_T iNanos); JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_MICROS_T iMicros); JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_MILLIS_T iMillis); + +/** Conversions between timestamp and double (truncating semantics) */ JUNO_RESULT_F64_T JunoTime_TimestampToDouble(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTimestamp); JUNO_TIMESTAMP_RESULT_T JunoTime_DoubleToTimestamp(JUNO_TIME_T *ptTime, double dTimestamp); diff --git a/src/juno_time.c b/src/juno_time.c index 0e8c0ca3..7212e62f 100644 --- a/src/juno_time.c +++ b/src/juno_time.c @@ -88,14 +88,14 @@ JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_T *ptTime, JUNO_T return tResult; } JUNO_TIME_ROOT_T *ptTimeRoot = (JUNO_TIME_ROOT_T *)(ptTime); - const JUNO_TIME_MICROS_T iMAX_MICROS = -1; + const JUNO_TIME_MICROS_T iMAX_MICROS = (JUNO_TIME_MICROS_T)-1; const JUNO_TIME_MICROS_T iMICROS_PER_SEC = 1000 * 1000; tResult.tStatus = JUNO_STATUS_SUCCESS; - // check if seconds -1 would overflow nanos + // check if seconds -1 would overflow micros if(tTime.iSeconds > iMAX_MICROS / iMICROS_PER_SEC - 1) { tResult.tStatus = JUNO_STATUS_INVALID_DATA_ERROR; - JUNO_FAIL_ROOT(tResult.tStatus, ptTimeRoot, "Overflow when converting nanos"); + JUNO_FAIL_ROOT(tResult.tStatus, ptTimeRoot, "Overflow when converting micros"); return tResult; } tResult.tOk = tTime.iSeconds * iMICROS_PER_SEC; @@ -112,14 +112,14 @@ JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_T *ptTime, JUNO_T return tResult; } JUNO_TIME_ROOT_T *ptTimeRoot = (JUNO_TIME_ROOT_T *)(ptTime); - const JUNO_TIME_MICROS_T iMAX_MILLIS = -1; - const JUNO_TIME_MICROS_T iMILLIS_PER_SEC = 1000; + const JUNO_TIME_MILLIS_T iMAX_MILLIS = (JUNO_TIME_MILLIS_T)-1; + const JUNO_TIME_MILLIS_T iMILLIS_PER_SEC = 1000; tResult.tStatus = JUNO_STATUS_SUCCESS; - // check if seconds -1 would overflow nanos + // check if seconds -1 would overflow millis if(tTime.iSeconds > iMAX_MILLIS / iMILLIS_PER_SEC - 1) { tResult.tStatus = JUNO_STATUS_INVALID_DATA_ERROR; - JUNO_FAIL_ROOT(tResult.tStatus, ptTimeRoot, "Overflow when converting nanos"); + JUNO_FAIL_ROOT(tResult.tStatus, ptTimeRoot, "Overflow when converting millis"); return tResult; } tResult.tOk = tTime.iSeconds * iMILLIS_PER_SEC; @@ -151,7 +151,7 @@ JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIM { return tResult; } - const JUNO_TIME_NANOS_T iMICROS_PER_SEC = 1000 * 1000; + const JUNO_TIME_MICROS_T iMICROS_PER_SEC = 1000 * 1000; const JUNO_TIME_SUBSECONDS_T iSUBSECS_PER_MICRO = giSUBSECS_MAX / iMICROS_PER_SEC; tResult.tStatus = JUNO_STATUS_SUCCESS; tResult.tOk.iSeconds = iMicros / iMICROS_PER_SEC; @@ -167,7 +167,7 @@ JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIM { return tResult; } - const JUNO_TIME_NANOS_T iMILLIS_PER_SEC = 1000; + const JUNO_TIME_MILLIS_T iMILLIS_PER_SEC = 1000; const JUNO_TIME_SUBSECONDS_T iSUBSECS_PER_MILLI = giSUBSECS_MAX / iMILLIS_PER_SEC; tResult.tStatus = JUNO_STATUS_SUCCESS; tResult.tOk.iSeconds = iMillis / iMILLIS_PER_SEC; diff --git a/tests/test_cpp.cpp b/tests/test_cpp.cpp index f65827a7..aa8c1c2c 100644 --- a/tests/test_cpp.cpp +++ b/tests/test_cpp.cpp @@ -14,7 +14,6 @@ #include "juno/sb/msg_api.h" #include "juno/sb/publisher_api.h" #include "juno/sb/subscriber_api.h" -#include "juno/string/string_api.h" #include "juno/sm/sm_api.h" int main() diff --git a/tests/test_heap.c b/tests/test_heap.c index be0f1880..40c02927 100644 --- a/tests/test_heap.c +++ b/tests/test_heap.c @@ -373,7 +373,7 @@ static void test_delete_on_empty_and_delete_reset_behaviour(void) TEST_ASSERT_EQUAL(1u, h.tRoot.zLength); TEST_ASSERT_EQUAL(0, h.data[last_index_before]); // Reset should have zeroed this - // Now demonstrate that Delete ignores Reset errors (it still returns success) + // Now demonstrate that Delete propagates Reset errors (it should return an error) make_heap(&h, &kMaxApi, 8); ir = JunoDs_Heap_Insert(&h.tRoot); h.data[ir.tOk] = 5; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoDs_Heap_Update(&h.tRoot)); ir = JunoDs_Heap_Insert(&h.tRoot); h.data[ir.tOk] = 4; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoDs_Heap_Update(&h.tRoot)); From 6f5ae2038883a877570b4a4a9f076fe0ae31bb50 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Sat, 20 Sep 2025 13:17:41 -0500 Subject: [PATCH 07/34] :memo: Change Readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e95e36c1..b799d2d8 100644 --- a/README.md +++ b/README.md @@ -61,3 +61,4 @@ Juno is the name of my wonderful dog and she has brought me so much comfort and stability throughout the years. I wanted to honor her legacy by naming an open-source library after her. + From f87f005dd8e07938f862b940c62f05eb884f1cfc Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Sun, 21 Sep 2025 05:52:19 -0500 Subject: [PATCH 08/34] :sparkles: Change assert semicolon --- examples/example_state_machine.c | 10 ++++----- include/juno/ds/heap_api.h | 20 ++++++++--------- include/juno/macros.h | 2 +- include/juno/map/map_api.h | 24 ++++++++++----------- include/juno/sm/sm_api.h | 6 +++--- src/juno_heap.c | 20 ++++++++--------- src/juno_map.c | 10 ++++----- src/juno_memory_block.c | 8 +++---- templates/template_app/src/template_app.cpp | 2 +- templates/template_impl/src/template_impl.c | 2 +- templates/template_lib/src/template_impl.c | 2 +- 11 files changed, 53 insertions(+), 53 deletions(-) diff --git a/examples/example_state_machine.c b/examples/example_state_machine.c index 671b3e8d..b57ef58d 100644 --- a/examples/example_state_machine.c +++ b/examples/example_state_machine.c @@ -27,7 +27,7 @@ union JUNO_SM_STATE_T JUNO_MODULE(JUNO_SM_STATE_API_T, JUNO_SM_STATE_ROOT_T, static JUNO_STATUS_T StateAction(JUNO_SM_STATE_T *ptJunoSm) { JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; printf("Current State: %u\n", ptTrafficLightState->tThisLight); sleep(1); @@ -41,7 +41,7 @@ static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm) JUNO_RESULT_BOOL_T tResult = {0}; TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; tResult.tStatus = tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tStatus, return tResult); tResult.tOk = ptTrafficLightState->iCounter == 10; return tResult; } @@ -50,7 +50,7 @@ static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm) static JUNO_STATUS_T ResetState(JUNO_SM_STATE_T *ptJunoSm) { JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; ptTrafficLightState->iCounter = 0; return JUNO_STATUS_SUCCESS; @@ -97,13 +97,13 @@ int main() while(true) { JUNO_SM_RESULT_STATE_T tStateResult = JunoSm_GetCurrentState(&tSm.tRoot); - JUNO_ASSERT_SUCCESS(tStateResult.tStatus, break;); + JUNO_ASSERT_SUCCESS(tStateResult.tStatus, break); JUNO_SM_STATE_ROOT_T *ptSmState = &tStateResult.tOk->tRoot; if(ptSmState) { const JUNO_SM_STATE_API_T *ptSmStateApi = ptSmState->ptApi; JUNO_RESULT_BOOL_T tBoolResult = ptSmStateApi->ShouldExit((JUNO_SM_STATE_T *)ptSmState); - JUNO_ASSERT_SUCCESS(tBoolResult.tStatus, break;); + JUNO_ASSERT_SUCCESS(tBoolResult.tStatus, break); if(tBoolResult.tOk) { ptSmStateApi->ResetState((JUNO_SM_STATE_T *)ptSmState); diff --git a/include/juno/ds/heap_api.h b/include/juno/ds/heap_api.h index a9fb722b..3eb3e4ff 100644 --- a/include/juno/ds/heap_api.h +++ b/include/juno/ds/heap_api.h @@ -246,7 +246,7 @@ static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetLeft(JUNO_D { JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); iIndex = 2 * iIndex + 1; if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity) { @@ -273,7 +273,7 @@ static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetRight(JUNO_ { JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); iIndex = 2 * iIndex + 2; if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity) { @@ -300,7 +300,7 @@ static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetParent(JUNO { JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); iIndex = (iIndex - 1)/2; if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity) { @@ -333,7 +333,7 @@ static inline JUNO_DS_HEAP_INDEX_RESULT_T JunoDs_Heap_Insert(JUNO_DS_HEAP_ROOT_T { JUNO_DS_HEAP_INDEX_RESULT_T tResult = {JUNO_STATUS_SUCCESS, 0}; tResult.tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); if(ptHeap->zLength >= ptHeap->zCapacity) { tResult.tStatus = JUNO_STATUS_ERR; @@ -356,13 +356,13 @@ static inline JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap) { JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); if(ptHeap->zLength == 0) { return JUNO_STATUS_ERR; } JUNO_DS_HEAP_INDEX_OPTION_RESULT_T iIndexResult = JunoDs_Heap_ChildGetParent(ptHeap, ptHeap->zLength); - JUNO_ASSERT_SUCCESS(iIndexResult.tStatus, return iIndexResult.tStatus;) + JUNO_ASSERT_SUCCESS(iIndexResult.tStatus, return iIndexResult.tStatus); if(!iIndexResult.tOk.bIsSome) { return tStatus; @@ -372,7 +372,7 @@ static inline JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap) { size_t iCurrentIndex = iIndex - i; tStatus = JunoDs_Heap_SiftDown(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tStatus, continue;) + JUNO_ASSERT_SUCCESS(tStatus, continue); } return tStatus; } @@ -396,16 +396,16 @@ static inline JUNO_STATUS_T JunoDs_Heap_Delete(JUNO_DS_HEAP_ROOT_T *ptHeap) { JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS;; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); if(ptHeap->zLength <= 0) { tStatus = JUNO_STATUS_ERR; return tStatus; } tStatus = ptHeap->ptApi->Swap(ptHeap, ptHeap->zLength-1, 0); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); tStatus = ptHeap->ptApi->Reset(ptHeap, ptHeap->zLength-1); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); ptHeap->zLength -= 1; return JunoDs_Heap_SiftDown(ptHeap, 0); } diff --git a/include/juno/macros.h b/include/juno/macros.h index 1da420eb..a234b9e8 100644 --- a/include/juno/macros.h +++ b/include/juno/macros.h @@ -51,7 +51,7 @@ if(!(ptr)) \ */ #define JUNO_ASSERT_SUCCESS(tStatus, ...) if(tStatus != JUNO_STATUS_SUCCESS) \ { \ - __VA_ARGS__ \ + __VA_ARGS__; \ } diff --git a/include/juno/map/map_api.h b/include/juno/map/map_api.h index 957884ce..4580f7ad 100644 --- a/include/juno/map/map_api.h +++ b/include/juno/map/map_api.h @@ -90,7 +90,7 @@ static inline JUNO_STATUS_T JunoMap_Verify(JUNO_MAP_ROOT_T *ptMap) { JUNO_ASSERT_EXISTS(ptMap); JUNO_STATUS_T tStatus = JunoMap_VerifyApi(ptMap->ptApi); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_ASSERT_EXISTS(ptMap->zCapacity); return tStatus; } @@ -103,17 +103,17 @@ static inline JUNO_STATUS_T JunoMap_Set(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey, { // verify the map JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); // Get the index for the key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tStatus = tSizeResult.tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); // Set the key for the index tStatus = ptJunoMap->ptApi->SetKey(tSizeResult.tOk, ptKey); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); // Set the value for the index tStatus = ptJunoMap->ptApi->SetValue(tSizeResult.tOk, ptValue); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; } @@ -122,15 +122,15 @@ static inline JUNO_RESULT_VOID_PTR_T JunoMap_Get(JUNO_MAP_ROOT_T *ptJunoMap, voi { JUNO_RESULT_VOID_PTR_T tResult = {0, NULL}; tResult.tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); // Get the index for the key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tResult.tStatus = tSizeResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); // Check if the value at the index is empty JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); tResult.tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); bool bIsEmpty = tBoolResult.tOk; if(bIsEmpty) { @@ -146,15 +146,15 @@ static inline JUNO_RESULT_VOID_PTR_T JunoMap_Get(JUNO_MAP_ROOT_T *ptJunoMap, voi static inline JUNO_STATUS_T JunoMap_Remove(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { JUNO_STATUS_T tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); // Get the index for the given key JUNO_RESULT_SIZE_T tSizeResult = JunoMap_GetIndex(ptJunoMap, ptKey); tStatus = tSizeResult.tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); // Check if the key is empty JUNO_RESULT_BOOL_T tBoolResult = ptJunoMap->ptApi->IsEmpty(tSizeResult.tOk); tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); bool bIsEmpty = tBoolResult.tOk; if(bIsEmpty) { @@ -163,7 +163,7 @@ static inline JUNO_STATUS_T JunoMap_Remove(JUNO_MAP_ROOT_T *ptJunoMap, void *ptK } // Remove the key, value at the index tStatus = ptJunoMap->ptApi->Remove(tSizeResult.tOk); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; } diff --git a/include/juno/sm/sm_api.h b/include/juno/sm/sm_api.h index c539fc1f..5c9dffb4 100644 --- a/include/juno/sm/sm_api.h +++ b/include/juno/sm/sm_api.h @@ -119,7 +119,7 @@ static inline JUNO_STATUS_T JunoSm_Init(JUNO_SM_ROOT_T *ptSmRoot, JUNO_SM_STATE_ ptSmRoot->_pfcnFailureHandler = pfcnFailureHandler; ptSmRoot->_pvFailureUserData = pvFailureUserData; JUNO_STATUS_T tStatus = JunoSm_Verify(ptSmRoot); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; } @@ -127,7 +127,7 @@ static inline JUNO_SM_RESULT_STATE_T JunoSm_GetCurrentState(JUNO_SM_ROOT_T *ptSm { JUNO_SM_RESULT_STATE_T tResult = {JUNO_STATUS_ERR, NULL}; tResult.tStatus = JunoSm_Verify(ptSmRoot); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); tResult.tStatus = JUNO_STATUS_SUCCESS; tResult.tOk = ptSmRoot->ptCurrentState; return tResult; @@ -139,7 +139,7 @@ static inline JUNO_SM_RESULT_OPTION_STATE_T JunoSm_TransitionState(JUNO_SM_ROOT_ JUNO_NONE_OPTION(NULL) ); tResult.tStatus = JunoSm_Verify(ptSmRoot); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); tResult.tStatus = JUNO_STATUS_SUCCESS; JUNO_SM_STATE_ROOT_T *ptCurrentStateRoot = (JUNO_SM_STATE_ROOT_T*) ptSmRoot->ptCurrentState; if(ptCurrentStateRoot->tOptionNextState.bIsSome) diff --git a/src/juno_heap.c b/src/juno_heap.c index 8aed1c0e..a7a69f48 100644 --- a/src/juno_heap.c +++ b/src/juno_heap.c @@ -6,7 +6,7 @@ JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap) { JUNO_STATUS_T tStatus = {0}; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); if(ptHeap->zLength == 0) { tStatus = JUNO_STATUS_ERR; @@ -24,7 +24,7 @@ JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap) for(size_t i = 0; i < ptHeap->zLength; ++i) { tIndexResult = JunoDs_Heap_ChildGetParent(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus;) + JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus); if(!tIndexResult.tOk.bIsSome) { return tStatus; @@ -33,11 +33,11 @@ JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap) iParentIndex = tIndexResult.tOk.tSome; // Assign to the parent metrix JUNO_DS_HEAP_COMPARE_RESULT_T tCompareResult = ptHeap->ptApi->Compare(ptHeap, iParentIndex, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus;) + JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus); if(!tCompareResult.tOk) { tStatus = ptHeap->ptApi->Swap(ptHeap, iCurrentIndex, iParentIndex); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); } if(iParentIndex == 0) { @@ -52,7 +52,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) { JUNO_STATUS_T tStatus = {0}; tStatus = JunoDs_Heap_Verify(ptHeap); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); if(ptHeap->zLength <= 0) { tStatus = JUNO_STATUS_ERR; @@ -65,7 +65,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) iCurrentIndex = iRoot; JUNO_DS_HEAP_COMPARE_RESULT_T tCompareResult = {0}; JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tIndexResult = JunoDs_Heap_ChildGetLeft(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus;) + JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus); size_t iLeft = 0; bool bLeftSome = tIndexResult.tOk.bIsSome; if(tIndexResult.tOk.bIsSome) @@ -73,7 +73,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) iLeft = tIndexResult.tOk.tSome; } tIndexResult = JunoDs_Heap_ChildGetRight(ptHeap, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus;) + JUNO_ASSERT_SUCCESS(tIndexResult.tStatus, return tIndexResult.tStatus); size_t iRight = 0; bool bRightSome = tIndexResult.tOk.bIsSome; if(tIndexResult.tOk.bIsSome) @@ -83,7 +83,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) if(bLeftSome) { tCompareResult = ptHeap->ptApi->Compare(ptHeap, iCurrentIndex, iLeft); - JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus;) + JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus); if(!tCompareResult.tOk) { iCurrentIndex = iLeft; @@ -92,7 +92,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) if(bRightSome) { tCompareResult = ptHeap->ptApi->Compare(ptHeap, iCurrentIndex, iRight); - JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus;) + JUNO_ASSERT_SUCCESS(tCompareResult.tStatus, return tCompareResult.tStatus); if(!tCompareResult.tOk) { iCurrentIndex = iRight; @@ -101,7 +101,7 @@ JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart) if(iCurrentIndex != iRoot) { tStatus = ptHeap->ptApi->Swap(ptHeap, iRoot, iCurrentIndex); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); iRoot = iCurrentIndex; } else diff --git a/src/juno_map.c b/src/juno_map.c index 50369356..8e8719a9 100644 --- a/src/juno_map.c +++ b/src/juno_map.c @@ -26,10 +26,10 @@ JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) { JUNO_RESULT_SIZE_T tResult = {0, 0}; tResult.tStatus = JunoMap_Verify(ptJunoMap); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); const JUNO_MAP_API_T *ptApi = ptJunoMap->ptApi; tResult = ptApi->Hash(ptKey); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); size_t iHash = tResult.tOk; // Get the capacity size_t zCapacity = ptJunoMap->zCapacity; @@ -44,7 +44,7 @@ JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) JUNO_RESULT_BOOL_T tBoolResult = ptApi->IsEmpty( zIndex); tResult.tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); bool bIsEmpty = tBoolResult.tOk; // Check if the spot is empty or the key is equal if(bIsEmpty) @@ -56,11 +56,11 @@ JUNO_RESULT_SIZE_T JunoMap_GetIndex(JUNO_MAP_ROOT_T *ptJunoMap, void *ptKey) } JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetKey(zIndex); tResult.tStatus = tPtrResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); void *pvAddr = tPtrResult.tOk; tBoolResult = ptApi->KeyIsEqual(ptKey, pvAddr); tResult.tStatus = tBoolResult.tStatus; - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult;) + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); bool bIsEqual = tBoolResult.tOk; if(bIsEqual) { diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index fb379ac5..c275f115 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -49,7 +49,7 @@ static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_M { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_MEMORY_ALLOC_BLOCK_T *ptMemBlk = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); if(!zSize) { @@ -105,7 +105,7 @@ static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUN { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_MEMORY_ALLOC_BLOCK_T *ptMem = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); if(zNewSize > ptMem->zTypeSize) { @@ -122,7 +122,7 @@ static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_M { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_MEMORY_ALLOC_BLOCK_T *ptMemBlk = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); JUNO_ASSERT_EXISTS(ptMemory && ptMemory->pvAddr); JUNO_MEMORY_T tMemory = *ptMemory; @@ -227,6 +227,6 @@ JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_T *ptJunoMemory, // Initially, no freed blocks are available ptJunoMemoryBlock->zFreed = 0; JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; } diff --git a/templates/template_app/src/template_app.cpp b/templates/template_app/src/template_app.cpp index b447ded3..68681174 100644 --- a/templates/template_app/src/template_app.cpp +++ b/templates/template_app/src/template_app.cpp @@ -115,7 +115,7 @@ JUNO_STATUS_T TemplateApp( ptTemplateApp->tRoot.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptTemplateApp->tRoot.JUNO_FAILURE_USER_DATA = pvFailureUserData; JUNO_STATUS_T tStatus = Verify(ptJunoApp); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); ptTemplateApp->ptLogger = ptLogger; return tStatus; } diff --git a/templates/template_impl/src/template_impl.c b/templates/template_impl/src/template_impl.c index 96a869d9..d432dc11 100644 --- a/templates/template_impl/src/template_impl.c +++ b/templates/template_impl/src/template_impl.c @@ -73,7 +73,7 @@ JUNO_STATUS_T Template_ImplApi(TEMPLATE_T *ptTemplate, JUNO_FAILURE_HANDLER_T pf ptTemplateImpl->JUNO_MODULE_SUPER.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptTemplateImpl->JUNO_MODULE_SUPER.JUNO_FAILURE_USER_DATA = pvFailureUserData; JUNO_STATUS_T tStatus = Verify(ptTemplate); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); /* TODO: Assign private members here diff --git a/templates/template_lib/src/template_impl.c b/templates/template_lib/src/template_impl.c index 3f37bf68..07de3464 100644 --- a/templates/template_lib/src/template_impl.c +++ b/templates/template_lib/src/template_impl.c @@ -73,7 +73,7 @@ JUNO_STATUS_T Template_ImplApi(TEMPLATE_T *ptTemplate, JUNO_FAILURE_HANDLER_T pf ptTemplateImpl->tRoot.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptTemplateImpl->tRoot.JUNO_FAILURE_USER_DATA = pvFailureUserData; JUNO_STATUS_T tStatus = Verify(ptTemplate); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus;) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); /* TODO: Assign private members here From 725e6151edb830924c5a1367e58cb5fab3484d5b Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Mon, 22 Sep 2025 15:37:49 +0000 Subject: [PATCH 09/34] Add api to queue buff --- include/juno/ds/buff_queue_api.h | 121 ++++++++++------- include/juno/module.h | 2 +- tests/test_buff.c | 220 ++++++++++++++++--------------- 3 files changed, 188 insertions(+), 155 deletions(-) diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index e8f40d17..e08008b4 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -30,6 +30,7 @@ #include "juno/status.h" #include "juno/module.h" #include "juno/types.h" +#include #ifdef __cplusplus extern "C" { @@ -37,11 +38,12 @@ extern "C" /// The Buffer queue root typedef struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_BUFF_QUEUE_ROOT_T; +typedef struct JUNO_BUFF_QUEUE_API_TAG JUNO_BUFF_QUEUE_API_T; /// The Buffer queue module typedef union JUNO_BUFF_QUEUE_T JUNO_BUFF_QUEUE_T; /// The root buffee queue -struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_MODULE_ROOT(void, +struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BUFF_QUEUE_API_T, /// The start index of the buffer (ie the first element) size_t iStartIndex; /// The current length of the buffer @@ -50,85 +52,102 @@ struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_MODULE_ROOT(void, size_t zCapacity; ); -/// Initialize a buffer queue with a capacity -static inline JUNO_STATUS_T JunoBuff_QueueInit(JUNO_BUFF_QUEUE_T *ptQueue, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +struct JUNO_BUFF_QUEUE_API_TAG +{ + JUNO_STATUS_T (*SetAt)(JUNO_BUFF_QUEUE_T *ptQueue, void *ptItem, size_t iIndex); + JUNO_RESULT_VOID_PTR_T (*GetAt)(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); + JUNO_STATUS_T (*RemoveAt)(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); + JUNO_STATUS_T (*Copy)(void *ptDest, void *ptSrc); +}; + +static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) { JUNO_ASSERT_EXISTS(ptQueue); - JUNO_BUFF_QUEUE_ROOT_T *ptQueueRoot = (JUNO_BUFF_QUEUE_ROOT_T *)(ptQueue); - ptQueueRoot->iStartIndex = 0; - ptQueueRoot->zLength = 0; - ptQueueRoot->zCapacity = zCapacity; - ptQueueRoot->_pfcnFailureHandler = pfcnFailureHdlr; - ptQueueRoot->_pvFailureUserData = pvFailureUserData; + JUNO_ASSERT_EXISTS( + ptQueue->ptApi && + ptQueue->zCapacity && + ptQueue->ptApi->GetAt && + ptQueue->ptApi->SetAt && + ptQueue->ptApi->RemoveAt + ); return JUNO_STATUS_SUCCESS; } +/// Initialize a buffer queue with a capacity +static inline JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +{ + JUNO_ASSERT_EXISTS(ptQueue); + ptQueue->ptApi = ptApi; + ptQueue->iStartIndex = 0; + ptQueue->zLength = 0; + ptQueue->zCapacity = zCapacity; + ptQueue->_pfcnFailureHandler = pfcnFailureHdlr; + ptQueue->_pvFailureUserData = pvFailureUserData; + return JunoDs_Buff_QueueVerify(ptQueue); +} + /// Enqueue an item into the buffer /// @returns The index to place the enqueued item -static inline JUNO_RESULT_SIZE_T JunoBuff_QueueEnqueue(JUNO_BUFF_QUEUE_T *ptQueue) +static inline JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem) { - JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; - if(!ptQueue) - { - tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; - return tResult; - } - JUNO_BUFF_QUEUE_ROOT_T *ptQueueRoot = (JUNO_BUFF_QUEUE_ROOT_T *)(ptQueue); - if(ptQueueRoot->zLength < ptQueueRoot->zCapacity) + JUNO_ASSERT_EXISTS(ptQueue); + JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); + if(ptQueue->zLength < ptQueue->zCapacity) { - tResult.tOk = (ptQueueRoot->iStartIndex + ptQueueRoot->zLength) % ptQueueRoot->zCapacity; - ptQueueRoot->zLength += 1; + size_t iIndex = (ptQueue->iStartIndex + ptQueue->zLength) % ptQueue->zCapacity; + tStatus = ptQueue->ptApi->SetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptItem, iIndex); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + ptQueue->zLength += 1; } else { - tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tResult.tStatus, ptQueueRoot->_pfcnFailureHandler, ptQueueRoot->_pvFailureUserData, "Failed to enqueue data"); - return tResult; + tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + JUNO_FAIL(tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Failed to enqueue data"); + return tStatus; } - return tResult; + return tStatus; } /// Dequeue an item from the buffer /// @returns The index to dequeue the item from -static inline JUNO_RESULT_SIZE_T JunoBuff_QueueDequeue(JUNO_BUFF_QUEUE_T *ptQueue) +static inline JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptReturn) { - JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; - if(!ptQueue) + JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_EXISTS(ptReturn); + if(ptQueue->zLength > 0) { - tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; - return tResult; + const JUNO_BUFF_QUEUE_API_T *ptApi = ptQueue->ptApi; + size_t iDequeueIndex = ptQueue->iStartIndex; + JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); + JUNO_ASSERT_SUCCESS(tPtrResult.tStatus, return tPtrResult.tStatus); + tStatus = ptApi->Copy(ptReturn, JUNO_OK(tPtrResult)); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = ptApi->RemoveAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + ptQueue->iStartIndex = (ptQueue->iStartIndex + 1) % ptQueue->zCapacity; + ptQueue->zLength -= 1; + return tStatus; } - JUNO_BUFF_QUEUE_ROOT_T *ptQueueRoot = (JUNO_BUFF_QUEUE_ROOT_T *)(ptQueue); - if(ptQueueRoot->zLength > 0) - { - tResult.tOk = ptQueueRoot->iStartIndex; - ptQueueRoot->iStartIndex = (ptQueueRoot->iStartIndex + 1) % ptQueueRoot->zCapacity; - ptQueueRoot->zLength -= 1; - return tResult; - } - tResult.tStatus = JUNO_STATUS_ERR; - JUNO_FAIL(tResult.tStatus, ptQueueRoot->_pfcnFailureHandler, ptQueueRoot->_pvFailureUserData, "Queue is empty"); - return tResult; + tStatus = JUNO_STATUS_ERR; + JUNO_FAIL(tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); + return tStatus; } /// Peek at the next item in the queue /// @returns the index of the next item in the queue -static inline JUNO_RESULT_SIZE_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_T *ptQueue) +static inline JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) { - JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; - if(!ptQueue) - { - tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; - return tResult; - } - JUNO_BUFF_QUEUE_ROOT_T *ptQueueRoot = (JUNO_BUFF_QUEUE_ROOT_T *)(ptQueue); - if(ptQueueRoot->zLength == 0) + JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); + tResult.tStatus = JunoDs_Buff_QueueVerify(ptQueue); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + if(ptQueue->zLength == 0) { tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tResult.tStatus, ptQueueRoot->_pfcnFailureHandler, ptQueueRoot->_pvFailureUserData, "Queue is empty"); + JUNO_FAIL(tResult.tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); return tResult; } - tResult.tOk = ptQueueRoot->iStartIndex; + tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptQueue->iStartIndex); return tResult; } diff --git a/include/juno/module.h b/include/juno/module.h index 98bb3fd9..9a8eda70 100644 --- a/include/juno/module.h +++ b/include/juno/module.h @@ -227,7 +227,7 @@ typedef struct NAME_T \ OK_T tOk; \ } NAME_T -#define JUNO_OK(result, ...) result.tOk +#define JUNO_OK(result) result.tOk #define JUNO_ASSERT_OK(result, ...) JUNO_ASSERT_SUCCESS(result.tStatus, __VA_ARGS__) #define JUNO_OK_RESULT(value) {JUNO_STATUS_SUCCESS, value} #define JUNO_ERR_RESULT(err, value) {err, value} diff --git a/tests/test_buff.c b/tests/test_buff.c index 71f27239..ce17d7fe 100644 --- a/tests/test_buff.c +++ b/tests/test_buff.c @@ -18,7 +18,25 @@ void tearDown(void) } +typedef struct TEST_QUEUE JUNO_MODULE_DERIVE(JUNO_BUFF_QUEUE_ROOT_T, + uint8_t iTestQueue[10]; +) TEST_QUEUE; + + +static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_T *ptQueue, void *ptItem, size_t iIndex); +static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); +static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); +static inline JUNO_STATUS_T Queue_Copy(void *ptDest, void *ptSrc); + +const JUNO_BUFF_QUEUE_API_T gtQueueApi = { + Queue_SetAt, + Queue_GetAt, + Queue_RemoveAt, + Queue_Copy +}; + union JUNO_BUFF_QUEUE_T JUNO_MODULE(void, JUNO_BUFF_QUEUE_ROOT_T, + TEST_QUEUE tTestQueue; ); union JUNO_BUFF_STACK_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, @@ -26,131 +44,99 @@ union JUNO_BUFF_STACK_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, static void test_queue(void) { - uint8_t iTestQueue[10] = {0}; - JUNO_BUFF_QUEUE_ROOT_T tQueueRoot = {0}; - JUNO_RESULT_SIZE_T tResult = {0}; - JUNO_BUFF_QUEUE_T tQueue = {.tRoot = tQueueRoot}; - tResult.tStatus = JunoBuff_QueueInit(&tQueue, sizeof(iTestQueue), NULL, NULL); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + TEST_QUEUE tTestQueue = {0}; + JUNO_STATUS_T tStatus = JunoDs_Buff_QueueInit(&tTestQueue.tRoot, >QueueApi, 10, NULL, NULL); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + JUNO_BUFF_QUEUE_T tQueue = {.tTestQueue = tTestQueue}; + uint8_t iValue = 0; + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - size_t iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestQueue[iIndex] = i+1; + iValue = i + 1; + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - size_t iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueDequeue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(i+1, iTestQueue[iIndex]); + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i+1, iValue); } - tResult = JunoBuff_QueueDequeue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestQueue[iIndex] = i+1; + iValue = i + 1; + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueDequeue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(i+1, iTestQueue[iIndex]); + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i+1, iValue); } - tResult = JunoBuff_QueueDequeue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestQueue[iIndex] = i+1; - tResult = JunoBuff_QueueDequeue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(i+1, iTestQueue[iIndex]); + iValue = i + 1; + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i+1, iValue); } - tResult = JunoBuff_QueueDequeue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestQueue[iIndex] = i+1; + iValue = i + 1; + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueDequeue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(i+1, iTestQueue[iIndex]); + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i+1, iValue); } - tResult = JunoBuff_QueueDequeue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - memset(iTestQueue, 0, sizeof(iTestQueue)); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + memset(&tTestQueue.iTestQueue, 0, sizeof(tTestQueue.iTestQueue)); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestQueue[iIndex] = i+1; + iValue = i + 1; + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - for(size_t i = 0; i < sizeof(iTestQueue)/2; i++) + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue)/2; i++) { - iIndex = 0; - tResult = JunoBuff_QueueDequeue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(i+1, iTestQueue[iIndex]); - iTestQueue[iIndex] = 0; + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - for(size_t i = 0; i < sizeof(iTestQueue)/2; i++) + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue)/2; i++) { - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestQueue[iIndex] = i + 1+ sizeof(iTestQueue)/2; + iValue = i + 1 + sizeof(tTestQueue.iTestQueue)/2; + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - iIndex = 0; - tResult = JunoBuff_QueueEnqueue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestQueue); i++) + tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { - iIndex = 0; - tResult = JunoBuff_QueueDequeue(&tQueue); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - uint8_t iTruth = (i % (sizeof(iTestQueue)/2)) + 1 + sizeof(iTestQueue)/2; - TEST_ASSERT_EQUAL(iTruth, iTestQueue[iIndex]); - iTestQueue[iIndex] = 0; + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + uint8_t iTruth = (i % (sizeof(tTestQueue.iTestQueue)/2)) + 1 + sizeof(tTestQueue.iTestQueue)/2; + TEST_ASSERT_EQUAL(iTruth, iValue); } - tResult = JunoBuff_QueueDequeue(&tQueue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); + tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } static void test_stack(void) @@ -213,3 +199,31 @@ int main(void) RUN_TEST(test_stack); return UNITY_END(); } + +static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_T *ptQueue, void *ptItem, size_t iIndex) +{ + uint8_t *iItem = (void *) ptItem; + ptQueue->tTestQueue.iTestQueue[iIndex] = *iItem; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex) +{ + JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptQueue->tTestQueue.iTestQueue[iIndex]); + return tResult; +} + +static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex) +{ + ptQueue->tTestQueue.iTestQueue[iIndex] = 0; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T Queue_Copy(void *ptDest, void *ptSrc) +{ + uint8_t *iDest = (void *) ptDest; + uint8_t *iSrc= (void *) ptSrc; + *iDest = *iSrc; + return JUNO_STATUS_SUCCESS; +} + From f0d304886e412fbb07df945d8defccda949c3b10 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Mon, 22 Sep 2025 10:41:00 -0500 Subject: [PATCH 10/34] Update src/juno_time.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/juno_time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/juno_time.c b/src/juno_time.c index 7212e62f..33180e66 100644 --- a/src/juno_time.c +++ b/src/juno_time.c @@ -3,7 +3,7 @@ #include "juno/time/time_api.h" #include -static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = ((JUNO_TIME_SUBSECONDS_T)~0ull); +static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = ((JUNO_TIME_SUBSECONDS_T)~(JUNO_TIME_SUBSECONDS_T)0); JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd) { From b18a8a97d0d55713d098ce5b3744aef944165bc0 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Mon, 22 Sep 2025 10:50:45 -0500 Subject: [PATCH 11/34] Update tests/test_map.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/test_map.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_map.c b/tests/test_map.c index 71e43ec4..f96e243d 100644 --- a/tests/test_map.c +++ b/tests/test_map.c @@ -337,12 +337,15 @@ static void test_duplicate_key_insertion(void) static void test_overflow_map(void) { int vals[TEST_MAP_CAPACITY]; - char keybuf[32]; + char keys[TEST_MAP_CAPACITY][8]; for (size_t i = 0; i < TEST_MAP_CAPACITY; i++) { vals[i] = (int)i + 1; - snprintf(keybuf, sizeof(keybuf), "#%u", (unsigned)i); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, keybuf, &vals[i])); + snprintf(keys[i], sizeof(keys[i]), "#%u", (unsigned)i); + } + for (size_t i = 0; i < TEST_MAP_CAPACITY; i++) + { + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, JunoMap_Set(&gRoot, keys[i], &vals[i])); } TEST_ASSERT_EQUAL(TEST_MAP_CAPACITY, TestMap_CountOccupied()); From b996834e289ede257164c7d8102c4cde7ce6a8ac Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Mon, 22 Sep 2025 16:27:18 +0000 Subject: [PATCH 12/34] Move inline to global --- include/juno/ds/buff_queue_api.h | 74 +++--------------------------- src/juno_buff_queue.c | 79 ++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 src/juno_buff_queue.c diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index e08008b4..eeeaf09d 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -74,83 +74,21 @@ static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(JUNO_BUFF_QUEUE_ROOT_T *ptQu } /// Initialize a buffer queue with a capacity -static inline JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) -{ - JUNO_ASSERT_EXISTS(ptQueue); - ptQueue->ptApi = ptApi; - ptQueue->iStartIndex = 0; - ptQueue->zLength = 0; - ptQueue->zCapacity = zCapacity; - ptQueue->_pfcnFailureHandler = pfcnFailureHdlr; - ptQueue->_pvFailureUserData = pvFailureUserData; - return JunoDs_Buff_QueueVerify(ptQueue); -} +JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); /// Enqueue an item into the buffer /// @returns The index to place the enqueued item -static inline JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem) -{ - JUNO_ASSERT_EXISTS(ptQueue); - JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); - if(ptQueue->zLength < ptQueue->zCapacity) - { - size_t iIndex = (ptQueue->iStartIndex + ptQueue->zLength) % ptQueue->zCapacity; - tStatus = ptQueue->ptApi->SetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptItem, iIndex); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptQueue->zLength += 1; - } - else - { - tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Failed to enqueue data"); - return tStatus; - } - return tStatus; -} +JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem); + /// Dequeue an item from the buffer /// @returns The index to dequeue the item from -static inline JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptReturn) -{ - JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - JUNO_ASSERT_EXISTS(ptReturn); - if(ptQueue->zLength > 0) - { - const JUNO_BUFF_QUEUE_API_T *ptApi = ptQueue->ptApi; - size_t iDequeueIndex = ptQueue->iStartIndex; - JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); - JUNO_ASSERT_SUCCESS(tPtrResult.tStatus, return tPtrResult.tStatus); - tStatus = ptApi->Copy(ptReturn, JUNO_OK(tPtrResult)); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - tStatus = ptApi->RemoveAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptQueue->iStartIndex = (ptQueue->iStartIndex + 1) % ptQueue->zCapacity; - ptQueue->zLength -= 1; - return tStatus; - } - tStatus = JUNO_STATUS_ERR; - JUNO_FAIL(tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); - return tStatus; -} +JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptReturn); + /// Peek at the next item in the queue /// @returns the index of the next item in the queue -static inline JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) -{ - JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); - tResult.tStatus = JunoDs_Buff_QueueVerify(ptQueue); - JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); - if(ptQueue->zLength == 0) - { - tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tResult.tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); - return tResult; - } - tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptQueue->iStartIndex); - return tResult; -} - +JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue); #ifdef __cplusplus } diff --git a/src/juno_buff_queue.c b/src/juno_buff_queue.c new file mode 100644 index 00000000..80ffdd06 --- /dev/null +++ b/src/juno_buff_queue.c @@ -0,0 +1,79 @@ +#include "juno/ds/buff_queue_api.h" + +/// Initialize a buffer queue with a capacity +JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +{ + JUNO_ASSERT_EXISTS(ptQueue); + ptQueue->ptApi = ptApi; + ptQueue->iStartIndex = 0; + ptQueue->zLength = 0; + ptQueue->zCapacity = zCapacity; + ptQueue->_pfcnFailureHandler = pfcnFailureHdlr; + ptQueue->_pvFailureUserData = pvFailureUserData; + return JunoDs_Buff_QueueVerify(ptQueue); +} + +/// Enqueue an item into the buffer +/// @returns The index to place the enqueued item +JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem) +{ + JUNO_ASSERT_EXISTS(ptQueue); + JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); + if(ptQueue->zLength < ptQueue->zCapacity) + { + size_t iIndex = (ptQueue->iStartIndex + ptQueue->zLength) % ptQueue->zCapacity; + tStatus = ptQueue->ptApi->SetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptItem, iIndex); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + ptQueue->zLength += 1; + } + else + { + tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + JUNO_FAIL(tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Failed to enqueue data"); + return tStatus; + } + return tStatus; +} + +/// Dequeue an item from the buffer +/// @returns The index to dequeue the item from +JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptReturn) +{ + JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ASSERT_EXISTS(ptReturn); + if(ptQueue->zLength > 0) + { + const JUNO_BUFF_QUEUE_API_T *ptApi = ptQueue->ptApi; + size_t iDequeueIndex = ptQueue->iStartIndex; + JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); + JUNO_ASSERT_SUCCESS(tPtrResult.tStatus, return tPtrResult.tStatus); + tStatus = ptApi->Copy(ptReturn, JUNO_OK(tPtrResult)); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = ptApi->RemoveAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + ptQueue->iStartIndex = (ptQueue->iStartIndex + 1) % ptQueue->zCapacity; + ptQueue->zLength -= 1; + return tStatus; + } + tStatus = JUNO_STATUS_ERR; + JUNO_FAIL(tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); + return tStatus; +} + +/// Peek at the next item in the queue +/// @returns the index of the next item in the queue +JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) +{ + JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); + tResult.tStatus = JunoDs_Buff_QueueVerify(ptQueue); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + if(ptQueue->zLength == 0) + { + tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + JUNO_FAIL(tResult.tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); + return tResult; + } + tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptQueue->iStartIndex); + return tResult; +} \ No newline at end of file From b64ef83c2e9712330d526b99c27b3b41ea520fdd Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Mon, 22 Sep 2025 16:29:04 +0000 Subject: [PATCH 13/34] Fix newline --- src/juno_buff_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/juno_buff_queue.c b/src/juno_buff_queue.c index 80ffdd06..b320ac28 100644 --- a/src/juno_buff_queue.c +++ b/src/juno_buff_queue.c @@ -76,4 +76,4 @@ JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) } tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptQueue->iStartIndex); return tResult; -} \ No newline at end of file +} From 583d52823c8ecc9050e7bbb0a5a0eac73c949583 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Tue, 23 Sep 2025 04:20:15 -0500 Subject: [PATCH 14/34] :fire: Remove union forward declare --- include/juno/app/app_api.h | 7 +- include/juno/ds/buff_api.hpp | 22 ++-- include/juno/ds/buff_queue_api.h | 8 +- include/juno/ds/buff_stack_api.h | 10 +- include/juno/ds/juno_buff.hpp | 46 +++------ include/juno/io/async_io_api.h | 15 ++- include/juno/io/i2c_io_api.h | 3 +- include/juno/io/spi_io_api.h | 3 +- include/juno/log/log_api.h | 9 +- include/juno/map/map_api.h | 1 - include/juno/math/juno_dyn_types.h | 2 +- include/juno/memory/memory_api.h | 7 +- include/juno/memory/memory_block.h | 16 +-- include/juno/sb/subscriber_api.h | 2 +- include/juno/sch/juno_sch_api.h | 11 +- include/juno/sm/sm_api.h | 22 ++-- include/juno/time/time_api.h | 47 +++++---- src/juno_buff_queue.c | 8 +- src/juno_memory_block.c | 15 ++- src/juno_time.c | 20 ++-- tests/test_buff_cpp.cpp | 4 +- tests/test_memory.c | 155 ++++++++++++----------------- tests/test_time.c | 17 ++-- 23 files changed, 180 insertions(+), 270 deletions(-) diff --git a/include/juno/app/app_api.h b/include/juno/app/app_api.h index cb112ca4..a1d5f9b6 100644 --- a/include/juno/app/app_api.h +++ b/include/juno/app/app_api.h @@ -35,16 +35,15 @@ extern "C" typedef struct JUNO_APP_API_TAG JUNO_APP_API_T; -typedef union JUNO_APP_T JUNO_APP_T; typedef struct JUNO_APP_ROOT_TAG JUNO_APP_ROOT_T; struct JUNO_APP_ROOT_TAG JUNO_MODULE_ROOT(JUNO_APP_API_T, JUNO_MODULE_EMPTY); struct JUNO_APP_API_TAG { - JUNO_STATUS_T (*OnInit)(JUNO_APP_T *ptJunoApp); - JUNO_STATUS_T (*OnProcess)(JUNO_APP_T *ptJunoApp); - JUNO_STATUS_T (*OnExit)(JUNO_APP_T *ptJunoApp); + JUNO_STATUS_T (*OnInit)(JUNO_APP_ROOT_T *ptJunoApp); + JUNO_STATUS_T (*OnProcess)(JUNO_APP_ROOT_T *ptJunoApp); + JUNO_STATUS_T (*OnExit)(JUNO_APP_ROOT_T *ptJunoApp); }; #ifdef __cplusplus diff --git a/include/juno/ds/buff_api.hpp b/include/juno/ds/buff_api.hpp index a51b6808..dd0764df 100644 --- a/include/juno/ds/buff_api.hpp +++ b/include/juno/ds/buff_api.hpp @@ -43,12 +43,6 @@ namespace buff template struct QUEUE_API_T; -/** - The queue buffer module -*/ -template -union QUEUE_T; - /** The queue root implementation */ @@ -66,11 +60,11 @@ template struct QUEUE_API_T { /// Enqueue data into the queue buffer - JUNO_STATUS_T (*Enqueue)(QUEUE_T& tQueue, T tData); + JUNO_STATUS_T (*Enqueue)(QUEUE_ROOT_T& tQueue, T tData); /// Dequeue data from the queue buffer - RESULT_T (*Dequeue)(QUEUE_T& tQueue); + RESULT_T (*Dequeue)(QUEUE_ROOT_T& tQueue); /// Peek at the next data item in the queue buffer. Calling Dequeue would dequeue this - RESULT_T (*Peek)(QUEUE_T& tQueue); + RESULT_T (*Peek)(QUEUE_ROOT_T& tQueue); }; @@ -78,10 +72,6 @@ struct QUEUE_API_T template struct STACK_API_T; -/// The stack module -template -union STACK_T; - /// The stack root module template struct STACK_ROOT_T JUNO_MODULE_ROOT(JUNO_MODULE_ARG(STACK_API_T), @@ -94,11 +84,11 @@ template struct STACK_API_T { /// Push data onto the stack buffer - JUNO_STATUS_T (*Push)(STACK_T& tStack, T tData); + JUNO_STATUS_T (*Push)(STACK_ROOT_T& tStack, T tData); /// Pop data from the stack buffer - RESULT_T (*Pop)(STACK_T& tStack); + RESULT_T (*Pop)(STACK_ROOT_T& tStack); /// Peek into data on the stack buffer - RESULT_T (*Peek)(STACK_T& tStack); + RESULT_T (*Peek)(STACK_ROOT_T& tStack); }; } diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index eeeaf09d..a9ea3f83 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -39,8 +39,6 @@ extern "C" /// The Buffer queue root typedef struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_BUFF_QUEUE_ROOT_T; typedef struct JUNO_BUFF_QUEUE_API_TAG JUNO_BUFF_QUEUE_API_T; -/// The Buffer queue module -typedef union JUNO_BUFF_QUEUE_T JUNO_BUFF_QUEUE_T; /// The root buffee queue struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BUFF_QUEUE_API_T, @@ -54,9 +52,9 @@ struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BUFF_QUEUE_API_T, struct JUNO_BUFF_QUEUE_API_TAG { - JUNO_STATUS_T (*SetAt)(JUNO_BUFF_QUEUE_T *ptQueue, void *ptItem, size_t iIndex); - JUNO_RESULT_VOID_PTR_T (*GetAt)(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); - JUNO_STATUS_T (*RemoveAt)(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); + JUNO_STATUS_T (*SetAt)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem, size_t iIndex); + JUNO_RESULT_VOID_PTR_T (*GetAt)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); + JUNO_STATUS_T (*RemoveAt)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); JUNO_STATUS_T (*Copy)(void *ptDest, void *ptSrc); }; diff --git a/include/juno/ds/buff_stack_api.h b/include/juno/ds/buff_stack_api.h index e12bd96c..ab2098c0 100644 --- a/include/juno/ds/buff_stack_api.h +++ b/include/juno/ds/buff_stack_api.h @@ -37,8 +37,6 @@ extern "C" /// The buffer stack root module typedef struct JUNO_BUFF_STACK_ROOT_TAG JUNO_BUFF_STACK_ROOT_T; -/// The buffer stack -typedef union JUNO_BUFF_STACK_T JUNO_BUFF_STACK_T; struct JUNO_BUFF_STACK_ROOT_TAG JUNO_MODULE_ROOT(void, /// The current length of the stack @@ -48,7 +46,7 @@ struct JUNO_BUFF_STACK_ROOT_TAG JUNO_MODULE_ROOT(void, ); /// Initialize a buffer stack -static inline JUNO_STATUS_T JunoBuff_StackInit(JUNO_BUFF_STACK_T *ptStack, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +static inline JUNO_STATUS_T JunoBuff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) { JUNO_ASSERT_EXISTS(ptStack); JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); @@ -61,7 +59,7 @@ static inline JUNO_STATUS_T JunoBuff_StackInit(JUNO_BUFF_STACK_T *ptStack, size_ /// Push an item onto the stack /// @returns an index to write the pushed item to -static inline JUNO_RESULT_SIZE_T JunoBuff_StackPush(JUNO_BUFF_STACK_T *ptStack) +static inline JUNO_RESULT_SIZE_T JunoBuff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptStack) { JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; if(!ptStack) @@ -86,7 +84,7 @@ static inline JUNO_RESULT_SIZE_T JunoBuff_StackPush(JUNO_BUFF_STACK_T *ptStack) /// Pop an item from the stack /// @returns an index of the popped item -static inline JUNO_RESULT_SIZE_T JunoBuff_StackPop(JUNO_BUFF_STACK_T *ptStack) +static inline JUNO_RESULT_SIZE_T JunoBuff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptStack) { JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; if(!ptStack) @@ -108,7 +106,7 @@ static inline JUNO_RESULT_SIZE_T JunoBuff_StackPop(JUNO_BUFF_STACK_T *ptStack) /// Peek at an item on the stack /// @returns The index of the next item -static inline JUNO_RESULT_SIZE_T JunoBuff_StackPeek(JUNO_BUFF_STACK_T *ptStack) +static inline JUNO_RESULT_SIZE_T JunoBuff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptStack) { JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; if(!ptStack) diff --git a/include/juno/ds/juno_buff.hpp b/include/juno/ds/juno_buff.hpp index 29ef771f..d6837c93 100644 --- a/include/juno/ds/juno_buff.hpp +++ b/include/juno/ds/juno_buff.hpp @@ -36,15 +36,15 @@ namespace juno namespace buff { template -JUNO_STATUS_T Enqueue(QUEUE_T& tQueue, T tData); +JUNO_STATUS_T Enqueue(QUEUE_ROOT_T& tQueue, T tData); template -RESULT_T Dequeue(QUEUE_T& tQueue); +RESULT_T Dequeue(QUEUE_ROOT_T& tQueue); template -RESULT_T QueuePeek(QUEUE_T& tQueue); +RESULT_T QueuePeek(QUEUE_ROOT_T& tQueue); template struct JUNO_QUEUE_T JUNO_MODULE_DERIVE(JUNO_MODULE_ARG(QUEUE_ROOT_T), - static JUNO_STATUS_T New(QUEUE_T &tQueue, const QUEUE_API_T &tApi, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) + static JUNO_STATUS_T New(QUEUE_ROOT_T &tQueue, const QUEUE_API_T &tApi, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) { auto& tNew = reinterpret_cast&>(tQueue); tNew.tRoot.ptApi = &tApi; @@ -60,17 +60,8 @@ struct JUNO_QUEUE_T JUNO_MODULE_DERIVE(JUNO_MODULE_ARG(QUEUE_ROOT_T), } ); -#ifndef JUNO_QUEUE_CUSTOM - -template -union QUEUE_T JUNO_MODULE(JUNO_MODULE_ARG(QUEUE_API_T), JUNO_MODULE_ARG(QUEUE_ROOT_T), - JUNO_QUEUE_T tJunoQueue; -); - -#endif - template -RESULT_T Dequeue(QUEUE_T& tQueue) +RESULT_T Dequeue(QUEUE_ROOT_T& tQueue) { auto& tJunoQueue = reinterpret_cast&>(tQueue); RESULT_T tResult{JUNO_STATUS_SUCCESS, {}}; @@ -87,7 +78,7 @@ RESULT_T Dequeue(QUEUE_T& tQueue) } template -JUNO_STATUS_T Enqueue(QUEUE_T& tQueue, T tData) +JUNO_STATUS_T Enqueue(QUEUE_ROOT_T& tQueue, T tData) { auto& tJunoQueue = reinterpret_cast&>(tQueue); if(tJunoQueue.tRoot.zLength < N) @@ -101,7 +92,7 @@ JUNO_STATUS_T Enqueue(QUEUE_T& tQueue, T tData) } template -RESULT_T QueuePeek(QUEUE_T& tQueue) +RESULT_T QueuePeek(QUEUE_ROOT_T& tQueue) { auto& tJunoQueue = reinterpret_cast&>(tQueue); RESULT_T tResult{JUNO_STATUS_SUCCESS, {}}; @@ -116,15 +107,15 @@ RESULT_T QueuePeek(QUEUE_T& tQueue) } template -JUNO_STATUS_T Push(STACK_T& tStack, T tData); +JUNO_STATUS_T Push(STACK_ROOT_T& tStack, T tData); template -RESULT_T Pop(STACK_T& tStack); +RESULT_T Pop(STACK_ROOT_T& tStack); template -RESULT_T StackPeek(STACK_T& tStack); +RESULT_T StackPeek(STACK_ROOT_T& tStack); template struct JUNO_STACK_T JUNO_MODULE_DERIVE(JUNO_MODULE_ARG(STACK_ROOT_T), - static JUNO_STATUS_T New(STACK_T& tStack, const STACK_API_T& tApi, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) + static JUNO_STATUS_T New(STACK_ROOT_T& tStack, const STACK_API_T& tApi, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) { auto& tNew = reinterpret_cast&>(tStack); tNew.tRoot.ptApi = &tApi; @@ -141,17 +132,8 @@ struct JUNO_STACK_T JUNO_MODULE_DERIVE(JUNO_MODULE_ARG(STACK_ROOT_T), ); -#ifndef JUNO_STACK_CUSTOM - -template -union STACK_T JUNO_MODULE(JUNO_MODULE_ARG(STACK_API_T), JUNO_MODULE_ARG(STACK_ROOT_T), - JUNO_STACK_T tJunoStack; -); - -#endif - template -RESULT_T Pop(STACK_T& tStack) +RESULT_T Pop(STACK_ROOT_T& tStack) { auto& tJunoStack = reinterpret_cast&>(tStack); RESULT_T tResult{JUNO_STATUS_SUCCESS, {}}; @@ -167,7 +149,7 @@ RESULT_T Pop(STACK_T& tStack) } template -JUNO_STATUS_T Push(STACK_T& tStack, T tData) +JUNO_STATUS_T Push(STACK_ROOT_T& tStack, T tData) { auto& tJunoStack = reinterpret_cast&>(tStack); if(tJunoStack.tRoot.zLength < N) @@ -181,7 +163,7 @@ JUNO_STATUS_T Push(STACK_T& tStack, T tData) } template -RESULT_T StackPeek(STACK_T& tStack) +RESULT_T StackPeek(STACK_ROOT_T& tStack) { auto& tJunoStack = reinterpret_cast&>(tStack); RESULT_T tResult{JUNO_STATUS_SUCCESS, {}}; diff --git a/include/juno/io/async_io_api.h b/include/juno/io/async_io_api.h index 72be1865..a330f786 100644 --- a/include/juno/io/async_io_api.h +++ b/include/juno/io/async_io_api.h @@ -37,7 +37,6 @@ extern "C" typedef struct JUNO_ASYNC_IO_API_TAG JUNO_ASYNC_IO_API_T; -typedef union JUNO_ASYNC_IO_TAG JUNO_ASYNC_IO_T; typedef struct JUNO_ASYNC_IO_ROOT_TAG JUNO_ASYNC_IO_ROOT_T; struct JUNO_ASYNC_IO_ROOT_TAG JUNO_MODULE_ROOT(JUNO_ASYNC_IO_API_T, JUNO_MODULE_EMPTY); @@ -45,19 +44,19 @@ struct JUNO_ASYNC_IO_ROOT_TAG JUNO_MODULE_ROOT(JUNO_ASYNC_IO_API_T, JUNO_MODULE_ struct JUNO_ASYNC_IO_API_TAG { /// Read the specified number of bytes from the IO - JUNO_STATUS_T (*Read)(JUNO_ASYNC_IO_T *ptIo, char *pcBuff, size_t *pzBuffSize); + JUNO_STATUS_T (*Read)(JUNO_ASYNC_IO_ROOT_T *ptIo, char *pcBuff, size_t *pzBuffSize); /// Try to read from the IO until timeout expires - JUNO_STATUS_T (*TryRead)(JUNO_ASYNC_IO_T *ptIo, char *pcBuff, size_t *pzBuffSize, JUNO_TIME_MICROS_T iTimeoutUs); + JUNO_STATUS_T (*TryRead)(JUNO_ASYNC_IO_ROOT_T *ptIo, char *pcBuff, size_t *pzBuffSize, JUNO_TIME_MICROS_T iTimeoutUs); /// Read from the IO until the set of characters is recieved - JUNO_STATUS_T (*ReadUntil)(JUNO_ASYNC_IO_T *ptIo, char *pcBuff, size_t *pzBuffSize, const char *pcStopChars, size_t zSizeStopChars); + JUNO_STATUS_T (*ReadUntil)(JUNO_ASYNC_IO_ROOT_T *ptIo, char *pcBuff, size_t *pzBuffSize, const char *pcStopChars, size_t zSizeStopChars); /// Try to read from the IO until the set of characters is recieved - JUNO_STATUS_T (*TryReadUntil)(JUNO_ASYNC_IO_T *ptIo, char *pcBuff, size_t *pzBuffSize, const char *pcStopChars, size_t zSizeStopChars, JUNO_TIME_MICROS_T iTimeoutUs); + JUNO_STATUS_T (*TryReadUntil)(JUNO_ASYNC_IO_ROOT_T *ptIo, char *pcBuff, size_t *pzBuffSize, const char *pcStopChars, size_t zSizeStopChars, JUNO_TIME_MICROS_T iTimeoutUs); /// Write the specified number of bytes to the IO - JUNO_STATUS_T (*Write)(JUNO_ASYNC_IO_T *ptIo, const void *pvBuff, size_t *pzBuffSize); + JUNO_STATUS_T (*Write)(JUNO_ASYNC_IO_ROOT_T *ptIo, const void *pvBuff, size_t *pzBuffSize); /// Try to write the specified number of bytes to the IO - JUNO_STATUS_T (*TryWrite)(JUNO_ASYNC_IO_T *ptIo, const void *pvBuff, size_t *pzBuffSize, JUNO_TIME_MICROS_T iTimeoutUs); + JUNO_STATUS_T (*TryWrite)(JUNO_ASYNC_IO_ROOT_T *ptIo, const void *pvBuff, size_t *pzBuffSize, JUNO_TIME_MICROS_T iTimeoutUs); /// Poll the IO - JUNO_STATUS_T (*Poll)(JUNO_ASYNC_IO_T *ptIo, JUNO_TIME_MICROS_T iTimeoutUs, bool *pbHasData); + JUNO_STATUS_T (*Poll)(JUNO_ASYNC_IO_ROOT_T *ptIo, JUNO_TIME_MICROS_T iTimeoutUs, bool *pbHasData); }; #ifdef __cplusplus diff --git a/include/juno/io/i2c_io_api.h b/include/juno/io/i2c_io_api.h index 6f376a78..a04ed928 100644 --- a/include/juno/io/i2c_io_api.h +++ b/include/juno/io/i2c_io_api.h @@ -41,7 +41,6 @@ typedef struct JUNO_I2C_IO_MSG_R_TAG JUNO_I2C_IO_MSG_R_T; typedef struct JUNO_I2C_IO_MSG_W_TAG JUNO_I2C_IO_MSG_W_T; typedef struct JUNO_I2C_IO_MSG_HDR_TAG JUNO_I2C_IO_MSG_HDR_T; typedef union JUNO_I2C_IO_MSG_TAG JUNO_I2C_IO_MSG_T; -JUNO_MODULE_DECLARE(JUNO_I2C_IO_T); JUNO_MODULE_ROOT_DECLARE(JUNO_I2C_IO_ROOT_T); typedef enum JUNO_I2C_IO_MSG_TYPE_TAG @@ -128,7 +127,7 @@ struct JUNO_I2C_IO_API_TAG @param zMsgArrLen Number of messages in the array. @return JUNO_STATUS_SUCCESS on success, error code otherwise. */ - JUNO_STATUS_T (*Transfer)(JUNO_I2C_IO_T *ptI2c, const JUNO_I2C_IO_MSG_T *ptArrMsgs, size_t zMsgArrLen); + JUNO_STATUS_T (*Transfer)(JUNO_I2C_IO_ROOT_T *ptI2c, const JUNO_I2C_IO_MSG_T *ptArrMsgs, size_t zMsgArrLen); }; #ifdef __cplusplus diff --git a/include/juno/io/spi_io_api.h b/include/juno/io/spi_io_api.h index 5b0593be..b95da31e 100644 --- a/include/juno/io/spi_io_api.h +++ b/include/juno/io/spi_io_api.h @@ -37,7 +37,6 @@ extern "C" #endif typedef struct JUNO_SPI_IO_API_TAG JUNO_SPI_IO_API_T; -typedef union JUNO_SPI_IO_TAG JUNO_SPI_IO_T; typedef struct JUNO_SPI_IO_ROOT_TAG JUNO_SPI_IO_ROOT_T; struct JUNO_SPI_IO_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SPI_IO_API_T, JUNO_MODULE_EMPTY); @@ -46,7 +45,7 @@ struct JUNO_SPI_IO_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SPI_IO_API_T, JUNO_MODULE_EMPT struct JUNO_SPI_IO_API_TAG { /// Perform an SPI transaction - JUNO_STATUS_T (*Transaction)(JUNO_SPI_IO_T *ptIo, char *pcReadBuff, size_t zReadBuffSize, const void *pvWriteBuff, size_t zWriteBuffSize); + JUNO_STATUS_T (*Transaction)(JUNO_SPI_IO_ROOT_T *ptIo, char *pcReadBuff, size_t zReadBuffSize, const void *pvWriteBuff, size_t zWriteBuffSize); }; #ifdef __cplusplus diff --git a/include/juno/log/log_api.h b/include/juno/log/log_api.h index 2cafc82e..7b7c0692 100644 --- a/include/juno/log/log_api.h +++ b/include/juno/log/log_api.h @@ -35,17 +35,16 @@ extern "C" typedef struct JUNO_LOG_API_TAG JUNO_LOG_API_T; -typedef union JUNO_LOG_TAG JUNO_LOG_T; typedef struct JUNO_LOG_ROOT_TAG JUNO_LOG_ROOT_T; struct JUNO_LOG_ROOT_TAG JUNO_MODULE_ROOT(JUNO_LOG_API_T, JUNO_MODULE_EMPTY); struct JUNO_LOG_API_TAG { - JUNO_STATUS_T (*LogDebug)(JUNO_LOG_T *ptJunoLog, const char *pcMsg, ...); - JUNO_STATUS_T (*LogInfo)(JUNO_LOG_T *ptJunoLog, const char *pcMsg, ...); - JUNO_STATUS_T (*LogWarning)(JUNO_LOG_T *ptJunoLog, const char *pcMsg, ...); - JUNO_STATUS_T (*LogError)(JUNO_LOG_T *ptJunoLog, const char *pcMsg, ...); + JUNO_STATUS_T (*LogDebug)(JUNO_LOG_ROOT_T *ptJunoLog, const char *pcMsg, ...); + JUNO_STATUS_T (*LogInfo)(JUNO_LOG_ROOT_T *ptJunoLog, const char *pcMsg, ...); + JUNO_STATUS_T (*LogWarning)(JUNO_LOG_ROOT_T *ptJunoLog, const char *pcMsg, ...); + JUNO_STATUS_T (*LogError)(JUNO_LOG_ROOT_T *ptJunoLog, const char *pcMsg, ...); }; #ifdef __cplusplus diff --git a/include/juno/map/map_api.h b/include/juno/map/map_api.h index 4580f7ad..bd06d6b8 100644 --- a/include/juno/map/map_api.h +++ b/include/juno/map/map_api.h @@ -39,7 +39,6 @@ extern "C" typedef struct JUNO_MAP_API_TAG JUNO_MAP_API_T; -typedef union JUNO_MAP_TAG JUNO_MAP_T; typedef struct JUNO_MAP_ROOT_TAG JUNO_MAP_ROOT_T; struct JUNO_MAP_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MAP_API_T, diff --git a/include/juno/math/juno_dyn_types.h b/include/juno/math/juno_dyn_types.h index 8362f6ab..b62d9903 100644 --- a/include/juno/math/juno_dyn_types.h +++ b/include/juno/math/juno_dyn_types.h @@ -25,7 +25,7 @@ typedef union JUNO_KMAT_TAG JUNO_KMAT_T; typedef struct JUNO_KMAT_API_TAG JUNO_KMAT_API_T; typedef struct JUNO_KMAT_ROOT_TAG JUNO_MODULE_ROOT(JUNO_KMAT_API_T, - JUNO_TIME_T *ptTime; + JUNO_TIME_ROOT_T *ptTime; JUNO_KSTATE_F64_T tState; )JUNO_KMAT_ROOT_T; diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index 764ea2ef..6eabae1a 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -60,7 +60,6 @@ struct JUNO_MEMORY_TAG typedef struct JUNO_MEMORY_ALLOC_API_TAG JUNO_MEMORY_ALLOC_API_T; -typedef union JUNO_MEMORY_ALLOC_TAG JUNO_MEMORY_ALLOC_T; typedef struct JUNO_MEMORY_ALLOC_ROOT_TAG JUNO_MEMORY_ALLOC_ROOT_T; struct JUNO_MEMORY_ALLOC_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MEMORY_ALLOC_API_T, JUNO_MODULE_EMPTY); @@ -73,7 +72,7 @@ struct JUNO_MEMORY_ALLOC_API_TAG /// @param pvRetAddr Pointer to a memory descriptor where allocation details will be stored. /// @param zSize Size of the memory block to allocate in bytes. /// @return JUNO_STATUS_T Status of the allocation operation. - JUNO_STATUS_T (*Get)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *pvRetAddr, size_t zSize); + JUNO_STATUS_T (*Get)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_MEMORY_T *pvRetAddr, size_t zSize); /// @brief Updates an existing memory allocation to a new size. /// @@ -81,14 +80,14 @@ struct JUNO_MEMORY_ALLOC_API_TAG /// @param ptMemory Pointer to the memory descriptor to update. /// @param zNewSize The new size for the memory block. /// @return JUNO_STATUS_T Status of the update operation. - JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zNewSize); + JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zNewSize); /// @brief Frees an allocated memory block. /// /// @param ptMem Pointer to the memory allocation structure. /// @param pvAddr Pointer to the memory block to free. /// @return JUNO_STATUS_T Status of the free operation. - JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *pvAddr); + JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_MEMORY_T *pvAddr); }; diff --git a/include/juno/memory/memory_block.h b/include/juno/memory/memory_block.h index 586321ff..7949ce3f 100644 --- a/include/juno/memory/memory_block.h +++ b/include/juno/memory/memory_block.h @@ -56,7 +56,6 @@ extern "C" typedef struct JUNO_MEMORY_BLOCK_METADATA_TAG JUNO_MEMORY_BLOCK_METADATA_T; -typedef struct JUNO_MEMORY_BLOCK_TAG JUNO_MEMORY_BLOCK_T; typedef struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MEMORY_ALLOC_BLOCK_T; struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MODULE_DERIVE(JUNO_MEMORY_ALLOC_ROOT_T, @@ -68,20 +67,7 @@ struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MODULE_DERIVE(JUNO_MEMORY_ALLOC_ROOT_T, size_t zFreed; ///< Current count of freed blocks in the free stack. ); -#ifndef JUNO_MEMORY_CUSTOM -/** - This is the default implementation for `JUNO_MEMORY_T`. - If you want to derive new implementations for `JUNO_MEMORY_T` - use `#define JUNO_MEMORY_DERIVED` prior to including - `#include "juno_memory_block.h"` - Note: If you are blockementing a derived module you will need - to blockement `JUNO_MEMORY_BLOCK`. -*/ -union JUNO_MEMORY_ALLOC_TAG JUNO_MODULE(JUNO_MEMORY_ALLOC_API_T, JUNO_MEMORY_ALLOC_ROOT_T, - JUNO_MEMORY_ALLOC_BLOCK_T tJunoMemoryBlock; -); -#endif /// @brief Initializes a memory block for allocation. /// Sets up a memory block with an associated free stack for managing fixed-size allocations. @@ -93,7 +79,7 @@ union JUNO_MEMORY_ALLOC_TAG JUNO_MODULE(JUNO_MEMORY_ALLOC_API_T, JUNO_MEMORY_ALL /// @param pfcnFailureHandler Callback function to handle failures. /// @param pvUserData User data passed to the failure handler. /// @return JUNO_STATUS_T Status of the initialization. -JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_T *ptJunoMemory, +JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemory, void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, diff --git a/include/juno/sb/subscriber_api.h b/include/juno/sb/subscriber_api.h index bc8da965..1b2b9c11 100644 --- a/include/juno/sb/subscriber_api.h +++ b/include/juno/sb/subscriber_api.h @@ -43,7 +43,7 @@ typedef union JUNO_SUBSCRIBER_TAG JUNO_SUBSCRIBER_T; typedef struct JUNO_SUBSCRIBER_ROOT_TAG JUNO_SUBSCRIBER_ROOT_T; struct JUNO_SUBSCRIBER_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SUBSCRIBER_API_T, - JUNO_MEMORY_ALLOC_T *ptAlloc; + JUNO_MEMORY_ALLOC_ROOT_T *ptAlloc; ); struct JUNO_SUBSCRIBER_API_TAG diff --git a/include/juno/sch/juno_sch_api.h b/include/juno/sch/juno_sch_api.h index 9064ec85..87863731 100644 --- a/include/juno/sch/juno_sch_api.h +++ b/include/juno/sch/juno_sch_api.h @@ -38,15 +38,14 @@ extern "C" typedef struct JUNO_SCH_API_TAG JUNO_SCH_API_T; -typedef union JUNO_SCH_TAG JUNO_SCH_T; typedef struct JUNO_SCH_ROOT_TAG JUNO_SCH_ROOT_T; #define JUNO_SCH_TABLE_NEW(ptArrName, zAppsPerMinorFrame, zNumMinorFrames, ...) \ JUNO_APP_T *ptArrName[zNumMinorFrames * zAppsPerMinorFrame] = {__VA_ARGS__} struct JUNO_SCH_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SCH_API_T, - JUNO_TIME_T *ptTime; - JUNO_APP_T **ptArrSchTable; + JUNO_TIME_ROOT_T *ptTime; + JUNO_APP_ROOT_T **ptArrSchTable; size_t zAppsPerMinorFrame; size_t zNumMinorFrames; JUNO_TIMESTAMP_T tMinorFramePeriod; @@ -54,9 +53,9 @@ struct JUNO_SCH_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SCH_API_T, struct JUNO_SCH_API_TAG { - JUNO_STATUS_T (*Execute)(JUNO_SCH_T *ptJunoSch); - JUNO_TIMESTAMP_RESULT_T (*GetMinorFramePeriod)(JUNO_SCH_T *ptJunoSch); - JUNO_TIMESTAMP_RESULT_T (*GetMajorFramePeriod)(JUNO_SCH_T *ptJunoSch); + JUNO_STATUS_T (*Execute)(JUNO_SCH_ROOT_T *ptJunoSch); + JUNO_TIMESTAMP_RESULT_T (*GetMinorFramePeriod)(JUNO_SCH_ROOT_T *ptJunoSch); + JUNO_TIMESTAMP_RESULT_T (*GetMajorFramePeriod)(JUNO_SCH_ROOT_T *ptJunoSch); }; #ifdef __cplusplus diff --git a/include/juno/sm/sm_api.h b/include/juno/sm/sm_api.h index 5c9dffb4..e325a5af 100644 --- a/include/juno/sm/sm_api.h +++ b/include/juno/sm/sm_api.h @@ -40,37 +40,35 @@ extern "C" typedef struct JUNO_SM_ROOT_TAG JUNO_SM_ROOT_T; typedef struct JUNO_SM_STATE_API_TAG JUNO_SM_STATE_API_T; -JUNO_MODULE_DECLARE(JUNO_SM_STATE_T); -JUNO_MODULE_DECLARE(JUNO_SM_T); typedef struct JUNO_SM_STATE_ROOT_TAG JUNO_SM_STATE_ROOT_T; /// A result type for returning a SM state JUNO_MODULE_RESULT(JUNO_SM_RESULT_STATE_ROOT_T, JUNO_SM_STATE_ROOT_T *); -JUNO_MODULE_RESULT(JUNO_SM_RESULT_STATE_T, JUNO_SM_STATE_T *); +JUNO_MODULE_RESULT(JUNO_SM_RESULT_STATE_T, JUNO_SM_STATE_ROOT_T *); JUNO_MODULE_OPTION(JUNO_SM_OPTION_STATE_ROOT_T, JUNO_SM_STATE_ROOT_T *); -JUNO_MODULE_OPTION(JUNO_SM_OPTION_STATE_T, JUNO_SM_STATE_T *); +JUNO_MODULE_OPTION(JUNO_SM_OPTION_STATE_T, JUNO_SM_STATE_ROOT_T *); JUNO_MODULE_RESULT(JUNO_SM_RESULT_OPTION_STATE_ROOT_T, JUNO_SM_OPTION_STATE_ROOT_T); JUNO_MODULE_RESULT(JUNO_SM_RESULT_OPTION_STATE_T, JUNO_SM_OPTION_STATE_T); /// A State Machine State struct JUNO_SM_STATE_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SM_STATE_API_T, - JUNO_SM_T *ptSm; + JUNO_SM_ROOT_T *ptSm; JUNO_SM_OPTION_STATE_T tOptionNextState; ); struct JUNO_SM_STATE_API_TAG { /// The action that should be executed in this state - JUNO_STATUS_T (*StateAction)(JUNO_SM_STATE_T *ptJunoSm); + JUNO_STATUS_T (*StateAction)(JUNO_SM_STATE_ROOT_T *ptJunoSm); /// Returns a bool result whether the current state should exit - JUNO_RESULT_BOOL_T (*ShouldExit)(JUNO_SM_STATE_T *ptJunoSm); + JUNO_RESULT_BOOL_T (*ShouldExit)(JUNO_SM_STATE_ROOT_T *ptJunoSm); /// Reset the state - JUNO_STATUS_T (*ResetState)(JUNO_SM_STATE_T *ptJunoSm); + JUNO_STATUS_T (*ResetState)(JUNO_SM_STATE_ROOT_T *ptJunoSm); }; struct JUNO_SM_ROOT_TAG JUNO_MODULE_ROOT(void, /// The current state - JUNO_SM_STATE_T *ptCurrentState; + JUNO_SM_STATE_ROOT_T *ptCurrentState; ); /// Verify if this is a valid state machine @@ -95,14 +93,14 @@ static inline JUNO_STATUS_T JunoSm_StateVerify(JUNO_SM_STATE_ROOT_T *ptSmState) static inline JUNO_STATUS_T JunoSm_StateInit(JUNO_SM_ROOT_T *ptSm, JUNO_SM_STATE_ROOT_T *ptStateRoot, JUNO_SM_STATE_ROOT_T *ptNextState, const JUNO_SM_STATE_API_T *ptStateApi, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) { JUNO_ASSERT_EXISTS(ptStateRoot && ptStateApi && ptSm); - ptStateRoot->ptSm = (JUNO_SM_T *) ptSm; + ptStateRoot->ptSm = (JUNO_SM_ROOT_T *) ptSm; ptStateRoot->_pfcnFailureHandler = pfcnFailureHandler; ptStateRoot->_pvFailureUserData = pvFailureUserData; ptStateRoot->ptApi = ptStateApi; if(ptNextState) { ptStateRoot->tOptionNextState.bIsSome = true; - ptStateRoot->tOptionNextState.tSome = (JUNO_SM_STATE_T *) ptNextState; + ptStateRoot->tOptionNextState.tSome = (JUNO_SM_STATE_ROOT_T *) ptNextState; } else { @@ -115,7 +113,7 @@ static inline JUNO_STATUS_T JunoSm_StateInit(JUNO_SM_ROOT_T *ptSm, JUNO_SM_STATE static inline JUNO_STATUS_T JunoSm_Init(JUNO_SM_ROOT_T *ptSmRoot, JUNO_SM_STATE_ROOT_T *ptStartState, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData) { JUNO_ASSERT_EXISTS(ptSmRoot); - ptSmRoot->ptCurrentState = (JUNO_SM_STATE_T *) ptStartState; + ptSmRoot->ptCurrentState = (JUNO_SM_STATE_ROOT_T *) ptStartState; ptSmRoot->_pfcnFailureHandler = pfcnFailureHandler; ptSmRoot->_pvFailureUserData = pvFailureUserData; JUNO_STATUS_T tStatus = JunoSm_Verify(ptSmRoot); diff --git a/include/juno/time/time_api.h b/include/juno/time/time_api.h index dab0a259..9a557d6d 100644 --- a/include/juno/time/time_api.h +++ b/include/juno/time/time_api.h @@ -62,7 +62,6 @@ extern "C" #endif typedef struct JUNO_TIME_API_TAG JUNO_TIME_API_T; -typedef union JUNO_TIME_TAG JUNO_TIME_T; typedef struct JUNO_TIME_ROOT_TAG JUNO_TIME_ROOT_T; typedef struct JUNO_TIMESTAMP_TAG JUNO_TIMESTAMP_T; @@ -109,31 +108,31 @@ JUNO_MODULE_RESULT(JUNO_TIME_SUBSECONDS_RESULT_T, JUNO_TIME_SUBSECONDS_T); struct JUNO_TIME_API_TAG { /// Get the current time as specified by the implementation - JUNO_TIMESTAMP_RESULT_T (*Now)(JUNO_TIME_T *ptTime); + JUNO_TIMESTAMP_RESULT_T (*Now)(JUNO_TIME_ROOT_T *ptTime); /// Perform addition with time - JUNO_STATUS_T (*AddTime)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd); + JUNO_STATUS_T (*AddTime)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd); /// Perform subtraction with time - JUNO_STATUS_T (*SubtractTime)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract); + JUNO_STATUS_T (*SubtractTime)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract); /// Sleep this thread until a specific time - JUNO_STATUS_T (*SleepTo)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTimeToWakeup); + JUNO_STATUS_T (*SleepTo)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTimeToWakeup); /// Sleep this thread for a duration - JUNO_STATUS_T (*Sleep)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tDuration); + JUNO_STATUS_T (*Sleep)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tDuration); /// Convert a timestamp to nanoseconds - JUNO_TIME_NANOS_RESULT_T (*TimestampToNanos)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); + JUNO_TIME_NANOS_RESULT_T (*TimestampToNanos)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime); /// Convert a timestamp to microseconds - JUNO_TIME_MICROS_RESULT_T (*TimestampToMicros)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); + JUNO_TIME_MICROS_RESULT_T (*TimestampToMicros)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime); /// Convert a timestamp to milliseconds - JUNO_TIME_MILLIS_RESULT_T (*TimestampToMillis)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); + JUNO_TIME_MILLIS_RESULT_T (*TimestampToMillis)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime); /// Convert nanoseconds to a timestamp - JUNO_TIMESTAMP_RESULT_T (*NanosToTimestamp)(JUNO_TIME_T *ptTime, JUNO_TIME_NANOS_T iNanos); + JUNO_TIMESTAMP_RESULT_T (*NanosToTimestamp)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_NANOS_T iNanos); /// Convert microseconds to a timestamp - JUNO_TIMESTAMP_RESULT_T (*MicrosToTimestamp)(JUNO_TIME_T *ptTime, JUNO_TIME_MICROS_T iMicros); + JUNO_TIMESTAMP_RESULT_T (*MicrosToTimestamp)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_MICROS_T iMicros); /// Convert milliseconds to a timestamp - JUNO_TIMESTAMP_RESULT_T (*MillisToTimestamp)(JUNO_TIME_T *ptTime, JUNO_TIME_MILLIS_T iMillis); + JUNO_TIMESTAMP_RESULT_T (*MillisToTimestamp)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_MILLIS_T iMillis); /// Convert a timestamp to a double - JUNO_RESULT_F64_T (*TimestampToDouble)(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTimestamp); + JUNO_RESULT_F64_T (*TimestampToDouble)(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTimestamp); /// Convert a double to a timestamp - JUNO_TIMESTAMP_RESULT_T (*DoubleToTimestamp)(JUNO_TIME_T *ptTime, double dTimestamp); + JUNO_TIMESTAMP_RESULT_T (*DoubleToTimestamp)(JUNO_TIME_ROOT_T *ptTime, double dTimestamp); }; @@ -144,7 +143,7 @@ struct JUNO_TIME_API_TAG * @param tTimeToAdd Duration to add. * @return JUNO_STATUS_SUCCESS on success. */ -JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd); +JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd); /** * @brief Subtract a duration from a timestamp in-place. @@ -152,21 +151,21 @@ JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, * to 0 seconds and 0 subseconds, and JUNO_STATUS_INVALID_DATA_ERROR is * returned. */ -JUNO_STATUS_T JunoTime_SubtractTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract); +JUNO_STATUS_T JunoTime_SubtractTime(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract); /** Conversions from timestamp to integer durations (truncates fractional) */ -JUNO_TIME_NANOS_RESULT_T JunoTime_TimestampToNanos(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); -JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); -JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime); +JUNO_TIME_NANOS_RESULT_T JunoTime_TimestampToNanos(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime); +JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime); +JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime); /** Conversions from integer durations to timestamp */ -JUNO_TIMESTAMP_RESULT_T JunoTime_NanosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_NANOS_T iNanos); -JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_MICROS_T iMicros); -JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_MILLIS_T iMillis); +JUNO_TIMESTAMP_RESULT_T JunoTime_NanosToTimestamp(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_NANOS_T iNanos); +JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_MICROS_T iMicros); +JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_MILLIS_T iMillis); /** Conversions between timestamp and double (truncating semantics) */ -JUNO_RESULT_F64_T JunoTime_TimestampToDouble(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTimestamp); -JUNO_TIMESTAMP_RESULT_T JunoTime_DoubleToTimestamp(JUNO_TIME_T *ptTime, double dTimestamp); +JUNO_RESULT_F64_T JunoTime_TimestampToDouble(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTimestamp); +JUNO_TIMESTAMP_RESULT_T JunoTime_DoubleToTimestamp(JUNO_TIME_ROOT_T *ptTime, double dTimestamp); #define JUNO_TIME_NEW_API(Now, SleepTo, Sleep) \ { \ diff --git a/src/juno_buff_queue.c b/src/juno_buff_queue.c index b320ac28..ed0a9a6b 100644 --- a/src/juno_buff_queue.c +++ b/src/juno_buff_queue.c @@ -22,7 +22,7 @@ JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *pt if(ptQueue->zLength < ptQueue->zCapacity) { size_t iIndex = (ptQueue->iStartIndex + ptQueue->zLength) % ptQueue->zCapacity; - tStatus = ptQueue->ptApi->SetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptItem, iIndex); + tStatus = ptQueue->ptApi->SetAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, ptItem, iIndex); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); ptQueue->zLength += 1; } @@ -46,11 +46,11 @@ JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *pt { const JUNO_BUFF_QUEUE_API_T *ptApi = ptQueue->ptApi; size_t iDequeueIndex = ptQueue->iStartIndex; - JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); + JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, iDequeueIndex); JUNO_ASSERT_SUCCESS(tPtrResult.tStatus, return tPtrResult.tStatus); tStatus = ptApi->Copy(ptReturn, JUNO_OK(tPtrResult)); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - tStatus = ptApi->RemoveAt((JUNO_BUFF_QUEUE_T *) ptQueue, iDequeueIndex); + tStatus = ptApi->RemoveAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, iDequeueIndex); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); ptQueue->iStartIndex = (ptQueue->iStartIndex + 1) % ptQueue->zCapacity; ptQueue->zLength -= 1; @@ -74,6 +74,6 @@ JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) JUNO_FAIL(tResult.tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); return tResult; } - tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_T *) ptQueue, ptQueue->iStartIndex); + tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, ptQueue->iStartIndex); return tResult; } diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index c275f115..2dd84030 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -23,7 +23,7 @@ static const JUNO_MEMORY_ALLOC_API_T tJunoMemoryBlockApi; -static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_T *ptJunoMemory) +static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory) { JUNO_ASSERT_EXISTS(ptJunoMemory); JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); @@ -45,7 +45,7 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_T *ptJunoMemory) return JUNO_STATUS_SUCCESS; } -static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory, size_t zSize) +static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory, size_t zSize) { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); @@ -101,7 +101,7 @@ static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_M return tStatus; } -static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory, size_t zNewSize) +static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory, size_t zNewSize) { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); @@ -118,7 +118,7 @@ static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUN return tStatus; } -static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory) +static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory) { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); @@ -202,7 +202,7 @@ static const JUNO_MEMORY_ALLOC_API_T tJunoMemoryBlockApi = { }; /* TODO: Insert initialization arguments for module members here*/ -JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_T *ptJunoMemory, +JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock, void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, @@ -211,8 +211,7 @@ JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_T *ptJunoMemory, JUNO_USER_DATA_T *pvFailureUserData ) { - JUNO_ASSERT_EXISTS(ptJunoMemory); - JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); + JUNO_ASSERT_EXISTS(ptJunoMemoryBlock); ptJunoMemoryBlock->JUNO_MODULE_SUPER.ptApi = &tJunoMemoryBlockApi; ptJunoMemoryBlock->JUNO_MODULE_SUPER.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptJunoMemoryBlock->JUNO_MODULE_SUPER.JUNO_FAILURE_USER_DATA = pvFailureUserData; @@ -226,7 +225,7 @@ JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_T *ptJunoMemory, ptJunoMemoryBlock->zUsed = 0; // Initially, no freed blocks are available ptJunoMemoryBlock->zFreed = 0; - JUNO_STATUS_T tStatus = Verify(ptJunoMemory); + JUNO_STATUS_T tStatus = Verify((JUNO_MEMORY_ALLOC_ROOT_T *) ptJunoMemoryBlock); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; } diff --git a/src/juno_time.c b/src/juno_time.c index 33180e66..41404493 100644 --- a/src/juno_time.c +++ b/src/juno_time.c @@ -5,7 +5,7 @@ static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = ((JUNO_TIME_SUBSECONDS_T)~(JUNO_TIME_SUBSECONDS_T)0); -JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd) +JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd) { JUNO_ASSERT_EXISTS(ptTime && ptRetTime); // Add seconds @@ -27,7 +27,7 @@ JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, return JUNO_STATUS_SUCCESS; } -JUNO_STATUS_T JunoTime_SubtractTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract) +JUNO_STATUS_T JunoTime_SubtractTime(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToSubtract) { JUNO_ASSERT_EXISTS(ptTime && ptRetTime); JUNO_TIME_ROOT_T *ptTimeRoot = (JUNO_TIME_ROOT_T *)(ptTime); @@ -55,7 +55,7 @@ JUNO_STATUS_T JunoTime_SubtractTime(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T *ptRet return JUNO_STATUS_SUCCESS; } -JUNO_TIME_NANOS_RESULT_T JunoTime_TimestampToNanos(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime) +JUNO_TIME_NANOS_RESULT_T JunoTime_TimestampToNanos(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime) { JUNO_TIME_NANOS_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -79,7 +79,7 @@ JUNO_TIME_NANOS_RESULT_T JunoTime_TimestampToNanos(JUNO_TIME_T *ptTime, JUNO_TIM return tResult; } -JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime) +JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime) { JUNO_TIME_MICROS_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -103,7 +103,7 @@ JUNO_TIME_MICROS_RESULT_T JunoTime_TimestampToMicros(JUNO_TIME_T *ptTime, JUNO_T return tResult; } -JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTime) +JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTime) { JUNO_TIME_MILLIS_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -127,7 +127,7 @@ JUNO_TIME_MILLIS_RESULT_T JunoTime_TimestampToMillis(JUNO_TIME_T *ptTime, JUNO_T return tResult; } -JUNO_TIMESTAMP_RESULT_T JunoTime_NanosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_NANOS_T iNanos) +JUNO_TIMESTAMP_RESULT_T JunoTime_NanosToTimestamp(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_NANOS_T iNanos) { JUNO_TIMESTAMP_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -143,7 +143,7 @@ JUNO_TIMESTAMP_RESULT_T JunoTime_NanosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME return tResult; } -JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_MICROS_T iMicros) +JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_MICROS_T iMicros) { JUNO_TIMESTAMP_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -159,7 +159,7 @@ JUNO_TIMESTAMP_RESULT_T JunoTime_MicrosToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIM return tResult; } -JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIME_MILLIS_T iMillis) +JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_ROOT_T *ptTime, JUNO_TIME_MILLIS_T iMillis) { JUNO_TIMESTAMP_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -176,7 +176,7 @@ JUNO_TIMESTAMP_RESULT_T JunoTime_MillisToTimestamp(JUNO_TIME_T *ptTime, JUNO_TIM } -JUNO_RESULT_F64_T JunoTime_TimestampToDouble(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTimestamp) +JUNO_RESULT_F64_T JunoTime_TimestampToDouble(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTimestamp) { JUNO_RESULT_F64_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; @@ -190,7 +190,7 @@ JUNO_RESULT_F64_T JunoTime_TimestampToDouble(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP return tResult; } -JUNO_TIMESTAMP_RESULT_T JunoTime_DoubleToTimestamp(JUNO_TIME_T *ptTime, double dTimestamp) +JUNO_TIMESTAMP_RESULT_T JunoTime_DoubleToTimestamp(JUNO_TIME_ROOT_T *ptTime, double dTimestamp) { JUNO_TIMESTAMP_RESULT_T tResult = {0}; tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; diff --git a/tests/test_buff_cpp.cpp b/tests/test_buff_cpp.cpp index be788e9a..94d686e8 100644 --- a/tests/test_buff_cpp.cpp +++ b/tests/test_buff_cpp.cpp @@ -20,7 +20,7 @@ static void test_queue(void) // Initialize queue via API auto api_q = JUNO_QUEUE_T::NewApi(); - QUEUE_T queueRoot{}; + QUEUE_ROOT_T queueRoot{}; auto tStatus = JUNO_QUEUE_T::New(queueRoot, api_q, nullptr, nullptr); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); // — fill to capacity @@ -80,7 +80,7 @@ static void test_stack(void) // Initialize stack via API auto api_s = JUNO_STACK_T::NewApi(); - STACK_T stackRoot{}; + STACK_ROOT_T stackRoot{}; auto tStatus = JUNO_STACK_T::New(stackRoot, api_s, nullptr, nullptr); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); // — fill to capacity diff --git a/tests/test_memory.c b/tests/test_memory.c index fbc8002e..06e798fa 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -32,7 +32,7 @@ void tearDown(void) static void test_nominal_single_alloc_and_free(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -44,18 +44,18 @@ static void test_nominal_single_alloc_and_free(void) ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); JUNO_MEMORY_T tMemory = {0}; - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); TEST_ASSERT_EQUAL(1, tMemory.iRefCount); - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(tMemory.pvAddr); TEST_ASSERT_EQUAL(0, tMemory.pvAddr); TEST_ASSERT_EQUAL(0, tMemory.iRefCount); - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); @@ -67,7 +67,7 @@ static void test_nominal_single_alloc_and_free(void) TEST_ASSERT_NOT_NULL(JUNO_REF(tMemory)->pvAddr); TEST_ASSERT_NOT_EQUAL(0, JUNO_REF(tMemory)->pvAddr); TEST_ASSERT_EQUAL(2, JUNO_REF(tMemory)->iRefCount); - tStatus = ptApi->Put(&tMem, JUNO_REF(tMemory)); + tStatus = ptApi->Put(&tMem.tRoot, JUNO_REF(tMemory)); TEST_ASSERT_EQUAL(JUNO_STATUS_REF_IN_USE_ERROR, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); @@ -87,17 +87,16 @@ static void test_nominal_single_alloc_and_free(void) TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); TEST_ASSERT_EQUAL(1, tMemory.iRefCount); - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(tMemory.pvAddr); TEST_ASSERT_EQUAL(0, tMemory.pvAddr); TEST_ASSERT_EQUAL(0, tMemory.iRefCount); - } static void test_nominal_multiple_alloc_and_free(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -108,14 +107,14 @@ static void test_nominal_multiple_alloc_and_free(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; TEST_BLOCK_T *ptTestPtr[10] = {0}; JUNO_MEMORY_T ptMemory[10] = {0}; for (int j = 0; j < 5; j++) { for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Get(&tMem, &ptMemory[i], sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -125,7 +124,7 @@ static void test_nominal_multiple_alloc_and_free(void) } for (size_t i = 0; i < 5; i++) { - tStatus = ptApi->Put(&tMem, &ptMemory[i]); + tStatus = ptApi->Put(&tMem.tRoot, &ptMemory[i]); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(ptMemory[i].pvAddr); TEST_ASSERT_EQUAL(0, ptMemory[i].pvAddr); @@ -133,7 +132,7 @@ static void test_nominal_multiple_alloc_and_free(void) } for (size_t i = 0; i < 5; i++) { - tStatus = ptApi->Get(&tMem, &ptMemory[i], sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -141,7 +140,7 @@ static void test_nominal_multiple_alloc_and_free(void) } for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Put(&tMem, &ptMemory[i]); + tStatus = ptApi->Put(&tMem.tRoot, &ptMemory[i]); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(ptMemory[i].pvAddr); TEST_ASSERT_EQUAL(0, ptMemory[i].pvAddr); @@ -152,7 +151,7 @@ static void test_nominal_multiple_alloc_and_free(void) static void test_negative_memory_empty(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -163,18 +162,18 @@ static void test_negative_memory_empty(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; JUNO_MEMORY_T tFailMemory = { .pvAddr = ptTestBlock, .zSize = 128 }; - tStatus = ptApi->Put(&tMem, &tFailMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tFailMemory); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_BLOCK_T *ptTestPtr[10] = {0}; JUNO_MEMORY_T ptMemory[10] = {0}; for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Get(&tMem, &ptMemory[i], sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -184,19 +183,19 @@ static void test_negative_memory_empty(void) } for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Put(&tMem, &ptMemory[i]); + tStatus = ptApi->Put(&tMem.tRoot, &ptMemory[i]); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(ptMemory[i].pvAddr); TEST_ASSERT_EQUAL(0, ptMemory[i].pvAddr); ptTestPtr[i] = NULL; } - tStatus = ptApi->Put(&tMem, &ptMemory[0]); + tStatus = ptApi->Put(&tMem.tRoot, &ptMemory[0]); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } static void test_negative_memory_full(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -207,12 +206,12 @@ static void test_negative_memory_full(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; TEST_BLOCK_T *ptTestPtr[10] = {0}; JUNO_MEMORY_T ptMemory[10] = {0}; for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Get(&tMem, &ptMemory[i], sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -221,17 +220,15 @@ static void test_negative_memory_full(void) ptTestPtr[i]->iTestNum = i; } JUNO_MEMORY_T tFailMemory = {0}; - tStatus = ptApi->Get(&tMem, &tFailMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &tFailMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_MEMALLOC_ERROR, tStatus); } /* New tests for higher code coverage */ -// Test initializing the memory block with invalid parameters. static void test_invalid_init_parameters(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; - // Passing NULL for memory and metadata. + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, NULL, @@ -241,14 +238,12 @@ static void test_invalid_init_parameters(void) NULL, NULL ); - // Expect failure (error status) when invalid pointers are used. TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } -// Test double-free of the same allocation. static void test_double_free(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -259,23 +254,20 @@ static void test_double_free(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - // First free should succeed. - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - // Second free should fail. - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } -// Test freeing an allocation that was never obtained. static void test_free_unallocated(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -286,19 +278,15 @@ static void test_free_unallocated(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; JUNO_MEMORY_T tMemory = {0}; - // tMemory never allocated via Get should be flagged as unallocated. - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } -// Test generic update function on block allocation. -// Note: Depending on your implementation, update might only succeed when the new size -// equals the block size. Here we attempt an update with the same size and a different size. static void test_update_memory(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -309,30 +297,24 @@ static void test_update_memory(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - // Attempt update with same size: should succeed. - tStatus = ptApi->Update(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Update(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - // Attempt update with a different size: expect failure. - tStatus = ptApi->Update(&tMem, &tMemory, sizeof(TEST_BLOCK_T) + 1); + tStatus = ptApi->Update(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T) + 1); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - // Free the memory. - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } -// Test generic memory allocation functions using the block allocator. -// Casting the block allocator to the generic interface. static void test_generic_memory_get_put(void) { - // Use the block as a generic allocator. - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -343,29 +325,24 @@ static void test_generic_memory_get_put(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - // Cast the address to the generic allocator type. - JUNO_MEMORY_ALLOC_T *ptAlloc = (JUNO_MEMORY_ALLOC_T *)&tMem; + JUNO_MEMORY_ALLOC_ROOT_T *ptAlloc = &tMem.tRoot; JUNO_MEMORY_T tMemory = {0}; - // Use the generic get function. tStatus = ptApi->Get(ptAlloc, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - // Use the generic update function with a valid size. tStatus = ptApi->Update(ptAlloc, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - // Free using the generic free function. tStatus = ptApi->Put(ptAlloc, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(tMemory.pvAddr); } -// Test allocation with zero size static void test_zero_size_allocation(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -376,18 +353,15 @@ static void test_zero_size_allocation(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; JUNO_MEMORY_T tMemory = {0}; - // Attempt zero-size allocation - tStatus = ptApi->Get(&tMem, &tMemory, 0); - // The implementation should handle this gracefully + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, 0); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } -// Test allocation with zero size static void test_bad_api(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -398,27 +372,25 @@ static void test_bad_api(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; + tMem.tRoot.ptApi = NULL; JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem, &tMemory, 0); - tStatus = ptApi->Put(&tMem, &tMemory); - tStatus = ptApi->Update(&tMem, &tMemory, 0); - // The implementation should handle this gracefully + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, 0); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); + tStatus = ptApi->Update(&tMem.tRoot, &tMemory, 0); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + tMem.tRoot.ptApi = &ptApi[1]; - tStatus = ptApi->Get(&tMem, &tMemory, 0); - tStatus = ptApi->Put(&tMem, &tMemory); - tStatus = ptApi->Update(&tMem, &tMemory, 0); - // The implementation should handle this gracefully + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, 0); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); + tStatus = ptApi->Update(&tMem.tRoot, &tMemory, 0); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - - static void test_invalid_size_and_addr(void) { - JUNO_MEMORY_ALLOC_T tMem = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, ptTestBlock, @@ -430,23 +402,23 @@ static void test_invalid_size_and_addr(void) ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); JUNO_MEMORY_T tMemory = {0}; - const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tJunoMemoryBlock.tRoot.ptApi; - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)+1); + const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)+1); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); JUNO_MEMORY_T tMemory2 = {0}; - tStatus = ptApi->Get(&tMem, &tMemory, sizeof(TEST_BLOCK_T)); + tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); TEST_ASSERT_EQUAL(1, tMemory.iRefCount); tMemory2 = tMemory; - tStatus = ptApi->Put(&tMem, &tMemory); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - tMem.tJunoMemoryBlock.zFreed = 1; - tMem.tJunoMemoryBlock.ptMetadata[0].ptFreeMem = (uint8_t *)(tMemory2.pvAddr); - tStatus = ptApi->Put(&tMem, &tMemory2); + tMem.zFreed = 1; + tMem.ptMetadata[0].ptFreeMem = (uint8_t *)(tMemory2.pvAddr); + tStatus = ptApi->Put(&tMem.tRoot, &tMemory2); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } @@ -467,3 +439,4 @@ int main(void) RUN_TEST(test_invalid_size_and_addr); return UNITY_END(); } + diff --git a/tests/test_time.c b/tests/test_time.c index 1f8cb46f..8a9ca2b9 100644 --- a/tests/test_time.c +++ b/tests/test_time.c @@ -7,13 +7,8 @@ #include #include // For UINT64_MAX -// Bind the time API into a module for testing -union JUNO_TIME_TAG JUNO_MODULE(JUNO_TIME_API_T, JUNO_TIME_ROOT_T, - JUNO_MODULE_EMPTY -); - // Now implementation uses real clock; verify it returns reasonable values -static JUNO_TIMESTAMP_RESULT_T Now(JUNO_TIME_T *ptTime) +static JUNO_TIMESTAMP_RESULT_T Now(JUNO_TIME_ROOT_T *ptTime) { struct timespec tTimeNow = {0}; clock_gettime(CLOCK_REALTIME, &tTimeNow); @@ -24,14 +19,14 @@ static JUNO_TIMESTAMP_RESULT_T Now(JUNO_TIME_T *ptTime) } // Stub SleepTo always succeeds -static JUNO_STATUS_T SleepTo(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tTimeToWakeup) +static JUNO_STATUS_T SleepTo(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tTimeToWakeup) { (void)ptTime; (void)tTimeToWakeup; return JUNO_STATUS_SUCCESS; } // Stub Sleep always succeeds -static JUNO_STATUS_T Sleep(JUNO_TIME_T *ptTime, JUNO_TIMESTAMP_T tDuration) +static JUNO_STATUS_T Sleep(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T tDuration) { (void)ptTime; (void)tDuration; return JUNO_STATUS_SUCCESS; @@ -55,19 +50,19 @@ const JUNO_TIME_API_T tTimeApi = }; // Global module instance -JUNO_TIME_T tTimeMod = {0}; +JUNO_TIME_ROOT_T tTimeMod = {0}; void setUp(void) { // Initialize module with our API - tTimeMod = (JUNO_TIME_T){0}; + tTimeMod = (JUNO_TIME_ROOT_T){0}; tTimeMod.ptApi = &tTimeApi; } void tearDown(void) { // Reset module - tTimeMod = (JUNO_TIME_T){0}; + tTimeMod = (JUNO_TIME_ROOT_T){0}; } // Positive test: AddTime without subseconds overflow From 49c33d30103902fd77b44bf59ebc4b329fe8cf53 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Tue, 23 Sep 2025 04:23:41 -0500 Subject: [PATCH 15/34] :sparkles: Remove forward union declare and upadet tests --- tests/test_buff.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/tests/test_buff.c b/tests/test_buff.c index ce17d7fe..7b439763 100644 --- a/tests/test_buff.c +++ b/tests/test_buff.c @@ -23,9 +23,9 @@ typedef struct TEST_QUEUE JUNO_MODULE_DERIVE(JUNO_BUFF_QUEUE_ROOT_T, ) TEST_QUEUE; -static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_T *ptQueue, void *ptItem, size_t iIndex); -static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); -static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex); +static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem, size_t iIndex); +static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); +static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); static inline JUNO_STATUS_T Queue_Copy(void *ptDest, void *ptSrc); const JUNO_BUFF_QUEUE_API_T gtQueueApi = { @@ -35,7 +35,7 @@ const JUNO_BUFF_QUEUE_API_T gtQueueApi = { Queue_Copy }; -union JUNO_BUFF_QUEUE_T JUNO_MODULE(void, JUNO_BUFF_QUEUE_ROOT_T, +union JUNO_BUFF_QUEUE_ROOT_T JUNO_MODULE(void, JUNO_BUFF_QUEUE_ROOT_T, TEST_QUEUE tTestQueue; ); @@ -47,7 +47,7 @@ static void test_queue(void) TEST_QUEUE tTestQueue = {0}; JUNO_STATUS_T tStatus = JunoDs_Buff_QueueInit(&tTestQueue.tRoot, >QueueApi, 10, NULL, NULL); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - JUNO_BUFF_QUEUE_T tQueue = {.tTestQueue = tTestQueue}; + TEST_QUEUE tQueue = tTestQueue; uint8_t iValue = 0; for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) { @@ -144,7 +144,7 @@ static void test_stack(void) uint8_t iTestStack[10]; JUNO_BUFF_STACK_ROOT_T tStackRoot = {0}; JUNO_RESULT_SIZE_T tResult = {0}; - JUNO_BUFF_STACK_T tStack = {.tRoot = tStackRoot}; + JUNO_BUFF_STACK_ROOT_T tStack = tStackRoot; tResult.tStatus = JunoBuff_StackInit(&tStack, sizeof(iTestStack), NULL, NULL); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); for(size_t i = 0; i < sizeof(iTestStack); i++) @@ -200,22 +200,25 @@ int main(void) return UNITY_END(); } -static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_T *ptQueue, void *ptItem, size_t iIndex) +static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem, size_t iIndex) { uint8_t *iItem = (void *) ptItem; - ptQueue->tTestQueue.iTestQueue[iIndex] = *iItem; + TEST_QUEUE *ptTestQueue = (TEST_QUEUE *) ptQueue; + ptTestQueue->iTestQueue[iIndex] = *iItem; return JUNO_STATUS_SUCCESS; } -static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex) +static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex) { - JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptQueue->tTestQueue.iTestQueue[iIndex]); + TEST_QUEUE *ptTestQueue = (TEST_QUEUE *) ptQueue; + JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptTestQueue->iTestQueue[iIndex]); return tResult; } -static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_T *ptQueue, size_t iIndex) +static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex) { - ptQueue->tTestQueue.iTestQueue[iIndex] = 0; + TEST_QUEUE *ptTestQueue = (TEST_QUEUE *) ptQueue; + ptTestQueue->iTestQueue[iIndex] = 0; return JUNO_STATUS_SUCCESS; } From f2a7be3428ee1b53641ead20d07f921107827c91 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Tue, 23 Sep 2025 04:30:18 -0500 Subject: [PATCH 16/34] :sparkles: Add copy to queue verify --- include/juno/ds/buff_queue_api.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index a9ea3f83..8069f42c 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -66,7 +66,8 @@ static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(JUNO_BUFF_QUEUE_ROOT_T *ptQu ptQueue->zCapacity && ptQueue->ptApi->GetAt && ptQueue->ptApi->SetAt && - ptQueue->ptApi->RemoveAt + ptQueue->ptApi->RemoveAt && + ptQueue->ptApi->Copy ); return JUNO_STATUS_SUCCESS; } From 3e8f3a0534ca33e568016ec9441e6947a18ccf25 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Wed, 1 Oct 2025 05:57:52 -0500 Subject: [PATCH 17/34] :sparkles: Update stack --- include/juno/ds/buff_stack_api.h | 99 ++++++++----------------- src/juno_buff_queue.c | 2 +- src/juno_buff_stack.c | 75 +++++++++++++++++++ tests/test_buff.c | 121 ++++++++++++++++++++----------- 4 files changed, 187 insertions(+), 110 deletions(-) create mode 100644 src/juno_buff_stack.c diff --git a/include/juno/ds/buff_stack_api.h b/include/juno/ds/buff_stack_api.h index ab2098c0..ab7759bc 100644 --- a/include/juno/ds/buff_stack_api.h +++ b/include/juno/ds/buff_stack_api.h @@ -37,88 +37,53 @@ extern "C" /// The buffer stack root module typedef struct JUNO_BUFF_STACK_ROOT_TAG JUNO_BUFF_STACK_ROOT_T; +typedef struct JUNO_BUFF_STACK_API_TAG JUNO_BUFF_STACK_API_T; -struct JUNO_BUFF_STACK_ROOT_TAG JUNO_MODULE_ROOT(void, +struct JUNO_BUFF_STACK_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BUFF_STACK_API_T, /// The current length of the stack size_t zLength; /// The capacity of the stack size_t zCapacity; ); -/// Initialize a buffer stack -static inline JUNO_STATUS_T JunoBuff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +struct JUNO_BUFF_STACK_API_TAG +{ + JUNO_STATUS_T (*SetAt)(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex); + JUNO_RESULT_VOID_PTR_T (*GetAt)(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); + JUNO_STATUS_T (*RemoveAt)(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); + JUNO_STATUS_T (*Copy)(void *ptDest, void *ptSrc); +}; + +static inline JUNO_STATUS_T JunoDs_Buff_StackVerify(JUNO_BUFF_STACK_ROOT_T *ptStack) { JUNO_ASSERT_EXISTS(ptStack); - JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - ptStackRoot->zLength = 0; - ptStackRoot->zCapacity = zCapacity; - ptStackRoot->_pfcnFailureHandler = pfcnFailureHdlr; - ptStackRoot->_pvFailureUserData = pvFailureUserData; + JUNO_ASSERT_EXISTS( + ptStack->ptApi && + ptStack->zCapacity && + ptStack->ptApi->GetAt && + ptStack->ptApi->SetAt && + ptStack->ptApi->RemoveAt && + ptStack->ptApi->Copy + ); return JUNO_STATUS_SUCCESS; } -/// Push an item onto the stack -/// @returns an index to write the pushed item to -static inline JUNO_RESULT_SIZE_T JunoBuff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptStack) -{ - JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; - if(!ptStack) - { - tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; - return tResult; - } - JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - if(ptStackRoot->zLength < ptStackRoot->zCapacity) - { - tResult.tOk = ptStackRoot->zLength; - ptStackRoot->zLength += 1; - } - else - { - tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tResult.tStatus, ptStackRoot->_pfcnFailureHandler, ptStackRoot->_pvFailureUserData, "Failed to enqueue data"); - return tResult; - } - return tResult; -} +/// Initialize a buffer queue with a capacity +JUNO_STATUS_T JunoDs_Buff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptQueue, const JUNO_BUFF_STACK_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); -/// Pop an item from the stack -/// @returns an index of the popped item -static inline JUNO_RESULT_SIZE_T JunoBuff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptStack) -{ - JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; - if(!ptStack) - { - tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; - return tResult; - } - JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - if(ptStackRoot->zLength > 0) - { - ptStackRoot->zLength -= 1; - tResult.tOk = ptStackRoot->zLength; - return tResult; - } - tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; - JUNO_FAIL(tResult.tStatus, ptStackRoot->_pfcnFailureHandler, ptStackRoot->_pvFailureUserData, "Failed to enqueue data"); - return tResult; -} +/// Enqueue an item into the buffer +/// @returns The index to place the enqueued item +JUNO_STATUS_T JunoDs_Buff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptQueue, void *ptItem); + + +/// Dequeue an item from the buffer +/// @returns The index to dequeue the item from +JUNO_STATUS_T JunoDs_Buff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptQueue, void *ptReturn); -/// Peek at an item on the stack -/// @returns The index of the next item -static inline JUNO_RESULT_SIZE_T JunoBuff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptStack) -{ - JUNO_RESULT_SIZE_T tResult = {JUNO_STATUS_SUCCESS,0}; - if(!ptStack) - { - tResult.tStatus = JUNO_STATUS_NULLPTR_ERROR; - return tResult; - } - JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - tResult.tOk = ptStackRoot->zLength; - return tResult; -} +/// Peek at the next item in the queue +/// @returns the index of the next item in the queue +JUNO_RESULT_VOID_PTR_T JunoDs_Buff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptQueue); #ifdef __cplusplus } diff --git a/src/juno_buff_queue.c b/src/juno_buff_queue.c index ed0a9a6b..4d72d727 100644 --- a/src/juno_buff_queue.c +++ b/src/juno_buff_queue.c @@ -63,7 +63,7 @@ JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *pt /// Peek at the next item in the queue /// @returns the index of the next item in the queue -JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) +JUNO_RESULT_VOID_PTR_T JunoDs_Buff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) { JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); tResult.tStatus = JunoDs_Buff_QueueVerify(ptQueue); diff --git a/src/juno_buff_stack.c b/src/juno_buff_stack.c new file mode 100644 index 00000000..03ebd14b --- /dev/null +++ b/src/juno_buff_stack.c @@ -0,0 +1,75 @@ +#include "juno/ds/buff_stack_api.h" +#include "juno/macros.h" +#include "juno/status.h" +/// Initialize a buffer queue with a capacity +JUNO_STATUS_T JunoDs_Buff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptStack, const JUNO_BUFF_STACK_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +{ + JUNO_ASSERT_EXISTS(ptStack); + JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); + ptStackRoot->zLength = 0; + ptStackRoot->zCapacity = zCapacity; + ptStackRoot->_pfcnFailureHandler = pfcnFailureHdlr; + ptStackRoot->_pvFailureUserData = pvFailureUserData; + ptStackRoot->ptApi = ptApi; + return JunoDs_Buff_StackVerify(ptStack); +} + +/// Enqueue an item into the buffer +/// @returns The index to place the enqueued item +JUNO_STATUS_T JunoDs_Buff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem) +{ + JUNO_STATUS_T tStatus = JunoDs_Buff_StackVerify(ptStack); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); + if(ptStackRoot->zLength < ptStackRoot->zCapacity) + { + tStatus = ptStack->ptApi->SetAt(ptStack, ptItem, ptStackRoot->zLength); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + ptStackRoot->zLength += 1; + } + else + { + tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + JUNO_FAIL(tStatus, ptStackRoot->_pfcnFailureHandler, ptStackRoot->_pvFailureUserData, "Failed to enqueue data"); + } + return tStatus; +} + + +/// Dequeue an item from the buffer +/// @returns The index to dequeue the item from +JUNO_STATUS_T JunoDs_Buff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptReturn) +{ + JUNO_STATUS_T tStatus = JunoDs_Buff_StackVerify(ptStack); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); + if(ptStackRoot->zLength > 0) + { + ptStackRoot->zLength -= 1; + JUNO_RESULT_VOID_PTR_T tResult = ptStack->ptApi->GetAt(ptStack, ptStackRoot->zLength); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult.tStatus); + tStatus = ptStackRoot->ptApi->Copy(ptReturn, tResult.tOk); + return tStatus; + } + tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + JUNO_FAIL(tStatus, ptStackRoot->_pfcnFailureHandler, ptStackRoot->_pvFailureUserData, "Failed to enqueue data"); + return tStatus; +} + + +/// Peek at the next item in the queue +/// @returns the index of the next item in the queue +JUNO_RESULT_VOID_PTR_T JunoDs_Buff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptStack) +{ + JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); + tResult.tStatus = JunoDs_Buff_StackVerify(ptStack); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + if(ptStack->zLength == 0) + { + tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + JUNO_FAIL(tResult.tStatus, ptStack->_pfcnFailureHandler, ptStack->_pvFailureUserData, "Queue is empty"); + return tResult; + } + tResult = ptStack->ptApi->GetAt(ptStack, 0); + return tResult; +} diff --git a/tests/test_buff.c b/tests/test_buff.c index 7b439763..25aeedf8 100644 --- a/tests/test_buff.c +++ b/tests/test_buff.c @@ -39,7 +39,24 @@ union JUNO_BUFF_QUEUE_ROOT_T JUNO_MODULE(void, JUNO_BUFF_QUEUE_ROOT_T, TEST_QUEUE tTestQueue; ); -union JUNO_BUFF_STACK_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, +typedef struct TEST_STACK JUNO_MODULE_DERIVE(JUNO_BUFF_STACK_ROOT_T, + uint8_t iTestStack[10]; +) TEST_STACK; + +static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex); +static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); +static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); +static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc); + +const JUNO_BUFF_STACK_API_T gtStackApi = { + Stack_SetAt, + Stack_GetAt, + Stack_RemoveAt, + Stack_Copy +}; + +union JUNO_BUFF_STACK_ROOT_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, + TEST_STACK tTestStack; ); static void test_queue(void) @@ -141,55 +158,45 @@ static void test_queue(void) static void test_stack(void) { - uint8_t iTestStack[10]; - JUNO_BUFF_STACK_ROOT_T tStackRoot = {0}; - JUNO_RESULT_SIZE_T tResult = {0}; - JUNO_BUFF_STACK_ROOT_T tStack = tStackRoot; - tResult.tStatus = JunoBuff_StackInit(&tStack, sizeof(iTestStack), NULL, NULL); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestStack); i++) + TEST_STACK tTestStack = (TEST_STACK){0}; + JUNO_STATUS_T tStatus = JunoDs_Buff_StackInit(&tTestStack.tRoot, >StackApi, 10, NULL, NULL); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_STACK tStack = tTestStack; + uint8_t iValue = 0; + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) { - size_t iIndex = 0; - tResult = JunoBuff_StackPush(&tStack); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestStack[iIndex] = i+1; + iValue = i + 1; + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - size_t iIndex = 0; - tResult = JunoBuff_StackPush(&tStack); - iIndex = tResult.tOk; - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestStack); i++) + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) { - iIndex = 0; - tResult = JunoBuff_StackPop(&tStack); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(sizeof(iTestStack) - i, iTestStack[iIndex]); + iValue = 0; + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); } - tResult = JunoBuff_StackPop(&tStack); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestStack); i++) + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) { - iIndex = 0; - tResult = JunoBuff_StackPush(&tStack); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - iTestStack[iIndex] = i+1; + iValue = i + 1; + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - iIndex = 0; - tResult = JunoBuff_StackPush(&tStack); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - for(size_t i = 0; i < sizeof(iTestStack); i++) + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) { - iIndex = 0; - tResult = JunoBuff_StackPop(&tStack); - iIndex = tResult.tOk; - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); - TEST_ASSERT_EQUAL(sizeof(iTestStack) - i, iTestStack[iIndex]); + iValue = 0; + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); } - tResult = JunoBuff_StackPop(&tStack); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tResult.tStatus); + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } int main(void) @@ -230,3 +237,33 @@ static inline JUNO_STATUS_T Queue_Copy(void *ptDest, void *ptSrc) return JUNO_STATUS_SUCCESS; } +static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex) +{ + uint8_t *iItem = (void *) ptItem; + TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; + ptTestStack->iTestStack[iIndex] = *iItem; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) +{ + TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; + JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptTestStack->iTestStack[iIndex]); + return tResult; +} + +static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) +{ + TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; + ptTestStack->iTestStack[iIndex] = 0; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc) +{ + uint8_t *iDest = (void *) ptDest; + uint8_t *iSrc= (void *) ptSrc; + *iDest = *iSrc; + return JUNO_STATUS_SUCCESS; +} + From 615be36dd2160e5215a1eef7e86267dca03a13f5 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Wed, 1 Oct 2025 06:01:06 -0500 Subject: [PATCH 18/34] :sparkles: Remove src specific libs --- CMakeLists.txt | 80 +++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b3451fe..2e7ec607 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,8 @@ add_library(${PROJECT_NAME} STATIC target_include_directories(${PROJECT_NAME} PUBLIC $ $ + PRIVATE + ${PROJECT_SOURCE_DIR}/src ) set(JUNO_COMPILE_OPTIONS @@ -68,57 +70,39 @@ if(JUNO_COVERAGE) link_libraries(gcov) endif() -set(JUNO_LIBS ${PROJECT_NAME}) -foreach(file ${JUNO_SRCS}) - # Get the file name without extension (NAME_WE stands for Name Without Extension) - get_filename_component(lib_name ${file} NAME_WE) - add_library(${lib_name} STATIC - ${file} - ) - list(APPEND JUNO_LIBS ${lib_name}) -endforeach() -# Specify the include directories for consumers of this library -foreach(lib ${JUNO_LIBS}) - target_include_directories(${lib} PUBLIC - $ - $ - PRIVATE - ${PROJECT_SOURCE_DIR}/src +if(JUNO_FREESTANDING) + list(APPEND JUNO_COMPILE_C_OPTIONS + -nostdlib + -ffreestanding + ) + target_link_options(${lib} PRIVATE + -nostdlib + ) +endif() +if(JUNO_ASAN) + add_compile_options( + -fsanitize=address ) - if(JUNO_FREESTANDING) - list(APPEND JUNO_COMPILE_C_OPTIONS - -nostdlib - -ffreestanding - ) - target_link_options(${lib} PRIVATE - -nostdlib - ) - endif() - if(JUNO_ASAN) - add_compile_options( - -fsanitize=address - ) - add_link_options( - -fsanitize=address - ) - endif() - if(JUNO_UBSAN) - add_compile_options( - -fsanitize=undefined - ) - add_link_options( - -fsanitize=undefined - ) - endif() - # Enable a comprehensive set of warnings - target_compile_options(${lib} PRIVATE - ${JUNO_COMPILE_OPTIONS} - $<$:${JUNO_COMPILE_C_OPTIONS}> - $<$:${JUNO_COMPILE_CXX_OPTIONS}> + add_link_options( + -fsanitize=address ) +endif() +if(JUNO_UBSAN) + add_compile_options( + -fsanitize=undefined + ) + add_link_options( + -fsanitize=undefined + ) +endif() +# Enable a comprehensive set of warnings +target_compile_options(${PROJECT_NAME} PRIVATE + ${JUNO_COMPILE_OPTIONS} + $<$:${JUNO_COMPILE_C_OPTIONS}> + $<$:${JUNO_COMPILE_CXX_OPTIONS}> -endforeach() +) if(JUNO_SHARED) set(JUNO_SHARED_TARGET ${PROJECT_NAME}_shared) @@ -126,6 +110,8 @@ if(JUNO_SHARED) target_include_directories(${JUNO_SHARED_TARGET} PUBLIC $ $ + PRIVATE + ${PROJECT_SOURCE_DIR}/src ) endif() From 08e280ec6c2c5bc61ffc50dc243e997160014314 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 07:30:00 -0500 Subject: [PATCH 19/34] :sparkles: Update memory api --- CMakeLists.txt | 6 + examples/CMakeLists.txt | 17 +++ examples/di_example.c | 4 + examples/example_sb.c | 6 + examples/example_state_machine.c | 23 ++-- examples/memory_example.c | 185 ----------------------------- examples/minimal_memory_example.c | 74 ++++++------ include/juno/ds/array_api.h | 75 ++++++++++++ include/juno/ds/buff_queue_api.h | 42 +++---- include/juno/{map => ds}/map_api.h | 0 include/juno/map/README.md | 5 - include/juno/memory/README.md | 36 +++--- include/juno/memory/memory_api.h | 104 ++++++++++------ include/juno/memory/memory_block.h | 4 +- include/juno/module.h | 14 ++- include/juno/sb/broker_api.h | 76 ------------ include/juno/sb/msg_api.h | 38 ++---- include/juno/sb/publisher_api.h | 58 --------- include/juno/sb/subscriber_api.h | 62 ---------- src/juno_map.c | 2 +- src/juno_memory_block.c | 75 ++++++------ tests/test_cpp.cpp | 4 +- tests/test_map.c | 2 +- tests/test_memory.c | 159 +++++++++++++++---------- 24 files changed, 414 insertions(+), 657 deletions(-) create mode 100644 examples/CMakeLists.txt create mode 100644 examples/example_sb.c delete mode 100644 examples/memory_example.c create mode 100644 include/juno/ds/array_api.h rename include/juno/{map => ds}/map_api.h (100%) delete mode 100644 include/juno/map/README.md delete mode 100644 include/juno/sb/broker_api.h delete mode 100644 include/juno/sb/publisher_api.h delete mode 100644 include/juno/sb/subscriber_api.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e7ec607..8896dc9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ option(JUNO_SHARED "Compile the juno shared library" OFF) option(JUNO_FREESTANDING "Compile as a freestanding library" OFF) option(JUNO_ASAN "Compile ASAN" OFF) option(JUNO_UBSAN "Compile with UBSAN" OFF) +option(JUNO_EXAMPLES "Compile Juno Examples" OFF) message("Compiler: ${CMAKE_C_COMPILER}") message("Testing: ${JUNO_TESTS}") @@ -139,6 +140,11 @@ if(JUNO_TESTS) add_subdirectory(${PROJECT_SOURCE_DIR}/tests) endif() +if(JUNO_EXAMPLES) + set(CMAKE_BUILD_TYPE Debug) + add_subdirectory(${PROJECT_SOURCE_DIR}/examples) +endif() + if(JUNO_DOCS) # 1) Find Doxygen diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..7b66fff1 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,17 @@ +# Create the library (update the source files as needed) +set(JUNO_EXAMPLE_DIR ${PROJECT_SOURCE_DIR}/examples) +aux_source_directory(${JUNO_EXAMPLE_DIR} JUNO_EXAMPLE_SRCS) + + +# Loop over each file and remove the extension +foreach(file ${JUNO_EXAMPLE_SRCS}) + # Get the file name without extension (NAME_WE stands for Name Without Extension) + get_filename_component(example_name ${file} NAME_WE) + add_executable(${example_name} ${file}) + target_link_libraries(${example_name} ${PROJECT_NAME} unity m) + target_compile_options(${example_name} PRIVATE + ${JUNO_COMPILE_OPTIONS} + $<$:${JUNO_COMPILE_C_OPTIONS}> + $<$:${JUNO_COMPILE_CXX_OPTIONS}> + ) +endforeach() diff --git a/examples/di_example.c b/examples/di_example.c index 3b137d1b..3bbf60b9 100644 --- a/examples/di_example.c +++ b/examples/di_example.c @@ -30,3 +30,7 @@ In this tutorial, we’ll walk through: We’ll use the example code provided in the “gastank\_api.h”, “engine\_api.h”, “battery\_api.h”, “car\_api.h” files, plus their implementations, to illustrate these concepts. By the end, you’ll see how a modular, DI-driven design can keep your embedded software clean, testable, and maintainable. */ +int main(void) +{ + return 0; +} diff --git a/examples/example_sb.c b/examples/example_sb.c new file mode 100644 index 00000000..6b5fcbd1 --- /dev/null +++ b/examples/example_sb.c @@ -0,0 +1,6 @@ +#include "juno/sb/msg_api.h" + +int main(void) +{ + return 0; +} diff --git a/examples/example_state_machine.c b/examples/example_state_machine.c index b57ef58d..bdad078b 100644 --- a/examples/example_state_machine.c +++ b/examples/example_state_machine.c @@ -24,9 +24,9 @@ union JUNO_SM_STATE_T JUNO_MODULE(JUNO_SM_STATE_API_T, JUNO_SM_STATE_ROOT_T, ); /// The action that should be executed in this state -static JUNO_STATUS_T StateAction(JUNO_SM_STATE_T *ptJunoSm) +static JUNO_STATUS_T StateAction(JUNO_SM_STATE_ROOT_T *ptJunoSm) { - JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); + JUNO_STATUS_T tStatus = JunoSm_StateVerify(ptJunoSm); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; printf("Current State: %u\n", ptTrafficLightState->tThisLight); @@ -35,9 +35,9 @@ static JUNO_STATUS_T StateAction(JUNO_SM_STATE_T *ptJunoSm) return JUNO_STATUS_SUCCESS; } /// Returns a bool result whether the current state should exit -static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm) +static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_ROOT_T *ptJunoSm) { - JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); + JUNO_STATUS_T tStatus = JunoSm_StateVerify(ptJunoSm); JUNO_RESULT_BOOL_T tResult = {0}; TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; tResult.tStatus = tStatus; @@ -47,9 +47,9 @@ static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm) } -static JUNO_STATUS_T ResetState(JUNO_SM_STATE_T *ptJunoSm) +static JUNO_STATUS_T ResetState(JUNO_SM_STATE_ROOT_T *ptJunoSm) { - JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot); + JUNO_STATUS_T tStatus = JunoSm_StateVerify(ptJunoSm); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm; ptTrafficLightState->iCounter = 0; @@ -86,9 +86,10 @@ TRAFFIC_LIGHT_SM_T tSm = { }, }; -int main() +int main(void) { JUNO_STATUS_T tStatus = JunoSm_Init(&tSm.tRoot, &tSm.tStates[TRAFFIC_RED].tRoot, NULL, NULL); + JUNO_ASSERT_SUCCESS(tStatus, return -1); for(size_t i = 0; i < TRAFFIC_COUNT; i++) { TRAFFIC_LIGHT_STATE_T *ptSmState = &tSm.tStates[i]; @@ -98,20 +99,20 @@ int main() { JUNO_SM_RESULT_STATE_T tStateResult = JunoSm_GetCurrentState(&tSm.tRoot); JUNO_ASSERT_SUCCESS(tStateResult.tStatus, break); - JUNO_SM_STATE_ROOT_T *ptSmState = &tStateResult.tOk->tRoot; + JUNO_SM_STATE_ROOT_T *ptSmState = tStateResult.tOk; if(ptSmState) { const JUNO_SM_STATE_API_T *ptSmStateApi = ptSmState->ptApi; - JUNO_RESULT_BOOL_T tBoolResult = ptSmStateApi->ShouldExit((JUNO_SM_STATE_T *)ptSmState); + JUNO_RESULT_BOOL_T tBoolResult = ptSmStateApi->ShouldExit(ptSmState); JUNO_ASSERT_SUCCESS(tBoolResult.tStatus, break); if(tBoolResult.tOk) { - ptSmStateApi->ResetState((JUNO_SM_STATE_T *)ptSmState); + ptSmStateApi->ResetState(ptSmState); JunoSm_TransitionState(&tSm.tRoot); } else { - ptSmStateApi->StateAction((JUNO_SM_STATE_T *)ptSmState); + ptSmStateApi->StateAction(ptSmState); } } } diff --git a/examples/memory_example.c b/examples/memory_example.c deleted file mode 100644 index 429c7bfc..00000000 --- a/examples/memory_example.c +++ /dev/null @@ -1,185 +0,0 @@ -#include "juno/memory/memory_api.h" -#define JUNO_MEMORY_DEFAULT -#include "juno/memory/memory_block.h" -#include "juno/status.h" -#include - -/// A SLL node -typedef struct SINGLE_LINKED_LIST_NODE_TAG SINGLE_LINKED_LIST_NODE_T; -/// THe SLL -typedef struct SINGLE_LINKED_LIST_TAG SINGLE_LINKED_LIST_T; - -struct SINGLE_LINKED_LIST_NODE_TAG -{ - /// The next node in the SLL - SINGLE_LINKED_LIST_NODE_T *ptNext; - /// The Juno memory since the node owns it - JUNO_MEMORY_T tMemory; - /// The Example data in the node - int iExampleData; -}; - -struct SINGLE_LINKED_LIST_TAG -{ - /// The start of the SLL - SINGLE_LINKED_LIST_NODE_T *ptStart; - /// The length of the SLL - size_t zLen; - JUNO_FAILURE_HANDLER_T pfcnFailureHandler; - JUNO_USER_DATA_T *pvFailureUserData; -}; - -/// The memory for the SLL. Supports a max of 100 nodes -JUNO_MEMORY_BLOCK(ptSllMemory, SINGLE_LINKED_LIST_NODE_T, 100); -/// The metadata for the SLL -JUNO_MEMORY_BLOCK_METADATA(ptSllMemoryMetadata, 100); - -void FailureHandler(JUNO_STATUS_T tStatus, const char *pcMsg, JUNO_USER_DATA_T *ptUserData) -{ - // We don't have user data - (void)ptUserData; - printf("Memory operation failed: %s\n", pcMsg); -} - -static JUNO_STATUS_T Push(JUNO_MEMORY_ALLOC_T *ptAlloc, SINGLE_LINKED_LIST_T *ptSll, int iData) -{ - // Initialize the status with success - JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS; - // Initialize the current node with the start of the SLL - SINGLE_LINKED_LIST_NODE_T *ptThisNode = ptSll->ptStart; - // Check if the current node has been initialized - if(!ptThisNode) - { - // Create a new node and return the status - // Allocate the memory for the first node - JUNO_MEMORY_T tMem = {}; - const JUNO_MEMORY_ALLOC_API_T *ptApi = ptAlloc->tRoot.ptApi; - JUNO_STATUS_T tStatus = ptApi->Get(ptAlloc, &tMem, sizeof(SINGLE_LINKED_LIST_NODE_T)); - if(tStatus) return tStatus; - // Using the memory directly since the SLL will own this memory - ptThisNode = (SINGLE_LINKED_LIST_NODE_T *) tMem.pvAddr; - // Set the data - ptThisNode->iExampleData = iData; - // Give the SLL Node the memory - ptThisNode->tMemory = tMem; - ptSll->ptStart = ptThisNode; - // Return the status - ptSll->zLen += 1; - return tStatus; - } - for(size_t i = 0; i < ptSll->zLen && ptThisNode->ptNext; ++i) - { - ptThisNode = ptThisNode->ptNext; - } - // Allocate the memory for the first node - JUNO_MEMORY_T tMem = {}; - const JUNO_MEMORY_ALLOC_API_T *ptApi = ptAlloc->tRoot.ptApi; - tStatus = ptApi->Get(ptAlloc, &tMem, sizeof(SINGLE_LINKED_LIST_NODE_T)); - if(tStatus) return tStatus; - // Using the memory directly since the SLL will own this memory - ptThisNode->ptNext = (SINGLE_LINKED_LIST_NODE_T *) tMem.pvAddr; - // Set the data - ptThisNode->ptNext->iExampleData = iData; - // Give the SLL Node the memory - ptThisNode->ptNext->tMemory = tMem; - // Return the status - ptSll->zLen += 1; - return tStatus; -} - -static JUNO_STATUS_T Pop(JUNO_MEMORY_ALLOC_T *ptAlloc, SINGLE_LINKED_LIST_T *ptSll, int *piRetData) -{ - // Initialize the status with success - JUNO_STATUS_T tStatus = JUNO_STATUS_SUCCESS; - // Check if the return data is null - if(!piRetData) - { - // Return data is null, call failure handler - tStatus = JUNO_STATUS_NULLPTR_ERROR; - JUNO_FAIL(tStatus, ptSll->pfcnFailureHandler, ptSll->pvFailureUserData, "Return data is null"); - return tStatus; - } - // Initialize the current node with the start of the SLL - SINGLE_LINKED_LIST_NODE_T *ptThisNode = ptSll->ptStart; - // Check if the current node has been initialized - if(!ptThisNode) - { - // Create a new node and return the status - return JUNO_STATUS_DNE_ERROR; - } - ptSll->ptStart = ptThisNode->ptNext; - *piRetData = ptThisNode->iExampleData; - const JUNO_MEMORY_ALLOC_API_T *ptApi = ptAlloc->tRoot.ptApi; - tStatus = ptApi->Put(ptAlloc, &ptThisNode->tMemory); - return tStatus; -} - -int main() -{ - // Instantiate the memory API - // The memory allocator - JUNO_MEMORY_ALLOC_T tMemAlloc = {}; - // Initialize the block allocator - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( - &tMemAlloc, - ptSllMemory, - ptSllMemoryMetadata, - sizeof(SINGLE_LINKED_LIST_NODE_T), - 100, - FailureHandler, - NULL - ); - // If the init has a failed status (which is non-zero) exit - // The failure handler automatically gets calles - if(tStatus) return -1; - // Create the linked list with the failure handler - SINGLE_LINKED_LIST_T tSll = { - .pfcnFailureHandler = FailureHandler, - .pvFailureUserData = NULL - }; - // Create another linked list with references - SINGLE_LINKED_LIST_T tSll2 = { - .pfcnFailureHandler = FailureHandler, - .pvFailureUserData = NULL - }; - // Push example data onto the queue - for(int i = 10; i < 20; i++) - { - Push(&tMemAlloc, &tSll, i); - } - // Copy the data to the SLL by reference - JUNO_NEW_REF(ptNodeRef) = Juno_MemoryGetRef(&tSll.ptStart->tMemory); - tSll2.ptStart = (SINGLE_LINKED_LIST_NODE_T *) JUNO_REF(ptNodeRef->pvAddr); - tSll2.zLen = tSll.zLen; - // Print the values in the queue and sll 2 - SINGLE_LINKED_LIST_NODE_T *ptThisNode = tSll.ptStart; - SINGLE_LINKED_LIST_NODE_T *ptThisStackNode = tSll2.ptStart; - for(size_t i = 0; i < tSll.zLen && i < tSll2.zLen; i++) - { - printf("SLL 1 | Node: %lu | Data: %i\n", i, ptThisNode->iExampleData); - printf("SLL 2 | Node: %lu | Data: %i\n", i, ptThisStackNode->iExampleData); - ptThisNode = ptThisNode->ptNext; - ptThisStackNode = ptThisStackNode->ptNext; - } - // Attempt to free memory in first SLL. This will fail since - // the references are in use - printf("--------------------------\n"); - printf("Attempting to free memory in use.\nThis should fail and call failure handler\n" - ); - printf("--------------------------\n"); - int iRetData = 0; - tStatus = Pop(&tMemAlloc, &tSll, &iRetData); - printf("--------------------------\n"); - printf("Freeing memory references.\n"); - printf("--------------------------\n"); - Juno_MemoryPutRef(&tSll2.ptStart->tMemory); - printf("--------------------------\n"); - printf("Freeing memory\n"); - printf("--------------------------\n"); - for(size_t i = 0; i < tSll.zLen; i++) - { - int iRetData = 0; - Pop(&tMemAlloc, &tSll, &iRetData); - printf("Freeing Node: %lu\n", i); - } -} diff --git a/examples/minimal_memory_example.c b/examples/minimal_memory_example.c index dd164b10..e3a52aaa 100644 --- a/examples/minimal_memory_example.c +++ b/examples/minimal_memory_example.c @@ -1,3 +1,4 @@ +#include "juno/macros.h" #include "juno/memory/memory_api.h" #define JUNO_MEMORY_DEFAULT #include "juno/memory/memory_block.h" @@ -11,6 +12,35 @@ typedef struct { float value; } USER_DATA_T; +// Define the pointer api for this type +static JUNO_STATUS_T UserDataCopy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) +{ + JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tDest, USER_DATA_T); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JUNO_ASSERT_POINTER_TYPE(tSrc, USER_DATA_T); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + USER_DATA_T *ptDest = (USER_DATA_T *)tDest.pvAddr; + USER_DATA_T *ptSrc = (USER_DATA_T *)tSrc.pvAddr; + *ptDest = *ptSrc; + return tStatus; +} + +/// Reset the memory at the pointer. This could mean zero-initialization +static JUNO_STATUS_T UserDataReset(JUNO_POINTER_T tPointer) +{ + JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tPointer, USER_DATA_T); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + USER_DATA_T *ptBlock = (USER_DATA_T *)tPointer.pvAddr; + *ptBlock = (USER_DATA_T){0}; + return tStatus; +} + +const JUNO_POINTER_API_T gtUserDataPointerApi = { + UserDataCopy, + UserDataReset +}; + + // Declare memory block for 5 USER_DATA_T objects JUNO_MEMORY_BLOCK(gUserDataMemory, USER_DATA_T, 5); JUNO_MEMORY_BLOCK_METADATA(gUserDataMetadata, 5); @@ -26,9 +56,10 @@ int main(void) { printf("------------------------------------\n\n"); // Step 1: Initialize the memory allocator - JUNO_MEMORY_ALLOC_T tMemAlloc = {0}; + JUNO_MEMORY_ALLOC_BLOCK_T tMemAlloc = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMemAlloc, + >UserDataPointerApi, gUserDataMemory, gUserDataMetadata, sizeof(USER_DATA_T), @@ -45,14 +76,10 @@ int main(void) { printf("Memory block initialized successfully\n"); // Step 2: Allocate memory - JUNO_MEMORY_T tMemory = {0}; + JUNO_POINTER_T tMemory = {0}; const JUNO_MEMORY_ALLOC_API_T *ptApi = tMemAlloc.tRoot.ptApi; - tStatus = ptApi->Get(&tMemAlloc, &tMemory, sizeof(USER_DATA_T)); - - if (tStatus != JUNO_STATUS_SUCCESS) { - printf("Failed to allocate memory\n"); - return -1; - } + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMemAlloc.tRoot, sizeof(USER_DATA_T)); + JUNO_ASSERT_SUCCESS(tPointerResult.tStatus, return -1); printf("Memory allocated successfully\n"); @@ -64,33 +91,10 @@ int main(void) { printf("Data stored: ID=%d, Name=%s, Value=%.2f\n", pUserData->id, pUserData->name, pUserData->value); - - // Step 4: Create a reference to share the memory - printf("\nCreating a reference to memory...\n"); - JUNO_NEW_REF(userDataRef) = Juno_MemoryGetRef(&tMemory); - - printf("Reference count: %zu\n", tMemory.iRefCount); - - // Access through the reference - USER_DATA_T *pSharedData = (USER_DATA_T *)JUNO_REF(userDataRef)->pvAddr; - printf("Accessed via reference: ID=%d, Name=%s, Value=%.2f\n", - pSharedData->id, pSharedData->name, pSharedData->value); - - // Step 5: Try to free memory while reference exists - printf("\nAttempting to free memory with active references...\n"); - tStatus = ptApi->Put(&tMemAlloc, &tMemory); - - if (tStatus == JUNO_STATUS_REF_IN_USE_ERROR) { - printf("As expected, could not free memory with active references\n"); - } - - // Step 6: Release reference and try again - printf("\nReleasing reference...\n"); - Juno_MemoryPutRef(JUNO_REF(userDataRef)); - printf("Reference count after release: %zu\n", tMemory.iRefCount); - + + printf("Freeing memory...\n"); - tStatus = ptApi->Put(&tMemAlloc, &tMemory); + tStatus = ptApi->Put(&tMemAlloc.tRoot, &tMemory); if (tStatus == JUNO_STATUS_SUCCESS) { printf("Memory freed successfully\n"); @@ -99,4 +103,4 @@ int main(void) { } return 0; -} \ No newline at end of file +} diff --git a/include/juno/ds/array_api.h b/include/juno/ds/array_api.h new file mode 100644 index 00000000..26226977 --- /dev/null +++ b/include/juno/ds/array_api.h @@ -0,0 +1,75 @@ +/* + MIT License + + Copyright (c) 2025 Robin A. Onsay + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. +*/ + +/** + This API has been generated by LibJuno: + https://www.robinonsay.com/libjuno/ +*/ + +/** + This header contains the juno_buff_queue library API + @author Robin Onsay +*/ +#ifndef JUNO_BUFF_API_H +#define JUNO_BUFF_API_H +#include "juno/macros.h" +#include "juno/memory/memory_api.h" +#include "juno/status.h" +#include "juno/module.h" +#include "juno/types.h" +#include +#ifdef __cplusplus +extern "C" +{ +#endif + +/// The Buffer queue root +typedef struct JUNO_ARRAY_ROOT_TAG JUNO_ARRAY_ROOT_T; +typedef struct JUNO_ARRAY_API_TAG JUNO_ARRAY_API_T; + +/// The root buffee queue +struct JUNO_ARRAY_ROOT_TAG JUNO_MODULE_ROOT(JUNO_ARRAY_API_T, + /// The current length of the buffer + size_t zLength; + size_t zCapacity; +); + +struct JUNO_ARRAY_API_TAG +{ + JUNO_STATUS_T (*SetAt)(JUNO_ARRAY_ROOT_T *ptArray, JUNO_POINTER_T tItem, size_t iIndex); + JUNO_RESULT_POINTER_T (*GetAt)(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex); + JUNO_STATUS_T (*RemoveAt)(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex); +}; + +static inline JUNO_STATUS_T JunoDs_ArrayVerify(JUNO_ARRAY_ROOT_T *ptArray) +{ + JUNO_ASSERT_EXISTS(ptArray); + JUNO_ASSERT_EXISTS( + ptArray->ptApi && + ptArray->zCapacity && + ptArray->ptApi->GetAt && + ptArray->ptApi->SetAt && + ptArray->ptApi->RemoveAt + ); + return JUNO_STATUS_SUCCESS; +} + +#ifdef __cplusplus +} +#endif +#endif // JUNO_BUFF_QUEUE_API_H + diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index 8069f42c..a97e4733 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -26,10 +26,11 @@ */ #ifndef JUNO_BUFF_QUEUE_API_H #define JUNO_BUFF_QUEUE_API_H +#include "juno/ds/array_api.h" #include "juno/macros.h" +#include "juno/memory/memory_api.h" #include "juno/status.h" #include "juno/module.h" -#include "juno/types.h" #include #ifdef __cplusplus extern "C" @@ -42,32 +43,31 @@ typedef struct JUNO_BUFF_QUEUE_API_TAG JUNO_BUFF_QUEUE_API_T; /// The root buffee queue struct JUNO_BUFF_QUEUE_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BUFF_QUEUE_API_T, + JUNO_ARRAY_ROOT_T *ptBuffer; /// The start index of the buffer (ie the first element) size_t iStartIndex; - /// The current length of the buffer - size_t zLength; - /// The capacity of the buffer - size_t zCapacity; ); struct JUNO_BUFF_QUEUE_API_TAG { - JUNO_STATUS_T (*SetAt)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem, size_t iIndex); - JUNO_RESULT_VOID_PTR_T (*GetAt)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); - JUNO_STATUS_T (*RemoveAt)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); - JUNO_STATUS_T (*Copy)(void *ptDest, void *ptSrc); + /// Enqueue an item on the queue + JUNO_STATUS_T (*Enqueue)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, JUNO_POINTER_T tItem); + /// Dequeue an item from the queue + JUNO_STATUS_T (*Dequeue)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, JUNO_POINTER_T tReturn); + /// Peek at the next item in the queue + JUNO_RESULT_POINTER_T (*Peek)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue); }; static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) { JUNO_ASSERT_EXISTS(ptQueue); + JUNO_STATUS_T tStatus = JunoDs_ArrayVerify(ptQueue->ptBuffer); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_ASSERT_EXISTS( ptQueue->ptApi && - ptQueue->zCapacity && - ptQueue->ptApi->GetAt && - ptQueue->ptApi->SetAt && - ptQueue->ptApi->RemoveAt && - ptQueue->ptApi->Copy + ptQueue->ptApi->Enqueue && + ptQueue->ptApi->Dequeue && + ptQueue->ptApi->Peek ); return JUNO_STATUS_SUCCESS; } @@ -75,20 +75,6 @@ static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(JUNO_BUFF_QUEUE_ROOT_T *ptQu /// Initialize a buffer queue with a capacity JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); -/// Enqueue an item into the buffer -/// @returns The index to place the enqueued item -JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem); - - -/// Dequeue an item from the buffer -/// @returns The index to dequeue the item from -JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptReturn); - - -/// Peek at the next item in the queue -/// @returns the index of the next item in the queue -JUNO_RESULT_VOID_PTR_T JunoBuff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue); - #ifdef __cplusplus } #endif diff --git a/include/juno/map/map_api.h b/include/juno/ds/map_api.h similarity index 100% rename from include/juno/map/map_api.h rename to include/juno/ds/map_api.h diff --git a/include/juno/map/README.md b/include/juno/map/README.md deleted file mode 100644 index 57b50a7c..00000000 --- a/include/juno/map/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Juno Map Module (Beta) - -* This module is early in development -* The API is volatile right now and subject to frequent changes - diff --git a/include/juno/memory/README.md b/include/juno/memory/README.md index c1a783c9..b92fd4f8 100644 --- a/include/juno/memory/README.md +++ b/include/juno/memory/README.md @@ -102,7 +102,7 @@ Allocate memory for your data type: ```c // Declare a memory descriptor -JUNO_MEMORY_T tMemory = {0}; +JUNO_POINTER_T tMemory = {0}; // Allocate memory tStatus = ptApi->Get(&tMemAlloc, &tMemory, sizeof(MY_DATA_T)); @@ -123,7 +123,7 @@ Use reference counting to safely share memory: ```c // Create a reference to the memory -JUNO_MEMORY_T *ptMemoryRef = Juno_MemoryGetRef(&tMemory); +JUNO_POINTER_T *ptMemoryRef = Juno_MemoryGetRef(&tMemory); // Or using the helper macros for cleaner code JUNO_NEW_REF(memoryRef) = Juno_MemoryGetRef(&tMemory); @@ -165,7 +165,7 @@ For a more dynamic approach, you can use the Memory API interface: // Access the allocator API vtable through the union's ptApi field const JUNO_MEMORY_ALLOC_API_T *ptMemApi = tMemAlloc.ptApi; -JUNO_MEMORY_T tMemory = {0}; +JUNO_POINTER_T tMemory = {0}; JUNO_STATUS_T tStatus = ptMemApi->Get(&tMemAlloc, &tMemory, sizeof(MY_DATA_T)); // ... use the memory ... @@ -178,7 +178,7 @@ tStatus = ptMemApi->Put(&tMemAlloc, &tMemory); 1. **Not checking status codes**: Always check return values for errors. 2. **Freeing memory with active references**: This will fail with `JUNO_STATUS_REF_IN_USE_ERROR`. -3. **Not initializing memory structures**: Always initialize `JUNO_MEMORY_T` with `{}` before passing to functions. +3. **Not initializing memory structures**: Always initialize `JUNO_POINTER_T` with `{}` before passing to functions. 4. **Using the wrong size**: Always pass the correct size for your data type. ## Features @@ -210,7 +210,7 @@ Memory is allocated from a pre-defined block using the `Juno_MemoryGet` function ```c // Allocate memory -JUNO_MEMORY_T tMemory = {0}; +JUNO_POINTER_T tMemory = {0}; JUNO_STATUS_T tStatus = ptApi->Get(&tMemAlloc, &tMemory, sizeof(MY_STRUCT_T)); ``` @@ -220,7 +220,7 @@ The module provides reference counting to safely share memory between different ```c // Get a reference to existing memory -JUNO_MEMORY_T *ptMemoryRef = Juno_MemoryGetRef(&tExistingMemory); +JUNO_POINTER_T *ptMemoryRef = Juno_MemoryGetRef(&tExistingMemory); // Release a reference when done Juno_MemoryPutRef(ptMemoryRef); @@ -237,12 +237,12 @@ JUNO_STATUS_T tStatus = ptApi->Put(&tMemAlloc, &tMemory); ## Data Types -### JUNO_MEMORY_T +### JUNO_POINTER_T The fundamental structure representing an allocated memory segment: ```c -struct JUNO_MEMORY_TAG +struct JUNO_POINTER_TAG { void *pvAddr; // Pointer to the allocated memory size_t zSize; // Size of the allocated memory in bytes @@ -309,13 +309,13 @@ Initializes a memory block for allocation. Parameters: ```c // Allocate -JUNO_STATUS_T (*Get)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zSize); +JUNO_STATUS_T (*Get)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_POINTER_T *ptMemory, size_t zSize); // Resize (cannot exceed element size in block allocator) -JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zNewSize); +JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_POINTER_T *ptMemory, size_t zNewSize); // Free -JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_MEMORY_T *ptMemory); +JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_T *ptMem, JUNO_POINTER_T *ptMemory); ``` Access these through `const JUNO_MEMORY_ALLOC_API_T *ptApi = tMemAlloc.ptApi;` then @@ -324,7 +324,7 @@ call `ptApi->Get(...)`, etc. ### Reference Management ```c -JUNO_MEMORY_T* Juno_MemoryGetRef(JUNO_MEMORY_T *ptMemory); +JUNO_POINTER_T* Juno_MemoryGetRef(JUNO_POINTER_T *ptMemory); ``` Gets a reference to memory, incrementing its reference count. Parameters: @@ -332,7 +332,7 @@ Gets a reference to memory, incrementing its reference count. Parameters: - Returns: The same memory pointer with increased reference count ```c -void Juno_MemoryPutRef(JUNO_MEMORY_T *ptMemory); +void Juno_MemoryPutRef(JUNO_POINTER_T *ptMemory); ``` Releases a reference to memory, decrementing its reference count. Parameters: @@ -351,7 +351,7 @@ The following example demonstrates how to use the Juno Memory Module to implemen // Define linked list node structure typedef struct SINGLE_LINKED_LIST_NODE_TAG { struct SINGLE_LINKED_LIST_NODE_TAG *ptNext; - JUNO_MEMORY_T tMemory; + JUNO_POINTER_T tMemory; int iData; } SINGLE_LINKED_LIST_NODE_T; @@ -400,7 +400,7 @@ int main() { // Add some nodes for(int i = 0; i < 5; i++) { // Allocate memory for new node - JUNO_MEMORY_T tNodeMem = {}; + JUNO_POINTER_T tNodeMem = {}; tStatus = ptMemApi->Get(&tMemAlloc, &tNodeMem, sizeof(SINGLE_LINKED_LIST_NODE_T)); if(tStatus != JUNO_STATUS_SUCCESS) { break; @@ -495,14 +495,14 @@ The reference counting macros (`JUNO_REF` and `JUNO_NEW_REF`) can be confusing a The `JUNO_NEW_REF` macro creates a new pointer to hold a reference to a memory object: ```c -// This expands to: JUNO_MEMORY_T *REFmyMemoryRef +// This expands to: JUNO_POINTER_T *REFmyMemoryRef JUNO_NEW_REF(myMemoryRef) = Juno_MemoryGetRef(&originalMemory); ``` This is equivalent to: ```c -JUNO_MEMORY_T *REFmyMemoryRef = Juno_MemoryGetRef(&originalMemory); +JUNO_POINTER_T *REFmyMemoryRef = Juno_MemoryGetRef(&originalMemory); ``` ### JUNO_REF Macro @@ -526,7 +526,7 @@ Here's a complete example of using these macros: ```c // Original memory allocation -JUNO_MEMORY_T tMemory = {0}; +JUNO_POINTER_T tMemory = {0}; tStatus = ptApi->Get(&tMemAlloc, &tMemory, sizeof(MY_DATA_T)); // Create a named reference using the macro diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index 6eabae1a..d6bb9b01 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -26,6 +26,7 @@ */ #ifndef JUNO_MEMORY_API_H #define JUNO_MEMORY_API_H +#include "juno/macros.h" #include "juno/status.h" #include "juno/module.h" #include @@ -36,9 +37,12 @@ extern "C" /// Define a reference for memory #define JUNO_REF(name) REF##name /// Create a new reference for memory -#define JUNO_NEW_REF(name) JUNO_MEMORY_T *JUNO_REF(name) +#define JUNO_NEW_REF(name) JUNO_POINTER_T *JUNO_REF(name) -typedef struct JUNO_MEMORY_TAG JUNO_MEMORY_T; +typedef struct JUNO_POINTER_TAG JUNO_POINTER_T; +typedef struct JUNO_POINTER_API_TAG JUNO_POINTER_API_T; +typedef struct JUNO_MEMORY_ALLOC_API_TAG JUNO_MEMORY_ALLOC_API_T; +typedef struct JUNO_MEMORY_ALLOC_ROOT_TAG JUNO_MEMORY_ALLOC_ROOT_T; /// The memory metadata struct JUNO_MEMORY_BLOCK_METADATA_TAG @@ -48,21 +52,29 @@ struct JUNO_MEMORY_BLOCK_METADATA_TAG /// @brief Structure for an allocated memory segment. /// Describes the allocated memory with a pointer to the start and its size. -struct JUNO_MEMORY_TAG -{ +struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, /// Pointer to the allocated memory. void *pvAddr; /// Size of the allocated memory, in bytes. size_t zSize; - /// The reference count for this memory - size_t iRefCount; -}; +); -typedef struct JUNO_MEMORY_ALLOC_API_TAG JUNO_MEMORY_ALLOC_API_T; +#define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, NULL, NULL, addr, sizeof(type), 0} +#define JUNO_ASSERT_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type))?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR -typedef struct JUNO_MEMORY_ALLOC_ROOT_TAG JUNO_MEMORY_ALLOC_ROOT_T; +struct JUNO_POINTER_API_TAG +{ + /// Copy memory from one pointer to another + JUNO_STATUS_T (*Copy)(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc); + /// Reset the memory at the pointer. This could mean zero-initialization + JUNO_STATUS_T (*Reset)(JUNO_POINTER_T tPointer); +}; + +JUNO_MODULE_RESULT(JUNO_RESULT_POINTER_T, JUNO_POINTER_T); -struct JUNO_MEMORY_ALLOC_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MEMORY_ALLOC_API_T, JUNO_MODULE_EMPTY); +struct JUNO_MEMORY_ALLOC_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MEMORY_ALLOC_API_T, + const JUNO_POINTER_API_T *ptPointerApi; +); struct JUNO_MEMORY_ALLOC_API_TAG { @@ -72,7 +84,7 @@ struct JUNO_MEMORY_ALLOC_API_TAG /// @param pvRetAddr Pointer to a memory descriptor where allocation details will be stored. /// @param zSize Size of the memory block to allocate in bytes. /// @return JUNO_STATUS_T Status of the allocation operation. - JUNO_STATUS_T (*Get)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_MEMORY_T *pvRetAddr, size_t zSize); + JUNO_RESULT_POINTER_T (*Get)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, size_t zSize); /// @brief Updates an existing memory allocation to a new size. /// @@ -80,49 +92,63 @@ struct JUNO_MEMORY_ALLOC_API_TAG /// @param ptMemory Pointer to the memory descriptor to update. /// @param zNewSize The new size for the memory block. /// @return JUNO_STATUS_T Status of the update operation. - JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_MEMORY_T *ptMemory, size_t zNewSize); + JUNO_STATUS_T (*Update)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_POINTER_T *ptMemory, size_t zNewSize); /// @brief Frees an allocated memory block. /// /// @param ptMem Pointer to the memory allocation structure. /// @param pvAddr Pointer to the memory block to free. /// @return JUNO_STATUS_T Status of the free operation. - JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_MEMORY_T *pvAddr); + JUNO_STATUS_T (*Put)(JUNO_MEMORY_ALLOC_ROOT_T *ptMem, JUNO_POINTER_T *pvAddr); }; - -/// Get the reference to this juno memory -/// - This function will track the reference count to this memory -/// - The reference count is used to prevent freeing of used memory -/// - When using `JUNO_MEMORY_T` it is recommended to pass memory -/// around using this function to increment/decrement the reference count -/// @param ptMemory The memory to get the reference to -/// @return The reference to the memory -static inline JUNO_MEMORY_T * Juno_MemoryGetRef(JUNO_MEMORY_T *ptMemory) +static inline JUNO_STATUS_T JunoMemory_AllocApiVerify(const JUNO_MEMORY_ALLOC_API_T *ptAllocApi) { - if(ptMemory->iRefCount) - { - ptMemory->iRefCount += 1; - } - return ptMemory; + JUNO_ASSERT_EXISTS( + ptAllocApi && + ptAllocApi->Get && + ptAllocApi->Put && + ptAllocApi->Update + ); + return JUNO_STATUS_SUCCESS; } -/// Put the reference to this juno memory -/// - This function will track the reference count to this memory -/// - The reference count is used to prevent freeing of used memory -/// - When using `JUNO_MEMORY_T` it is recommended to pass memory -/// around using this function to increment /decrement the reference count -/// @param ptMemory The memory to put the reference away -/// @return The reference to the memory -static inline void Juno_MemoryPutRef(JUNO_MEMORY_T *ptMemory) +static inline JUNO_STATUS_T JunoMemory_PointerApiVerify(const JUNO_POINTER_API_T *ptPointerApi) { - if(ptMemory->iRefCount) - { - ptMemory->iRefCount -= 1; - } + JUNO_ASSERT_EXISTS( + ptPointerApi && + ptPointerApi->Copy && + ptPointerApi->Reset + ); + return JUNO_STATUS_SUCCESS; } +static inline JUNO_STATUS_T JunoMemory_AllocVerify(const JUNO_MEMORY_ALLOC_ROOT_T *ptAlloc) +{ + JUNO_ASSERT_EXISTS( + ptAlloc && + ptAlloc->ptApi && + ptAlloc->ptPointerApi + ); + JUNO_STATUS_T tStatus = JunoMemory_AllocApiVerify(ptAlloc->ptApi); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JunoMemory_PointerApiVerify(ptAlloc->ptPointerApi); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + return tStatus; +} +static inline JUNO_STATUS_T JunoMemory_PointerVerify(const JUNO_POINTER_T *ptPointer) +{ + JUNO_ASSERT_EXISTS( + ptPointer && + ptPointer->ptApi && + ptPointer->pvAddr && + ptPointer->zSize + ); + JUNO_STATUS_T tStatus = JunoMemory_PointerApiVerify(ptPointer->ptApi); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + return tStatus; +} #ifdef __cplusplus } diff --git a/include/juno/memory/memory_block.h b/include/juno/memory/memory_block.h index 7949ce3f..0b4d1699 100644 --- a/include/juno/memory/memory_block.h +++ b/include/juno/memory/memory_block.h @@ -79,7 +79,9 @@ struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MODULE_DERIVE(JUNO_MEMORY_ALLOC_ROOT_T, /// @param pfcnFailureHandler Callback function to handle failures. /// @param pvUserData User data passed to the failure handler. /// @return JUNO_STATUS_T Status of the initialization. -JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemory, +JUNO_STATUS_T JunoMemory_BlockApi( + JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemory, + const JUNO_POINTER_API_T *ptPointerApi, void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, diff --git a/include/juno/module.h b/include/juno/module.h index 9a8eda70..d0518f02 100644 --- a/include/juno/module.h +++ b/include/juno/module.h @@ -182,9 +182,21 @@ #define JUNO_MODULE_ROOT(API_T, ...) \ { \ const API_T *ptApi; \ - __VA_ARGS__ \ JUNO_FAILURE_HANDLER_T JUNO_FAILURE_HANDLER; \ JUNO_USER_DATA_T *JUNO_FAILURE_USER_DATA; \ + __VA_ARGS__ \ +} + +#define JUNO_MODULE_LITE_ROOT(API_T, ...) \ +{ \ + const API_T *ptApi; \ + __VA_ARGS__ \ +} + +#define JUNO_MODULE_API_DERIVE(API_T, ...) \ +{ \ + API_T JUNO_MODULE_SUPER; \ + __VA_ARGS__ \ } /** diff --git a/include/juno/sb/broker_api.h b/include/juno/sb/broker_api.h deleted file mode 100644 index d50ed8ae..00000000 --- a/include/juno/sb/broker_api.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - * @file include/juno/sb/broker_api.h - * @brief Juno broker API. - * - * Defines a broker interface that may work with JUNO_MSG_T messages. - * Note: This header intentionally uses a broker-specific buffer header - * type (JUNO_BROKER_BUFFER_HDR_T) to avoid conflicts with msg_api.h. - * - * @author Robin Onsay - */ -#ifndef JUNO_BROKER_API_H -#define JUNO_BROKER_API_H -#include "juno/memory/memory_api.h" -#include "juno/status.h" -#include "juno/module.h" -#include -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct JUNO_BROKER_API_TAG JUNO_BROKER_API_T; -typedef struct JUNO_BROKER_BUFFER_HDR_TAG JUNO_BROKER_BUFFER_HDR_T; - -typedef union JUNO_MSG_TAG JUNO_MSG_T; -typedef struct JUNO_MSG_ROOT_TAG JUNO_MSG_ROOT_T; - -struct JUNO_BROKER_BUFFER_HDR_TAG -{ - JUNO_BROKER_BUFFER_HDR_T *ptNext; - size_t zBufferSize; -}; - -/// Creates a new buffer -#define JunoBroker_NewBuffer(BUFFER_T, ...) {{NULL, sizeof(BUFFER_T)}, __VA_ARGS__} - -struct JUNO_MSG_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BROKER_API_T, - JUNO_MEMORY_ALLOC_T *ptAlloc; -); - -struct JUNO_BROKER_API_TAG -{ - /// Verify the message - JUNO_STATUS_T (*VerifyMsg)(JUNO_MSG_T *ptJunoMsg); - /// Get the message buffer header (out parameter) - JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, JUNO_BROKER_BUFFER_HDR_T *ptRetBuffer); - /// Set the message buffer header (by value) - JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_BROKER_BUFFER_HDR_T tBuffer); -}; - -#ifdef __cplusplus -} -#endif -#endif // JUNO_BROKER_API_H diff --git a/include/juno/sb/msg_api.h b/include/juno/sb/msg_api.h index f7809289..8ab2d138 100644 --- a/include/juno/sb/msg_api.h +++ b/include/juno/sb/msg_api.h @@ -23,51 +23,29 @@ /** * @file include/juno/sb/msg_api.h * @brief Juno message abstraction API. - * - * Provides a generic message type (JUNO_MSG_T) and buffer accessor API. The - * buffer is described by a pointer and a size. Implementations should set the - * buffer using SetBuffer and return it via GetBuffer. - * - * GetBuffer uses an out-parameter (non-const) to return the current buffer - * descriptor. SetBuffer accepts a buffer descriptor by value. - * * @author Robin Onsay */ #ifndef JUNO_MSG_API_H #define JUNO_MSG_API_H #include "juno/status.h" #include "juno/module.h" +#include "juno/ds/buff_queue_api.h" #include #ifdef __cplusplus extern "C" { #endif -typedef struct JUNO_MSG_API_TAG JUNO_MSG_API_T; -typedef struct JUNO_MSG_BUFFER_HDR_TAG JUNO_MSG_BUFFER_T; +typedef struct JUNO_MSG_QUEUE_API_TAG JUNO_MSG_QUEUE_API_T; +typedef struct JUNO_MSG_QUEUE_ROOT_TAG JUNO_MSG_QUEUE_ROOT_T; -typedef union JUNO_MSG_TAG JUNO_MSG_T; -typedef struct JUNO_MSG_ROOT_TAG JUNO_MSG_ROOT_T; - -struct JUNO_MSG_BUFFER_HDR_TAG -{ - void *pvBuffer; - size_t zBufferSize; -}; - -struct JUNO_MSG_ROOT_TAG JUNO_MODULE_ROOT(JUNO_MSG_API_T, - const JUNO_MSG_BUFFER_T *ptBuffer; +struct JUNO_MSG_QUEUE_ROOT_TAG JUNO_MODULE_DERIVE(JUNO_BUFF_QUEUE_ROOT_T, ); -struct JUNO_MSG_API_TAG -{ - /// Verify the message - JUNO_STATUS_T (*VerifyMsg)(JUNO_MSG_T *ptJunoMsg); - /// Get the message buffer (out parameter) - JUNO_STATUS_T (*GetBuffer)(JUNO_MSG_T *ptJunoMsg, JUNO_MSG_BUFFER_T *ptRetBuffer); - /// Set the message buffer (by value) - JUNO_STATUS_T (*SetBuffer)(JUNO_MSG_T *ptJunoMsg, const JUNO_MSG_BUFFER_T tBuffer); -}; +struct JUNO_MSG_QUEUE_API_TAG JUNO_MODULE_API_DERIVE(JUNO_BUFF_QUEUE_API_T, + /// Gets the unique id of this msg type + JUNO_RESULT_VOID_PTR_T (*GetMsgQueueUid)(JUNO_MSG_QUEUE_ROOT_T *ptJunoMsg); +); #ifdef __cplusplus } diff --git a/include/juno/sb/publisher_api.h b/include/juno/sb/publisher_api.h deleted file mode 100644 index 7e89c5f6..00000000 --- a/include/juno/sb/publisher_api.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_publisher library API - @author Robin Onsay -*/ -#ifndef JUNO_PUBLISHER_API_H -#define JUNO_PUBLISHER_API_H -#include "juno/sb/msg_api.h" -#include "juno/status.h" -#include "juno/module.h" -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct JUNO_PUBLISHER_API_TAG JUNO_PUBLISHER_API_T; -typedef struct JUNO_PUBLISHER_ID_TAG JUNO_PUBLISHER_ID_T; - -typedef union JUNO_PUBLISHER_TAG JUNO_PUBLISHER_T; -typedef struct JUNO_PUBLISHER_ROOT_TAG JUNO_PUBLISHER_ROOT_T; - -struct JUNO_PUBLISHER_ROOT_TAG JUNO_MODULE_ROOT(JUNO_PUBLISHER_API_T, - JUNO_PUBLISHER_ID_T *ptPublisherId; -); - -struct JUNO_PUBLISHER_API_TAG -{ - /// Publish a sb messaage - JUNO_STATUS_T (*Publish)(JUNO_PUBLISHER_T *ptJunoPublisher, const JUNO_MSG_T *ptMsg); - /// Get the publisher ID - JUNO_STATUS_T (*GetPublisherId)(JUNO_PUBLISHER_T *ptJunoPublisher, JUNO_PUBLISHER_ID_T *ptRetPublisherId); -}; - -#ifdef __cplusplus -} -#endif -#endif // JUNO_PUBLISHER_API_H diff --git a/include/juno/sb/subscriber_api.h b/include/juno/sb/subscriber_api.h deleted file mode 100644 index 1b2b9c11..00000000 --- a/include/juno/sb/subscriber_api.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - MIT License - - Copyright (c) 2025 Robin A. Onsay - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. -*/ - -/** - This API has been generated by LibJuno: - https://www.robinonsay.com/libjuno/ -*/ - -/** - This header contains the juno_subscriber library API - @author Robin Onsay -*/ -#ifndef JUNO_SUBSCRIBER_API_H -#define JUNO_SUBSCRIBER_API_H -#include "juno/memory/memory_api.h" -#include "juno/sb/msg_api.h" -#include "juno/sb/publisher_api.h" -#include "juno/status.h" -#include "juno/module.h" -#include "juno/time/time_api.h" -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef struct JUNO_SUBSCRIBER_API_TAG JUNO_SUBSCRIBER_API_T; - -typedef union JUNO_SUBSCRIBER_TAG JUNO_SUBSCRIBER_T; -typedef struct JUNO_SUBSCRIBER_ROOT_TAG JUNO_SUBSCRIBER_ROOT_T; - -struct JUNO_SUBSCRIBER_ROOT_TAG JUNO_MODULE_ROOT(JUNO_SUBSCRIBER_API_T, - JUNO_MEMORY_ALLOC_ROOT_T *ptAlloc; -); - -struct JUNO_SUBSCRIBER_API_TAG -{ - /// Subscribe to a publisher - JUNO_STATUS_T (*Subscribe)(JUNO_SUBSCRIBER_T *ptJunoSubscriber, const JUNO_PUBLISHER_ID_T *ptPublisher); - /// Recv subscribed messages - JUNO_STATUS_T (*Recv)(JUNO_SUBSCRIBER_T *ptJunoSubscriber, JUNO_MSG_T *ptMsg); - /// Try to recv subscribed messages - JUNO_STATUS_T (*TryRecv)(JUNO_SUBSCRIBER_T *ptJunoSubscriber, JUNO_MSG_T *ptMsg, JUNO_TIME_MICROS_T iTimeoutUs); -}; - -#ifdef __cplusplus -} -#endif -#endif // JUNO_SUBSCRIBER_API_H diff --git a/src/juno_map.c b/src/juno_map.c index 8e8719a9..aeac7d37 100644 --- a/src/juno_map.c +++ b/src/juno_map.c @@ -15,7 +15,7 @@ included in all copies or substantial portions of the Software. */ #include "juno/macros.h" -#include "juno/map/map_api.h" +#include "juno/ds/map_api.h" #include "juno/status.h" #include "juno/macros.h" #include diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index 2dd84030..b23235ab 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -27,6 +27,8 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory) { JUNO_ASSERT_EXISTS(ptJunoMemory); JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); + JUNO_STATUS_T tStatus = JunoMemory_AllocVerify(ptJunoMemory); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_ASSERT_EXISTS_MODULE( ptJunoMemory && ptJunoMemoryBlock->JUNO_MODULE_SUPER.ptApi && @@ -45,40 +47,41 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory) return JUNO_STATUS_SUCCESS; } -static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory, size_t zSize) +static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, size_t zSize) { + JUNO_RESULT_POINTER_T tResult = {0}; // Validate the memory block structure - JUNO_STATUS_T tStatus = Verify(ptJunoMemory); - JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tResult.tStatus = Verify(ptJunoMemory); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); JUNO_MEMORY_ALLOC_BLOCK_T *ptMemBlk = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); if(!zSize) { - tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; + tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; } - if(tStatus) + if(tResult.tStatus) { - JUNO_FAIL_MODULE(tStatus, ptMemBlk, + JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Attempted to allocate memory with size 0"); - return tStatus; + return tResult; } // Delegate to block allocation getter if(zSize > ptMemBlk->zTypeSize) { - tStatus = JUNO_STATUS_MEMALLOC_ERROR; - JUNO_FAIL_MODULE(tStatus, ptMemBlk, + tResult.tStatus = JUNO_STATUS_MEMALLOC_ERROR; + JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Invalid size for block alloc" ); - return tStatus; + return tResult; } // Check if there is room for allocation (either new or from freed list) if(!(ptMemBlk->zUsed < ptMemBlk->zLength || ptMemBlk->zFreed)) { - tStatus = JUNO_STATUS_MEMALLOC_ERROR; + tResult.tStatus = JUNO_STATUS_MEMALLOC_ERROR; // Log error through the failure handler - JUNO_FAIL_MODULE(tStatus, ptMemBlk, + JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Failed to allocate block memory. Memory is full" ); - return tStatus; + return tResult; } // If no freed block is available, allocate a new block @@ -92,16 +95,19 @@ static JUNO_STATUS_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, J // Increment the used block counter ptMemBlk->zUsed += 1; } + tResult.tOk.ptApi = ptMemBlk->tRoot.ptPointerApi; // Retrieve the latest free block and update free stack - ptMemory->pvAddr = ptMemBlk->ptMetadata[ptMemBlk->zFreed-1].ptFreeMem; - ptMemory->zSize = ptMemBlk->zTypeSize; - ptMemory->iRefCount = 1; + tResult.tOk.pvAddr = ptMemBlk->ptMetadata[ptMemBlk->zFreed-1].ptFreeMem; + tResult.tOk.zSize = ptMemBlk->zTypeSize; ptMemBlk->zFreed -= 1; ptMemBlk->ptMetadata[ptMemBlk->zFreed].ptFreeMem = NULL; - return tStatus; + tResult.tStatus = JunoMemory_PointerVerify(&tResult.tOk); + JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); + tResult.tStatus = tResult.tOk.ptApi->Reset(tResult.tOk); + return tResult; } -static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory, size_t zNewSize) +static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_POINTER_T *ptMemory, size_t zNewSize) { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); @@ -118,28 +124,18 @@ static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory return tStatus; } -static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_MEMORY_T *ptMemory) +static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, JUNO_POINTER_T *ptMemory) { // Validate the memory block structure JUNO_STATUS_T tStatus = Verify(ptJunoMemory); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JunoMemory_PointerVerify(ptMemory); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_MEMORY_ALLOC_BLOCK_T *ptMemBlk = (JUNO_MEMORY_ALLOC_BLOCK_T *)(ptJunoMemory); JUNO_ASSERT_EXISTS(ptMemory && ptMemory->pvAddr); - JUNO_MEMORY_T tMemory = *ptMemory; + JUNO_POINTER_T tMemory = *ptMemory; ptMemory->pvAddr = NULL; ptMemory->zSize = 0; - ptMemory->iRefCount = 0; - // There are still valid references to this memory, end with success - if(tMemory.iRefCount != 1) - { - tStatus = JUNO_STATUS_REF_IN_USE_ERROR; - // Log error if invalid address detected - JUNO_FAIL_MODULE(tStatus, ptMemBlk, - "Failed to free block memory. Memory in use" - ); - *ptMemory = tMemory; - return tStatus; - } // Calculate start and end addresses for the memory block area void *pvStartAddr = ptMemBlk->pvMemory; void *pvEndAddr = &ptMemBlk->pvMemory[ptMemBlk->zTypeSize * ptMemBlk->zLength]; @@ -170,13 +166,8 @@ static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, J return tStatus; } } - - // Clear the block memory - for(size_t i = 0; i < ptMemBlk->zTypeSize; i++) - { - uint8_t *piAddr = (uint8_t *)(tMemory.pvAddr); - piAddr[i] = 0; - } + tStatus = tMemory.ptApi->Reset(tMemory); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); // Check if the block being freed is the last allocated block void *pvEndOfBlk = &ptMemBlk->pvMemory[(ptMemBlk->zUsed - 1) * ptMemBlk->zTypeSize]; if(pvEndOfBlk == tMemory.pvAddr) @@ -194,7 +185,6 @@ static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, J return tStatus; } - static const JUNO_MEMORY_ALLOC_API_T tJunoMemoryBlockApi = { .Get = Juno_MemoryBlkGet, .Update = Juno_MemoryBlkUpdate, @@ -202,7 +192,9 @@ static const JUNO_MEMORY_ALLOC_API_T tJunoMemoryBlockApi = { }; /* TODO: Insert initialization arguments for module members here*/ -JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock, +JUNO_STATUS_T JunoMemory_BlockApi( + JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock, + const JUNO_POINTER_API_T *ptPointerApi, void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, @@ -215,6 +207,7 @@ JUNO_STATUS_T JunoMemory_BlockApi(JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock, ptJunoMemoryBlock->JUNO_MODULE_SUPER.ptApi = &tJunoMemoryBlockApi; ptJunoMemoryBlock->JUNO_MODULE_SUPER.JUNO_FAILURE_HANDLER = pfcnFailureHandler; ptJunoMemoryBlock->JUNO_MODULE_SUPER.JUNO_FAILURE_USER_DATA = pvFailureUserData; + ptJunoMemoryBlock->tRoot.ptPointerApi = ptPointerApi; // Initialize memory area and free stack pointer ptJunoMemoryBlock->pvMemory = (uint8_t *) pvMemory; ptJunoMemoryBlock->ptMetadata = ptMetadata; diff --git a/tests/test_cpp.cpp b/tests/test_cpp.cpp index aa8c1c2c..645fab28 100644 --- a/tests/test_cpp.cpp +++ b/tests/test_cpp.cpp @@ -7,13 +7,11 @@ #include "juno/io/i2c_io_api.h" #include "juno/io/spi_io_api.h" #include "juno/log/log_api.h" -#include "juno/map/map_api.h" +#include "juno/ds/map_api.h" #include "juno/math/juno_math.h" #include "juno/memory/memory_api.h" #include "juno/time/time_api.h" #include "juno/sb/msg_api.h" -#include "juno/sb/publisher_api.h" -#include "juno/sb/subscriber_api.h" #include "juno/sm/sm_api.h" int main() diff --git a/tests/test_map.c b/tests/test_map.c index f96e243d..6fe43993 100644 --- a/tests/test_map.c +++ b/tests/test_map.c @@ -2,7 +2,7 @@ #include #include #include -#include "juno/map/map_api.h" +#include "juno/ds/map_api.h" #ifndef TEST_MAP_CAPACITY #define TEST_MAP_CAPACITY 16 diff --git a/tests/test_memory.c b/tests/test_memory.c index 06e798fa..f3e046ce 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -1,3 +1,4 @@ +#include "juno/macros.h" #include "juno/memory/memory_api.h" #define JUNO_MEMORY_DEFAULT #include "juno/memory/memory_block.h" @@ -18,6 +19,33 @@ typedef struct TEST_BLOCK_TAG JUNO_MEMORY_BLOCK(ptTestBlock, TEST_BLOCK_T, 10); JUNO_MEMORY_BLOCK_METADATA(ptTestMetadata, 10); +/// Copy memory from one pointer to another +static JUNO_STATUS_T Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) +{ + JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tDest, TEST_BLOCK_T); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JUNO_ASSERT_POINTER_TYPE(tSrc, TEST_BLOCK_T); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + TEST_BLOCK_T *ptDest = (TEST_BLOCK_T *)tDest.pvAddr; + TEST_BLOCK_T *ptSrc = (TEST_BLOCK_T *)tSrc.pvAddr; + *ptDest = *ptSrc; + return tStatus; +} + +/// Reset the memory at the pointer. This could mean zero-initialization +static JUNO_STATUS_T Reset(JUNO_POINTER_T tPointer) +{ + JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tPointer, TEST_BLOCK_T); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + TEST_BLOCK_T *ptBlock = (TEST_BLOCK_T *)tPointer.pvAddr; + *ptBlock = (TEST_BLOCK_T){0}; + return tStatus; +} + +const JUNO_POINTER_API_T gtTestBlockApi = { + Copy, + Reset +}; void setUp(void) { @@ -35,6 +63,7 @@ static void test_nominal_single_alloc_and_free(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -43,55 +72,28 @@ static void test_nominal_single_alloc_and_free(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - JUNO_MEMORY_T tMemory = {0}; + JUNO_POINTER_T tMemory = {0}; const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + tMemory = tPointerResult.tOk; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(1, tMemory.iRefCount); tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(tMemory.pvAddr); TEST_ASSERT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(0, tMemory.iRefCount); - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); + tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + tMemory = tPointerResult.tOk; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(1, tMemory.iRefCount); - JUNO_NEW_REF(tMemory) = Juno_MemoryGetRef(&tMemory); - TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(2, tMemory.iRefCount); - TEST_ASSERT_NOT_NULL(JUNO_REF(tMemory)->pvAddr); - TEST_ASSERT_NOT_EQUAL(0, JUNO_REF(tMemory)->pvAddr); - TEST_ASSERT_EQUAL(2, JUNO_REF(tMemory)->iRefCount); - tStatus = ptApi->Put(&tMem.tRoot, JUNO_REF(tMemory)); - TEST_ASSERT_EQUAL(JUNO_STATUS_REF_IN_USE_ERROR, tStatus); - TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(2, tMemory.iRefCount); - JUNO_REF(tMemory) = Juno_MemoryGetRef(&tMemory); - TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(3, tMemory.iRefCount); - TEST_ASSERT_NOT_NULL(JUNO_REF(tMemory)->pvAddr); - TEST_ASSERT_NOT_EQUAL(0, JUNO_REF(tMemory)->pvAddr); - TEST_ASSERT_EQUAL(3, JUNO_REF(tMemory)->iRefCount); - Juno_MemoryPutRef(JUNO_REF(tMemory)); - TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(2, tMemory.iRefCount); - Juno_MemoryPutRef(JUNO_REF(tMemory)); - TEST_ASSERT_NOT_NULL(tMemory.pvAddr); - TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(1, tMemory.iRefCount); tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NULL(tMemory.pvAddr); TEST_ASSERT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(0, tMemory.iRefCount); } static void test_nominal_multiple_alloc_and_free(void) @@ -99,6 +101,7 @@ static void test_nominal_multiple_alloc_and_free(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -109,12 +112,14 @@ static void test_nominal_multiple_alloc_and_free(void) TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; TEST_BLOCK_T *ptTestPtr[10] = {0}; - JUNO_MEMORY_T ptMemory[10] = {0}; + JUNO_POINTER_T ptMemory[10] = {0}; for (int j = 0; j < 5; j++) { for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + ptMemory[i] = tPointerResult.tOk; ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -132,7 +137,9 @@ static void test_nominal_multiple_alloc_and_free(void) } for (size_t i = 0; i < 5; i++) { - tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + ptMemory[i] = tPointerResult.tOk; ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -154,6 +161,7 @@ static void test_negative_memory_empty(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -163,17 +171,19 @@ static void test_negative_memory_empty(void) ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - JUNO_MEMORY_T tFailMemory = { + JUNO_POINTER_T tFailMemory = { .pvAddr = ptTestBlock, .zSize = 128 }; tStatus = ptApi->Put(&tMem.tRoot, &tFailMemory); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_BLOCK_T *ptTestPtr[10] = {0}; - JUNO_MEMORY_T ptMemory[10] = {0}; + JUNO_POINTER_T ptMemory[10] = {0}; for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + ptMemory[i] = tPointerResult.tOk; ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -198,6 +208,7 @@ static void test_negative_memory_full(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -208,10 +219,12 @@ static void test_negative_memory_full(void) TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; TEST_BLOCK_T *ptTestPtr[10] = {0}; - JUNO_MEMORY_T ptMemory[10] = {0}; + JUNO_POINTER_T ptMemory[10] = {0}; for (size_t i = 0; i < 10; i++) { - tStatus = ptApi->Get(&tMem.tRoot, &ptMemory[i], sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + ptMemory[i] = tPointerResult.tOk; ptTestPtr[i] = ptMemory[i].pvAddr; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(ptMemory[i].pvAddr); @@ -219,8 +232,8 @@ static void test_negative_memory_full(void) ptTestPtr[i]->bTestFlag = true; ptTestPtr[i]->iTestNum = i; } - JUNO_MEMORY_T tFailMemory = {0}; - tStatus = ptApi->Get(&tMem.tRoot, &tFailMemory, sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; TEST_ASSERT_EQUAL(JUNO_STATUS_MEMALLOC_ERROR, tStatus); } @@ -233,6 +246,7 @@ static void test_invalid_init_parameters(void) &tMem, NULL, NULL, + NULL, sizeof(TEST_BLOCK_T), 10, NULL, @@ -246,6 +260,7 @@ static void test_double_free(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -255,8 +270,10 @@ static void test_double_free(void) ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); + JUNO_POINTER_T tMemory = {0}; + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + tMemory = tPointerResult.tOk; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); tStatus = ptApi->Put(&tMem.tRoot, &tMemory); @@ -270,6 +287,7 @@ static void test_free_unallocated(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -279,7 +297,7 @@ static void test_free_unallocated(void) ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - JUNO_MEMORY_T tMemory = {0}; + JUNO_POINTER_T tMemory = {0}; tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } @@ -289,6 +307,7 @@ static void test_update_memory(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -299,8 +318,10 @@ static void test_update_memory(void) TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); + JUNO_POINTER_T tMemory = {0}; + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + tMemory = tPointerResult.tOk; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); tStatus = ptApi->Update(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); @@ -317,6 +338,7 @@ static void test_generic_memory_get_put(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -328,9 +350,11 @@ static void test_generic_memory_get_put(void) const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; JUNO_MEMORY_ALLOC_ROOT_T *ptAlloc = &tMem.tRoot; - JUNO_MEMORY_T tMemory = {0}; + JUNO_POINTER_T tMemory = {0}; - tStatus = ptApi->Get(ptAlloc, &tMemory, sizeof(TEST_BLOCK_T)); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(ptAlloc, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; + tMemory = tPointerResult.tOk; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); TEST_ASSERT_NOT_NULL(tMemory.pvAddr); tStatus = ptApi->Update(ptAlloc, &tMemory, sizeof(TEST_BLOCK_T)); @@ -345,6 +369,7 @@ static void test_zero_size_allocation(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -355,8 +380,8 @@ static void test_zero_size_allocation(void) TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, 0); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, 0); + tStatus = tPointerResult.tStatus; TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } static void test_bad_api(void) @@ -364,6 +389,7 @@ static void test_bad_api(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -375,15 +401,19 @@ static void test_bad_api(void) const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; tMem.tRoot.ptApi = NULL; - JUNO_MEMORY_T tMemory = {0}; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, 0); + JUNO_POINTER_T tMemory = {0}; + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, 0); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tPointerResult.tStatus); tStatus = ptApi->Put(&tMem.tRoot, &tMemory); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); tStatus = ptApi->Update(&tMem.tRoot, &tMemory, 0); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); tMem.tRoot.ptApi = &ptApi[1]; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, 0); + tPointerResult = ptApi->Get(&tMem.tRoot, 0); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tPointerResult.tStatus); tStatus = ptApi->Put(&tMem.tRoot, &tMemory); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); tStatus = ptApi->Update(&tMem.tRoot, &tMemory, 0); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } @@ -393,6 +423,7 @@ static void test_invalid_size_and_addr(void) JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; JUNO_STATUS_T tStatus = JunoMemory_BlockApi( &tMem, + >TestBlockApi, ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), @@ -401,18 +432,22 @@ static void test_invalid_size_and_addr(void) NULL ); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - JUNO_MEMORY_T tMemory = {0}; + JUNO_POINTER_T tMemory = {0}; const JUNO_MEMORY_ALLOC_API_T *ptApi = tMem.tRoot.ptApi; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)+1); + JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)+1); + tStatus = tPointerResult.tStatus; TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); + tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - JUNO_MEMORY_T tMemory2 = {0}; - tStatus = ptApi->Get(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T)); + tMemory = tPointerResult.tOk; + JUNO_POINTER_T tMemory2 = {0}; + tPointerResult = ptApi->Get(&tMem.tRoot, sizeof(TEST_BLOCK_T)); + tStatus = tPointerResult.tStatus; TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + tMemory = tPointerResult.tOk; TEST_ASSERT_NOT_NULL(tMemory.pvAddr); TEST_ASSERT_NOT_EQUAL(0, tMemory.pvAddr); - TEST_ASSERT_EQUAL(1, tMemory.iRefCount); tMemory2 = tMemory; tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); From 84ae751a8aec6bca3379109bd678646ffd22890d Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 09:13:18 -0500 Subject: [PATCH 20/34] :sparkles: Fix unit tests --- include/juno/ds/array_api.h | 29 +++- include/juno/ds/buff_queue_api.h | 23 +-- include/juno/memory/memory_api.h | 2 +- src/juno_buff_queue.c | 85 +++++----- src/juno_memory_block.c | 1 + tests/test_buff.c | 269 ------------------------------- tests/test_memory.c | 1 - tests/test_queue.c | 213 ++++++++++++++++++++++++ tests/test_stack.c | 121 ++++++++++++++ 9 files changed, 421 insertions(+), 323 deletions(-) delete mode 100644 tests/test_buff.c create mode 100644 tests/test_queue.c create mode 100644 tests/test_stack.c diff --git a/include/juno/ds/array_api.h b/include/juno/ds/array_api.h index 26226977..aba6f640 100644 --- a/include/juno/ds/array_api.h +++ b/include/juno/ds/array_api.h @@ -43,8 +43,11 @@ typedef struct JUNO_ARRAY_API_TAG JUNO_ARRAY_API_T; /// The root buffee queue struct JUNO_ARRAY_ROOT_TAG JUNO_MODULE_ROOT(JUNO_ARRAY_API_T, + /// The pointer api for this array + const JUNO_POINTER_API_T *ptPointerApi; /// The current length of the buffer size_t zLength; + /// The capacity of this array size_t zCapacity; ); @@ -55,18 +58,30 @@ struct JUNO_ARRAY_API_TAG JUNO_STATUS_T (*RemoveAt)(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex); }; -static inline JUNO_STATUS_T JunoDs_ArrayVerify(JUNO_ARRAY_ROOT_T *ptArray) +static inline JUNO_STATUS_T JunoDs_ArrayApiVerify(const JUNO_ARRAY_API_T *ptArrayApi) { - JUNO_ASSERT_EXISTS(ptArray); + JUNO_ASSERT_EXISTS(ptArrayApi); JUNO_ASSERT_EXISTS( - ptArray->ptApi && - ptArray->zCapacity && - ptArray->ptApi->GetAt && - ptArray->ptApi->SetAt && - ptArray->ptApi->RemoveAt + ptArrayApi && + ptArrayApi->GetAt && + ptArrayApi->SetAt && + ptArrayApi->RemoveAt ); return JUNO_STATUS_SUCCESS; } +static inline JUNO_STATUS_T JunoDs_ArrayVerify(const JUNO_ARRAY_ROOT_T *ptArray) +{ + JUNO_ASSERT_EXISTS(ptArray); + JUNO_ASSERT_EXISTS( + ptArray->zCapacity && + ptArray->ptPointerApi + ); + JUNO_STATUS_T tStatus = JunoDs_ArrayApiVerify(ptArray->ptApi); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JunoMemory_PointerApiVerify(ptArray->ptPointerApi); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + return tStatus; +} #ifdef __cplusplus } diff --git a/include/juno/ds/buff_queue_api.h b/include/juno/ds/buff_queue_api.h index a97e4733..5f1178ba 100644 --- a/include/juno/ds/buff_queue_api.h +++ b/include/juno/ds/buff_queue_api.h @@ -58,22 +58,27 @@ struct JUNO_BUFF_QUEUE_API_TAG JUNO_RESULT_POINTER_T (*Peek)(JUNO_BUFF_QUEUE_ROOT_T *ptQueue); }; -static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) +static inline JUNO_STATUS_T JunoDs_Buff_QueueApiVerify(const JUNO_BUFF_QUEUE_API_T *ptQueueApi) +{ + JUNO_ASSERT_EXISTS( + ptQueueApi && + ptQueueApi->Enqueue && + ptQueueApi->Dequeue && + ptQueueApi->Peek + ); + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T JunoDs_Buff_QueueVerify(const JUNO_BUFF_QUEUE_ROOT_T *ptQueue) { JUNO_ASSERT_EXISTS(ptQueue); JUNO_STATUS_T tStatus = JunoDs_ArrayVerify(ptQueue->ptBuffer); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - JUNO_ASSERT_EXISTS( - ptQueue->ptApi && - ptQueue->ptApi->Enqueue && - ptQueue->ptApi->Dequeue && - ptQueue->ptApi->Peek - ); - return JUNO_STATUS_SUCCESS; + return JunoDs_Buff_QueueApiVerify(ptQueue->ptApi); } /// Initialize a buffer queue with a capacity -JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); +JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, JUNO_ARRAY_ROOT_T *ptBuffer, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); #ifdef __cplusplus } diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index d6bb9b01..ce472c5d 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -59,7 +59,7 @@ struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, size_t zSize; ); -#define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, NULL, NULL, addr, sizeof(type), 0} +#define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type)} #define JUNO_ASSERT_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type))?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR struct JUNO_POINTER_API_TAG diff --git a/src/juno_buff_queue.c b/src/juno_buff_queue.c index 4d72d727..7d0732aa 100644 --- a/src/juno_buff_queue.c +++ b/src/juno_buff_queue.c @@ -1,30 +1,23 @@ +#include "juno/ds/array_api.h" #include "juno/ds/buff_queue_api.h" +#include "juno/macros.h" +#include "juno/memory/memory_api.h" -/// Initialize a buffer queue with a capacity -JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, const JUNO_BUFF_QUEUE_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) -{ - JUNO_ASSERT_EXISTS(ptQueue); - ptQueue->ptApi = ptApi; - ptQueue->iStartIndex = 0; - ptQueue->zLength = 0; - ptQueue->zCapacity = zCapacity; - ptQueue->_pfcnFailureHandler = pfcnFailureHdlr; - ptQueue->_pvFailureUserData = pvFailureUserData; - return JunoDs_Buff_QueueVerify(ptQueue); -} - -/// Enqueue an item into the buffer -/// @returns The index to place the enqueued item -JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem) +/// Enqueue an item on the queue +static JUNO_STATUS_T JunoEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, JUNO_POINTER_T tItem) { JUNO_ASSERT_EXISTS(ptQueue); JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); - if(ptQueue->zLength < ptQueue->zCapacity) + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JunoMemory_PointerVerify(&tItem); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ARRAY_ROOT_T *ptBuffer = ptQueue->ptBuffer; + if(ptBuffer->zLength < ptBuffer->zCapacity) { - size_t iIndex = (ptQueue->iStartIndex + ptQueue->zLength) % ptQueue->zCapacity; - tStatus = ptQueue->ptApi->SetAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, ptItem, iIndex); + size_t iIndex = (ptQueue->iStartIndex + ptBuffer->zLength) % ptBuffer->zCapacity; + tStatus = ptBuffer->ptApi->SetAt(ptBuffer, tItem, iIndex); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptQueue->zLength += 1; + ptBuffer->zLength += 1; } else { @@ -35,25 +28,26 @@ JUNO_STATUS_T JunoDs_Buff_QueueEnqueue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *pt return tStatus; } -/// Dequeue an item from the buffer -/// @returns The index to dequeue the item from -JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptReturn) +/// Dequeue an item from the queue +static JUNO_STATUS_T JunoDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, JUNO_POINTER_T tReturn) { JUNO_STATUS_T tStatus = JunoDs_Buff_QueueVerify(ptQueue); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - JUNO_ASSERT_EXISTS(ptReturn); - if(ptQueue->zLength > 0) + tStatus = JunoMemory_PointerVerify(&tReturn); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + JUNO_ARRAY_ROOT_T *ptBuffer = ptQueue->ptBuffer; + if(ptBuffer->zLength > 0) { - const JUNO_BUFF_QUEUE_API_T *ptApi = ptQueue->ptApi; + const JUNO_ARRAY_API_T *ptApi = ptBuffer->ptApi; size_t iDequeueIndex = ptQueue->iStartIndex; - JUNO_RESULT_VOID_PTR_T tPtrResult = ptApi->GetAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, iDequeueIndex); + JUNO_RESULT_POINTER_T tPtrResult = ptApi->GetAt(ptBuffer, iDequeueIndex); JUNO_ASSERT_SUCCESS(tPtrResult.tStatus, return tPtrResult.tStatus); - tStatus = ptApi->Copy(ptReturn, JUNO_OK(tPtrResult)); + tStatus = tPtrResult.tOk.ptApi->Copy(tReturn, JUNO_OK(tPtrResult)); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - tStatus = ptApi->RemoveAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, iDequeueIndex); + tStatus = ptApi->RemoveAt(ptBuffer, iDequeueIndex); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptQueue->iStartIndex = (ptQueue->iStartIndex + 1) % ptQueue->zCapacity; - ptQueue->zLength -= 1; + ptQueue->iStartIndex = (ptQueue->iStartIndex + 1) % ptBuffer->zCapacity; + ptBuffer->zLength -= 1; return tStatus; } tStatus = JUNO_STATUS_ERR; @@ -62,18 +56,37 @@ JUNO_STATUS_T JunoDs_Buff_QueueDequeue(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *pt } /// Peek at the next item in the queue -/// @returns the index of the next item in the queue -JUNO_RESULT_VOID_PTR_T JunoDs_Buff_QueuePeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) +static JUNO_RESULT_POINTER_T JunoPeek(JUNO_BUFF_QUEUE_ROOT_T *ptQueue) { - JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); + JUNO_RESULT_POINTER_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, {0}); tResult.tStatus = JunoDs_Buff_QueueVerify(ptQueue); JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); - if(ptQueue->zLength == 0) + JUNO_ARRAY_ROOT_T *ptBuffer = ptQueue->ptBuffer; + if(ptBuffer->zLength == 0) { tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; JUNO_FAIL(tResult.tStatus, ptQueue->_pfcnFailureHandler, ptQueue->_pvFailureUserData, "Queue is empty"); return tResult; } - tResult = ptQueue->ptApi->GetAt((JUNO_BUFF_QUEUE_ROOT_T *) ptQueue, ptQueue->iStartIndex); + tResult = ptBuffer->ptApi->GetAt(ptBuffer, ptQueue->iStartIndex); return tResult; } + +static const JUNO_BUFF_QUEUE_API_T gtBuffQueueApi = +{ + JunoEnqueue, + JunoDequeue, + JunoPeek +}; + +/// Initialize a buffer queue with a capacity +JUNO_STATUS_T JunoDs_Buff_QueueInit(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, JUNO_ARRAY_ROOT_T *ptBuffer, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +{ + JUNO_ASSERT_EXISTS(ptQueue); + ptQueue->ptApi = >BuffQueueApi; + ptQueue->iStartIndex = 0; + ptQueue->ptBuffer = ptBuffer; + ptQueue->_pfcnFailureHandler = pfcnFailureHdlr; + ptQueue->_pvFailureUserData = pvFailureUserData; + return JunoDs_Buff_QueueVerify(ptQueue); +} diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index b23235ab..eeeb1112 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -119,6 +119,7 @@ static JUNO_STATUS_T Juno_MemoryBlkUpdate(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory JUNO_FAIL_MODULE(tStatus, ptMem, "Failed to update memory, size is too big" ); + return tStatus; } ptMemory->zSize = zNewSize; return tStatus; diff --git a/tests/test_buff.c b/tests/test_buff.c deleted file mode 100644 index 25aeedf8..00000000 --- a/tests/test_buff.c +++ /dev/null @@ -1,269 +0,0 @@ -#include "juno/module.h" -#include "juno/status.h" -#include "unity.h" -#include "unity_internals.h" -#include "juno/ds/buff_queue_api.h" -#include "juno/ds/buff_stack_api.h" -#include -#include -#include - - -void setUp(void) -{ - -} -void tearDown(void) -{ - -} - -typedef struct TEST_QUEUE JUNO_MODULE_DERIVE(JUNO_BUFF_QUEUE_ROOT_T, - uint8_t iTestQueue[10]; -) TEST_QUEUE; - - -static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem, size_t iIndex); -static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); -static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex); -static inline JUNO_STATUS_T Queue_Copy(void *ptDest, void *ptSrc); - -const JUNO_BUFF_QUEUE_API_T gtQueueApi = { - Queue_SetAt, - Queue_GetAt, - Queue_RemoveAt, - Queue_Copy -}; - -union JUNO_BUFF_QUEUE_ROOT_T JUNO_MODULE(void, JUNO_BUFF_QUEUE_ROOT_T, - TEST_QUEUE tTestQueue; -); - -typedef struct TEST_STACK JUNO_MODULE_DERIVE(JUNO_BUFF_STACK_ROOT_T, - uint8_t iTestStack[10]; -) TEST_STACK; - -static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex); -static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); -static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); -static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc); - -const JUNO_BUFF_STACK_API_T gtStackApi = { - Stack_SetAt, - Stack_GetAt, - Stack_RemoveAt, - Stack_Copy -}; - -union JUNO_BUFF_STACK_ROOT_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, - TEST_STACK tTestStack; -); - -static void test_queue(void) -{ - TEST_QUEUE tTestQueue = {0}; - JUNO_STATUS_T tStatus = JunoDs_Buff_QueueInit(&tTestQueue.tRoot, >QueueApi, 10, NULL, NULL); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_QUEUE tQueue = tTestQueue; - uint8_t iValue = 0; - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(i+1, iValue); - } - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(i+1, iValue); - } - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(i+1, iValue); - } - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(i+1, iValue); - } - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - memset(&tTestQueue.iTestQueue, 0, sizeof(tTestQueue.iTestQueue)); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue)/2; i++) - { - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue)/2; i++) - { - iValue = i + 1 + sizeof(tTestQueue.iTestQueue)/2; - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - tStatus = JunoDs_Buff_QueueEnqueue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestQueue.iTestQueue); i++) - { - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - uint8_t iTruth = (i % (sizeof(tTestQueue.iTestQueue)/2)) + 1 + sizeof(tTestQueue.iTestQueue)/2; - TEST_ASSERT_EQUAL(iTruth, iValue); - } - tStatus = JunoDs_Buff_QueueDequeue(&tQueue.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); -} - -static void test_stack(void) -{ - TEST_STACK tTestStack = (TEST_STACK){0}; - JUNO_STATUS_T tStatus = JunoDs_Buff_StackInit(&tTestStack.tRoot, >StackApi, 10, NULL, NULL); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_STACK tStack = tTestStack; - uint8_t iValue = 0; - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) - { - iValue = 0; - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); - } - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) - { - iValue = i + 1; - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - } - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) - { - iValue = 0; - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); - TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); - } - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); - TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); -} - -int main(void) -{ - UNITY_BEGIN(); - RUN_TEST(test_queue); - RUN_TEST(test_stack); - return UNITY_END(); -} - -static inline JUNO_STATUS_T Queue_SetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, void *ptItem, size_t iIndex) -{ - uint8_t *iItem = (void *) ptItem; - TEST_QUEUE *ptTestQueue = (TEST_QUEUE *) ptQueue; - ptTestQueue->iTestQueue[iIndex] = *iItem; - return JUNO_STATUS_SUCCESS; -} - -static inline JUNO_RESULT_VOID_PTR_T Queue_GetAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex) -{ - TEST_QUEUE *ptTestQueue = (TEST_QUEUE *) ptQueue; - JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptTestQueue->iTestQueue[iIndex]); - return tResult; -} - -static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_BUFF_QUEUE_ROOT_T *ptQueue, size_t iIndex) -{ - TEST_QUEUE *ptTestQueue = (TEST_QUEUE *) ptQueue; - ptTestQueue->iTestQueue[iIndex] = 0; - return JUNO_STATUS_SUCCESS; -} - -static inline JUNO_STATUS_T Queue_Copy(void *ptDest, void *ptSrc) -{ - uint8_t *iDest = (void *) ptDest; - uint8_t *iSrc= (void *) ptSrc; - *iDest = *iSrc; - return JUNO_STATUS_SUCCESS; -} - -static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex) -{ - uint8_t *iItem = (void *) ptItem; - TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; - ptTestStack->iTestStack[iIndex] = *iItem; - return JUNO_STATUS_SUCCESS; -} - -static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) -{ - TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; - JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptTestStack->iTestStack[iIndex]); - return tResult; -} - -static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) -{ - TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; - ptTestStack->iTestStack[iIndex] = 0; - return JUNO_STATUS_SUCCESS; -} - -static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc) -{ - uint8_t *iDest = (void *) ptDest; - uint8_t *iSrc= (void *) ptSrc; - *iDest = *iSrc; - return JUNO_STATUS_SUCCESS; -} - diff --git a/tests/test_memory.c b/tests/test_memory.c index f3e046ce..7a524c42 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -328,7 +328,6 @@ static void test_update_memory(void) TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); tStatus = ptApi->Update(&tMem.tRoot, &tMemory, sizeof(TEST_BLOCK_T) + 1); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - tStatus = ptApi->Put(&tMem.tRoot, &tMemory); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } diff --git a/tests/test_queue.c b/tests/test_queue.c new file mode 100644 index 00000000..933440c9 --- /dev/null +++ b/tests/test_queue.c @@ -0,0 +1,213 @@ +#include "juno/memory/memory_api.h" +#include "juno/module.h" +#include "juno/status.h" +#include "unity.h" +#include "unity_internals.h" +#include "juno/ds/buff_queue_api.h" +#include "juno/ds/buff_stack_api.h" +#include +#include +#include + + +void setUp(void) +{ + +} +void tearDown(void) +{ + +} + + + +typedef struct TEST_ARRAY JUNO_MODULE_DERIVE(JUNO_ARRAY_ROOT_T, + uint8_t iTestQueue[10]; +) TEST_ARRAY; + + +static inline JUNO_STATUS_T Queue_SetAt(JUNO_ARRAY_ROOT_T *ptQueue, JUNO_POINTER_T tItem, size_t iIndex); +static inline JUNO_RESULT_POINTER_T Queue_GetAt(JUNO_ARRAY_ROOT_T *ptQueue, size_t iIndex); +static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_ARRAY_ROOT_T *ptQueue, size_t iIndex); +static inline JUNO_STATUS_T Queue_Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc); +static inline JUNO_STATUS_T Queue_Reset(JUNO_POINTER_T tDest); + +const JUNO_ARRAY_API_T gtQueueApi = { + Queue_SetAt, + Queue_GetAt, + Queue_RemoveAt, +}; + +const JUNO_POINTER_API_T gtPointerApi = { + .Copy = Queue_Copy, + .Reset = Queue_Reset, +}; + +union JUNO_ARRAY_ROOT_T JUNO_MODULE(void, JUNO_ARRAY_ROOT_T, + TEST_ARRAY tTestQueue; +); + +static void test_queue(void) +{ + // Prepare the backing array (buffer) + TEST_ARRAY tBuffer = (TEST_ARRAY){0}; + JUNO_ARRAY_ROOT_T *ptArray = (JUNO_ARRAY_ROOT_T *)&tBuffer; + + // Initialize the array root fields + ptArray->ptApi = >QueueApi; + ptArray->ptPointerApi = >PointerApi; + ptArray->zCapacity = sizeof(tBuffer.iTestQueue); + ptArray->zLength = 0; + + // Initialize the queue with the backing array + JUNO_BUFF_QUEUE_ROOT_T tQueue = (JUNO_BUFF_QUEUE_ROOT_T){0}; + JUNO_STATUS_T tStatus = JunoDs_Buff_QueueInit(&tQueue, ptArray, NULL, NULL); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + uint8_t iValue = 0; + JUNO_POINTER_T tValPtr = Juno_PointerInit(>PointerApi, uint8_t, &iValue); + + // Fill the queue + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + iValue = (uint8_t)(i + 1); + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + // One too many + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + + // Drain the queue + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i + 1, iValue); + } + // One too many + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + + // Fill and drain again + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + iValue = (uint8_t)(i + 1); + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i + 1, iValue); + } + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + + // Interleave enqueue/dequeue + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + iValue = (uint8_t)(i + 1); + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i + 1, iValue); + } + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + + // Fill, half-drain, wrap-around, then drain all + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + iValue = (uint8_t)(i + 1); + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(i + 1, iValue); + } + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + memset(&tBuffer.iTestQueue, 0, sizeof(tBuffer.iTestQueue)); + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + iValue = (uint8_t)(i + 1); + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue) / 2; i++) + { + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue) / 2; i++) + { + iValue = (uint8_t)(i + 1 + sizeof(tBuffer.iTestQueue) / 2); + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + tStatus = tQueue.ptApi->Enqueue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for (size_t i = 0; i < sizeof(tBuffer.iTestQueue); i++) + { + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + uint8_t iTruth = (uint8_t)((i % (sizeof(tBuffer.iTestQueue) / 2)) + 1 + sizeof(tBuffer.iTestQueue) / 2); + TEST_ASSERT_EQUAL(iTruth, iValue); + } + tStatus = tQueue.ptApi->Dequeue(&tQueue, tValPtr); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_queue); + return UNITY_END(); +} + +static inline JUNO_STATUS_T Queue_SetAt(JUNO_ARRAY_ROOT_T *ptQueue, JUNO_POINTER_T tItem, size_t iIndex) +{ + uint8_t *iItem = (void *) tItem.pvAddr; + TEST_ARRAY *ptTestQueue = (TEST_ARRAY *) ptQueue; + ptTestQueue->iTestQueue[iIndex] = *iItem; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_RESULT_POINTER_T Queue_GetAt(JUNO_ARRAY_ROOT_T *ptQueue, size_t iIndex) +{ + TEST_ARRAY *ptTestQueue = (TEST_ARRAY *) ptQueue; + JUNO_RESULT_POINTER_T tResult = JUNO_OK_RESULT(Juno_PointerInit(>PointerApi, uint8_t, &ptTestQueue->iTestQueue[iIndex])); + return tResult; +} + +static inline JUNO_STATUS_T Queue_RemoveAt(JUNO_ARRAY_ROOT_T *ptQueue, size_t iIndex) +{ + TEST_ARRAY *ptTestQueue = (TEST_ARRAY *) ptQueue; + ptTestQueue->iTestQueue[iIndex] = 0; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T Queue_Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) +{ + uint8_t *iDest = (uint8_t *) tDest.pvAddr; + uint8_t *iSrc = (uint8_t *) tSrc.pvAddr; + *iDest = *iSrc; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T Queue_Reset(JUNO_POINTER_T tDest) +{ + uint8_t *iDest = (uint8_t *) tDest.pvAddr; + *iDest = 0; + return JUNO_STATUS_SUCCESS; +} + diff --git a/tests/test_stack.c b/tests/test_stack.c new file mode 100644 index 00000000..dbf9e9e9 --- /dev/null +++ b/tests/test_stack.c @@ -0,0 +1,121 @@ +#include "juno/module.h" +#include "juno/status.h" +#include "unity.h" +#include "unity_internals.h" +#include "juno/ds/buff_queue_api.h" +#include "juno/ds/buff_stack_api.h" +#include +#include +#include + + +void setUp(void) +{ + +} +void tearDown(void) +{ + +} + + +typedef struct TEST_STACK JUNO_MODULE_DERIVE(JUNO_BUFF_STACK_ROOT_T, + uint8_t iTestStack[10]; +) TEST_STACK; + +static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex); +static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); +static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); +static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc); + +const JUNO_BUFF_STACK_API_T gtStackApi = { + Stack_SetAt, + Stack_GetAt, + Stack_RemoveAt, + Stack_Copy +}; + +union JUNO_BUFF_STACK_ROOT_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, + TEST_STACK tTestStack; +); + +static void test_stack(void) +{ + TEST_STACK tTestStack = (TEST_STACK){0}; + JUNO_STATUS_T tStatus = JunoDs_Buff_StackInit(&tTestStack.tRoot, >StackApi, 10, NULL, NULL); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_STACK tStack = tTestStack; + uint8_t iValue = 0; + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + { + iValue = i + 1; + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + { + iValue = 0; + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); + } + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + { + iValue = i + 1; + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + } + tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + { + iValue = 0; + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); + TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); + } + tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); +} + +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_stack); + return UNITY_END(); +} + +static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex) +{ + uint8_t *iItem = (void *) ptItem; + TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; + ptTestStack->iTestStack[iIndex] = *iItem; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) +{ + TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; + JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptTestStack->iTestStack[iIndex]); + return tResult; +} + +static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) +{ + TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; + ptTestStack->iTestStack[iIndex] = 0; + return JUNO_STATUS_SUCCESS; +} + +static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc) +{ + uint8_t *iDest = (void *) ptDest; + uint8_t *iSrc= (void *) ptSrc; + *iDest = *iSrc; + return JUNO_STATUS_SUCCESS; +} + From 6d17201d054974bd0920d8b7d8400b0c95af5684 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 09:30:35 -0500 Subject: [PATCH 21/34] :sparkles: Add alignment checks --- examples/minimal_memory_example.c | 2 +- include/juno/memory/README.md | 8 ++-- include/juno/memory/memory_block.h | 7 +++- src/juno_memory_block.c | 59 +++++++++++++++++++++++++++++- tests/test_memory.c | 24 ++++++------ 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/examples/minimal_memory_example.c b/examples/minimal_memory_example.c index e3a52aaa..784ae3d7 100644 --- a/examples/minimal_memory_example.c +++ b/examples/minimal_memory_example.c @@ -57,7 +57,7 @@ int main(void) { // Step 1: Initialize the memory allocator JUNO_MEMORY_ALLOC_BLOCK_T tMemAlloc = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMemAlloc, >UserDataPointerApi, gUserDataMemory, diff --git a/include/juno/memory/README.md b/include/juno/memory/README.md index b92fd4f8..58e045e8 100644 --- a/include/juno/memory/README.md +++ b/include/juno/memory/README.md @@ -42,7 +42,7 @@ To help understand how memory blocks work in Juno, here's a visualization of the Block Control Structure ``` -When calling `JunoMemory_BlockApi()`: +When calling `JunoMemory_BlockInit()`: 1. You pass in a pre-allocated memory array (`JUNO_MEMORY_BLOCK`) 2. You pass in a pre-allocated metadata array (`JUNO_MEMORY_BLOCK_METADATA`) 3. The function initializes the control structure that tracks: @@ -79,7 +79,7 @@ Create and initialize a memory allocator to manage the block: JUNO_MEMORY_ALLOC_T tMemAlloc = {0}; // Initialize the block allocator -JUNO_STATUS_T tStatus = JunoMemory_BlockApi( +JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMemAlloc, // Pointer to memory block structure gptMyMemoryBlock, // Memory block array gptMyMemoryMetadata, // Metadata array @@ -285,7 +285,7 @@ union JUNO_MEMORY_ALLOC_TAG ### Initialization ```c -JUNO_STATUS_T JunoMemory_BlockApi( +JUNO_STATUS_T JunoMemory_BlockInit( JUNO_MEMORY_ALLOC_T *ptJunoMemory, void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, @@ -377,7 +377,7 @@ int main() { // Initialize the memory allocator JUNO_MEMORY_ALLOC_T tMemAlloc = {}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMemAlloc, nodeMemory, nodeMetadata, diff --git a/include/juno/memory/memory_block.h b/include/juno/memory/memory_block.h index 0b4d1699..b1707709 100644 --- a/include/juno/memory/memory_block.h +++ b/include/juno/memory/memory_block.h @@ -79,7 +79,7 @@ struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MODULE_DERIVE(JUNO_MEMORY_ALLOC_ROOT_T, /// @param pfcnFailureHandler Callback function to handle failures. /// @param pvUserData User data passed to the failure handler. /// @return JUNO_STATUS_T Status of the initialization. -JUNO_STATUS_T JunoMemory_BlockApi( +JUNO_STATUS_T JunoMemory_BlockInit( JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemory, const JUNO_POINTER_API_T *ptPointerApi, void *pvMemory, @@ -89,6 +89,11 @@ JUNO_STATUS_T JunoMemory_BlockApi( JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData ); + +/// Typed wrappers to reduce size mismatches +#define JunoMemory_BlockGetT(ptBlkRoot, type) (ptBlkRoot)->tRoot.ptApi->Get(&(ptBlkRoot)->tRoot, sizeof(type)) +#define JunoMemory_BlockPutT(ptBlkRoot, pPtr) (ptBlkRoot)->tRoot.ptApi->Put(&(ptBlkRoot)->tRoot, (pPtr)) + #ifdef __cplusplus } #endif diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index eeeb1112..08be28eb 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -39,6 +39,20 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory) ptJunoMemoryBlock, "Module does not have all dependencies" ); + // Guard overflow of zTypeSize * zLength and ensure base alignment + if (ptJunoMemoryBlock->zTypeSize != 0 && + ptJunoMemoryBlock->zLength > (SIZE_MAX / ptJunoMemoryBlock->zTypeSize)) + { + JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, + "Invalid memory block configuration: size overflow"); + return JUNO_STATUS_ERR; + } + if (((uintptr_t)ptJunoMemoryBlock->pvMemory) % ptJunoMemoryBlock->zTypeSize != 0) + { + JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, + "Invalid memory alignment for block base pointer"); + return JUNO_STATUS_ERR; + } if(ptJunoMemoryBlock->JUNO_MODULE_SUPER.ptApi != &tJunoMemoryBlockApi) { JUNO_FAIL_MODULE(JUNO_STATUS_INVALID_TYPE_ERROR, ptJunoMemoryBlock, "Module has invalid API"); @@ -83,10 +97,23 @@ static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoM ); return tResult; } + // Sanity invariants + if(ptMemBlk->zUsed > ptMemBlk->zLength || ptMemBlk->zFreed > ptMemBlk->zLength) + { + tResult.tStatus = JUNO_STATUS_ERR; + JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Corrupt allocator counters"); + return tResult; + } // If no freed block is available, allocate a new block if(ptMemBlk->zFreed == 0) { + if(ptMemBlk->zUsed >= ptMemBlk->zLength) + { + tResult.tStatus = JUNO_STATUS_MEMALLOC_ERROR; + JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Allocator full"); + return tResult; + } // Compute the offset for the next available block size_t zNextFreeBlock = ptMemBlk->zUsed * ptMemBlk->zTypeSize; // Place the new block on the free stack @@ -97,6 +124,12 @@ static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoM } tResult.tOk.ptApi = ptMemBlk->tRoot.ptPointerApi; // Retrieve the latest free block and update free stack + if(ptMemBlk->zFreed == 0) + { + tResult.tStatus = JUNO_STATUS_ERR; + JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Free list underflow"); + return tResult; + } tResult.tOk.pvAddr = ptMemBlk->ptMetadata[ptMemBlk->zFreed-1].ptFreeMem; tResult.tOk.zSize = ptMemBlk->zTypeSize; ptMemBlk->zFreed -= 1; @@ -179,6 +212,14 @@ static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, J else { // Otherwise, add the block back to the free stack. + if (ptMemBlk->zFreed >= ptMemBlk->zLength) + { + // Free stack overflow (should be impossible with correct invariants) + tStatus = JUNO_STATUS_MEMFREE_ERROR; + JUNO_FAIL_MODULE(tStatus, ptMemBlk, "Free list overflow"); + *ptMemory = tMemory; + return tStatus; + } ptMemBlk->ptMetadata[ptMemBlk->zFreed].ptFreeMem = tMemory.pvAddr; ptMemBlk->zFreed += 1; } @@ -193,7 +234,7 @@ static const JUNO_MEMORY_ALLOC_API_T tJunoMemoryBlockApi = { }; /* TODO: Insert initialization arguments for module members here*/ -JUNO_STATUS_T JunoMemory_BlockApi( +JUNO_STATUS_T JunoMemory_BlockInit( JUNO_MEMORY_ALLOC_BLOCK_T *ptJunoMemoryBlock, const JUNO_POINTER_API_T *ptPointerApi, void *pvMemory, @@ -219,6 +260,22 @@ JUNO_STATUS_T JunoMemory_BlockApi( ptJunoMemoryBlock->zUsed = 0; // Initially, no freed blocks are available ptJunoMemoryBlock->zFreed = 0; + // Early validation before Verify performs module checks + if (!ptPointerApi || !pvMemory || !ptMetadata || zTypeSize == 0 || zLength == 0) + { + JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Invalid init parameters"); + return JUNO_STATUS_ERR; + } + if (zTypeSize != 0 && zLength > (SIZE_MAX / zTypeSize)) + { + JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Init size overflow"); + return JUNO_STATUS_ERR; + } + if (((uintptr_t)pvMemory) % zTypeSize != 0) + { + JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Init memory pointer misaligned"); + return JUNO_STATUS_ERR; + } JUNO_STATUS_T tStatus = Verify((JUNO_MEMORY_ALLOC_ROOT_T *) ptJunoMemoryBlock); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); return tStatus; diff --git a/tests/test_memory.c b/tests/test_memory.c index 7a524c42..b75fa9f8 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -61,7 +61,7 @@ void tearDown(void) static void test_nominal_single_alloc_and_free(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -99,7 +99,7 @@ static void test_nominal_single_alloc_and_free(void) static void test_nominal_multiple_alloc_and_free(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -159,7 +159,7 @@ static void test_nominal_multiple_alloc_and_free(void) static void test_negative_memory_empty(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -206,7 +206,7 @@ static void test_negative_memory_empty(void) static void test_negative_memory_full(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -242,7 +242,7 @@ static void test_negative_memory_full(void) static void test_invalid_init_parameters(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, NULL, NULL, @@ -258,7 +258,7 @@ static void test_invalid_init_parameters(void) static void test_double_free(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -285,7 +285,7 @@ static void test_double_free(void) static void test_free_unallocated(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -305,7 +305,7 @@ static void test_free_unallocated(void) static void test_update_memory(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -335,7 +335,7 @@ static void test_update_memory(void) static void test_generic_memory_get_put(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -366,7 +366,7 @@ static void test_generic_memory_get_put(void) static void test_zero_size_allocation(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -386,7 +386,7 @@ static void test_zero_size_allocation(void) static void test_bad_api(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, @@ -420,7 +420,7 @@ static void test_bad_api(void) static void test_invalid_size_and_addr(void) { JUNO_MEMORY_ALLOC_BLOCK_T tMem = {0}; - JUNO_STATUS_T tStatus = JunoMemory_BlockApi( + JUNO_STATUS_T tStatus = JunoMemory_BlockInit( &tMem, >TestBlockApi, ptTestBlock, From 996d28acb494bfe7166ed89f36ea92c50fe330a1 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 09:55:49 -0500 Subject: [PATCH 22/34] :sparkles: Update stack api --- .github/copilot-instructions.md | 264 ++++++++++++------------------- CMakeLists.txt | 2 +- include/juno/ds/buff_stack_api.h | 48 +++--- include/juno/module.h | 9 ++ src/juno_buff_stack.c | 66 +++++--- tests/test_stack.c | 135 +++++++++------- 6 files changed, 251 insertions(+), 273 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 63e0c52e..05d027dc 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,205 +1,137 @@ -# .github/copilot-instructions.md +# LibJuno — Copilot review playbook (repo-specific) -> **Purpose:** Onboard a coding agent to perform **thorough merge-request code reviews** for a **freestanding embedded C library**, with an emphasis on **memory safety, reliability, developer experience, and deployability on new systems**. -> **Scope:** General, repo-agnostic playbook (≤2 pages). Use these steps first; only search the repo when information here is incomplete or wrong. +Purpose: Enable thorough MR reviews for LibJuno, a lightweight C11 library for embedded/freestanding targets, with emphasis on memory safety, determinism, developer experience, and deployability. ---- - -## 1) High-Level Overview (for the agent) - -* **What this repository is (expected):** A C library intended for **embedded/freestanding** targets that helps developers **build quickly and test easily**. Likely provides headers in `include/`, sources in `src/`, examples in `examples/`, tests in `tests/` or `test/`. -* **Project type & languages:** C (C99/C11 typical), optional C++ shims, build via **CMake** or **Make** (sometimes **Meson**, **Zephyr/West**, or **PlatformIO**). Host tests run on Linux/macOS/Windows; cross builds for ARM/RISC-V etc. -* **Repo size (estimate at review time):** Run a quick inventory (see §4) and note line counts, dependency weight, and key dirs. Record any large test assets or submodules. - -> **Rule:** Trust this playbook. Prefer the commands and checklists here before ad-hoc greps or trial-and-error. Search only when a step is missing or fails. +Trust this file first. Search the repo only when a step is unclear or fails. --- -## 2) Build, Test, Lint, Run — Standard Sequences - -> **Preconditions (always do):** -> -> * Ensure a clean tree: `git submodule update --init --recursive` (if `.gitmodules` exists). -> * If present: `scripts/bootstrap.*` or `tools/bootstrap.*` (read & run first). -> * Prefer out-of-tree builds (`build/` dir). Avoid root pollution. - -### A) CMake (most common) - -```bash -# Configure (host) -cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -# Or add sanitizers for review -cmake -S . -B build-asan -DCMAKE_BUILD_TYPE=Debug -DSANITIZE=Address,Undefined - -# Build -cmake --build build -j - -# Tests (ctest is typical) -ctest --test-dir build --output-on-failure - -# Lint/format (if defined) -cmake --build build --target clang-format-check || true -cmake --build build --target clang-tidy || true -``` - -**Cross-compile (example ARM GCC):** - -```bash -cmake -S . -B build-arm -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm-gcc.cmake -DCMAKE_BUILD_TYPE=Release -cmake --build build-arm -j -``` - -### B) Makefile - -```bash -make clean || true -make -j -make test # if defined -make format lint # if defined -``` - -### C) Meson (if `meson.build` exists) - -```bash -meson setup build -meson compile -C build -meson test -C build --print-errorlogs -``` - -### D) Zephyr / West (if `west.yml` or `zephyr/` present) - -```bash -west update -west build -b samples/ # verify library links cleanly -``` +## 1) What LibJuno is (and is not) -### E) PlatformIO (if `platformio.ini` exists) - -```bash -pio run -pio test -``` - -> **If commands fail:** -> -> * Re-run from a clean out-of-tree dir. -> * Check required tool versions in `CMakeLists.txt`, `toolchain.cmake`, `Makefile`, or CI workflow. -> * Prefer `-DCMAKE_C_STANDARD=11` (or repo’s declared standard) for consistency. +- Lightweight C11 library designed for embedded systems; can build freestanding (no libc) and emphasizes memory safety and determinism. +- Core themes: + - A small module system with dependency-injection (DI) via API vtables and macros (see `include/juno/README.md`). + - Deterministic memory utilities: block-based allocator with reference counting (no malloc required) and helpers (see `include/juno/memory/README.md`). + - Utility algorithms and containers (CRC variants, buffers/queues/stacks, maps, time, etc.). +- Tests use the Unity framework vendored in `deps/unity/`. --- -## 3) Validation Pipeline (replicate CI locally) - -1. **Discover checks:** Open `.github/workflows/*.yml` (and any other CI config). List jobs: **format**, **lint**, **build (host & cross)**, **unit/integration tests**, **coverage**, **package/install**. -2. **Replicate locally** in this order: - - * **Format**: `clang-format -i` or run provided target. - * **Lint**: `clang-tidy` / `cppcheck` using project config. - * **Build (Debug+ASan/UBSan)**, then **run all tests** with verbose failures. - * **Build (Release)** for size/perf checks. - * **Coverage** (if enabled): `gcov`/`lcov/genhtml`. - * **Install/package** (CMake: `cmake --install build --prefix `). -3. **Record deviations:** If CI runs extra scripts (e.g., `scripts/ci/*.sh`), run them locally and note required env vars. - -> **Time-outs:** Note any step that routinely exceeds 10 minutes; capture mitigation (e.g., `-j`, ccache). +## 2) Build, test, docs — how to run here + +Preconditions +- Use out-of-tree builds (`build/`). Initialize submodules if added in future. +- C standard is enforced as C11; warnings are enabled and treated as errors. + +Common CMake flows +- Configure (static lib by default): + - Debug + tests: `cmake -S . -B build -DJUNO_TESTS=ON -DCMAKE_BUILD_TYPE=Debug` + - Release: `cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo` +- Sanitizers (host review): add any of + - `-DJUNO_ASAN=ON`, `-DJUNO_UBSAN=ON` +- Freestanding (no hosted libc): + - `-DJUNO_FREESTANDING=ON` (adds `-ffreestanding -nostdlib`; ensure no hosted headers in changes) +- Coverage (host): + - `-DJUNO_COVERAGE=ON` (links `gcov`, enables coverage flags) +- Examples: `-DJUNO_EXAMPLES=ON` to build samples in `examples/`. +- Shared library: `-DJUNO_SHARED=ON` to also build a shared artifact. + +Build and test +- Build: `cmake --build build -j` +- Run tests (when `JUNO_TESTS=ON`): + - `ctest --test-dir build --output-on-failure` + - Tests are auto-discovered from `tests/` and link `unity` and `m`. + +Docs +- Doxygen: configure with `-DJUNO_DOCS=ON`, then `cmake --build build --target docs`. + +Install/package +- Install headers and libs: `cmake --install build --prefix ` +- CMake package export: `cmake/junoConfig.cmake.in` is provided; verify `find_package(juno)` consumers as part of packaging checks. --- -## 4) Fast Inventory & Layout Hints +## 3) Directory map (quick mental model) -* **Root files to find quickly:** `README.md`, `CONTRIBUTING.md`, `LICENSE`, `CMakeLists.txt` or `Makefile`, `meson.build`, `.clang-format`, `.clang-tidy`, `.editorconfig`, `Doxyfile`, `.github/workflows/`. -* **Key dirs:** `include/` (public headers), `src/` (lib sources), `tests?/` (unit), `examples?/`, `cmake/` (toolchains/macros), `ports/` or `platform/` (HAL/MCU), `scripts/` or `tools/` (dev utilities). -* **Config locations:** Lint (.clang-\*), compilation options (CMake toolchain or top-level), test config (CTest/Meson), preferences (.editorconfig), package metadata (`pkgconfig/`, `cmake/.cmake`). -* **Dependencies not obvious:** Submodules in `third_party/`, codegen scripts (Python/Lua), optional RTOS shims, platform drivers. +- `include/juno/` — public headers (module system, memory, status, APIs). See `include/juno/README.md` and `include/juno/memory/README.md`. +- `src/` — implementation: CRCs (`juno_ccitt*.c`, `juno_kermit.c`, `juno_zip.c`), buffers/queues/stacks, memory block/heap, maps, time, etc. +- `tests/` — unit tests compiled when `JUNO_TESTS=ON`; `deps/unity` vendored test framework. +- `examples/` — minimal usage and DI demos; gated by `JUNO_EXAMPLES`. +- `docs/` + `Doxyfile.in` — documentation assets and template. +- `cmake/` — packaging config. +- `scripts/` — helper generators (templates, docs, versioning). --- -## 5) Expert Embedded C Code-Review Checklist (use for every MR) - -### Memory Safety & Undefined Behavior - -* **Bounds/overflow:** Array indices validated; no off-by-one; careful `memcpy/memmove/str*` lengths; avoid `strcpy/sprintf` (prefer length-bounded variants). -* **Integer issues:** Signed/unsigned mixing, shifts by width, overflow/underflow, implicit narrowing (`-Wconversion`), sentinel `size_t` vs `int`. -* **Pointer hygiene:** Null checks, lifetime/aliasing, alignment, strict aliasing violations, double-free, use-after-free, dangling pointers after realloc. -* **Ownership & API contracts:** Who allocates/frees? Clarify in docstrings. Avoid hidden allocations in hot paths and **never in ISRs**. -* **UB hotspots:** Uninitialized reads, out-of-range enums, `volatile` misuse, data races, order of evaluation assumptions. - -### Concurrency, ISR, and Real-Time - -* **ISR-safety:** No blocking or heap; atomicity around shared state; minimal critical sections; correct `volatile` and memory barriers. -* **Reentrancy/thread-safety:** No shared mutable statics unless guarded; documented guarantees. -* **Timing:** O(1) where required; avoid unpredictable latency (I/O, locks, malloc). +## 4) Validation pipeline for this repo -### Portability & Freestanding Constraints +Run locally in this order and record results: +1) Configure + build (Debug) with sanitizers (when host review): + - `-DJUNO_TESTS=ON -DJUNO_ASAN=ON -DJUNO_UBSAN=ON -DCMAKE_BUILD_TYPE=Debug` +2) Run all tests via `ctest --output-on-failure`. +3) Build Release (`RelWithDebInfo`) and ensure no warnings (warnings are `-Werror`). +4) Optional: Coverage (`-DJUNO_COVERAGE=ON`) and generate reports (`lcov/genhtml`). +5) Docs build (`-DJUNO_DOCS=ON`, target `docs`). +6) Install/package sanity: `cmake --install` into a staging prefix; smoke check `junoConfig.cmake` and includes. -* Builds with `-ffreestanding` (if applicable) and without hosted headers; no forbidden syscalls; guarded `#ifdef` per platform; endianness and word-size handling; alignment assumptions explicit. -* **C standard:** Consistent (C11/C99). Don’t rely on compiler extensions unless wrapped. -* **Toolchains:** GCC/Clang/ARM-GCC flags sane; warnings as errors (`-Wall -Wextra -Werror -Wshadow -Wstrict-prototypes -Wcast-align -Wconversion -Wdouble-promotion -Wformat=2`, plus `-fanalyzer` where possible). +Notes +- Compilers: GCC/Clang expected. Project sets strict warnings (e.g., `-Wall -Wextra -Werror -Wshadow -Wcast-align -Wundef -Wswitch -Wmissing-field-initializers -fno-common -fno-strict-aliasing`). +- For freestanding builds, ensure added code avoids hosted headers and syscalls. -### API & Developer Experience (DX) - -* **Ease of use:** Simple init/deinit; clear error codes; consistent naming & prefixes; **zero-config sensible defaults** with optional advanced config via macros. -* **Docs:** Public headers self-documenting; examples compile; README quick-start works; Doxygen (if present) builds clean; change log updated. -* **Testing strategy:** Unit tests cover edge cases; fuzz targets (if any) run; deterministic behavior; host tests do not accidentally require target hardware. - -### Deployment & Packaging +--- -* **Installability:** `make install` or `cmake --install` installs headers+static/dynamic libs and `pkg-config`/CMake package files. -* **Cross builds:** Toolchain files provided; example commands documented; no hard-coded host paths. -* **ABI/semver:** Public symbols gated; no accidental API breaks; visibility flags set on shared libs. +## 5) LibJuno-focused code review checklist ---- +Memory safety & UB +- Block allocator: verify bounds, reuse of freed blocks, and reference counting semantics. Ensure: + - `JunoMemory_BlockInit` parameters are validated; type sizes match usage. + - `Get/Put/Update` respect element size and block limits; reject double-free; `Put` fails when refs > 1. + - All return codes (`JUNO_STATUS_T`) are checked at call sites. +- Avoid libc when `JUNO_FREESTANDING=ON`; no hidden dynamic allocation in hot paths. +- Integer and pointer hygiene: no narrowing, no invalid shifts, alignments explicit; observe strict aliasing rules. -## 6) Automated & Manual Analyses to Run (prefer host first) +Module system & DI (see `include/juno/README.md`) +- Every module sets `ptApi` to a valid vtable during init; failure handler (`JUNO_FAILURE_HANDLER`) and user data wired. +- Derived types overlay base via `JUNO_MODULE/JUNO_MODULE_DERIVE`; ensure member access uses the correct view and alignment. +- API contracts are clear: inputs validated, null checks present, and failure paths call the failure handler with actionable messages. -* **Static:** `clang-tidy` with project config; `cppcheck --enable=warning,performance,portability,unusedFunction`; compiler with max warnings + `-Werror`; optional `-fanalyzer`. -* **Dynamic (host):** AddressSanitizer + UndefinedBehaviorSanitizer builds; run all tests with `ASAN_OPTIONS=halt_on_error=1` etc. Valgrind Memcheck on non-ASan builds. -* **Coverage:** Build with `--coverage` or `-fprofile-arcs -ftest-coverage`; generate with `lcov/genhtml`. -* **Fuzz (if available):** libFuzzer/AFL targets; ensure no timeouts/oom. -* **Emulation (if applicable):** QEMU for target ISA; smoke test examples. +Concurrency/real-time +- No blocking I/O or heap in ISR-sensitive paths; minimal critical sections; volatile and barriers when required by shared state. ---- +Portability & build flags +- Code builds clean with the project’s warning set; no reliance on compiler-specific extensions unless guarded. +- When `JUNO_SHARED=ON`, confirm symbol visibility and no accidental ABI leaks from private headers. -## 7) MR Review Flow (step-by-step) +Tests & examples +- Unit tests cover edge cases for allocators (empty/full pool, refcounting, invalid free), containers (under/overflow), and CRC correctness against vectors. +- Examples compile with `JUNO_EXAMPLES=ON` and match documented usage in READMEs. -1. **Bootstrap quickly** using §2 for the detected build system. If both CMake and Make exist, prefer **CMake**. -2. **Run lint/format** and request fixes for automated violations; include a patch suggestion if trivial. -3. **Build Debug+ASan/UBSan**, run full test suite; then **Release** build to check size/perf warnings. -4. **Execute §5 checklist** across changed files: headers first (API), then sources (safety), then tests (quality). -5. **Replicate CI** locally; if CI differs, note the gap in the MR review. -6. **Try a cross build** using any provided toolchain; catch portability/packaging snags early. -7. **Check docs/examples** compile; ensure README quick start works exactly as written. -8. **Summarize findings** with specific file/line references, failing commands, and concrete diffs or snippets. +Docs & DX +- Public headers are self-documenting; Doxygen groups render without warnings. +- Namespaces/prefixes consistent (`Juno*`, `JUNO_*`); error codes and macro usage are discoverable from headers. --- -## 8) Common Pitfalls & Mitigations +## 6) Common pitfalls seen in this repo -* **Hidden deps:** Submodules not inited → run `git submodule update --init --recursive`. -* **Flaky order:** Always configure before build; avoid mixing generator & build dirs. -* **Tool mismatch:** If CI pins compilers, mirror locally (e.g., `clang-17`, `gcc-13`). -* **Sanitizer false positives on embedded stubs:** Exclude platform shims in host ASan runs; still test core logic. -* **ISR misuse:** Flag any memory allocation, logging, or blocking calls inside ISR paths. +- Freestanding mode requires avoiding hosted headers even in helpers/tests; gate usage with `#if !JUNO_FREESTANDING` where necessary. +- Tests link `m` (math); ensure new tests include only headers available on host. +- Watch for off-by-one in buffer/queue/stack implementations and mixing of signed/unsigned indices. +- When updating install/package, validate `cmake/junoConfig.cmake.in` and the exported targets; run a small consumer CMake to `find_package(juno)`. --- -## 9) What to Record in the Review +## 7) What to record in MR reviews -* Exact commands run and results (pass/fail), tool versions, and timing out steps. -* Any required environment setup that proved **actually necessary** (even if undocumented). -* Workarounds for non-deterministic or order-sensitive builds. -* Gaps between README/CI and reality. +- Exact configure/build/test commands and outcomes (pass/fail), compiler versions, sanitizer results. +- Any deviations from README or CI, including steps required to build docs or examples. +- Specific file/line issues with concrete suggestions or diffs (headers first, then sources, then tests). +- Packaging/install verification notes (what installed, include paths, and find_package smoke test results). --- -## 10) When to Search - -* **Only** if a step in this playbook is missing or fails for this repo. Then search the repo for: +## 8) When to search the repo - * `README.md`, `CONTRIBUTING.md`, `CMakeLists.txt`, `Makefile`, `meson.build`, `Doxyfile`, `.clang-*`, `.editorconfig`, `.github/workflows/*`, - * `scripts/`, `tools/`, `cmake/`, `ports/`, `platform/`, `examples/`, `tests/`, `third_party/`. -* Prefer reading the nearest script or config over generic web searching. - ---- +- If something is unclear or fails, consult: `README.md`, `include/juno/README.md`, `include/juno/memory/README.md`, top-level `CMakeLists.txt`, `tests/CMakeLists.txt`, `cmake/junoConfig.cmake.in`, `docs/`, `examples/`, `scripts/`. -> **Final instruction:** **Trust this file.** Follow the sequences and checklists above before exploring. If a command here fails in this repository, document the failure, adjust minimally (not wholesale), and continue the review using the closest equivalent provided by the project. +Final instruction: Prefer these sequences and checklists for LibJuno. If a command fails, document the failure, adjust minimally, and continue the review using the closest equivalent in this repository. diff --git a/CMakeLists.txt b/CMakeLists.txt index 8896dc9a..002ffdf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/include/juno/ds/buff_stack_api.h b/include/juno/ds/buff_stack_api.h index ab7759bc..ef8585c1 100644 --- a/include/juno/ds/buff_stack_api.h +++ b/include/juno/ds/buff_stack_api.h @@ -26,7 +26,9 @@ */ #ifndef JUNO_BUFF_STACK_API_H #define JUNO_BUFF_STACK_API_H +#include "juno/ds/array_api.h" #include "juno/macros.h" +#include "juno/memory/memory_api.h" #include "juno/status.h" #include "juno/module.h" #include "juno/types.h" @@ -40,50 +42,40 @@ typedef struct JUNO_BUFF_STACK_ROOT_TAG JUNO_BUFF_STACK_ROOT_T; typedef struct JUNO_BUFF_STACK_API_TAG JUNO_BUFF_STACK_API_T; struct JUNO_BUFF_STACK_ROOT_TAG JUNO_MODULE_ROOT(JUNO_BUFF_STACK_API_T, - /// The current length of the stack - size_t zLength; - /// The capacity of the stack - size_t zCapacity; + JUNO_ARRAY_ROOT_T *ptBuffer; ); struct JUNO_BUFF_STACK_API_TAG { - JUNO_STATUS_T (*SetAt)(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex); - JUNO_RESULT_VOID_PTR_T (*GetAt)(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); - JUNO_STATUS_T (*RemoveAt)(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); - JUNO_STATUS_T (*Copy)(void *ptDest, void *ptSrc); + /// Enqueue an item into the buffer + /// @returns The index to place the enqueued item + JUNO_STATUS_T (*Push)(JUNO_BUFF_STACK_ROOT_T *ptQueue, JUNO_POINTER_T tItem); + /// Dequeue an item from the buffer + /// @returns The index to dequeue the item from + JUNO_STATUS_T (*Pop)(JUNO_BUFF_STACK_ROOT_T *ptQueue, JUNO_POINTER_T tReturn); + /// Peek at the next item in the queue + /// @returns the index of the next item in the queue + JUNO_RESULT_POINTER_T (*Peek)(JUNO_BUFF_STACK_ROOT_T *ptQueue); }; -static inline JUNO_STATUS_T JunoDs_Buff_StackVerify(JUNO_BUFF_STACK_ROOT_T *ptStack) + +static inline JUNO_STATUS_T JunoDs_Buff_StackVerify(const JUNO_BUFF_STACK_ROOT_T *ptStack) { JUNO_ASSERT_EXISTS(ptStack); JUNO_ASSERT_EXISTS( ptStack->ptApi && - ptStack->zCapacity && - ptStack->ptApi->GetAt && - ptStack->ptApi->SetAt && - ptStack->ptApi->RemoveAt && - ptStack->ptApi->Copy + ptStack->ptApi->Push && + ptStack->ptApi->Pop && + ptStack->ptApi->Peek && + ptStack->ptBuffer ); - return JUNO_STATUS_SUCCESS; + return JunoDs_ArrayVerify(ptStack->ptBuffer); } /// Initialize a buffer queue with a capacity -JUNO_STATUS_T JunoDs_Buff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptQueue, const JUNO_BUFF_STACK_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); - -/// Enqueue an item into the buffer -/// @returns The index to place the enqueued item -JUNO_STATUS_T JunoDs_Buff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptQueue, void *ptItem); - - -/// Dequeue an item from the buffer -/// @returns The index to dequeue the item from -JUNO_STATUS_T JunoDs_Buff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptQueue, void *ptReturn); +JUNO_STATUS_T JunoDs_Buff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptQueue, JUNO_ARRAY_ROOT_T *ptBuffer, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData); -/// Peek at the next item in the queue -/// @returns the index of the next item in the queue -JUNO_RESULT_VOID_PTR_T JunoDs_Buff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptQueue); #ifdef __cplusplus } diff --git a/include/juno/module.h b/include/juno/module.h index d0518f02..9cef9a53 100644 --- a/include/juno/module.h +++ b/include/juno/module.h @@ -218,6 +218,15 @@ __VA_ARGS__ \ } +#define JUNO_MODULE_DERIVE_WITH_API(ROOT_T, API_T, ...) \ +{ \ + union { \ + ROOT_T JUNO_MODULE_SUPER; \ + const API_T *ptApi; \ + }; \ + __VA_ARGS__ \ +} + /** Get the API pointer from the module @param ptModule The module pointer diff --git a/src/juno_buff_stack.c b/src/juno_buff_stack.c index 03ebd14b..c9f7b4fd 100644 --- a/src/juno_buff_stack.c +++ b/src/juno_buff_stack.c @@ -1,31 +1,25 @@ +#include "juno/ds/array_api.h" #include "juno/ds/buff_stack_api.h" #include "juno/macros.h" +#include "juno/memory/memory_api.h" #include "juno/status.h" -/// Initialize a buffer queue with a capacity -JUNO_STATUS_T JunoDs_Buff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptStack, const JUNO_BUFF_STACK_API_T *ptApi, size_t zCapacity, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) -{ - JUNO_ASSERT_EXISTS(ptStack); - JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - ptStackRoot->zLength = 0; - ptStackRoot->zCapacity = zCapacity; - ptStackRoot->_pfcnFailureHandler = pfcnFailureHdlr; - ptStackRoot->_pvFailureUserData = pvFailureUserData; - ptStackRoot->ptApi = ptApi; - return JunoDs_Buff_StackVerify(ptStack); -} + /// Enqueue an item into the buffer /// @returns The index to place the enqueued item -JUNO_STATUS_T JunoDs_Buff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem) +static JUNO_STATUS_T JunoDs_Buff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptStack, JUNO_POINTER_T tItem) { JUNO_STATUS_T tStatus = JunoDs_Buff_StackVerify(ptStack); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JunoMemory_PointerVerify(&tItem); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - if(ptStackRoot->zLength < ptStackRoot->zCapacity) + JUNO_ARRAY_ROOT_T *ptBuffer = ptStack->ptBuffer; + if(ptBuffer->zLength < ptBuffer->zCapacity) { - tStatus = ptStack->ptApi->SetAt(ptStack, ptItem, ptStackRoot->zLength); + tStatus = ptBuffer->ptApi->SetAt(ptBuffer, tItem, ptBuffer->zLength); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - ptStackRoot->zLength += 1; + ptBuffer->zLength += 1; } else { @@ -38,17 +32,20 @@ JUNO_STATUS_T JunoDs_Buff_StackPush(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptIte /// Dequeue an item from the buffer /// @returns The index to dequeue the item from -JUNO_STATUS_T JunoDs_Buff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptReturn) +static JUNO_STATUS_T JunoDs_Buff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptStack, JUNO_POINTER_T tReturn) { JUNO_STATUS_T tStatus = JunoDs_Buff_StackVerify(ptStack); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); + tStatus = JunoMemory_PointerVerify(&tReturn); + JUNO_ASSERT_SUCCESS(tStatus, return tStatus); JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); - if(ptStackRoot->zLength > 0) + JUNO_ARRAY_ROOT_T *ptBuffer = ptStack->ptBuffer; + if(ptBuffer->zLength > 0) { - ptStackRoot->zLength -= 1; - JUNO_RESULT_VOID_PTR_T tResult = ptStack->ptApi->GetAt(ptStack, ptStackRoot->zLength); + ptBuffer->zLength -= 1; + JUNO_RESULT_POINTER_T tResult = ptBuffer->ptApi->GetAt(ptBuffer, ptBuffer->zLength); JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult.tStatus); - tStatus = ptStackRoot->ptApi->Copy(ptReturn, tResult.tOk); + tStatus = tReturn.ptApi->Copy(tReturn, tResult.tOk); return tStatus; } tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; @@ -59,17 +56,36 @@ JUNO_STATUS_T JunoDs_Buff_StackPop(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptRetu /// Peek at the next item in the queue /// @returns the index of the next item in the queue -JUNO_RESULT_VOID_PTR_T JunoDs_Buff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptStack) +static JUNO_RESULT_POINTER_T JunoDs_Buff_StackPeek(JUNO_BUFF_STACK_ROOT_T *ptStack) { - JUNO_RESULT_VOID_PTR_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, NULL); + JUNO_RESULT_POINTER_T tResult = JUNO_ERR_RESULT(JUNO_STATUS_ERR, {0}); tResult.tStatus = JunoDs_Buff_StackVerify(ptStack); JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); - if(ptStack->zLength == 0) + JUNO_ARRAY_ROOT_T *ptBuffer = ptStack->ptBuffer; + if(ptBuffer->zLength == 0) { tResult.tStatus = JUNO_STATUS_INVALID_SIZE_ERROR; JUNO_FAIL(tResult.tStatus, ptStack->_pfcnFailureHandler, ptStack->_pvFailureUserData, "Queue is empty"); return tResult; } - tResult = ptStack->ptApi->GetAt(ptStack, 0); + tResult = ptBuffer->ptApi->GetAt(ptBuffer, 0); return tResult; } + +static const JUNO_BUFF_STACK_API_T tStackApi = { + JunoDs_Buff_StackPush, + JunoDs_Buff_StackPop, + JunoDs_Buff_StackPeek, +}; + +/// Initialize a buffer queue with a capacity +JUNO_STATUS_T JunoDs_Buff_StackInit(JUNO_BUFF_STACK_ROOT_T *ptStack, JUNO_ARRAY_ROOT_T *ptBuffer, JUNO_FAILURE_HANDLER_T pfcnFailureHdlr, JUNO_USER_DATA_T *pvFailureUserData) +{ + JUNO_ASSERT_EXISTS(ptStack); + JUNO_BUFF_STACK_ROOT_T *ptStackRoot = (JUNO_BUFF_STACK_ROOT_T *)(ptStack); + ptStackRoot->ptBuffer = ptBuffer; + ptStackRoot->_pfcnFailureHandler = pfcnFailureHdlr; + ptStackRoot->_pvFailureUserData = pvFailureUserData; + ptStackRoot->ptApi = &tStackApi; + return JunoDs_Buff_StackVerify(ptStack); +} diff --git a/tests/test_stack.c b/tests/test_stack.c index dbf9e9e9..e9fbfe51 100644 --- a/tests/test_stack.c +++ b/tests/test_stack.c @@ -1,84 +1,106 @@ +// Updated to latest API: use JUNO_ARRAY_ROOT_T as backing storage and JUNO_POINTER_API +#include "juno/memory/memory_api.h" #include "juno/module.h" #include "juno/status.h" #include "unity.h" #include "unity_internals.h" -#include "juno/ds/buff_queue_api.h" +#include "juno/ds/array_api.h" #include "juno/ds/buff_stack_api.h" #include #include #include +void setUp(void) {} +void tearDown(void) {} -void setUp(void) -{ - -} -void tearDown(void) -{ - -} - - -typedef struct TEST_STACK JUNO_MODULE_DERIVE(JUNO_BUFF_STACK_ROOT_T, +// Backing array for the stack (10 bytes) +typedef struct TEST_ARRAY JUNO_MODULE_DERIVE(JUNO_ARRAY_ROOT_T, uint8_t iTestStack[10]; -) TEST_STACK; +) TEST_ARRAY; -static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex); -static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); -static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex); -static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc); +// Array API implementations over TEST_ARRAY +static inline JUNO_STATUS_T Stack_SetAt(JUNO_ARRAY_ROOT_T *ptArray, JUNO_POINTER_T tItem, size_t iIndex); +static inline JUNO_RESULT_POINTER_T Stack_GetAt(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex); +static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex); +// Pointer API implementations for uint8_t +static inline JUNO_STATUS_T Stack_Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc); +static inline JUNO_STATUS_T Stack_Reset(JUNO_POINTER_T tDest); -const JUNO_BUFF_STACK_API_T gtStackApi = { +const JUNO_ARRAY_API_T gtArrayApi = { Stack_SetAt, Stack_GetAt, Stack_RemoveAt, - Stack_Copy }; -union JUNO_BUFF_STACK_ROOT_T JUNO_MODULE(void, JUNO_BUFF_STACK_ROOT_T, - TEST_STACK tTestStack; +const JUNO_POINTER_API_T gtPointerApi = { + .Copy = Stack_Copy, + .Reset = Stack_Reset, +}; + +union JUNO_ARRAY_ROOT_T JUNO_MODULE(void, JUNO_ARRAY_ROOT_T, + TEST_ARRAY tTestArray; ); static void test_stack(void) { - TEST_STACK tTestStack = (TEST_STACK){0}; - JUNO_STATUS_T tStatus = JunoDs_Buff_StackInit(&tTestStack.tRoot, >StackApi, 10, NULL, NULL); + // Prepare the backing array (buffer) + TEST_ARRAY tBuffer = (TEST_ARRAY){0}; + JUNO_ARRAY_ROOT_T *ptArray = (JUNO_ARRAY_ROOT_T *)&tBuffer; + + // Initialize the array root fields + ptArray->ptApi = >ArrayApi; + ptArray->ptPointerApi = >PointerApi; + ptArray->zCapacity = sizeof(tBuffer.iTestStack); + ptArray->zLength = 0; + + // Initialize the stack with the backing array + JUNO_BUFF_STACK_ROOT_T tStack = (JUNO_BUFF_STACK_ROOT_T){0}; + JUNO_STATUS_T tStatus = JunoDs_Buff_StackInit(&tStack, ptArray, NULL, NULL); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_STACK tStack = tTestStack; + uint8_t iValue = 0; - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + JUNO_POINTER_T tValPtr = Juno_PointerInit(>PointerApi, uint8_t, &iValue); + + // Fill the stack + for (size_t i = 0; i < sizeof(tBuffer.iTestStack); i++) { - iValue = i + 1; - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + iValue = (uint8_t)(i + 1); + tStatus = tStack.ptApi->Push(&tStack, tValPtr); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + // One too many + tStatus = tStack.ptApi->Push(&tStack, tValPtr); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + + // Drain the stack (LIFO) + for (size_t i = 0; i < sizeof(tBuffer.iTestStack); i++) { iValue = 0; - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + tStatus = tStack.ptApi->Pop(&tStack, tValPtr); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); + TEST_ASSERT_EQUAL(sizeof(tBuffer.iTestStack) - i, iValue); } - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + // One too many + tStatus = tStack.ptApi->Pop(&tStack, tValPtr); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + + // Fill and drain again + for (size_t i = 0; i < sizeof(tBuffer.iTestStack); i++) { - iValue = i + 1; - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + iValue = (uint8_t)(i + 1); + tStatus = tStack.ptApi->Push(&tStack, tValPtr); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } - tStatus = JunoDs_Buff_StackPush(&tStack.tRoot, &iValue); + tStatus = tStack.ptApi->Push(&tStack, tValPtr); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - for(size_t i = 0; i < sizeof(tTestStack.iTestStack); i++) + for (size_t i = 0; i < sizeof(tBuffer.iTestStack); i++) { iValue = 0; - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + tStatus = tStack.ptApi->Pop(&tStack, tValPtr); TEST_ASSERT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); - TEST_ASSERT_EQUAL(sizeof(tTestStack.iTestStack) - i, iValue); + TEST_ASSERT_EQUAL(sizeof(tBuffer.iTestStack) - i, iValue); } - tStatus = JunoDs_Buff_StackPop(&tStack.tRoot, &iValue); + tStatus = tStack.ptApi->Pop(&tStack, tValPtr); TEST_ASSERT_NOT_EQUAL(JUNO_STATUS_SUCCESS, tStatus); } @@ -89,33 +111,40 @@ int main(void) return UNITY_END(); } -static inline JUNO_STATUS_T Stack_SetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, void *ptItem, size_t iIndex) +static inline JUNO_STATUS_T Stack_SetAt(JUNO_ARRAY_ROOT_T *ptArray, JUNO_POINTER_T tItem, size_t iIndex) { - uint8_t *iItem = (void *) ptItem; - TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; - ptTestStack->iTestStack[iIndex] = *iItem; + uint8_t *iItem = (uint8_t *)tItem.pvAddr; + TEST_ARRAY *ptTestArray = (TEST_ARRAY *)ptArray; + ptTestArray->iTestStack[iIndex] = *iItem; return JUNO_STATUS_SUCCESS; } -static inline JUNO_RESULT_VOID_PTR_T Stack_GetAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) +static inline JUNO_RESULT_POINTER_T Stack_GetAt(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex) { - TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; - JUNO_RESULT_VOID_PTR_T tResult = JUNO_OK_RESULT(&ptTestStack->iTestStack[iIndex]); + TEST_ARRAY *ptTestArray = (TEST_ARRAY *)ptArray; + JUNO_RESULT_POINTER_T tResult = JUNO_OK_RESULT(Juno_PointerInit(>PointerApi, uint8_t, &ptTestArray->iTestStack[iIndex])); return tResult; } -static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_BUFF_STACK_ROOT_T *ptStack, size_t iIndex) +static inline JUNO_STATUS_T Stack_RemoveAt(JUNO_ARRAY_ROOT_T *ptArray, size_t iIndex) { - TEST_STACK *ptTestStack = (TEST_STACK *) ptStack; - ptTestStack->iTestStack[iIndex] = 0; + TEST_ARRAY *ptTestArray = (TEST_ARRAY *)ptArray; + ptTestArray->iTestStack[iIndex] = 0; return JUNO_STATUS_SUCCESS; } -static inline JUNO_STATUS_T Stack_Copy(void *ptDest, void *ptSrc) +static inline JUNO_STATUS_T Stack_Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) { - uint8_t *iDest = (void *) ptDest; - uint8_t *iSrc= (void *) ptSrc; + uint8_t *iDest = (uint8_t *)tDest.pvAddr; + uint8_t *iSrc = (uint8_t *)tSrc.pvAddr; *iDest = *iSrc; return JUNO_STATUS_SUCCESS; } +static inline JUNO_STATUS_T Stack_Reset(JUNO_POINTER_T tDest) +{ + uint8_t *iDest = (uint8_t *)tDest.pvAddr; + *iDest = 0; + return JUNO_STATUS_SUCCESS; +} + From d29bef582244260501e170ec81cea38680f1897d Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 10:17:18 -0500 Subject: [PATCH 23/34] Update tests/test_stack.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/test_stack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_stack.c b/tests/test_stack.c index e9fbfe51..97df3f9c 100644 --- a/tests/test_stack.c +++ b/tests/test_stack.c @@ -1,4 +1,4 @@ -// Updated to latest API: use JUNO_ARRAY_ROOT_T as backing storage and JUNO_POINTER_API +// Updated to latest API: use JUNO_ARRAY_ROOT_T as backing storage and JUNO_POINTER_API_T #include "juno/memory/memory_api.h" #include "juno/module.h" #include "juno/status.h" From 77e0f81c2317e2c9b7f1a49dd528ddf699c767d3 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 10:17:35 -0500 Subject: [PATCH 24/34] Update tests/test_queue.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/test_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_queue.c b/tests/test_queue.c index 933440c9..9734c773 100644 --- a/tests/test_queue.c +++ b/tests/test_queue.c @@ -176,7 +176,7 @@ int main(void) static inline JUNO_STATUS_T Queue_SetAt(JUNO_ARRAY_ROOT_T *ptQueue, JUNO_POINTER_T tItem, size_t iIndex) { - uint8_t *iItem = (void *) tItem.pvAddr; + uint8_t *iItem = (uint8_t *) tItem.pvAddr; TEST_ARRAY *ptTestQueue = (TEST_ARRAY *) ptQueue; ptTestQueue->iTestQueue[iIndex] = *iItem; return JUNO_STATUS_SUCCESS; From 12dd4ac992858f3002306ff7daf3620bc90d980a Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 10:18:57 -0500 Subject: [PATCH 25/34] Update src/juno_memory_block.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/juno_memory_block.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index 08be28eb..f9f184d4 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -108,12 +108,6 @@ static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoM // If no freed block is available, allocate a new block if(ptMemBlk->zFreed == 0) { - if(ptMemBlk->zUsed >= ptMemBlk->zLength) - { - tResult.tStatus = JUNO_STATUS_MEMALLOC_ERROR; - JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Allocator full"); - return tResult; - } // Compute the offset for the next available block size_t zNextFreeBlock = ptMemBlk->zUsed * ptMemBlk->zTypeSize; // Place the new block on the free stack From 0ec5c0f07fe03c1152763788764997d86726e25f Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 15:29:05 +0000 Subject: [PATCH 26/34] Make small changes --- examples/minimal_memory_example.c | 2 +- include/juno/ds/array_api.h | 6 +++--- src/juno_memory_block.c | 7 ------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/examples/minimal_memory_example.c b/examples/minimal_memory_example.c index 784ae3d7..177a3b4e 100644 --- a/examples/minimal_memory_example.c +++ b/examples/minimal_memory_example.c @@ -80,7 +80,7 @@ int main(void) { const JUNO_MEMORY_ALLOC_API_T *ptApi = tMemAlloc.tRoot.ptApi; JUNO_RESULT_POINTER_T tPointerResult = ptApi->Get(&tMemAlloc.tRoot, sizeof(USER_DATA_T)); JUNO_ASSERT_SUCCESS(tPointerResult.tStatus, return -1); - + tMemory = tPointerResult.tOk; printf("Memory allocated successfully\n"); // Step 3: Use the memory diff --git a/include/juno/ds/array_api.h b/include/juno/ds/array_api.h index aba6f640..5f521971 100644 --- a/include/juno/ds/array_api.h +++ b/include/juno/ds/array_api.h @@ -24,8 +24,8 @@ This header contains the juno_buff_queue library API @author Robin Onsay */ -#ifndef JUNO_BUFF_API_H -#define JUNO_BUFF_API_H +#ifndef JUNO_ARRAY_API_H +#define JUNO_ARRAY_API_H #include "juno/macros.h" #include "juno/memory/memory_api.h" #include "juno/status.h" @@ -86,5 +86,5 @@ static inline JUNO_STATUS_T JunoDs_ArrayVerify(const JUNO_ARRAY_ROOT_T *ptArray) #ifdef __cplusplus } #endif -#endif // JUNO_BUFF_QUEUE_API_H +#endif // JUNO_ARRAY_API_H diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index f9f184d4..9de9ad09 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -117,13 +117,6 @@ static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoM ptMemBlk->zUsed += 1; } tResult.tOk.ptApi = ptMemBlk->tRoot.ptPointerApi; - // Retrieve the latest free block and update free stack - if(ptMemBlk->zFreed == 0) - { - tResult.tStatus = JUNO_STATUS_ERR; - JUNO_FAIL_MODULE(tResult.tStatus, ptMemBlk, "Free list underflow"); - return tResult; - } tResult.tOk.pvAddr = ptMemBlk->ptMetadata[ptMemBlk->zFreed-1].ptFreeMem; tResult.tOk.zSize = ptMemBlk->zTypeSize; ptMemBlk->zFreed -= 1; From 5fb844b088689b300a1f268f9336cc145b24257a Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 15:56:05 +0000 Subject: [PATCH 27/34] Change to check pointer type --- examples/minimal_memory_example.c | 6 +++--- include/juno/memory/memory_api.h | 2 +- tests/test_memory.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/minimal_memory_example.c b/examples/minimal_memory_example.c index 177a3b4e..d3ba4ab8 100644 --- a/examples/minimal_memory_example.c +++ b/examples/minimal_memory_example.c @@ -15,9 +15,9 @@ typedef struct { // Define the pointer api for this type static JUNO_STATUS_T UserDataCopy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) { - JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tDest, USER_DATA_T); + JUNO_STATUS_T tStatus = JUNO_CHECK_POINTER_TYPE(tDest, USER_DATA_T); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - tStatus = JUNO_ASSERT_POINTER_TYPE(tSrc, USER_DATA_T); + tStatus = JUNO_CHECK_POINTER_TYPE(tSrc, USER_DATA_T); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); USER_DATA_T *ptDest = (USER_DATA_T *)tDest.pvAddr; USER_DATA_T *ptSrc = (USER_DATA_T *)tSrc.pvAddr; @@ -28,7 +28,7 @@ static JUNO_STATUS_T UserDataCopy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) /// Reset the memory at the pointer. This could mean zero-initialization static JUNO_STATUS_T UserDataReset(JUNO_POINTER_T tPointer) { - JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tPointer, USER_DATA_T); + JUNO_STATUS_T tStatus = JUNO_CHECK_POINTER_TYPE(tPointer, USER_DATA_T); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); USER_DATA_T *ptBlock = (USER_DATA_T *)tPointer.pvAddr; *ptBlock = (USER_DATA_T){0}; diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index ce472c5d..c32c87b7 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -60,7 +60,7 @@ struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, ); #define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type)} -#define JUNO_ASSERT_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type))?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR +#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type))?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR struct JUNO_POINTER_API_TAG { diff --git a/tests/test_memory.c b/tests/test_memory.c index b75fa9f8..39fb1309 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -22,9 +22,9 @@ JUNO_MEMORY_BLOCK_METADATA(ptTestMetadata, 10); /// Copy memory from one pointer to another static JUNO_STATUS_T Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) { - JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tDest, TEST_BLOCK_T); + JUNO_STATUS_T tStatus = JUNO_CHECK_POINTER_TYPE(tDest, TEST_BLOCK_T); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); - tStatus = JUNO_ASSERT_POINTER_TYPE(tSrc, TEST_BLOCK_T); + tStatus = JUNO_CHECK_POINTER_TYPE(tSrc, TEST_BLOCK_T); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); TEST_BLOCK_T *ptDest = (TEST_BLOCK_T *)tDest.pvAddr; TEST_BLOCK_T *ptSrc = (TEST_BLOCK_T *)tSrc.pvAddr; @@ -35,7 +35,7 @@ static JUNO_STATUS_T Copy(JUNO_POINTER_T tDest, JUNO_POINTER_T tSrc) /// Reset the memory at the pointer. This could mean zero-initialization static JUNO_STATUS_T Reset(JUNO_POINTER_T tPointer) { - JUNO_STATUS_T tStatus = JUNO_ASSERT_POINTER_TYPE(tPointer, TEST_BLOCK_T); + JUNO_STATUS_T tStatus = JUNO_CHECK_POINTER_TYPE(tPointer, TEST_BLOCK_T); JUNO_ASSERT_SUCCESS(tStatus, return tStatus); TEST_BLOCK_T *ptBlock = (TEST_BLOCK_T *)tPointer.pvAddr; *ptBlock = (TEST_BLOCK_T){0}; From ac513e49d1a3274203921aa6f4ce99929e15e01b Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 15:59:07 +0000 Subject: [PATCH 28/34] Check pointer type also checks aligbnment --- include/juno/memory/memory_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index c32c87b7..bdcaba6d 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -60,7 +60,7 @@ struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, ); #define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type)} -#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type))?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR +#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type) && pointer.zSize % pointer.pvAddr == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR struct JUNO_POINTER_API_TAG { From 2abc6ef1bad20ba3693dd4fac586894e17107da1 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 16:00:49 +0000 Subject: [PATCH 29/34] cast in check pointer --- include/juno/memory/memory_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index bdcaba6d..9b781103 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -60,7 +60,7 @@ struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, ); #define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type)} -#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type) && pointer.zSize % pointer.pvAddr == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR +#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type) && pointer.zSize % (size_t) pointer.pvAddr == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR struct JUNO_POINTER_API_TAG { From dabeb140a726518dcbf2391ef8a9a165b1078003 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 17:01:18 +0000 Subject: [PATCH 30/34] Change cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 002ffdf2..eb5a068b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,7 @@ if(JUNO_SHARED) endif() install( - TARGETS ${JUNO_LIBS} ${JUNO_SHARED_TARGET} ${JUNO_POSIX_TARGET} + TARGETS ${PROJECT_NAME} ${JUNO_SHARED_TARGET} ${JUNO_POSIX_TARGET} EXPORT junoTargets # for later use in find_package() ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # usually “lib” LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} From 4c7660c599ca53a80e4462004691a51aff01c825 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 17:36:01 +0000 Subject: [PATCH 31/34] :sparkles: Fix alignment issue --- .vscode/settings.json | 3 ++- examples/minimal_memory_example.c | 4 +++- include/juno/memory/memory_api.h | 6 ++++-- include/juno/memory/memory_block.h | 2 ++ src/juno_memory_block.c | 11 ++++++++--- tests/test_memory.c | 13 +++++++++++++ 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 033697bd..54efd5c7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -55,6 +55,7 @@ "variant": "cpp", "algorithm": "cpp", "type_traits": "cpp", - "utility": "cpp" + "utility": "cpp", + "memory_api.h": "c" } } \ No newline at end of file diff --git a/examples/minimal_memory_example.c b/examples/minimal_memory_example.c index d3ba4ab8..43c582df 100644 --- a/examples/minimal_memory_example.c +++ b/examples/minimal_memory_example.c @@ -4,9 +4,10 @@ #include "juno/memory/memory_block.h" #include "juno/status.h" #include +#include // Define a simple data structure -typedef struct { +typedef struct USER_DATA_T { int id; char name[32]; float value; @@ -63,6 +64,7 @@ int main(void) { gUserDataMemory, gUserDataMetadata, sizeof(USER_DATA_T), + alignof(USER_DATA_T), 5, ErrorHandler, NULL diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index 9b781103..03955a34 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -30,6 +30,7 @@ #include "juno/status.h" #include "juno/module.h" #include +#include #ifdef __cplusplus extern "C" { @@ -57,10 +58,11 @@ struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, void *pvAddr; /// Size of the allocated memory, in bytes. size_t zSize; + size_t zAlignment; ); -#define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type)} -#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type) && pointer.zSize % (size_t) pointer.pvAddr == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR +#define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type), alignof(type)} +#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type) && (uintptr_t) pointer.pvAddr % pointer.zAlignment == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR struct JUNO_POINTER_API_TAG { diff --git a/include/juno/memory/memory_block.h b/include/juno/memory/memory_block.h index b1707709..e707399a 100644 --- a/include/juno/memory/memory_block.h +++ b/include/juno/memory/memory_block.h @@ -62,6 +62,7 @@ struct JUNO_MEMORY_ALLOC_BLOCK_TAG JUNO_MODULE_DERIVE(JUNO_MEMORY_ALLOC_ROOT_T, uint8_t *pvMemory; ///< Pointer to the allocated memory area. JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata; ///< Array of metadata for each block. size_t zTypeSize; ///< Size of each block element. + size_t zAlignment; size_t zLength; ///< Total number of blocks available. size_t zUsed; ///< Current count of allocated blocks. size_t zFreed; ///< Current count of freed blocks in the free stack. @@ -85,6 +86,7 @@ JUNO_STATUS_T JunoMemory_BlockInit( void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, + size_t zAlignment, size_t zLength, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index 9de9ad09..ce286b99 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -35,7 +35,8 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory) ptJunoMemoryBlock->pvMemory && ptJunoMemoryBlock->ptMetadata && ptJunoMemoryBlock->zLength && - ptJunoMemoryBlock->zTypeSize, + ptJunoMemoryBlock->zTypeSize && + ptJunoMemoryBlock->zAlignment, ptJunoMemoryBlock, "Module does not have all dependencies" ); @@ -119,6 +120,7 @@ static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoM tResult.tOk.ptApi = ptMemBlk->tRoot.ptPointerApi; tResult.tOk.pvAddr = ptMemBlk->ptMetadata[ptMemBlk->zFreed-1].ptFreeMem; tResult.tOk.zSize = ptMemBlk->zTypeSize; + tResult.tOk.zAlignment = ptMemBlk->zAlignment; ptMemBlk->zFreed -= 1; ptMemBlk->ptMetadata[ptMemBlk->zFreed].ptFreeMem = NULL; tResult.tStatus = JunoMemory_PointerVerify(&tResult.tOk); @@ -157,6 +159,7 @@ static JUNO_STATUS_T Juno_MemoryBlkPut(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory, J JUNO_POINTER_T tMemory = *ptMemory; ptMemory->pvAddr = NULL; ptMemory->zSize = 0; + ptMemory->zAlignment = 0; // Calculate start and end addresses for the memory block area void *pvStartAddr = ptMemBlk->pvMemory; void *pvEndAddr = &ptMemBlk->pvMemory[ptMemBlk->zTypeSize * ptMemBlk->zLength]; @@ -227,6 +230,7 @@ JUNO_STATUS_T JunoMemory_BlockInit( void *pvMemory, JUNO_MEMORY_BLOCK_METADATA_T *ptMetadata, size_t zTypeSize, + size_t zAlignment, size_t zLength, JUNO_FAILURE_HANDLER_T pfcnFailureHandler, JUNO_USER_DATA_T *pvFailureUserData @@ -242,13 +246,14 @@ JUNO_STATUS_T JunoMemory_BlockInit( ptJunoMemoryBlock->ptMetadata = ptMetadata; // Set type size and total number of blocks ptJunoMemoryBlock->zTypeSize = zTypeSize; + ptJunoMemoryBlock->zAlignment = zAlignment; ptJunoMemoryBlock->zLength = zLength; // No block is in use yet ptJunoMemoryBlock->zUsed = 0; // Initially, no freed blocks are available ptJunoMemoryBlock->zFreed = 0; // Early validation before Verify performs module checks - if (!ptPointerApi || !pvMemory || !ptMetadata || zTypeSize == 0 || zLength == 0) + if (!ptPointerApi || !pvMemory || !ptMetadata || zTypeSize == 0 || zLength == 0 || zAlignment == 0) { JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Invalid init parameters"); return JUNO_STATUS_ERR; @@ -258,7 +263,7 @@ JUNO_STATUS_T JunoMemory_BlockInit( JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Init size overflow"); return JUNO_STATUS_ERR; } - if (((uintptr_t)pvMemory) % zTypeSize != 0) + if (((uintptr_t)pvMemory) % zAlignment != 0) { JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Init memory pointer misaligned"); return JUNO_STATUS_ERR; diff --git a/tests/test_memory.c b/tests/test_memory.c index 39fb1309..20a415db 100644 --- a/tests/test_memory.c +++ b/tests/test_memory.c @@ -10,6 +10,7 @@ #include #include #include +#include typedef struct TEST_BLOCK_TAG { @@ -67,6 +68,7 @@ static void test_nominal_single_alloc_and_free(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -105,6 +107,7 @@ static void test_nominal_multiple_alloc_and_free(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -165,6 +168,7 @@ static void test_negative_memory_empty(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -212,6 +216,7 @@ static void test_negative_memory_full(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -248,6 +253,7 @@ static void test_invalid_init_parameters(void) NULL, NULL, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -264,6 +270,7 @@ static void test_double_free(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -291,6 +298,7 @@ static void test_free_unallocated(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -311,6 +319,7 @@ static void test_update_memory(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -341,6 +350,7 @@ static void test_generic_memory_get_put(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -372,6 +382,7 @@ static void test_zero_size_allocation(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -392,6 +403,7 @@ static void test_bad_api(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL @@ -426,6 +438,7 @@ static void test_invalid_size_and_addr(void) ptTestBlock, ptTestMetadata, sizeof(TEST_BLOCK_T), + alignof(TEST_BLOCK_T), 10, NULL, NULL From d639ff4db8497e7cd7643fc9a33b08fb68770a4c Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 17:45:08 +0000 Subject: [PATCH 32/34] Fix alignment bug --- src/juno_memory_block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index ce286b99..e38bb9c8 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -48,7 +48,7 @@ static inline JUNO_STATUS_T Verify(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoMemory) "Invalid memory block configuration: size overflow"); return JUNO_STATUS_ERR; } - if (((uintptr_t)ptJunoMemoryBlock->pvMemory) % ptJunoMemoryBlock->zTypeSize != 0) + if (((uintptr_t)ptJunoMemoryBlock->pvMemory) % ptJunoMemoryBlock->zAlignment != 0) { JUNO_FAIL_MODULE(JUNO_STATUS_ERR, ptJunoMemoryBlock, "Invalid memory alignment for block base pointer"); From 902cb14a6ca1cdfcb6c77360b3e85f43ef0bf420 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 18:25:16 +0000 Subject: [PATCH 33/34] i:sparkles: Make minor fixes --- .vscode/settings.json | 5 ++++- include/juno/memory/memory_api.h | 2 +- src/juno_memory_block.c | 6 ++++++ src/juno_time.c | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 54efd5c7..e541b9f2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -56,6 +56,9 @@ "algorithm": "cpp", "type_traits": "cpp", "utility": "cpp", - "memory_api.h": "c" + "memory_api.h": "c", + "compare": "c", + "functional": "c", + "tuple": "c" } } \ No newline at end of file diff --git a/include/juno/memory/memory_api.h b/include/juno/memory/memory_api.h index 03955a34..fc1ac377 100644 --- a/include/juno/memory/memory_api.h +++ b/include/juno/memory/memory_api.h @@ -62,7 +62,7 @@ struct JUNO_POINTER_TAG JUNO_MODULE_LITE_ROOT(JUNO_POINTER_API_T, ); #define Juno_PointerInit(api, type, addr) (JUNO_POINTER_T){api, addr, sizeof(type), alignof(type)} -#define JUNO_CHECK_POINTER_TYPE(pointer, type) (pointer.zSize == sizeof(type) && (uintptr_t) pointer.pvAddr % pointer.zAlignment == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR +#define JUNO_CHECK_POINTER_TYPE(pointer, type) ((pointer.zSize == sizeof(type) && (uintptr_t) pointer.pvAddr % pointer.zAlignment == 0)?JUNO_STATUS_SUCCESS:JUNO_STATUS_ERR) struct JUNO_POINTER_API_TAG { diff --git a/src/juno_memory_block.c b/src/juno_memory_block.c index e38bb9c8..86492e46 100644 --- a/src/juno_memory_block.c +++ b/src/juno_memory_block.c @@ -126,6 +126,12 @@ static JUNO_RESULT_POINTER_T Juno_MemoryBlkGet(JUNO_MEMORY_ALLOC_ROOT_T *ptJunoM tResult.tStatus = JunoMemory_PointerVerify(&tResult.tOk); JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult); tResult.tStatus = tResult.tOk.ptApi->Reset(tResult.tOk); + if (tResult.tStatus != JUNO_STATUS_SUCCESS) { + // Clean up: mark the block as unused and clear the pointer + ptMemBlk->zFreed += 1; + ptMemBlk->ptMetadata[ptMemBlk->zFreed-1].ptFreeMem = tResult.tOk.pvAddr; + tResult.tOk.pvAddr = NULL; + } return tResult; } diff --git a/src/juno_time.c b/src/juno_time.c index 41404493..439530ec 100644 --- a/src/juno_time.c +++ b/src/juno_time.c @@ -3,7 +3,7 @@ #include "juno/time/time_api.h" #include -static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = ((JUNO_TIME_SUBSECONDS_T)~(JUNO_TIME_SUBSECONDS_T)0); +static const JUNO_TIME_SUBSECONDS_T giSUBSECS_MAX = (~(JUNO_TIME_SUBSECONDS_T)0); JUNO_STATUS_T JunoTime_AddTime(JUNO_TIME_ROOT_T *ptTime, JUNO_TIMESTAMP_T *ptRetTime, JUNO_TIMESTAMP_T tTimeToAdd) { From a3783873645483b2e9faa548df0220d0d26f07a5 Mon Sep 17 00:00:00 2001 From: Robin Onsay Date: Thu, 2 Oct 2025 18:26:09 +0000 Subject: [PATCH 34/34] :sparkles: Increment cmake to v1.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb5a068b..5733360c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ option(JUNO_EXAMPLES "Compile Juno Examples" OFF) message("Compiler: ${CMAKE_C_COMPILER}") message("Testing: ${JUNO_TESTS}") -project(juno VERSION 0.42.0 LANGUAGES C CXX) +project(juno VERSION 1.0.0 LANGUAGES C CXX) if(JUNO_API) add_definitions(-DJUNO_API)