From 5e30f8bc3a2052846aba21224e15894573611918 Mon Sep 17 00:00:00 2001 From: Jonathan Hoffstadt Date: Wed, 2 Oct 2024 23:14:29 -0500 Subject: [PATCH] feat: 1.0 --- pl_ds.h | 14 +- pl_json.h | 1167 ++++++++++++++++++++++++++------------------------ pl_log.h | 963 +++++++++++++++++++++-------------------- pl_math.h | 142 +++--- pl_memory.h | 4 +- pl_profile.h | 177 +++++--- pl_stl.h | 10 + pl_test.h | 2 + 8 files changed, 1302 insertions(+), 1177 deletions(-) diff --git a/pl_ds.h b/pl_ds.h index 9ede5cf..f98a31b 100644 --- a/pl_ds.h +++ b/pl_ds.h @@ -3,7 +3,7 @@ * data structures */ -// library version +// library version (format XYYZZ) #define PL_DS_VERSION "1.0.0" #define PL_DS_VERSION_NUM 10000 @@ -125,16 +125,16 @@ HASHMAPS uint64_t pl_hm_hash(const void* pData, size_t szDataSize, uint64_t uSeed); Returns the CRC64 hash of some arbitrary data. - pl__hm_resize: - void pl__hm_resize(plHashMap*, uint32_t); + pl_hm_resize: + void pl_hm_resize(plHashMap*, uint32_t); Resizes the hashmap or frees it if zero is used. pl_hm_free: void pl_hm_free(plHashMap*); Frees the hashmap internal memory. - pl__hm_insert: - void pl__hm_insert(plHashMap*, uint64_t ulKey, uint64_t ulValue); + pl_hm_insert: + void pl_hm_insert(plHashMap*, uint64_t ulKey, uint64_t ulValue); Adds an entry to the hashmap where ulKey is a hashed key (usually a string) and ulValue is the index into the value array. @@ -158,8 +158,8 @@ HASHMAPS bool pl_hm_has_key(plHashMap*, const char*); Same as pl_hm_has_key but performs the hash for you. - pl__hm_insert_str: - void pl__hm_insert_str(plHashMap*, const char* pcKey, uint64_t ulValue); + pl_hm_insert_str: + void pl_hm_insert_str(plHashMap*, const char* pcKey, uint64_t ulValue); Same as pl__hm_insert but performs the hash for you. pl_hm_lookup_str: diff --git a/pl_json.h b/pl_json.h index 477c93e..100e987 100644 --- a/pl_json.h +++ b/pl_json.h @@ -1,6 +1,6 @@ /* pl_json.h - + * simple json library Do this: #define PL_JSON_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation. @@ -12,9 +12,9 @@ #include "pl_json.h" */ -// library version -#define PL_JSON_VERSION "0.2.0" -#define PL_JSON_VERSION_NUM 00200 +// library version (format XYYZZ) +#define PL_JSON_VERSION "1.0.0" +#define PL_JSON_VERSION_NUM 10000 /* Index of this file: @@ -22,7 +22,7 @@ Index of this file: // [SECTION] includes // [SECTION] forward declarations // [SECTION] public api -// [SECTION] internal structs +// [SECTION] enums // [SECTION] jsmn.h // [SECTION] c file */ @@ -34,125 +34,111 @@ Index of this file: #ifndef PL_JSON_H #define PL_JSON_H -#ifndef PL_JSON_MAX_NAME_LENGTH - #define PL_JSON_MAX_NAME_LENGTH 256 -#endif - //----------------------------------------------------------------------------- // [SECTION] includes //----------------------------------------------------------------------------- -#include -#include +#include // uint*_t +#include // bool //----------------------------------------------------------------------------- // [SECTION] forward declarations //----------------------------------------------------------------------------- // basic types -typedef struct _plJsonObject plJsonObject; // opaque pointer +typedef struct _plJsonObject plJsonObject; // opaque pointer to json object // enums -typedef int plJsonType; // internal +typedef int plJsonType; //----------------------------------------------------------------------------- // [SECTION] public api //----------------------------------------------------------------------------- // main -bool pl_load_json (const char* cPtrJson, plJsonObject* tPtrJsonOut); -void pl_unload_json (plJsonObject* tPtrJson); -char* pl_write_json (plJsonObject* tPtrJson, char* pcBuffer, uint32_t* puBufferSize); +bool pl_load_json (const char* pcJson, plJsonObject** pptJsonOut); +void pl_unload_json (plJsonObject**); +plJsonObject* pl_json_new_root_object(const char* pcName); // for writing +char* pl_write_json (plJsonObject*, char* pcBuffer, uint32_t* puBufferSize); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~reading~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // members -plJsonObject* pl_json_member_by_name (plJsonObject* tPtrJson, const char* pcName); -plJsonObject* pl_json_member_by_index (plJsonObject* tPtrJson, uint32_t uIndex); -void pl_json_member_list (plJsonObject* tPtrJson, char** cPtrListOut, uint32_t* uPtrSizeOut, uint32_t* uPtrLength); -bool pl_json_member_exist (plJsonObject* tPtrJson, const char* pcName); +plJsonObject* pl_json_member_by_index(plJsonObject*, uint32_t uIndex); +void pl_json_member_list (plJsonObject*, char** pcListOut, uint32_t* puSizeOut, uint32_t* puLength); +bool pl_json_member_exist (plJsonObject*, const char* pcName); +plJsonType pl_json_get_type (plJsonObject*); // retrieve and cast values (default used if member isn't present) -int pl_json_int_member (plJsonObject* tPtrJson, const char* pcName, int iDefaultValue); -uint32_t pl_json_uint_member (plJsonObject* tPtrJson, const char* pcName, uint32_t uDefaultValue); -float pl_json_float_member (plJsonObject* tPtrJson, const char* pcName, float fDefaultValue); -double pl_json_double_member (plJsonObject* tPtrJson, const char* pcName, double dDefaultValue); -char* pl_json_string_member (plJsonObject* tPtrJson, const char* pcName, char* cPtrDefaultValue, uint32_t uLength); -bool pl_json_bool_member (plJsonObject* tPtrJson, const char* pcName, bool bDefaultValue); -plJsonObject* pl_json_member (plJsonObject* tPtrJson, const char* pcName); -plJsonObject* pl_json_array_member (plJsonObject* tPtrJson, const char* pcName, uint32_t* uPtrSizeOut); +int pl_json_int_member (plJsonObject*, const char* pcName, int iDefaultValue); +uint32_t pl_json_uint_member (plJsonObject*, const char* pcName, uint32_t uDefaultValue); +float pl_json_float_member (plJsonObject*, const char* pcName, float fDefaultValue); +double pl_json_double_member(plJsonObject*, const char* pcName, double dDefaultValue); +char* pl_json_string_member(plJsonObject*, const char* pcName, char* pcDefaultValue, uint32_t uLength); +bool pl_json_bool_member (plJsonObject*, const char* pcName, bool bDefaultValue); +plJsonObject* pl_json_member (plJsonObject*, const char* pcName); +plJsonObject* pl_json_array_member (plJsonObject*, const char* pcName, uint32_t* puSizeOut); // retrieve and cast array values (default used if member isn't present) -void pl_json_int_array_member (plJsonObject* tPtrJson, const char* pcName, int* iPtrOut, uint32_t* uPtrSizeOut); -void pl_json_uint_array_member (plJsonObject* tPtrJson, const char* pcName, uint32_t* uPtrOut, uint32_t* uPtrSizeOut); -void pl_json_float_array_member (plJsonObject* tPtrJson, const char* pcName, float* fPtrOut, uint32_t* uPtrSizeOut); -void pl_json_double_array_member(plJsonObject* tPtrJson, const char* pcName, double* dPtrOut, uint32_t* uPtrSizeOut); -void pl_json_bool_array_member (plJsonObject* tPtrJson, const char* pcName, bool* bPtrOut, uint32_t* uPtrSizeOut); -void pl_json_string_array_member(plJsonObject* tPtrJson, const char* pcName, char** cPtrOut, uint32_t* uPtrSizeOut, uint32_t* uPtrLength); +void pl_json_int_array_member (plJsonObject*, const char* pcName, int* piOut, uint32_t* puSizeOut); +void pl_json_uint_array_member (plJsonObject*, const char* pcName, uint32_t* puOut, uint32_t* puSizeOut); +void pl_json_float_array_member (plJsonObject*, const char* pcName, float* pfOut, uint32_t* puSizeOut); +void pl_json_double_array_member(plJsonObject*, const char* pcName, double* pdOut, uint32_t* puSizeOut); +void pl_json_bool_array_member (plJsonObject*, const char* pcName, bool* pbOut, uint32_t* puSizeOut); +void pl_json_string_array_member(plJsonObject*, const char* pcName, char** pcOut, uint32_t* puSizeOut, uint32_t* puLength); // cast values -int pl_json_as_int (plJsonObject* tPtrJson); -uint32_t pl_json_as_uint (plJsonObject* tPtrJson); -float pl_json_as_float (plJsonObject* tPtrJson); -double pl_json_as_double (plJsonObject* tPtrJson); -const char* pl_json_as_string (plJsonObject* tPtrJson); -bool pl_json_as_bool (plJsonObject* tPtrJson); +int pl_json_as_int (plJsonObject*); +uint32_t pl_json_as_uint (plJsonObject*); +float pl_json_as_float (plJsonObject*); +double pl_json_as_double(plJsonObject*); +const char* pl_json_as_string(plJsonObject*); +bool pl_json_as_bool (plJsonObject*); // cast array values -void pl_json_as_int_array (plJsonObject* tPtrJson, int* iPtrOut, uint32_t* uPtrSizeOut); -void pl_json_as_uint_array (plJsonObject* tPtrJson, uint32_t* uPtrOut, uint32_t* uPtrSizeOut); -void pl_json_as_float_array (plJsonObject* tPtrJson, float* fPtrOut, uint32_t* uPtrSizeOut); -void pl_json_as_double_array (plJsonObject* tPtrJson, double* dPtrOut, uint32_t* uPtrSizeOut); -void pl_json_as_bool_array (plJsonObject* tPtrJson, bool* bPtrOut, uint32_t* uPtrSizeOut); -void pl_json_as_string_array (plJsonObject* tPtrJson, char** cPtrOut, uint32_t* uPtrSizeOut, uint32_t* uPtrLength); +void pl_json_as_int_array (plJsonObject*, int* piOut, uint32_t* puSizeOut); +void pl_json_as_uint_array (plJsonObject*, uint32_t* puOut, uint32_t* puSizeOut); +void pl_json_as_float_array (plJsonObject*, float* pfOut, uint32_t* puSizeOut); +void pl_json_as_double_array(plJsonObject*, double* pdOut, uint32_t* puSizeOut); +void pl_json_as_bool_array (plJsonObject*, bool* bpOut, uint32_t* puSizeOut); +void pl_json_as_string_array(plJsonObject*, char** pcOut, uint32_t* puSizeOut, uint32_t* puLength); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~writing~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -void pl_json_add_int_member (plJsonObject* tPtrJson, const char* pcName, int iValue); -void pl_json_add_uint_member (plJsonObject* tPtrJson, const char* pcName, uint32_t uValue); -void pl_json_add_float_member (plJsonObject* tPtrJson, const char* pcName, float fValue); -void pl_json_add_double_member (plJsonObject* tPtrJson, const char* pcName, double dValue); -void pl_json_add_bool_member (plJsonObject* tPtrJson, const char* pcName, bool bValue); -void pl_json_add_string_member (plJsonObject* tPtrJson, const char* pcName, const char* pcValue); -void pl_json_add_member (plJsonObject* tPtrJson, const char* pcName, plJsonObject* ptValue); -void pl_json_add_member_array (plJsonObject* tPtrJson, const char* pcName, plJsonObject* ptValues, uint32_t uSize); -void pl_json_add_int_array (plJsonObject* tPtrJson, const char* pcName, int* piValues, uint32_t uSize); -void pl_json_add_uint_array (plJsonObject* tPtrJson, const char* pcName, uint32_t* puValues, uint32_t uSize); -void pl_json_add_float_array (plJsonObject* tPtrJson, const char* pcName, float* pfValues, uint32_t uSize); -void pl_json_add_double_array (plJsonObject* tPtrJson, const char* pcName, double* pdValues, uint32_t uSize); -void pl_json_add_bool_array (plJsonObject* tPtrJson, const char* pcName, bool* pbValues, uint32_t uSize); -void pl_json_add_string_array (plJsonObject* tPtrJson, const char* pcName, char** ppcBuffer, uint32_t uSize); +// simple +void pl_json_add_int_member (plJsonObject*, const char* pcName, int); +void pl_json_add_uint_member (plJsonObject*, const char* pcName, uint32_t); +void pl_json_add_float_member (plJsonObject*, const char* pcName, float); +void pl_json_add_double_member(plJsonObject*, const char* pcName, double); +void pl_json_add_bool_member (plJsonObject*, const char* pcName, bool); +void pl_json_add_string_member(plJsonObject*, const char* pcName, const char*); + +// arrays +void pl_json_add_int_array (plJsonObject*, const char* pcName, int*, uint32_t uCount); +void pl_json_add_uint_array (plJsonObject*, const char* pcName, uint32_t*, uint32_t uCount); +void pl_json_add_float_array (plJsonObject*, const char* pcName, float*, uint32_t uCount); +void pl_json_add_double_array(plJsonObject*, const char* pcName, double*, uint32_t uCount); +void pl_json_add_bool_array (plJsonObject*, const char* pcName, bool*, uint32_t uCount); +void pl_json_add_string_array(plJsonObject*, const char* pcName, char**, uint32_t uCount); + +// objects & object arrays +plJsonObject* pl_json_add_member (plJsonObject*, const char* pcName); // returns object to be modified with above commands +plJsonObject* pl_json_add_member_array(plJsonObject*, const char* pcName, uint32_t uCount); // returns array of uCount length //----------------------------------------------------------------------------- -// [SECTION] internal structs +// [SECTION] enums //----------------------------------------------------------------------------- -typedef struct _plJsonObject +enum plJsonType_ { - plJsonType tType; - uint32_t uChildCount; - char acName[PL_JSON_MAX_NAME_LENGTH]; - plJsonObject* sbtChildren; - uint32_t uChildrenFound; - char* sbcBuffer; - char** psbcBuffer; - - union - { - struct - { - uint32_t* sbuValueOffsets; - uint32_t* sbuValueLength; - }; - - struct - { - uint32_t uValueOffset; - uint32_t uValueLength; - }; - }; - -} plJsonObject; + PL_JSON_TYPE_UNSPECIFIED, + PL_JSON_TYPE_STRING, + PL_JSON_TYPE_ARRAY, + PL_JSON_TYPE_NUMBER, + PL_JSON_TYPE_BOOL, + PL_JSON_TYPE_OBJECT, + PL_JSON_TYPE_NULL, +}; #endif //PL_JSON_H @@ -535,9 +521,10 @@ jsmn_init(jsmn_parser* parser) /* Index of this file: // [SECTION] includes +// [SECTION] defines +// [SECTION] internal types // [SECTION] stretchy buffer // [SECTION] internal api -// [SECTION] internal enums // [SECTION] public api implementation // [SECTION] internal api implementation */ @@ -546,9 +533,13 @@ Index of this file: // [SECTION] includes //----------------------------------------------------------------------------- -#include -#include -#include +#include // memset +#include // FLT_MAX +#include // sprintf + +//----------------------------------------------------------------------------- +// [SECTION] defines +//----------------------------------------------------------------------------- #ifndef PL_ASSERT #include @@ -569,6 +560,41 @@ Index of this file: #define PL_JSON_FREE(x) free((x)) #endif +#ifndef PL_JSON_MAX_NAME_LENGTH + #define PL_JSON_MAX_NAME_LENGTH 256 +#endif + +//----------------------------------------------------------------------------- +// [SECTION] internal types +//----------------------------------------------------------------------------- + +typedef struct _plJsonObject +{ + plJsonType tType; + uint32_t uChildCount; + plJsonObject* ptRootObject; + char acName[PL_JSON_MAX_NAME_LENGTH]; + plJsonObject* sbtChildren; + uint32_t uChildrenFound; + char* sbcBuffer; + + union + { + struct + { + uint32_t* sbuValueOffsets; + uint32_t* sbuValueLength; + }; + + struct + { + uint32_t uValueOffset; + uint32_t uValueLength; + }; + }; + +} plJsonObject; + //----------------------------------------------------------------------------- // [SECTION] stretchy buffer //----------------------------------------------------------------------------- @@ -618,10 +644,10 @@ typedef struct } plSbJsonHeader_; static void -pl__sb_json_grow(void** ptrBuffer, size_t szElementSize, size_t szNewItems) +pl__sb_json_grow(void** pBuffer, size_t szElementSize, size_t szNewItems) { - plSbJsonHeader_* ptOldHeader = pl__sb_json_header(*ptrBuffer); + plSbJsonHeader_* ptOldHeader = pl__sb_json_header(*pBuffer); plSbJsonHeader_* ptNewHeader = (plSbJsonHeader_*)PL_JSON_ALLOC((ptOldHeader->uCapacity + szNewItems) * szElementSize + sizeof(plSbJsonHeader_)); memset(ptNewHeader, 0, (ptOldHeader->uCapacity + szNewItems) * szElementSize + sizeof(plSbJsonHeader_)); @@ -629,21 +655,21 @@ pl__sb_json_grow(void** ptrBuffer, size_t szElementSize, size_t szNewItems) { ptNewHeader->uSize = ptOldHeader->uSize; ptNewHeader->uCapacity = ptOldHeader->uCapacity + (uint32_t)szNewItems; - memcpy(&ptNewHeader[1], *ptrBuffer, ptOldHeader->uSize * szElementSize); + memcpy(&ptNewHeader[1], *pBuffer, ptOldHeader->uSize * szElementSize); PL_JSON_FREE(ptOldHeader); - *ptrBuffer = &ptNewHeader[1]; + *pBuffer = &ptNewHeader[1]; } } static void -pl__sb_json_may_grow_(void** ptrBuffer, size_t szElementSize, size_t szNewItems, size_t szMinCapacity) +pl__sb_json_may_grow_(void** pBuffer, size_t szElementSize, size_t szNewItems, size_t szMinCapacity) { - if(*ptrBuffer) + if(*pBuffer) { - plSbJsonHeader_* ptOriginalHeader = pl__sb_json_header(*ptrBuffer); + plSbJsonHeader_* ptOriginalHeader = pl__sb_json_header(*pBuffer); if(ptOriginalHeader->uSize + szNewItems > ptOriginalHeader->uCapacity) { - pl__sb_json_grow(ptrBuffer, szElementSize, szNewItems); + pl__sb_json_grow(pBuffer, szElementSize, szNewItems); } } else // first run @@ -652,7 +678,7 @@ pl__sb_json_may_grow_(void** ptrBuffer, size_t szElementSize, size_t szNewItems, memset(ptHeader, 0, szMinCapacity * szElementSize + sizeof(plSbJsonHeader_)); if(ptHeader) { - *ptrBuffer = &ptHeader[1]; + *pBuffer = &ptHeader[1]; ptHeader->uSize = 0u; ptHeader->uCapacity = (uint32_t)szMinCapacity; } @@ -684,31 +710,27 @@ pl__sb_json_sprintf(char** ppcBuffer, const char* pcFormat, ...) // [SECTION] internal api //----------------------------------------------------------------------------- -static plJsonType pl__get_json_token_object_type(const char* cPtrJson, jsmntok_t* tPtrToken); +static plJsonType pl__get_json_token_object_type(const char* pcJson, jsmntok_t*); static void pl__write_json_object(plJsonObject* ptJson, char* pcBuffer, uint32_t* puBufferSize, uint32_t* puCursor, uint32_t* puDepth); static void pl__check_json_object(plJsonObject* ptJson, uint32_t* puBufferSize, uint32_t* puCursor, uint32_t* puDepth); -//----------------------------------------------------------------------------- -// [SECTION] internal enums -//----------------------------------------------------------------------------- - -enum plJsonType_ -{ - PL_JSON_TYPE_UNSPECIFIED, - PL_JSON_TYPE_STRING, - PL_JSON_TYPE_ARRAY, - PL_JSON_TYPE_NUMBER, - PL_JSON_TYPE_BOOL, - PL_JSON_TYPE_OBJECT, - PL_JSON_TYPE_NULL, -}; - //----------------------------------------------------------------------------- // [SECTION] public api implementation //----------------------------------------------------------------------------- +plJsonObject* +pl_json_new_root_object(const char* pcName) +{ + plJsonObject* ptJson = PL_JSON_ALLOC(sizeof(plJsonObject)); + memset(ptJson, 0, sizeof(plJsonObject)); + ptJson->tType = PL_JSON_TYPE_OBJECT; + ptJson->ptRootObject = ptJson; + strncpy(ptJson->acName, pcName, 256); + return ptJson; +} + bool -pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) +pl_load_json(const char* pcJson, plJsonObject** pptJsonOut) { jsmn_parser tP = {0}; jsmntok_t* sbtTokens = NULL; @@ -719,11 +741,14 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) int iResult = 0; while(true) { - iResult = jsmn_parse(&tP, cPtrJson, strlen(cPtrJson), sbtTokens, pl_sb_json_size(sbtTokens)); + iResult = jsmn_parse(&tP, pcJson, strlen(pcJson), sbtTokens, pl_sb_json_size(sbtTokens)); if(iResult == JSMN_ERROR_INVAL) { + pl_sb_json_free(sbtTokens); PL_ASSERT(false); + return false; + } else if(iResult == JSMN_ERROR_NOMEM) { @@ -731,7 +756,9 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) } else if(iResult == JSMN_ERROR_PART) { + pl_sb_json_free(sbtTokens); PL_ASSERT(false); + return false; } else { @@ -742,13 +769,16 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) uint32_t uLayer = 0; uint32_t uCurrentTokenIndex = 0; plJsonObject** sbtObjectStack = NULL; - tPtrJsonOut->tType = PL_JSON_TYPE_OBJECT; - pl_sb_json_reserve(tPtrJsonOut->sbcBuffer, strlen(cPtrJson)); - tPtrJsonOut->psbcBuffer = &tPtrJsonOut->sbcBuffer; - tPtrJsonOut->uChildCount = sbtTokens[uCurrentTokenIndex].size; - strcpy(tPtrJsonOut->acName, "ROOT"); - pl_sb_json_reserve(tPtrJsonOut->sbtChildren, sbtTokens[uCurrentTokenIndex].size); - pl_sb_json_push(sbtObjectStack, tPtrJsonOut); + *pptJsonOut = PL_JSON_ALLOC(sizeof(plJsonObject)); + memset(*pptJsonOut, 0, sizeof(plJsonObject)); + plJsonObject* ptJsonOut = *pptJsonOut; + ptJsonOut->ptRootObject = ptJsonOut; + ptJsonOut->tType = PL_JSON_TYPE_OBJECT; + pl_sb_json_reserve(ptJsonOut->sbcBuffer, strlen(pcJson)); + ptJsonOut->uChildCount = sbtTokens[uCurrentTokenIndex].size; + strcpy(ptJsonOut->acName, "ROOT"); + pl_sb_json_reserve(ptJsonOut->sbtChildren, sbtTokens[uCurrentTokenIndex].size); + pl_sb_json_push(sbtObjectStack, ptJsonOut); while(uCurrentTokenIndex < (uint32_t)iResult) { @@ -757,33 +787,33 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) else { - plJsonObject* tPtrParentObject = pl_sb_json_top(sbtObjectStack); + plJsonObject* ptParentObject = pl_sb_json_top(sbtObjectStack); - jsmntok_t* tPtrCurrentToken = &sbtTokens[uCurrentTokenIndex]; - jsmntok_t* tPtrNextToken = &sbtTokens[uCurrentTokenIndex + 1]; + jsmntok_t* ptCurrentToken = &sbtTokens[uCurrentTokenIndex]; + jsmntok_t* ptNextToken = &sbtTokens[uCurrentTokenIndex + 1]; - switch (tPtrCurrentToken->type) + switch (ptCurrentToken->type) { // value case JSMN_PRIMITIVE: - if(tPtrParentObject->tType == PL_JSON_TYPE_ARRAY) + if(ptParentObject->tType == PL_JSON_TYPE_ARRAY) { - const uint32_t uBufferLocation = pl_sb_json_size(tPtrJsonOut->sbcBuffer); - pl_sb_json_resize(tPtrJsonOut->sbcBuffer, uBufferLocation + tPtrCurrentToken->end - tPtrCurrentToken->start + 1); - memcpy(&tPtrJsonOut->sbcBuffer[uBufferLocation], &cPtrJson[tPtrCurrentToken->start], tPtrCurrentToken->end - tPtrCurrentToken->start); - pl_sb_json_push(tPtrParentObject->sbuValueOffsets, uBufferLocation); - pl_sb_json_push(tPtrParentObject->sbuValueLength, tPtrCurrentToken->end - tPtrCurrentToken->start); - tPtrParentObject->uChildrenFound++; + const uint32_t uBufferLocation = pl_sb_json_size(ptJsonOut->sbcBuffer); + pl_sb_json_resize(ptJsonOut->sbcBuffer, uBufferLocation + ptCurrentToken->end - ptCurrentToken->start + 1); + memcpy(&ptJsonOut->sbcBuffer[uBufferLocation], &pcJson[ptCurrentToken->start], ptCurrentToken->end - ptCurrentToken->start); + pl_sb_json_push(ptParentObject->sbuValueOffsets, uBufferLocation); + pl_sb_json_push(ptParentObject->sbuValueLength, ptCurrentToken->end - ptCurrentToken->start); + ptParentObject->uChildrenFound++; } else { - const uint32_t uBufferLocation = pl_sb_json_size(tPtrJsonOut->sbcBuffer); - pl_sb_json_resize(tPtrJsonOut->sbcBuffer, uBufferLocation + tPtrCurrentToken->end - tPtrCurrentToken->start + 1); - memcpy(&tPtrJsonOut->sbcBuffer[uBufferLocation], &cPtrJson[tPtrCurrentToken->start], tPtrCurrentToken->end - tPtrCurrentToken->start); - tPtrParentObject->uValueOffset = uBufferLocation; - tPtrParentObject->uValueLength = tPtrCurrentToken->end - tPtrCurrentToken->start; - tPtrParentObject->uChildrenFound++; + const uint32_t uBufferLocation = pl_sb_json_size(ptJsonOut->sbcBuffer); + pl_sb_json_resize(ptJsonOut->sbcBuffer, uBufferLocation + ptCurrentToken->end - ptCurrentToken->start + 1); + memcpy(&ptJsonOut->sbcBuffer[uBufferLocation], &pcJson[ptCurrentToken->start], ptCurrentToken->end - ptCurrentToken->start); + ptParentObject->uValueOffset = uBufferLocation; + ptParentObject->uValueLength = ptCurrentToken->end - ptCurrentToken->start; + ptParentObject->uChildrenFound++; pl_sb_json_pop(sbtObjectStack); } break; @@ -791,25 +821,25 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) case JSMN_STRING: { // value - if(tPtrCurrentToken->size == 0) + if(ptCurrentToken->size == 0) { - if(tPtrParentObject->tType == PL_JSON_TYPE_ARRAY) + if(ptParentObject->tType == PL_JSON_TYPE_ARRAY) { - const uint32_t uBufferLocation = pl_sb_json_size(tPtrJsonOut->sbcBuffer); - pl_sb_json_resize(tPtrJsonOut->sbcBuffer, uBufferLocation + tPtrCurrentToken->end - tPtrCurrentToken->start + 1); - memcpy(&tPtrJsonOut->sbcBuffer[uBufferLocation], &cPtrJson[tPtrCurrentToken->start], tPtrCurrentToken->end - tPtrCurrentToken->start); - pl_sb_json_push(tPtrParentObject->sbuValueOffsets, uBufferLocation); - pl_sb_json_push(tPtrParentObject->sbuValueLength, tPtrCurrentToken->end - tPtrCurrentToken->start); - tPtrParentObject->uChildrenFound++; + const uint32_t uBufferLocation = pl_sb_json_size(ptJsonOut->sbcBuffer); + pl_sb_json_resize(ptJsonOut->sbcBuffer, uBufferLocation + ptCurrentToken->end - ptCurrentToken->start + 1); + memcpy(&ptJsonOut->sbcBuffer[uBufferLocation], &pcJson[ptCurrentToken->start], ptCurrentToken->end - ptCurrentToken->start); + pl_sb_json_push(ptParentObject->sbuValueOffsets, uBufferLocation); + pl_sb_json_push(ptParentObject->sbuValueLength, ptCurrentToken->end - ptCurrentToken->start); + ptParentObject->uChildrenFound++; } else { - const uint32_t uBufferLocation = pl_sb_json_size(tPtrJsonOut->sbcBuffer); - pl_sb_json_resize(tPtrJsonOut->sbcBuffer, uBufferLocation + tPtrCurrentToken->end - tPtrCurrentToken->start + 1); - memcpy(&tPtrJsonOut->sbcBuffer[uBufferLocation], &cPtrJson[tPtrCurrentToken->start], tPtrCurrentToken->end - tPtrCurrentToken->start); - tPtrParentObject->uValueOffset = uBufferLocation; - tPtrParentObject->uValueLength = tPtrCurrentToken->end - tPtrCurrentToken->start; - tPtrParentObject->uChildrenFound++; + const uint32_t uBufferLocation = pl_sb_json_size(ptJsonOut->sbcBuffer); + pl_sb_json_resize(ptJsonOut->sbcBuffer, uBufferLocation + ptCurrentToken->end - ptCurrentToken->start + 1); + memcpy(&ptJsonOut->sbcBuffer[uBufferLocation], &pcJson[ptCurrentToken->start], ptCurrentToken->end - ptCurrentToken->start); + ptParentObject->uValueOffset = uBufferLocation; + ptParentObject->uValueLength = ptCurrentToken->end - ptCurrentToken->start; + ptParentObject->uChildrenFound++; pl_sb_json_pop(sbtObjectStack); } } @@ -818,21 +848,21 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) else { plJsonObject tNewJsonObject = { - pl__get_json_token_object_type(cPtrJson, tPtrNextToken), - (uint32_t)tPtrNextToken->size + pl__get_json_token_object_type(pcJson, ptNextToken), + (uint32_t)ptNextToken->size }; - tNewJsonObject.psbcBuffer = &tPtrJsonOut->sbcBuffer; + tNewJsonObject.ptRootObject = ptJsonOut; if(tNewJsonObject.uChildCount == 0) { tNewJsonObject.uChildrenFound--; } - tPtrParentObject->uChildrenFound++; - strncpy(tNewJsonObject.acName, &cPtrJson[tPtrCurrentToken->start], tPtrCurrentToken->end - tPtrCurrentToken->start); - pl_sb_json_push(tPtrParentObject->sbtChildren, tNewJsonObject); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbtChildren, tPtrNextToken->size); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbuValueOffsets, tPtrNextToken->size); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbuValueLength, tPtrNextToken->size); - pl_sb_json_push(sbtObjectStack, &pl_sb_json_top(tPtrParentObject->sbtChildren)); + ptParentObject->uChildrenFound++; + strncpy(tNewJsonObject.acName, &pcJson[ptCurrentToken->start], ptCurrentToken->end - ptCurrentToken->start); + pl_sb_json_push(ptParentObject->sbtChildren, tNewJsonObject); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbtChildren, ptNextToken->size); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbuValueOffsets, ptNextToken->size); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbuValueLength, ptNextToken->size); + pl_sb_json_push(sbtObjectStack, &pl_sb_json_top(ptParentObject->sbtChildren)); if(tNewJsonObject.tType == PL_JSON_TYPE_ARRAY) { @@ -844,59 +874,61 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) case JSMN_OBJECT: { - if(tPtrParentObject->tType == PL_JSON_TYPE_ARRAY) + if(ptParentObject->tType == PL_JSON_TYPE_ARRAY) { plJsonObject tNewJsonObject = { - pl__get_json_token_object_type(cPtrJson, tPtrCurrentToken), - (uint32_t)tPtrCurrentToken->size + pl__get_json_token_object_type(pcJson, ptCurrentToken), + (uint32_t)ptCurrentToken->size }; - tNewJsonObject.psbcBuffer = &tPtrJsonOut->sbcBuffer; + tNewJsonObject.ptRootObject = ptJsonOut; strcpy(tNewJsonObject.acName, "UNNAMED OBJECT"); - pl_sb_json_push(tPtrParentObject->sbtChildren, tNewJsonObject); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbtChildren, tPtrCurrentToken->size); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbuValueOffsets, tPtrCurrentToken->size); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbuValueLength, tPtrCurrentToken->size); - pl_sb_json_push(sbtObjectStack, &pl_sb_json_top(tPtrParentObject->sbtChildren)); - tPtrParentObject->uChildrenFound++; + pl_sb_json_push(ptParentObject->sbtChildren, tNewJsonObject); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbtChildren, ptCurrentToken->size); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbuValueOffsets, ptCurrentToken->size); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbuValueLength, ptCurrentToken->size); + pl_sb_json_push(sbtObjectStack, &pl_sb_json_top(ptParentObject->sbtChildren)); + ptParentObject->uChildrenFound++; } - else if(tPtrParentObject->tType == PL_JSON_TYPE_OBJECT) + else if(ptParentObject->tType == PL_JSON_TYPE_OBJECT) { // combining key/pair - // tPtrParentObject->uChildrenFound++; + // ptParentObject->uChildrenFound++; } else - { - + { + pl_sb_json_free(sbtTokens); PL_ASSERT(false); // shouldn't be possible + return false; } break; } case JSMN_ARRAY: { - if(tPtrParentObject->tType == PL_JSON_TYPE_ARRAY) + if(ptParentObject->tType == PL_JSON_TYPE_ARRAY) { plJsonObject tNewJsonObject = { - pl__get_json_token_object_type(cPtrJson, tPtrCurrentToken), - (uint32_t)tPtrCurrentToken->size + pl__get_json_token_object_type(pcJson, ptCurrentToken), + (uint32_t)ptCurrentToken->size }; - tNewJsonObject.psbcBuffer = &tPtrJsonOut->sbcBuffer; + tNewJsonObject.ptRootObject = ptJsonOut; strcpy(tNewJsonObject.acName, "UNNAMED ARRAY"); - pl_sb_json_push(tPtrParentObject->sbtChildren, tNewJsonObject); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbtChildren, tPtrCurrentToken->size); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbuValueOffsets, tPtrCurrentToken->size); - pl_sb_json_reserve(pl_sb_json_top(tPtrParentObject->sbtChildren).sbuValueLength, tPtrCurrentToken->size); - pl_sb_json_push(sbtObjectStack, &pl_sb_json_top(tPtrParentObject->sbtChildren)); - tPtrParentObject->uChildrenFound++; + pl_sb_json_push(ptParentObject->sbtChildren, tNewJsonObject); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbtChildren, ptCurrentToken->size); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbuValueOffsets, ptCurrentToken->size); + pl_sb_json_reserve(pl_sb_json_top(ptParentObject->sbtChildren).sbuValueLength, ptCurrentToken->size); + pl_sb_json_push(sbtObjectStack, &pl_sb_json_top(ptParentObject->sbtChildren)); + ptParentObject->uChildrenFound++; } - else if(tPtrParentObject->tType == PL_JSON_TYPE_STRING) + else if(ptParentObject->tType == PL_JSON_TYPE_STRING) { // combining key/pair } else { - // shouldn't be possible - PL_ASSERT(false); + pl_sb_json_free(sbtTokens); + PL_ASSERT(false); // shouldn't be possible + return false; } break; } @@ -913,583 +945,629 @@ pl_load_json(const char* cPtrJson, plJsonObject* tPtrJsonOut) return true; } -void -pl_unload_json(plJsonObject* tPtrJson) +static void +pl__free_json(plJsonObject* ptJson) { - for(uint32_t i = 0; i < pl_sb_json_size(tPtrJson->sbtChildren); i++) - pl_unload_json(&tPtrJson->sbtChildren[i]); + for(uint32_t i = 0; i < pl_sb_json_size(ptJson->sbtChildren); i++) + pl__free_json(&ptJson->sbtChildren[i]); - if(tPtrJson->tType == PL_JSON_TYPE_ARRAY) + if(ptJson->tType == PL_JSON_TYPE_ARRAY) { - pl_sb_json_free(tPtrJson->sbuValueOffsets); - pl_sb_json_free(tPtrJson->sbtChildren); - pl_sb_json_free(tPtrJson->sbuValueLength); + pl_sb_json_free(ptJson->sbuValueOffsets); + pl_sb_json_free(ptJson->sbtChildren); + pl_sb_json_free(ptJson->sbuValueLength); } else { - tPtrJson->uValueOffset = 0; - tPtrJson->uValueLength = 0; + ptJson->uValueOffset = 0; + ptJson->uValueLength = 0; } - tPtrJson->uChildCount = 0; - tPtrJson->uChildrenFound = 0; + ptJson->uChildCount = 0; + ptJson->uChildrenFound = 0; - pl_sb_json_free(tPtrJson->sbcBuffer); + pl_sb_json_free(ptJson->sbcBuffer); - memset(tPtrJson->acName, 0, PL_JSON_MAX_NAME_LENGTH); - tPtrJson->tType = PL_JSON_TYPE_UNSPECIFIED; + memset(ptJson->acName, 0, PL_JSON_MAX_NAME_LENGTH); + ptJson->tType = PL_JSON_TYPE_UNSPECIFIED; +} + +void +pl_unload_json(plJsonObject** pptJson) +{ + plJsonObject* ptJson = *pptJson; + for(uint32_t i = 0; i < pl_sb_json_size(ptJson->sbtChildren); i++) + pl__free_json(&ptJson->sbtChildren[i]); + + if(ptJson->tType == PL_JSON_TYPE_ARRAY) + { + pl_sb_json_free(ptJson->sbuValueOffsets); + pl_sb_json_free(ptJson->sbtChildren); + pl_sb_json_free(ptJson->sbuValueLength); + } + else + { + ptJson->uValueOffset = 0; + ptJson->uValueLength = 0; + } + + ptJson->uChildCount = 0; + ptJson->uChildrenFound = 0; + + pl_sb_json_free(ptJson->sbcBuffer); + + memset(ptJson->acName, 0, PL_JSON_MAX_NAME_LENGTH); + ptJson->tType = PL_JSON_TYPE_UNSPECIFIED; + PL_JSON_FREE(ptJson); + *pptJson = NULL; } char* -pl_write_json(plJsonObject* tPtrJson, char* pcBuffer, uint32_t* puBufferSize) +pl_write_json(plJsonObject* ptJson, char* pcBuffer, uint32_t* puBufferSize) { uint32_t uCursorPosition = 0; uint32_t uDepth = 0; if(pcBuffer) - pl__write_json_object(tPtrJson, pcBuffer, puBufferSize, &uCursorPosition, &uDepth); + pl__write_json_object(ptJson, pcBuffer, puBufferSize, &uCursorPosition, &uDepth); else - pl__check_json_object(tPtrJson, puBufferSize, &uCursorPosition, &uDepth); + pl__check_json_object(ptJson, puBufferSize, &uCursorPosition, &uDepth); *puBufferSize = uCursorPosition; return pcBuffer; } plJsonObject* -pl_json_member_by_name(plJsonObject* tPtrJson, const char* pcName) +pl_json_member_by_name(plJsonObject* ptJson, const char* pcName) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) + for(uint32_t i = 0; i < ptJson->uChildCount; i++) { - if(strncmp(pcName, tPtrJson->sbtChildren[i].acName, strlen(tPtrJson->sbtChildren[i].acName)) == 0) - return &tPtrJson->sbtChildren[i]; + if(strncmp(pcName, ptJson->sbtChildren[i].acName, strlen(ptJson->sbtChildren[i].acName)) == 0) + return &ptJson->sbtChildren[i]; } return NULL; } plJsonObject* -pl_json_member_by_index(plJsonObject* tPtrJson, uint32_t uIndex) +pl_json_member_by_index(plJsonObject* ptJson, uint32_t uIndex) { - PL_ASSERT(uIndex < tPtrJson->uChildCount); - return &tPtrJson->sbtChildren[uIndex]; + if(uIndex < ptJson->uChildCount) + return &ptJson->sbtChildren[uIndex]; + return NULL; } void -pl_json_member_list(plJsonObject* tPtrJson, char** cPtrListOut, uint32_t* uPtrSizeOut, uint32_t* uPtrLength) +pl_json_member_list(plJsonObject* ptJson, char** ppcListOut, uint32_t* puSizeOut, uint32_t* puLength) { - if(cPtrListOut) + if(ppcListOut) { - for(uint32_t i = 0; i < pl_sb_json_size(tPtrJson->sbtChildren); i++) - strcpy(cPtrListOut[i], tPtrJson->sbtChildren[i].acName); + for(uint32_t i = 0; i < pl_sb_json_size(ptJson->sbtChildren); i++) + strcpy(ppcListOut[i], ptJson->sbtChildren[i].acName); } - if(uPtrSizeOut) - *uPtrSizeOut = pl_sb_json_size(tPtrJson->sbtChildren); + if(puSizeOut) + *puSizeOut = pl_sb_json_size(ptJson->sbtChildren); - if(uPtrLength) + if(puLength) { - for(uint32_t i = 0; i < pl_sb_json_size(tPtrJson->sbtChildren); i++) + for(uint32_t i = 0; i < pl_sb_json_size(ptJson->sbtChildren); i++) { - const uint32_t uLength = (uint32_t)strlen(tPtrJson->sbtChildren[i].acName); - if(uLength > *uPtrLength) *uPtrLength = uLength; + const uint32_t uLength = (uint32_t)strlen(ptJson->sbtChildren[i].acName); + if(uLength > *puLength) *puLength = uLength; } } } -bool -pl_json_member_exist(plJsonObject* tPtrJson, const char* pcName) +plJsonType +pl_json_get_type(plJsonObject* ptJson) { - return pl_json_member_by_name(tPtrJson, pcName) != NULL; + return ptJson->tType; +} + +bool +pl_json_member_exist(plJsonObject* ptJson, const char* pcName) +{ + return pl_json_member_by_name(ptJson, pcName) != NULL; } int -pl_json_int_member(plJsonObject* tPtrJson, const char* pcName, int iDefaultValue) +pl_json_int_member(plJsonObject* ptJson, const char* pcName, int iDefaultValue) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - return pl_json_as_int(tPtrMember); + if(ptMember) + return pl_json_as_int(ptMember); return iDefaultValue; } uint32_t -pl_json_uint_member(plJsonObject* tPtrJson, const char* pcName, uint32_t uDefaultValue) +pl_json_uint_member(plJsonObject* ptJson, const char* pcName, uint32_t uDefaultValue) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - return pl_json_as_uint(tPtrMember); + if(ptMember) + return pl_json_as_uint(ptMember); return uDefaultValue; } float -pl_json_float_member(plJsonObject* tPtrJson, const char* pcName, float fDefaultValue) +pl_json_float_member(plJsonObject* ptJson, const char* pcName, float fDefaultValue) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - return pl_json_as_float(tPtrMember); + if(ptMember) + return pl_json_as_float(ptMember); return fDefaultValue; } double -pl_json_double_member(plJsonObject* tPtrJson, const char* pcName, double dDefaultValue) +pl_json_double_member(plJsonObject* ptJson, const char* pcName, double dDefaultValue) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - return pl_json_as_double(tPtrMember); + if(ptMember) + return pl_json_as_double(ptMember); return dDefaultValue; } char* -pl_json_string_member(plJsonObject* tPtrJson, const char* pcName, char* cPtrDefaultValue, uint32_t uLength) +pl_json_string_member(plJsonObject* ptJson, const char* pcName, char* pcDefaultValue, uint32_t uLength) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) + if(ptMember) { - PL_ASSERT(uLength >= tPtrMember->uValueLength); - memset(cPtrDefaultValue, 0, uLength); - strncpy(cPtrDefaultValue, &(*tPtrMember->psbcBuffer)[tPtrMember->uValueOffset], tPtrMember->uValueLength); + if(uLength < ptMember->uValueLength) + return NULL; + memset(pcDefaultValue, 0, uLength); + strncpy(pcDefaultValue, &ptMember->ptRootObject->sbcBuffer[ptMember->uValueOffset], ptMember->uValueLength); } - return cPtrDefaultValue; + return pcDefaultValue; } bool -pl_json_bool_member(plJsonObject* tPtrJson, const char* pcName, bool bDefaultValue) +pl_json_bool_member(plJsonObject* ptJson, const char* pcName, bool bDefaultValue) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - return pl_json_as_bool(tPtrMember); + if(ptMember) + return pl_json_as_bool(ptMember); return bDefaultValue; } plJsonObject* -pl_json_member(plJsonObject* tPtrJson, const char* pcName) +pl_json_member(plJsonObject* ptJson, const char* pcName) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) + if(ptMember) { - PL_ASSERT(tPtrMember->tType == PL_JSON_TYPE_OBJECT); - return tPtrMember; + PL_ASSERT(ptMember->tType == PL_JSON_TYPE_OBJECT); + if(ptMember->tType == PL_JSON_TYPE_OBJECT) + return ptMember; } return NULL; } plJsonObject* -pl_json_array_member(plJsonObject* tPtrJson, const char* pcName, uint32_t* uPtrSizeOut) +pl_json_array_member(plJsonObject* ptJson, const char* pcName, uint32_t* puSizeOut) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); - if(uPtrSizeOut) - *uPtrSizeOut = 0; + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); + if(puSizeOut) + *puSizeOut = 0; - if(tPtrMember) + if(ptMember) { - PL_ASSERT(tPtrMember->tType == PL_JSON_TYPE_ARRAY); - if(uPtrSizeOut) - *uPtrSizeOut = tPtrMember->uChildCount; - return tPtrMember->sbtChildren; + PL_ASSERT(ptMember->tType == PL_JSON_TYPE_ARRAY); + if(ptMember->tType == PL_JSON_TYPE_ARRAY) + { + if(puSizeOut) + *puSizeOut = ptMember->uChildCount; + return ptMember; + } } return NULL; } void -pl_json_int_array_member(plJsonObject* tPtrJson, const char* pcName, int* iPtrOut, uint32_t* uPtrSizeOut) +pl_json_int_array_member(plJsonObject* ptJson, const char* pcName, int* piOut, uint32_t* puSizeOut) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - pl_json_as_int_array(tPtrMember, iPtrOut, uPtrSizeOut); + if(ptMember) + pl_json_as_int_array(ptMember, piOut, puSizeOut); } void -pl_json_uint_array_member(plJsonObject* tPtrJson, const char* pcName, uint32_t* uPtrOut, uint32_t* uPtrSizeOut) +pl_json_uint_array_member(plJsonObject* ptJson, const char* pcName, uint32_t* puOut, uint32_t* puSizeOut) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - pl_json_as_uint_array(tPtrMember, uPtrOut, uPtrSizeOut); + if(ptMember) + pl_json_as_uint_array(ptMember, puOut, puSizeOut); } void -pl_json_float_array_member(plJsonObject* tPtrJson, const char* pcName, float* fPtrOut, uint32_t* uPtrSizeOut) +pl_json_float_array_member(plJsonObject* ptJson, const char* pcName, float* pfOut, uint32_t* puSizeOut) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - pl_json_as_float_array(tPtrMember, fPtrOut, uPtrSizeOut); + if(ptMember) + pl_json_as_float_array(ptMember, pfOut, puSizeOut); } void -pl_json_double_array_member(plJsonObject* tPtrJson, const char* pcName, double* dPtrOut, uint32_t* uPtrSizeOut) +pl_json_double_array_member(plJsonObject* ptJson, const char* pcName, double* pdOut, uint32_t* puSizeOut) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - pl_json_as_double_array(tPtrMember, dPtrOut, uPtrSizeOut); + if(ptMember) + pl_json_as_double_array(ptMember, pdOut, puSizeOut); } void -pl_json_string_array_member(plJsonObject* tPtrJson, const char* pcName, char** cPtrOut, uint32_t* uPtrSizeOut, uint32_t* uPtrLength) +pl_json_string_array_member(plJsonObject* ptJson, const char* pcName, char** pcOut, uint32_t* puSizeOut, uint32_t* puLength) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - pl_json_as_string_array(tPtrMember, cPtrOut, uPtrSizeOut, uPtrLength); + if(ptMember) + pl_json_as_string_array(ptMember, pcOut, puSizeOut, puLength); } void -pl_json_bool_array_member(plJsonObject* tPtrJson, const char* pcName, bool* bPtrOut, uint32_t* uPtrSizeOut) +pl_json_bool_array_member(plJsonObject* ptJson, const char* pcName, bool* pbOut, uint32_t* puSizeOut) { - plJsonObject* tPtrMember = pl_json_member_by_name(tPtrJson, pcName); + plJsonObject* ptMember = pl_json_member_by_name(ptJson, pcName); - if(tPtrMember) - pl_json_as_bool_array(tPtrMember, bPtrOut, uPtrSizeOut); + if(ptMember) + pl_json_as_bool_array(ptMember, pbOut, puSizeOut); } int -pl_json_as_int(plJsonObject* tPtrJson) +pl_json_as_int(plJsonObject* ptJson) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_NUMBER); - return (int)strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->uValueOffset], NULL); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_NUMBER); + if(ptJson->tType == PL_JSON_TYPE_NUMBER) + return (int)strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset], NULL); + return 0; } uint32_t -pl_json_as_uint(plJsonObject* tPtrJson) +pl_json_as_uint(plJsonObject* ptJson) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_NUMBER); - return (uint32_t)strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->uValueOffset], NULL); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_NUMBER); + if(ptJson->tType == PL_JSON_TYPE_NUMBER) + return (uint32_t)strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset], NULL); + return UINT32_MAX; } float -pl_json_as_float(plJsonObject* tPtrJson) +pl_json_as_float(plJsonObject* ptJson) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_NUMBER); - return (float)strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->uValueOffset], NULL); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_NUMBER); + if(ptJson->tType == PL_JSON_TYPE_NUMBER) + return (float)strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset], NULL); + return FLT_MAX; } double -pl_json_as_double(plJsonObject* tPtrJson) +pl_json_as_double(plJsonObject* ptJson) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_NUMBER); - return strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->uValueOffset], NULL); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_NUMBER); + if(ptJson->tType == PL_JSON_TYPE_NUMBER) + return strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset], NULL); + return DBL_MAX; } const char* -pl_json_as_string(plJsonObject* tPtrJson) +pl_json_as_string(plJsonObject* ptJson) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_STRING); - return &(*tPtrJson->psbcBuffer)[tPtrJson->uValueOffset]; + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_STRING); + if(ptJson->tType == PL_JSON_TYPE_STRING) + return &ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset]; + return NULL; } bool -pl_json_as_bool(plJsonObject* tPtrJson) +pl_json_as_bool(plJsonObject* ptJson) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_BOOL); - return (&(*tPtrJson->psbcBuffer)[tPtrJson->uValueOffset])[0] == 't'; + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_BOOL); + if(ptJson->tType == PL_JSON_TYPE_BOOL) + return (&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset])[0] == 't'; + return false; } void -pl_json_as_int_array(plJsonObject* tPtrJson, int* iPtrOut, uint32_t* uPtrSizeOut) +pl_json_as_int_array(plJsonObject* ptJson, int* piOut, uint32_t* puSizeOut) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_ARRAY); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_ARRAY); - if(uPtrSizeOut) - *uPtrSizeOut = tPtrJson->uChildCount; + if(ptJson->tType != PL_JSON_TYPE_ARRAY) + return; - if(iPtrOut) + if(puSizeOut) + *puSizeOut = ptJson->uChildCount; + + if(piOut) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) - iPtrOut[i] = (int)strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->sbuValueOffsets[i]], NULL); + for(uint32_t i = 0; i < ptJson->uChildCount; i++) + piOut[i] = (int)strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]], NULL); } } void -pl_json_as_uint_array(plJsonObject* tPtrJson, uint32_t* uPtrOut, uint32_t* uPtrSizeOut) +pl_json_as_uint_array(plJsonObject* ptJson, uint32_t* puOut, uint32_t* puSizeOut) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_ARRAY); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_ARRAY); - if(uPtrSizeOut) - *uPtrSizeOut = tPtrJson->uChildCount; + if(ptJson->tType != PL_JSON_TYPE_ARRAY) + return; - if(uPtrOut) + if(puSizeOut) + *puSizeOut = ptJson->uChildCount; + + if(puOut) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) - uPtrOut[i] = (uint32_t)strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->sbuValueOffsets[i]], NULL); + for(uint32_t i = 0; i < ptJson->uChildCount; i++) + puOut[i] = (uint32_t)strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]], NULL); } } void -pl_json_as_float_array(plJsonObject* tPtrJson, float* fPtrOut, uint32_t* uPtrSizeOut) +pl_json_as_float_array(plJsonObject* ptJson, float* pfOut, uint32_t* puSizeOut) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_ARRAY); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_ARRAY); - if(uPtrSizeOut) - { - *uPtrSizeOut = tPtrJson->uChildCount; - } + if(ptJson->tType != PL_JSON_TYPE_ARRAY) + return; - if(fPtrOut) + if(puSizeOut) + *puSizeOut = ptJson->uChildCount; + + if(pfOut) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) - fPtrOut[i] = (float)strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->sbuValueOffsets[i]], NULL); + for(uint32_t i = 0; i < ptJson->uChildCount; i++) + pfOut[i] = (float)strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]], NULL); } } void -pl_json_as_double_array(plJsonObject* tPtrJson, double* dPtrOut, uint32_t* uPtrSizeOut) +pl_json_as_double_array(plJsonObject* ptJson, double* pdOut, uint32_t* puSizeOut) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_ARRAY); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_ARRAY); - if(uPtrSizeOut) - *uPtrSizeOut = tPtrJson->uChildCount; + if(ptJson->tType != PL_JSON_TYPE_ARRAY) + return; - if(dPtrOut) + if(puSizeOut) + *puSizeOut = ptJson->uChildCount; + + if(pdOut) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) - dPtrOut[i] = strtod(&(*tPtrJson->psbcBuffer)[tPtrJson->sbuValueOffsets[i]], NULL); + for(uint32_t i = 0; i < ptJson->uChildCount; i++) + pdOut[i] = strtod(&ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]], NULL); } } void -pl_json_as_string_array(plJsonObject* tPtrJson, char** cPtrOut, uint32_t* uPtrSizeOut, uint32_t* uPtrLength) +pl_json_as_string_array(plJsonObject* ptJson, char** pcOut, uint32_t* puSizeOut, uint32_t* puLength) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_ARRAY); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_ARRAY); - if(cPtrOut) + if(ptJson->tType != PL_JSON_TYPE_ARRAY) + return; + + if(pcOut) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) + for(uint32_t i = 0; i < ptJson->uChildCount; i++) { - PL_ASSERT(*uPtrLength >= tPtrJson->sbuValueLength[i]); - memset(cPtrOut[i], 0, *uPtrLength); - strncpy(cPtrOut[i],&(*tPtrJson->psbcBuffer)[tPtrJson->sbuValueOffsets[i]], tPtrJson->sbuValueLength[i]); + PL_ASSERT(*puLength >= ptJson->sbuValueLength[i]); + memset(pcOut[i], 0, *puLength); + strncpy(pcOut[i],&ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]], ptJson->sbuValueLength[i]); } } - else if(uPtrSizeOut) - *uPtrSizeOut = tPtrJson->uChildCount; + else if(puSizeOut) + *puSizeOut = ptJson->uChildCount; - if(uPtrLength) + if(puLength) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) + for(uint32_t i = 0; i < ptJson->uChildCount; i++) { - if(tPtrJson->sbuValueLength[i] > *uPtrLength) - *uPtrLength = tPtrJson->sbuValueLength[i]; + if(ptJson->sbuValueLength[i] > *puLength) + *puLength = ptJson->sbuValueLength[i]; } } } void -pl_json_as_bool_array(plJsonObject* tPtrJson, bool* bPtrOut, uint32_t* uPtrSizeOut) +pl_json_as_bool_array(plJsonObject* ptJson, bool* pbOut, uint32_t* puSizeOut) { - PL_ASSERT(tPtrJson->tType == PL_JSON_TYPE_ARRAY); + PL_ASSERT(ptJson->tType == PL_JSON_TYPE_ARRAY); - if(uPtrSizeOut) - *uPtrSizeOut = tPtrJson->uChildCount; + if(ptJson->tType != PL_JSON_TYPE_ARRAY) + return; - if(bPtrOut) + if(puSizeOut) + *puSizeOut = ptJson->uChildCount; + + if(pbOut) { - for(uint32_t i = 0; i < tPtrJson->uChildCount; i++) - bPtrOut[i] = (&(*tPtrJson->psbcBuffer)[tPtrJson->sbuValueOffsets[i]])[0] == 't'; + for(uint32_t i = 0; i < ptJson->uChildCount; i++) + pbOut[i] = (&ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]])[0] == 't'; } } void -pl_json_add_int_member(plJsonObject* tPtrJson, const char* pcName, int iValue) +pl_json_add_int_member(plJsonObject* ptJson, const char* pcName, int iValue) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; - plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_NUMBER; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; - tNewJsonObject.uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + tNewJsonObject.uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); tNewJsonObject.uValueLength = snprintf(NULL, 0, "%i", iValue); - pl_sb_json_resize(*tPtrJson->psbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); - snprintf(&(*tPtrJson->psbcBuffer)[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength + 1, "%i", iValue); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); + snprintf(&ptJson->ptRootObject->sbcBuffer[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength + 1, "%i", iValue); - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_uint_member(plJsonObject* tPtrJson, const char* pcName, uint32_t uValue) +pl_json_add_uint_member(plJsonObject* ptJson, const char* pcName, uint32_t uValue) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_NUMBER; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; - tNewJsonObject.uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + tNewJsonObject.uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); tNewJsonObject.uValueLength = snprintf(NULL, 0, "%u", uValue); - pl_sb_json_resize(*tPtrJson->psbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); - snprintf(&(*tPtrJson->psbcBuffer)[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, "%u", uValue); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); + snprintf(&ptJson->ptRootObject->sbcBuffer[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, "%u", uValue); - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_float_member(plJsonObject* tPtrJson, const char* pcName, float fValue) +pl_json_add_float_member(plJsonObject* ptJson, const char* pcName, float fValue) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_NUMBER; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; - tNewJsonObject.uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + tNewJsonObject.uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); tNewJsonObject.uValueLength = snprintf(NULL, 0, "%0.7f", fValue); - pl_sb_json_resize(*tPtrJson->psbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); - snprintf(&(*tPtrJson->psbcBuffer)[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, "%0.7f", fValue); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); + snprintf(&ptJson->ptRootObject->sbcBuffer[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, "%0.7f", fValue); - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_double_member(plJsonObject* tPtrJson, const char* pcName, double dValue) +pl_json_add_double_member(plJsonObject* ptJson, const char* pcName, double dValue) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_NUMBER; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; - tNewJsonObject.uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + tNewJsonObject.uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); tNewJsonObject.uValueLength = snprintf(NULL, 0, "%0.15f", dValue); - pl_sb_json_resize(*tPtrJson->psbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); - snprintf(&(*tPtrJson->psbcBuffer)[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, "%0.15f", dValue); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); + snprintf(&ptJson->ptRootObject->sbcBuffer[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, "%0.15f", dValue); - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_bool_member(plJsonObject* tPtrJson, const char* pcName, bool bValue) +pl_json_add_bool_member(plJsonObject* ptJson, const char* pcName, bool bValue) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_BOOL; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; - tNewJsonObject.uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + tNewJsonObject.uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); tNewJsonObject.uValueLength = snprintf(NULL, 0, "%s", bValue ? "true" : "false"); - pl_sb_json_resize(*tPtrJson->psbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); - snprintf(&(*tPtrJson->psbcBuffer)[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, bValue ? "true" : "false"); - - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength); + snprintf(&ptJson->ptRootObject->sbcBuffer[tNewJsonObject.uValueOffset], tNewJsonObject.uValueLength, bValue ? "true" : "false"); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_string_member(plJsonObject* tPtrJson, const char* pcName, const char* pcValue) +pl_json_add_string_member(plJsonObject* ptJson, const char* pcName, const char* pcValue) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_STRING; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; - tNewJsonObject.uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + tNewJsonObject.uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); tNewJsonObject.uValueLength = (uint32_t)strlen(pcValue); - pl_sb_json_resize(*tPtrJson->psbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength + 1); - strncpy(&(*tPtrJson->psbcBuffer)[tNewJsonObject.uValueOffset], pcValue, tNewJsonObject.uValueLength); - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, tNewJsonObject.uValueOffset + tNewJsonObject.uValueLength + 1); + strncpy(&ptJson->ptRootObject->sbcBuffer[tNewJsonObject.uValueOffset], pcValue, tNewJsonObject.uValueLength); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } -void -pl_json_add_member(plJsonObject* tPtrJson, const char* pcName, plJsonObject* ptValue) +plJsonObject* +pl_json_add_member(plJsonObject* ptJson, const char* pcName) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; - - snprintf(ptValue->acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); - pl_sb_json_push(tPtrJson->sbtChildren, *ptValue); + pl_sb_json_add_n(ptJson->sbtChildren, 1); + plJsonObject* ptResult = &pl_sb_json_top(ptJson->sbtChildren); + memset(ptResult, 0, sizeof(plJsonObject)); + snprintf(ptResult->acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); + ptResult->tType = PL_JSON_TYPE_OBJECT; + ptResult->ptRootObject = ptJson->ptRootObject; + return ptResult; } -void -pl_json_add_member_array(plJsonObject* tPtrJson, const char* pcName, plJsonObject* ptValues, uint32_t uSize) +plJsonObject* +pl_json_add_member_array(plJsonObject* ptJson, const char* pcName, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; tNewJsonObject.sbuValueOffsets = NULL; tNewJsonObject.sbtChildren = NULL; pl_sb_json_resize(tNewJsonObject.sbtChildren, uSize); - for(uint32_t i = 0; i < uSize; i++) - tNewJsonObject.sbtChildren[i] = ptValues[i]; - - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + tNewJsonObject.sbtChildren[i].ptRootObject = ptJson->ptRootObject; + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); + return &pl_sb_json_top(ptJson->sbtChildren); } void -pl_json_add_int_array(plJsonObject* tPtrJson, const char* pcName, int* piValues, uint32_t uSize) +pl_json_add_int_array(plJsonObject* ptJson, const char* pcName, int* piValues, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; @@ -1499,34 +1577,31 @@ pl_json_add_int_array(plJsonObject* tPtrJson, const char* pcName, int* piValues, for(uint32_t i = 0; i < uSize; i++) { - const uint32_t uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + const uint32_t uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); const uint32_t uValueLength = snprintf(NULL, 0, "%i", piValues[i]); tNewJsonObject.sbuValueOffsets[i] = uValueOffset; tNewJsonObject.sbuValueLength[i] = uValueLength; - pl_sb_json_resize(*tPtrJson->psbcBuffer, uValueOffset + uValueLength + 1); - snprintf(&(*tPtrJson->psbcBuffer)[uValueOffset], uValueLength + 1, "%i", piValues[i]); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, uValueOffset + uValueLength + 1); + snprintf(&ptJson->ptRootObject->sbcBuffer[uValueOffset], uValueLength + 1, "%i", piValues[i]); } - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_uint_array(plJsonObject* tPtrJson, const char* pcName, uint32_t* puValues, uint32_t uSize) +pl_json_add_uint_array(plJsonObject* ptJson, const char* pcName, uint32_t* puValues, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; @@ -1536,34 +1611,31 @@ pl_json_add_uint_array(plJsonObject* tPtrJson, const char* pcName, uint32_t* puV for(uint32_t i = 0; i < uSize; i++) { - const uint32_t uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + const uint32_t uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); const uint32_t uValueLength = snprintf(NULL, 0, "%u", puValues[i]); tNewJsonObject.sbuValueOffsets[i] = uValueOffset; tNewJsonObject.sbuValueLength[i] = uValueLength; - pl_sb_json_resize(*tPtrJson->psbcBuffer, uValueOffset + uValueLength + 1); - snprintf(&(*tPtrJson->psbcBuffer)[uValueOffset], uValueLength + 1, "%u", puValues[i]); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, uValueOffset + uValueLength + 1); + snprintf(&ptJson->ptRootObject->sbcBuffer[uValueOffset], uValueLength + 1, "%u", puValues[i]); } - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_float_array(plJsonObject* tPtrJson, const char* pcName, float* pfValues, uint32_t uSize) +pl_json_add_float_array(plJsonObject* ptJson, const char* pcName, float* pfValues, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; @@ -1573,34 +1645,31 @@ pl_json_add_float_array(plJsonObject* tPtrJson, const char* pcName, float* pfVal for(uint32_t i = 0; i < uSize; i++) { - const uint32_t uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + const uint32_t uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); const uint32_t uValueLength = snprintf(NULL, 0, "%0.7f", pfValues[i]); tNewJsonObject.sbuValueOffsets[i] = uValueOffset; tNewJsonObject.sbuValueLength[i] = uValueLength; - pl_sb_json_resize(*tPtrJson->psbcBuffer, uValueOffset + uValueLength + 1); - snprintf(&(*tPtrJson->psbcBuffer)[uValueOffset], uValueLength + 1, "%0.7f", pfValues[i]); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, uValueOffset + uValueLength + 1); + snprintf(&ptJson->ptRootObject->sbcBuffer[uValueOffset], uValueLength + 1, "%0.7f", pfValues[i]); } - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_double_array(plJsonObject* tPtrJson, const char* pcName, double* pdValues, uint32_t uSize) +pl_json_add_double_array(plJsonObject* ptJson, const char* pcName, double* pdValues, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; @@ -1610,34 +1679,31 @@ pl_json_add_double_array(plJsonObject* tPtrJson, const char* pcName, double* pdV for(uint32_t i = 0; i < uSize; i++) { - const uint32_t uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + const uint32_t uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); const uint32_t uValueLength = snprintf(NULL, 0, "%0.15f", pdValues[i]); tNewJsonObject.sbuValueOffsets[i] = uValueOffset; tNewJsonObject.sbuValueLength[i] = uValueLength; - pl_sb_json_resize(*tPtrJson->psbcBuffer, uValueOffset + uValueLength + 1); - snprintf(&(*tPtrJson->psbcBuffer)[uValueOffset], uValueLength + 1, "%0.15f", pdValues[i]); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, uValueOffset + uValueLength + 1); + snprintf(&ptJson->ptRootObject->sbcBuffer[uValueOffset], uValueLength + 1, "%0.15f", pdValues[i]); } - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_bool_array(plJsonObject* tPtrJson, const char* pcName, bool* pbValues, uint32_t uSize) +pl_json_add_bool_array(plJsonObject* ptJson, const char* pcName, bool* pbValues, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; @@ -1647,34 +1713,31 @@ pl_json_add_bool_array(plJsonObject* tPtrJson, const char* pcName, bool* pbValue for(uint32_t i = 0; i < uSize; i++) { - const uint32_t uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + const uint32_t uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); const uint32_t uValueLength = snprintf(NULL, 0, "%s", pbValues[i] ? "true" : "false"); tNewJsonObject.sbuValueOffsets[i] = uValueOffset; tNewJsonObject.sbuValueLength[i] = uValueLength; - pl_sb_json_resize(*tPtrJson->psbcBuffer, uValueOffset + uValueLength + 1); - snprintf(&(*tPtrJson->psbcBuffer)[uValueOffset], uValueLength + 1, "%s", pbValues[i] ? "true" : "false"); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, uValueOffset + uValueLength + 1); + snprintf(&ptJson->ptRootObject->sbcBuffer[uValueOffset], uValueLength + 1, "%s", pbValues[i] ? "true" : "false"); } - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } void -pl_json_add_string_array(plJsonObject* tPtrJson, const char* pcName, char** ppcBuffer, uint32_t uSize) +pl_json_add_string_array(plJsonObject* ptJson, const char* pcName, char** ppcBuffer, uint32_t uSize) { - tPtrJson->uChildCount++; - tPtrJson->uChildrenFound++; - tPtrJson->tType = PL_JSON_TYPE_OBJECT; - - if(tPtrJson->psbcBuffer == NULL) - tPtrJson->psbcBuffer = &tPtrJson->sbcBuffer; + ptJson->uChildCount++; + ptJson->uChildrenFound++; + ptJson->tType = PL_JSON_TYPE_OBJECT; plJsonObject tNewJsonObject = {0}; tNewJsonObject.tType = PL_JSON_TYPE_ARRAY; + tNewJsonObject.ptRootObject = ptJson->ptRootObject; snprintf(tNewJsonObject.acName, PL_JSON_MAX_NAME_LENGTH, "%s", pcName); tNewJsonObject.sbcBuffer = NULL; - tNewJsonObject.psbcBuffer = tPtrJson->psbcBuffer; tNewJsonObject.uChildCount = uSize; tNewJsonObject.uChildrenFound = uSize; tNewJsonObject.sbuValueLength = NULL; @@ -1684,17 +1747,17 @@ pl_json_add_string_array(plJsonObject* tPtrJson, const char* pcName, char** ppcB for(uint32_t i = 0; i < uSize; i++) { - const uint32_t uValueOffset = pl_sb_json_size(*tPtrJson->psbcBuffer); + const uint32_t uValueOffset = pl_sb_json_size(ptJson->ptRootObject->sbcBuffer); const uint32_t uValueLength = snprintf(NULL, 0, "\"%s\"", ppcBuffer[i]); tNewJsonObject.sbuValueOffsets[i] = uValueOffset; tNewJsonObject.sbuValueLength[i] = uValueLength; - pl_sb_json_resize(*tPtrJson->psbcBuffer, uValueOffset + uValueLength + 1); - snprintf(&(*tPtrJson->psbcBuffer)[uValueOffset], uValueLength + 1, "\"%s\"", ppcBuffer[i]); + pl_sb_json_resize(ptJson->ptRootObject->sbcBuffer, uValueOffset + uValueLength + 1); + snprintf(&ptJson->ptRootObject->sbcBuffer[uValueOffset], uValueLength + 1, "\"%s\"", ppcBuffer[i]); } - pl_sb_json_push(tPtrJson->sbtChildren, tNewJsonObject); + pl_sb_json_push(ptJson->sbtChildren, tNewJsonObject); } //----------------------------------------------------------------------------- @@ -1702,16 +1765,16 @@ pl_json_add_string_array(plJsonObject* tPtrJson, const char* pcName, char** ppcB //----------------------------------------------------------------------------- static plJsonType -pl__get_json_token_object_type(const char* cPtrJson, jsmntok_t* tPtrToken) +pl__get_json_token_object_type(const char* pcJson, jsmntok_t* ptToken) { - switch (tPtrToken->type) + switch (ptToken->type) { case JSMN_ARRAY: return PL_JSON_TYPE_ARRAY; case JSMN_OBJECT: return PL_JSON_TYPE_OBJECT; case JSMN_STRING: return PL_JSON_TYPE_STRING; case JSMN_PRIMITIVE: - if (cPtrJson[tPtrToken->start] == 'n') { return PL_JSON_TYPE_NULL;} - else if(cPtrJson[tPtrToken->start] == 't' || cPtrJson[tPtrToken->start] == 'f') { return PL_JSON_TYPE_BOOL;} + if (pcJson[ptToken->start] == 'n') { return PL_JSON_TYPE_NULL;} + else if(pcJson[ptToken->start] == 't' || pcJson[ptToken->start] == 'f') { return PL_JSON_TYPE_BOOL;} else { return PL_JSON_TYPE_NUMBER;} default: PL_ASSERT(false); @@ -1739,22 +1802,22 @@ pl__write_json_object(plJsonObject* ptJson, char* pcBuffer, uint32_t* puBufferSi case PL_JSON_TYPE_BOOL: { - int iSizeNeeded = snprintf(NULL, 0, "%s", (&(*ptJson->psbcBuffer)[ptJson->uValueOffset])[0] == 't' ? "true" : "false"); - snprintf(&pcBuffer[uCursorPosition], iSizeNeeded + 1, "%s", (&(*ptJson->psbcBuffer)[ptJson->uValueOffset])[0] == 't' ? "true" : "false"); + int iSizeNeeded = snprintf(NULL, 0, "%s", (&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset])[0] == 't' ? "true" : "false"); + snprintf(&pcBuffer[uCursorPosition], iSizeNeeded + 1, "%s", (&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset])[0] == 't' ? "true" : "false"); uCursorPosition += iSizeNeeded; break; } case PL_JSON_TYPE_NUMBER: { - memcpy(&pcBuffer[uCursorPosition], &(*ptJson->psbcBuffer)[ptJson->uValueOffset], ptJson->uValueLength); + memcpy(&pcBuffer[uCursorPosition], &ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset], ptJson->uValueLength); uCursorPosition += ptJson->uValueLength; break; } case PL_JSON_TYPE_STRING: { - int iSizeNeeded = snprintf(&pcBuffer[uCursorPosition], (int)ptJson->uValueLength + 2 + 1, "\"%s\"", &(*ptJson->psbcBuffer)[ptJson->uValueOffset]); + int iSizeNeeded = snprintf(&pcBuffer[uCursorPosition], (int)ptJson->uValueLength + 2 + 1, "\"%s\"", &ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset]); uCursorPosition += iSizeNeeded; break; } @@ -1817,26 +1880,24 @@ pl__write_json_object(plJsonObject* ptJson, char* pcBuffer, uint32_t* puBufferSi for(uint32_t i = 0; i < ptJson->uChildCount; i++) { - // pl__write_json_object(&ptJson->sbtChildren[i], pcBuffer, &uBufferSize, &uCursorPosition, puDepth); - - const char* cPtrPrevChar = &(*ptJson->psbcBuffer)[ptJson->sbuValueOffsets[i]]; + const char* pcPrevChar = &ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]]; char cPreviousChar = ' '; - if(cPtrPrevChar) + if(pcPrevChar) { - const char* cPtrPrevCharAddr = cPtrPrevChar - 1; - cPreviousChar = cPtrPrevCharAddr[0]; + const char* pcPrevCharAddr = pcPrevChar - 1; + cPreviousChar = pcPrevCharAddr[0]; } if(cPreviousChar == '\"') { int iSizeNeeded2 = ptJson->sbuValueLength[i] + 2; - snprintf(&pcBuffer[uCursorPosition], iSizeNeeded2 + 1, "\"%s\"", &(*ptJson->psbcBuffer)[ptJson->sbuValueOffsets[i]]); + snprintf(&pcBuffer[uCursorPosition], iSizeNeeded2 + 1, "\"%s\"", &ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]]); uCursorPosition += iSizeNeeded2; } else { - memcpy(&pcBuffer[uCursorPosition], &(*ptJson->psbcBuffer)[ptJson->sbuValueOffsets[i]], ptJson->sbuValueLength[i]); + memcpy(&pcBuffer[uCursorPosition], &ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]], ptJson->sbuValueLength[i]); uCursorPosition += ptJson->sbuValueLength[i]; } @@ -1898,7 +1959,7 @@ pl__check_json_object(plJsonObject* ptJson, uint32_t* puBufferSize, uint32_t* pu case PL_JSON_TYPE_BOOL: { - int iSizeNeeded = snprintf(NULL, 0, "%s", (&(*ptJson->psbcBuffer)[ptJson->uValueOffset])[0] == 't' ? "true" : "false"); + int iSizeNeeded = snprintf(NULL, 0, "%s", (&ptJson->ptRootObject->sbcBuffer[ptJson->uValueOffset])[0] == 't' ? "true" : "false"); uCursorPosition += iSizeNeeded; break; } @@ -1959,12 +2020,12 @@ pl__check_json_object(plJsonObject* ptJson, uint32_t* puBufferSize, uint32_t* pu // pl__check_json_object(&ptJson->sbtChildren[i], &uBufferSize, &uCursorPosition, puDepth); - const char* cPtrPrevChar = &(*ptJson->psbcBuffer)[ptJson->sbuValueOffsets[i]]; + const char* pcPrevChar = &ptJson->ptRootObject->sbcBuffer[ptJson->sbuValueOffsets[i]]; char cPreviousChar = ' '; - if(cPtrPrevChar) + if(pcPrevChar) { - const char* cPtrPrevCharAddr = cPtrPrevChar - 1; - cPreviousChar = cPtrPrevCharAddr[0]; + const char* pcPrevCharAddr = pcPrevChar - 1; + cPreviousChar = pcPrevCharAddr[0]; } if(cPreviousChar == '\"') @@ -2003,4 +2064,4 @@ pl__check_json_object(plJsonObject* ptJson, uint32_t* puBufferSize, uint32_t* pu *puCursor = uCursorPosition; } -#endif // PL_JSON_IMPLEMENTATION +#endif // PL_JSON_IMPLEMENTATION \ No newline at end of file diff --git a/pl_log.h b/pl_log.h index 5057e14..321ad37 100644 --- a/pl_log.h +++ b/pl_log.h @@ -1,5 +1,6 @@ /* - pl_log + pl_log.h + * simple logging library Do this: #define PL_LOG_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation. @@ -11,9 +12,9 @@ #include "pl_log.h" */ -// library version -#define PL_LOG_VERSION "0.5.3" -#define PL_LOG_VERSION_NUM 00503 +// library version (format XYYZZ) +#define PL_LOG_VERSION "1.0.0" +#define PL_LOG_VERSION_NUM 10000 /* Index of this file: @@ -23,8 +24,8 @@ Index of this file: // [SECTION] defines // [SECTION] forward declarations & basic types // [SECTION] public api -// [SECTION] enums // [SECTION] structs +// [SECTION] enums // [SECTION] internal api // [SECTION] c file start */ @@ -53,88 +54,68 @@ SETUP Sets the current log context. Mostly used to allow logging across DLL boundaries. - pl_get_log_context: - plLogContext* pl_get_log_context(); - Returns the current log context. - CHANNELS pl_add_log_channel: - uint32_t pl_add_log_channel(const char* pcName, plChannelType tType); + uint64_t pl_add_log_channel(const char* pcName, plLogChannelInit tInfo); Creates a new log channel and returns the ID. pl_set_log_level: void pl_set_log_level(uID, uLevel); Sets the runtime logging level of the uID channel - pl_set_current_log_channel: - void pl_set_current_log_channel(uID); - Sets the current logging channel - - pl_get_current_log_channel: - uint32_t pl_get_current_log_channel(); - Gets the current logging channel - - pl_clear_log_level: - void pl_clear_log_level(uID); + pl_clear_log_channel: + void pl_clear_log_channel(uID); Frees the memory associated with log entries (for buffer channel types). - pl_reset_log_level: - void pl_reset_log_level(uID); + pl_reset_log_channel: + void pl_reset_log_channel(uID); Resets the log channel but does not free the memory. - pl_get_log_entries: - plLogEntry* pl_get_log_entries(uID, uint64_t* puEntryCount); - Returns a pointer to the log entries (or NULL if empty). Fills out puEntryCount - with the count. + pl_get_log_channel_id: + uint64_t pl_get_log_channel_id(const char* pcName); + Returns the ID of the channel with the pcName (or UINT32_MAX if not found) - pl_get_log_channels: - plLogChannel* pl_get_log_channels(uint32_t* puChannelCount); - Returns a pointer to the log channels (or NULL if empty). Fills out puChannelCount - with the count. + pl_get_log_channel_info + bool pl_get_log_channel_info(uint64_t uID, plLogChannelInfo*); + Returns information on a channel (used for visualizing). -SIMPLE LOGGING TO CURRENT CHANNEL + pl_get_log_channel_count: + uint64_t pl_get_log_channel_count(void); + Returns the number of channels (used with the above function to iterate through channel info mostly). + +SIMPLE LOGGING pl_log_trace pl_log_debug pl_log_info pl_log_warn pl_log_error - pl_log_fatal: - void pl_log_*(pcMessage); + pl_log_fatal; + void pl_log_*(uID, pcMessage); Logs at the specified level. No color information. Faster if in a tight loop. -LOGGING TO CURRENT CHANNEL WITH FORMAT SPECIFIERS +LOGGING WITH FORMAT SPECIFIERS pl_log_trace_f pl_log_debug_f pl_log_info_f pl_log_warn_f pl_log_error_f - pl_log_fatal_f: - void pl_log_*_f(pcFormatString, ...); + pl_log_fatal_f; + void pl_log_*_f(uID, pcFormatString, ...); Logs at the specified level. Includes color when console. -SIMPLE LOGGING TO SPECIFIED CHANNEL +CUSTOM LOGGING - pl_log_trace_to - pl_log_debug_to - pl_log_info_to - pl_log_warn_to - pl_log_error_to - pl_log_fatal_to; - void pl_log_*_to(uID, pcMessage); + pl_log; + void pl_log(pcPrefix, iPrefixSize, uLevel, uID, pcMessage); Logs at the specified level. No color information. Faster if in a tight loop. -LOGGING TO SPECIFIED CHANNEL WITH FORMAT SPECIFIERS +CUSTOM LOGGING WITH FORMAT SPECIFIERS - pl_log_trace_to_f - pl_log_debug_to_f - pl_log_info_to_f - pl_log_warn_to_f - pl_log_error_to_f - pl_log_fatal_to_f; - void pl_log_*_to_f(uID, pcFormatString, ...); + pl_log_f; + void pl_log_f(cPrefix, iPrefixSize, uLevel, uID, pcFormatString, ...); Logs at the specified level. Includes color when console. LOG LEVELS @@ -150,23 +131,24 @@ LOG LEVELS COMPILE TIME OPTIONS * Change maximum number of channels, define PL_LOG_MAX_CHANNEL_COUNT. (default is 16) - * Change maximum number of entries for cyclic loggers, define PL_LOG_CYCLIC_BUFFER_SIZE. (default is 256) - * Change initial number of log entries for buffer loggers, define PL_LOG_INITIAL_LOG_SIZE. (default is 1024) + * Change maximum lenght of lines, define PL_LOG_MAX_LINE_SIZE. (default is 1024) * Change the global log level, define PL_GLOBAL_LOG_LEVEL. (default is PL_LOG_LEVEL_ALL) * Change background colors by defining the following: - PL_LOG_TRACE_BG_COLOR - PL_LOG_DEBUG_BG_COLOR - PL_LOG_INFO_BG_COLOR - PL_LOG_WARN_BG_COLOR - PL_LOG_ERROR_BG_COLOR - PL_LOG_FATAL_BG_COLOR + PL_LOG_TRACE_BG_COLOR + PL_LOG_DEBUG_BG_COLOR + PL_LOG_INFO_BG_COLOR + PL_LOG_WARN_BG_COLOR + PL_LOG_ERROR_BG_COLOR + PL_LOG_FATAL_BG_COLOR + PL_LOG_CUSTOM_BG_COLOR * Change foreground colors by defining the following: - PL_LOG_TRACE_FG_COLOR - PL_LOG_DEBUG_FG_COLOR - PL_LOG_INFO_FG_COLOR - PL_LOG_WARN_FG_COLOR - PL_LOG_ERROR_FG_COLOR - PL_LOG_FATAL_FG_COLOR + PL_LOG_TRACE_FG_COLOR + PL_LOG_DEBUG_FG_COLOR + PL_LOG_INFO_FG_COLOR + PL_LOG_WARN_FG_COLOR + PL_LOG_ERROR_FG_COLOR + PL_LOG_FATAL_FG_COLOR + PL_LOG_CUSTOM_FG_COLOR * Use bold by defining the following: PL_LOG_TRACE_BOLD PL_LOG_DEBUG_BOLD @@ -174,6 +156,7 @@ COMPILE TIME OPTIONS PL_LOG_WARN_BOLD PL_LOG_ERROR_BOLD PL_LOG_FATAL_BOLD + PL_LOG_CUSTOM_BOLD * Use underline by defining the following: PL_LOG_TRACE_UNDERLINE PL_LOG_DEBUG_UNDERLINE @@ -181,6 +164,7 @@ COMPILE TIME OPTIONS PL_LOG_WARN_UNDERLINE PL_LOG_ERROR_UNDERLINE PL_LOG_FATAL_UNDERLINE + PL_LOG_CUSTOM_UNDERLINE * Change allocators by defining both: PL_LOG_ALLOC(x) PL_LOG_FREE(x) @@ -232,35 +216,19 @@ BACKGROUND COLOR OPTIONS #ifndef PL_LOG_H #define PL_LOG_H -#ifndef PL_LOG_ALLOC - #include - #define PL_LOG_ALLOC(x) malloc((x)) - #define PL_LOG_FREE(x) free((x)) -#endif - //----------------------------------------------------------------------------- // [SECTION] includes //----------------------------------------------------------------------------- -#include -#include +#include // size_t +#include // uint*_t +#include // var args +#include // bool //----------------------------------------------------------------------------- // [SECTION] defines //----------------------------------------------------------------------------- -#ifndef PL_LOG_MAX_LINE_SIZE - #define PL_LOG_MAX_LINE_SIZE 1024 -#endif - -#ifndef PL_LOG_CYCLIC_BUFFER_SIZE - #define PL_LOG_CYCLIC_BUFFER_SIZE 256 -#endif - -#ifndef PL_LOG_INITIAL_LOG_SIZE - #define PL_LOG_INITIAL_LOG_SIZE 1024 -#endif - #define PL_LOG_LEVEL_ALL 0 #define PL_LOG_LEVEL_TRACE 5000 #define PL_LOG_LEVEL_DEBUG 6000 @@ -284,8 +252,10 @@ BACKGROUND COLOR OPTIONS //----------------------------------------------------------------------------- // forward declarations -typedef struct _plLogContext plLogContext; // opaque struct -typedef struct _plLogEntry plLogEntry; // represents a single entry for "buffer" channel types +typedef struct _plLogContext plLogContext; // opaque struct +typedef struct _plLogChannelInit plLogChannelInit; // information to initialize a channel +typedef struct _plLogEntry plLogEntry; // represents a single entry for "buffer" channel types +typedef struct _plLogChannelInfo plLogChannelInfo; // information about a channel used mostly for visualization // enums typedef int plChannelType; @@ -297,137 +267,113 @@ typedef int plChannelType; #ifdef PL_LOG_ON // setup/shutdown - #define pl_create_log_context() pl__create_log_context() - #define pl_cleanup_log_context() pl__cleanup_log_context() + #define pl_create_log_context() pl__create_log_context() + #define pl_cleanup_log_context() pl__cleanup_log_context() #define pl_set_log_context(tPContext) pl__set_log_context((tPContext)) - #define pl_get_log_context() pl__get_log_context() // channels - #define pl_add_log_channel(pcName, tType) pl__add_log_channel((pcName), (tType)) - #define pl_set_log_level(uID, uLevel) pl__set_log_level((uID), (uLevel)) - #define pl_set_current_log_channel(uID) pl__set_current_log_channel((uID)) - #define pl_get_current_log_channel() pl__get_current_log_channel() - #define pl_clear_log_channel(uID) pl__clear_log_channel((uID)) - #define pl_reset_log_channel(uID) pl__reset_log_channel((uID)) - #define pl_get_log_entries(uID, puEntryCount) pl__get_log_entries((uID), (puEntryCount)) - #define pl_get_log_channels(puChannelCount) pl__get_log_channels((puChannelCount)) + #define pl_add_log_channel(pcName, tInfo) pl__add_log_channel((pcName), (tInfo)) + #define pl_set_log_level(uID, uLevel) pl__set_log_level((uID), (uLevel)) + #define pl_clear_log_channel(uID) pl__clear_log_channel((uID)) + #define pl_reset_log_channel(uID) pl__reset_log_channel((uID)) + #define pl_get_log_channel_count() pl__get_log_channel_count() + #define pl_get_log_channel_id(pcName) pl__get_log_channel_id((pcName)) + #define pl_get_log_channel_info(uID, ptInfoOut) pl__get_log_channel_info((uID), (ptInfoOut)) + + // custom levels + #define pl_log(pcPrefix, iPrefixSize, uLevel, uID, pcMessage) pl__log(pcPrefix, iPrefixSize, uLevel, uID, pcMessage) + #define pl_log_f(...) pl__log_p(__VA_ARGS__) #endif // PL_LOG_ON #if PL_GLOBAL_LOG_LEVEL < PL_LOG_LEVEL_TRACE + 1 && defined(PL_LOG_ON) - #define pl_log_trace(pcMessage) pl__log_trace(pl__get_current_log_channel(), (pcMessage)) - #define pl_log_trace_f(...) pl__log_trace_p(pl__get_current_log_channel(), __VA_ARGS__) - #define pl_log_trace_to(uID, pcMessage) pl__log_trace((uID), (pcMessage)) - #define pl_log_trace_to_f(...) pl__log_trace_p(__VA_ARGS__) + #define pl_log_trace(uID, pcMessage) pl__log_trace((uID), (pcMessage)) + #define pl_log_trace_f(...) pl__log_trace_p(__VA_ARGS__) #else - #define pl_log_trace(pcMessage) // + #define pl_log_trace(uID, pcMessage) // #define pl_log_trace_f(...) // - #define pl_log_trace_to(uID, pcMessage) // - #define pl_log_trace_to_f(...) // #endif #if PL_GLOBAL_LOG_LEVEL < PL_LOG_LEVEL_DEBUG + 1 && defined(PL_LOG_ON) - #define pl_log_debug(pcMessage) pl__log_debug(pl__get_current_log_channel(), (pcMessage)) - #define pl_log_debug_f(...) pl__log_debug_p(pl__get_current_log_channel(), __VA_ARGS__) - #define pl_log_debug_to(uID, pcMessage) pl__log_debug((uID), (pcMessage)) - #define pl_log_debug_to_f(...) pl__log_debug_p(__VA_ARGS__) + #define pl_log_debug(uID, pcMessage) pl__log_debug((uID), (pcMessage)) + #define pl_log_debug_f(...) pl__log_debug_p(__VA_ARGS__) #else - #define pl_log_debug(pcMessage) // + #define pl_log_debug(uID, pcMessage) // #define pl_log_debug_f(...) // - #define pl_log_debug_to(uID, pcMessage) // - #define pl_log_debug_to_f(...) // #endif #if PL_GLOBAL_LOG_LEVEL < PL_LOG_LEVEL_INFO + 1 && defined(PL_LOG_ON) - #define pl_log_info(pcMessage) pl__log_info(pl__get_current_log_channel(), (pcMessage)) - #define pl_log_info_f(...) pl__log_info_p(pl__get_current_log_channel(), __VA_ARGS__) - #define pl_log_info_to(uID, pcMessage) pl__log_info((uID), (pcMessage)) - #define pl_log_info_to_f(...) pl__log_info_p(__VA_ARGS__) + #define pl_log_info(uID, pcMessage) pl__log_info((uID), (pcMessage)) + #define pl_log_info_f(...) pl__log_info_p(__VA_ARGS__) #else - #define pl_log_info(pcMessage) // + #define pl_log_info(uID, pcMessage) // #define pl_log_info_f(...) // - #define pl_log_info_to(uID, pcMessage) // - #define pl_log_info_to_f(...) // #endif #if PL_GLOBAL_LOG_LEVEL < PL_LOG_LEVEL_WARN + 1 && defined(PL_LOG_ON) - #define pl_log_warn(pcMessage) pl__log_warn(pl__get_current_log_channel(), (pcMessage)) - #define pl_log_warn_f(...) pl__log_warn_p(pl__get_current_log_channel(), __VA_ARGS__) - #define pl_log_warn_to(uID, pcMessage) pl__log_warn((uID), (pcMessage)) - #define pl_log_warn_to_f(...) pl__log_warn_p(__VA_ARGS__) + #define pl_log_warn(uID, pcMessage) pl__log_warn((uID), (pcMessage)) + #define pl_log_warn_f(...) pl__log_warn_p(__VA_ARGS__) #else - #define pl_log_warn(pcMessage) // + #define pl_log_warn(tPContext, uID) // #define pl_log_warn_f(...) // - #define pl_log_warn_to(tPContext, uID) // - #define pl_log_warn_to_f(...) // #endif #if PL_GLOBAL_LOG_LEVEL < PL_LOG_LEVEL_ERROR + 1 && defined(PL_LOG_ON) - #define pl_log_error(pcMessage) pl__log_error(pl__get_current_log_channel(), (pcMessage)) - #define pl_log_error_f(...) pl__log_error_p(pl__get_current_log_channel(), __VA_ARGS__) - #define pl_log_error_to(uID, pcMessage) pl__log_error((uID), (pcMessage)) - #define pl_log_error_to_f(...) pl__log_error_p(__VA_ARGS__) + #define pl_log_error(uID, pcMessage) pl__log_error((uID), (pcMessage)) + #define pl_log_error_f(...) pl__log_error_p(__VA_ARGS__) #else - #define pl_log_error(pcMessage) // + #define pl_log_error(tPContext, uID) // #define pl_log_error_f(...) // - #define pl_log_error_to(tPContext, uID) // - #define pl_log_error_to_f(...) // #endif #if PL_GLOBAL_LOG_LEVEL < PL_LOG_LEVEL_FATAL + 1 && defined(PL_LOG_ON) - #define pl_log_fatal(pcMessage) pl__log_fatal(pl__get_current_log_channel(), (pcMessage)) - #define pl_log_fatal_f(...) pl__log_fatal_p(pl__get_current_log_channel(), __VA_ARGS__) - #define pl_log_fatal_to(uID, pcMessage) pl__log_fatal((uID), (pcMessage)) - #define pl_log_fatal_to_f(...) pl__log_fatal_p(__VA_ARGS__) + #define pl_log_fatal(uID, pcMessage) pl__log_fatal((uID), (pcMessage)) + #define pl_log_fatal_f(...) pl__log_fatal_p(__VA_ARGS__) #else - #define pl_log_fatal(pcMessage) // + #define pl_log_fatal(uID, pcMessage) // #define pl_log_fatal_f(...) // - #define pl_log_fatal_to(uID, pcMessage) // - #define pl_log_fatal_to_f(...) // #endif +//----------------------------------------------------------------------------- +// [SECTION] structs +//----------------------------------------------------------------------------- + +typedef struct _plLogChannelInit +{ + plChannelType tType; + uint64_t uEntryCount; // default: 1024 +} plLogChannelInit; + +typedef struct _plLogEntry +{ + uint64_t uLevel; + uint64_t uOffset; +} plLogEntry; + +typedef struct _plLogChannelInfo +{ + uint64_t uID; + plChannelType tType; + const char* pcName; + size_t szBufferSize; + char* pcBuffer; + uint64_t uEntryCount; + uint64_t uEntryCapacity; + plLogEntry* ptEntries; +} plLogChannelInfo; + //----------------------------------------------------------------------------- // [SECTION] enums //----------------------------------------------------------------------------- enum plChannelType_ { - PL_CHANNEL_TYPE_DEFAULT = 0, - PL_CHANNEL_TYPE_CONSOLE = 1 << 0, - PL_CHANNEL_TYPE_BUFFER = 1 << 1, - PL_CHANNEL_TYPE_CYCLIC_BUFFER = 1 << 2 + PL_CHANNEL_TYPE_DEFAULT = 0, + PL_CHANNEL_TYPE_CONSOLE = 1 << 0, + PL_CHANNEL_TYPE_BUFFER = 1 << 1, + PL_CHANNEL_TYPE_CYCLIC_BUFFER = 1 << 2 }; -//----------------------------------------------------------------------------- -// [SECTION] structs -//----------------------------------------------------------------------------- - -typedef struct _plLogEntry -{ - uint32_t uLevel; - uint64_t uOffset; - uint64_t uGeneration; -} plLogEntry; - -typedef struct _plLogChannel -{ - const char* pcName; - bool bOverflowInUse; - char* pcBuffer0; - char* pcBuffer1; - uint64_t uGeneration; - uint64_t uBufferSize; - uint64_t uBufferCapacity; - plLogEntry atEntries[PL_LOG_CYCLIC_BUFFER_SIZE]; - plLogEntry* pEntries; - uint64_t uEntryCount; - uint64_t uEntryCapacity; - uint64_t uNextEntry; - uint32_t uLevel; - plChannelType tType; - uint32_t uID; -} plLogChannel; - //----------------------------------------------------------------------------- // [SECTION] internal api //----------------------------------------------------------------------------- @@ -435,54 +381,55 @@ typedef struct _plLogChannel // setup/shutdown plLogContext* pl__create_log_context (void); void pl__cleanup_log_context(void); -void pl__set_log_context (plLogContext* tPContext); -plLogContext* pl__get_log_context (void); +void pl__set_log_context (plLogContext*); // channels -uint32_t pl__add_log_channel (const char* pcName, plChannelType tType); -uint32_t pl__get_current_log_channel(void); -void pl__set_current_log_channel(uint32_t uID); -void pl__set_log_level (uint32_t uID, uint32_t uLevel); -void pl__clear_log_channel (uint32_t uID); -void pl__reset_log_channel (uint32_t uID); -plLogEntry* pl__get_log_entries (uint32_t uID, uint64_t* puEntryCount); -plLogChannel* pl__get_log_channels (uint32_t* puChannelCount); +uint64_t pl__add_log_channel (const char* pcName, plLogChannelInit); +void pl__set_log_level (uint64_t uID, uint64_t uLevel); +void pl__clear_log_channel (uint64_t uID); +void pl__reset_log_channel (uint64_t uID); +uint64_t pl__get_log_channel_id (const char* pcName); +bool pl__get_log_channel_info (uint64_t uID, plLogChannelInfo*); +uint64_t pl__get_log_channel_count(void); // logging -void pl__log_trace(uint32_t uID, const char* pcMessage); -void pl__log_debug(uint32_t uID, const char* pcMessage); -void pl__log_info (uint32_t uID, const char* pcMessage); -void pl__log_warn (uint32_t uID, const char* pcMessage); -void pl__log_error(uint32_t uID, const char* pcMessage); -void pl__log_fatal(uint32_t uID, const char* pcMessage); +void pl__log (const char* pcPrefix, int iPrefixSize, uint64_t uLevel, uint64_t uID, const char* pcMessage); +void pl__log_trace(uint64_t uID, const char* pcMessage); +void pl__log_debug(uint64_t uID, const char* pcMessage); +void pl__log_info (uint64_t uID, const char* pcMessage); +void pl__log_warn (uint64_t uID, const char* pcMessage); +void pl__log_error(uint64_t uID, const char* pcMessage); +void pl__log_fatal(uint64_t uID, const char* pcMessage); -void pl__log_trace_p(uint32_t uID, const char* cPFormat, ...); -void pl__log_debug_p(uint32_t uID, const char* cPFormat, ...); -void pl__log_info_p (uint32_t uID, const char* cPFormat, ...); -void pl__log_warn_p (uint32_t uID, const char* cPFormat, ...); -void pl__log_error_p(uint32_t uID, const char* cPFormat, ...); -void pl__log_fatal_p(uint32_t uID, const char* cPFormat, ...); +void pl__log_p (const char* pcPrefix, int iPrefixSize, uint64_t uLevel, uint64_t uID, const char* cPFormat, ...); +void pl__log_trace_p(uint64_t uID, const char* cPFormat, ...); +void pl__log_debug_p(uint64_t uID, const char* cPFormat, ...); +void pl__log_info_p (uint64_t uID, const char* cPFormat, ...); +void pl__log_warn_p (uint64_t uID, const char* cPFormat, ...); +void pl__log_error_p(uint64_t uID, const char* cPFormat, ...); +void pl__log_fatal_p(uint64_t uID, const char* cPFormat, ...); -void pl__log_trace_va(uint32_t uID, const char* cPFormat, va_list args); -void pl__log_debug_va(uint32_t uID, const char* cPFormat, va_list args); -void pl__log_info_va (uint32_t uID, const char* cPFormat, va_list args); -void pl__log_warn_va (uint32_t uID, const char* cPFormat, va_list args); -void pl__log_error_va(uint32_t uID, const char* cPFormat, va_list args); -void pl__log_fatal_va(uint32_t uID, const char* cPFormat, va_list args); +void pl__log_va (const char* pcPrefix, int iPrefixSize, uint64_t uLevel, uint64_t uID, const char* cPFormat, va_list args); +void pl__log_trace_va(uint64_t uID, const char* cPFormat, va_list args); +void pl__log_debug_va(uint64_t uID, const char* cPFormat, va_list args); +void pl__log_info_va (uint64_t uID, const char* cPFormat, va_list args); +void pl__log_warn_va (uint64_t uID, const char* cPFormat, va_list args); +void pl__log_error_va(uint64_t uID, const char* cPFormat, va_list args); +void pl__log_fatal_va(uint64_t uID, const char* cPFormat, va_list args); #ifndef PL_LOG_ON #define pl_create_log_context() NULL #define pl_cleanup_log_context() // #define pl_set_log_context(ctx) // - #define pl_get_log_context() NULL - #define pl_add_log_channel(pcName, tType) 0u + #define pl_add_log_channel(pcName, tInfo) 0u #define pl_set_log_level(uID, uLevel) // #define pl_clear_log_channel(uID) // #define pl_reset_log_channel(uID) // - #define pl_get_log_entries(uID, puEntryCount) NULL - #define pl_set_current_log_channel(uID) // - #define pl_get_current_log_channel(uID) 0 - #define pl_get_log_channels(puChannelCount) NULL + #define pl_get_log_channel_count() 0 + #define pl_get_log_channel_id(pcName) 0 + #define pl_get_log_channel_info(uID, ptInfo) false + #define pl_log(pcPrefix, iPrefixSize, uLevel, uID, pcMessage) // + #define pl_log_f(...) // #endif #endif // PL_LOG_H @@ -499,7 +446,6 @@ Index of this file: // [SECTION] global context // [SECTION] internal api // [SECTION] public api implementation -// [SECTION] internal api implementation */ //----------------------------------------------------------------------------- @@ -508,88 +454,98 @@ Index of this file: #ifdef PL_LOG_IMPLEMENTATION +#ifndef PL_LOG_ALLOC + #include + #define PL_LOG_ALLOC(x) malloc((x)) + #define PL_LOG_FREE(x) free((x)) +#endif + #ifndef PL_LOG_MAX_CHANNEL_COUNT #define PL_LOG_MAX_CHANNEL_COUNT 16 #endif +#ifndef PL_LOG_MAX_LINE_SIZE + #define PL_LOG_MAX_LINE_SIZE 1024 +#endif + #ifdef _WIN32 -#define PL_LOG_BOLD_CODE "" -#define PL_LOG_UNDERLINE_CODE "" -#define PL_LOG_POP_CODE "" + #define PL_LOG_BOLD_CODE "" + #define PL_LOG_UNDERLINE_CODE "" + #define PL_LOG_POP_CODE "" -#define PL_LOG_FG_COLOR_CODE_BLACK "" -#define PL_LOG_FG_COLOR_CODE_RED "" -#define PL_LOG_FG_COLOR_CODE_GREEN "" -#define PL_LOG_FG_COLOR_CODE_YELLOW "" -#define PL_LOG_FG_COLOR_CODE_BLUE "" -#define PL_LOG_FG_COLOR_CODE_MAGENTA "" -#define PL_LOG_FG_COLOR_CODE_CYAN "" -#define PL_LOG_FG_COLOR_CODE_WHITE "" -#define PL_LOG_FG_COLOR_CODE_STRONG_BLACK "" -#define PL_LOG_FG_COLOR_CODE_STRONG_RED "" -#define PL_LOG_FG_COLOR_CODE_STRONG_GREEN "" -#define PL_LOG_FG_COLOR_CODE_STRONG_YELLOW "" -#define PL_LOG_FG_COLOR_CODE_STRONG_BLUE "" -#define PL_LOG_FG_COLOR_CODE_STRONG_MAGENTA "" -#define PL_LOG_FG_COLOR_CODE_STRONG_CYAN "" -#define PL_LOG_FG_COLOR_CODE_STRONG_WHITE "" + #define PL_LOG_FG_COLOR_CODE_BLACK "" + #define PL_LOG_FG_COLOR_CODE_RED "" + #define PL_LOG_FG_COLOR_CODE_GREEN "" + #define PL_LOG_FG_COLOR_CODE_YELLOW "" + #define PL_LOG_FG_COLOR_CODE_BLUE "" + #define PL_LOG_FG_COLOR_CODE_MAGENTA "" + #define PL_LOG_FG_COLOR_CODE_CYAN "" + #define PL_LOG_FG_COLOR_CODE_WHITE "" + #define PL_LOG_FG_COLOR_CODE_STRONG_BLACK "" + #define PL_LOG_FG_COLOR_CODE_STRONG_RED "" + #define PL_LOG_FG_COLOR_CODE_STRONG_GREEN "" + #define PL_LOG_FG_COLOR_CODE_STRONG_YELLOW "" + #define PL_LOG_FG_COLOR_CODE_STRONG_BLUE "" + #define PL_LOG_FG_COLOR_CODE_STRONG_MAGENTA "" + #define PL_LOG_FG_COLOR_CODE_STRONG_CYAN "" + #define PL_LOG_FG_COLOR_CODE_STRONG_WHITE "" -#define PL_LOG_BG_COLOR_CODE_BLACK "" -#define PL_LOG_BG_COLOR_CODE_RED "" -#define PL_LOG_BG_COLOR_CODE_GREEN "" -#define PL_LOG_BG_COLOR_CODE_YELLOW "" -#define PL_LOG_BG_COLOR_CODE_BLUE "" -#define PL_LOG_BG_COLOR_CODE_MAGENTA "" -#define PL_LOG_BG_COLOR_CODE_CYAN "" -#define PL_LOG_BG_COLOR_CODE_WHITE "" -#define PL_LOG_BG_COLOR_CODE_STRONG_BLACK "" -#define PL_LOG_BG_COLOR_CODE_STRONG_RED "" -#define PL_LOG_BG_COLOR_CODE_STRONG_GREEN "" -#define PL_LOG_BG_COLOR_CODE_STRONG_YELLOW "" -#define PL_LOG_BG_COLOR_CODE_STRONG_BLUE "" -#define PL_LOG_BG_COLOR_CODE_STRONG_MAGENTA "" -#define PL_LOG_BG_COLOR_CODE_STRONG_CYAN "" -#define PL_LOG_BG_COLOR_CODE_STRONG_WHITE "" + #define PL_LOG_BG_COLOR_CODE_BLACK "" + #define PL_LOG_BG_COLOR_CODE_RED "" + #define PL_LOG_BG_COLOR_CODE_GREEN "" + #define PL_LOG_BG_COLOR_CODE_YELLOW "" + #define PL_LOG_BG_COLOR_CODE_BLUE "" + #define PL_LOG_BG_COLOR_CODE_MAGENTA "" + #define PL_LOG_BG_COLOR_CODE_CYAN "" + #define PL_LOG_BG_COLOR_CODE_WHITE "" + #define PL_LOG_BG_COLOR_CODE_STRONG_BLACK "" + #define PL_LOG_BG_COLOR_CODE_STRONG_RED "" + #define PL_LOG_BG_COLOR_CODE_STRONG_GREEN "" + #define PL_LOG_BG_COLOR_CODE_STRONG_YELLOW "" + #define PL_LOG_BG_COLOR_CODE_STRONG_BLUE "" + #define PL_LOG_BG_COLOR_CODE_STRONG_MAGENTA "" + #define PL_LOG_BG_COLOR_CODE_STRONG_CYAN "" + #define PL_LOG_BG_COLOR_CODE_STRONG_WHITE "" #else -#define PL_LOG_BOLD_CODE "\033[1m" -#define PL_LOG_UNDERLINE_CODE "\033[4m" -#define PL_LOG_POP_CODE "\033[0m" + #define PL_LOG_BOLD_CODE "\033[1m" + #define PL_LOG_UNDERLINE_CODE "\033[4m" + #define PL_LOG_POP_CODE "\033[0m" -#define PL_LOG_FG_COLOR_CODE_BLACK "\033[30m" -#define PL_LOG_FG_COLOR_CODE_RED "\033[31m" -#define PL_LOG_FG_COLOR_CODE_GREEN "\033[32m" -#define PL_LOG_FG_COLOR_CODE_YELLOW "\033[33m" -#define PL_LOG_FG_COLOR_CODE_BLUE "\033[34m" -#define PL_LOG_FG_COLOR_CODE_MAGENTA "\033[35m" -#define PL_LOG_FG_COLOR_CODE_CYAN "\033[36m" -#define PL_LOG_FG_COLOR_CODE_WHITE "\033[37m" -#define PL_LOG_FG_COLOR_CODE_STRONG_BLACK "\033[90m" -#define PL_LOG_FG_COLOR_CODE_STRONG_RED "\033[91m" -#define PL_LOG_FG_COLOR_CODE_STRONG_GREEN "\033[92m" -#define PL_LOG_FG_COLOR_CODE_STRONG_YELLOW "\033[93m" -#define PL_LOG_FG_COLOR_CODE_STRONG_BLUE "\033[94m" -#define PL_LOG_FG_COLOR_CODE_STRONG_MAGENTA "\033[95m" -#define PL_LOG_FG_COLOR_CODE_STRONG_CYAN "\033[96m" -#define PL_LOG_FG_COLOR_CODE_STRONG_WHITE "\033[97m" + #define PL_LOG_FG_COLOR_CODE_BLACK "\033[30m" + #define PL_LOG_FG_COLOR_CODE_RED "\033[31m" + #define PL_LOG_FG_COLOR_CODE_GREEN "\033[32m" + #define PL_LOG_FG_COLOR_CODE_YELLOW "\033[33m" + #define PL_LOG_FG_COLOR_CODE_BLUE "\033[34m" + #define PL_LOG_FG_COLOR_CODE_MAGENTA "\033[35m" + #define PL_LOG_FG_COLOR_CODE_CYAN "\033[36m" + #define PL_LOG_FG_COLOR_CODE_WHITE "\033[37m" + #define PL_LOG_FG_COLOR_CODE_STRONG_BLACK "\033[90m" + #define PL_LOG_FG_COLOR_CODE_STRONG_RED "\033[91m" + #define PL_LOG_FG_COLOR_CODE_STRONG_GREEN "\033[92m" + #define PL_LOG_FG_COLOR_CODE_STRONG_YELLOW "\033[93m" + #define PL_LOG_FG_COLOR_CODE_STRONG_BLUE "\033[94m" + #define PL_LOG_FG_COLOR_CODE_STRONG_MAGENTA "\033[95m" + #define PL_LOG_FG_COLOR_CODE_STRONG_CYAN "\033[96m" + #define PL_LOG_FG_COLOR_CODE_STRONG_WHITE "\033[97m" -#define PL_LOG_BG_COLOR_CODE_BLACK "\033[40m" -#define PL_LOG_BG_COLOR_CODE_RED "\033[41m" -#define PL_LOG_BG_COLOR_CODE_GREEN "\033[42m" -#define PL_LOG_BG_COLOR_CODE_YELLOW "\033[43m" -#define PL_LOG_BG_COLOR_CODE_BLUE "\033[44m" -#define PL_LOG_BG_COLOR_CODE_MAGENTA "\033[45m" -#define PL_LOG_BG_COLOR_CODE_CYAN "\033[46m" -#define PL_LOG_BG_COLOR_CODE_WHITE "\033[47m" -#define PL_LOG_BG_COLOR_CODE_STRONG_BLACK "\033[100m" -#define PL_LOG_BG_COLOR_CODE_STRONG_RED "\033[101m" -#define PL_LOG_BG_COLOR_CODE_STRONG_GREEN "\033[102m" -#define PL_LOG_BG_COLOR_CODE_STRONG_YELLOW "\033[103m" -#define PL_LOG_BG_COLOR_CODE_STRONG_BLUE "\033[104m" -#define PL_LOG_BG_COLOR_CODE_STRONG_MAGENTA "\033[105m" -#define PL_LOG_BG_COLOR_CODE_STRONG_CYAN "\033[106m" -#define PL_LOG_BG_COLOR_CODE_STRONG_WHITE "\033[107m" + #define PL_LOG_BG_COLOR_CODE_BLACK "\033[40m" + #define PL_LOG_BG_COLOR_CODE_RED "\033[41m" + #define PL_LOG_BG_COLOR_CODE_GREEN "\033[42m" + #define PL_LOG_BG_COLOR_CODE_YELLOW "\033[43m" + #define PL_LOG_BG_COLOR_CODE_BLUE "\033[44m" + #define PL_LOG_BG_COLOR_CODE_MAGENTA "\033[45m" + #define PL_LOG_BG_COLOR_CODE_CYAN "\033[46m" + #define PL_LOG_BG_COLOR_CODE_WHITE "\033[47m" + #define PL_LOG_BG_COLOR_CODE_STRONG_BLACK "\033[100m" + #define PL_LOG_BG_COLOR_CODE_STRONG_RED "\033[101m" + #define PL_LOG_BG_COLOR_CODE_STRONG_GREEN "\033[102m" + #define PL_LOG_BG_COLOR_CODE_STRONG_YELLOW "\033[103m" + #define PL_LOG_BG_COLOR_CODE_STRONG_BLUE "\033[104m" + #define PL_LOG_BG_COLOR_CODE_STRONG_MAGENTA "\033[105m" + #define PL_LOG_BG_COLOR_CODE_STRONG_CYAN "\033[106m" + #define PL_LOG_BG_COLOR_CODE_STRONG_WHITE "\033[107m" #endif @@ -603,10 +559,10 @@ Index of this file: #define PL_LOG_DEBUG_FG_COLOR PL_LOG_FG_COLOR_CODE_CYAN #endif #ifndef PL_LOG_INFO_FG_COLOR - #define PL_LOG_INFO_FG_COLOR PL_LOG_FG_COLOR_CODE_WHITE + #define PL_LOG_INFO_FG_COLOR PL_LOG_FG_COLOR_CODE_WHITE #endif #ifndef PL_LOG_WARN_FG_COLOR - #define PL_LOG_WARN_FG_COLOR PL_LOG_FG_COLOR_CODE_YELLOW + #define PL_LOG_WARN_FG_COLOR PL_LOG_FG_COLOR_CODE_YELLOW #endif #ifndef PL_LOG_ERROR_FG_COLOR #define PL_LOG_ERROR_FG_COLOR PL_LOG_FG_COLOR_CODE_RED @@ -614,6 +570,12 @@ Index of this file: #ifndef PL_LOG_FATAL_FG_COLOR #define PL_LOG_FATAL_FG_COLOR PL_LOG_FG_COLOR_CODE_WHITE #endif +#ifndef PL_LOG_CUSTOM_FG_COLOR + #define PL_LOG_CUSTOM_FG_COLOR PL_LOG_FG_COLOR_CODE_WHITE +#endif +#ifndef PL_LOG_CUSTOM_BG_COLOR + #define PL_LOG_CUSTOM_BG_COLOR PL_LOG_BG_COLOR_CODE_CYAN +#endif //----------------------------------------------------------------------------- // [SECTION] includes @@ -637,38 +599,92 @@ Index of this file: // [SECTION] internal structs //----------------------------------------------------------------------------- +typedef struct _plLogChannel +{ + const char* pcName; + char* pcBuffer; + uint64_t szGeneration; + size_t szBufferSize; + size_t szBufferCapacity; // real capacity is 2x this + plLogEntry* ptEntries; + uint64_t uEntryCount; + uint64_t uEntryCapacity; + uint64_t uNextEntry; + uint64_t uLevel; + plChannelType tType; + uint64_t uID; +} plLogChannel; + typedef struct _plLogContext { plLogChannel atChannels[PL_LOG_MAX_CHANNEL_COUNT]; - uint32_t uChannelCount; - uint32_t uCurrentChannel; + uint64_t uChannelCount; } plLogContext; //----------------------------------------------------------------------------- // [SECTION] global context //----------------------------------------------------------------------------- -plLogContext* gptLogContext = NULL; +static plLogContext* gptLogContext = NULL; //----------------------------------------------------------------------------- // [SECTION] internal api //----------------------------------------------------------------------------- -static plLogEntry* pl__get_new_log_entry(uint32_t uID); - -static inline void pl__log_buffer_may_grow(plLogChannel* ptChannel, int iAdditionalSize) +static plLogEntry* +pl__get_new_log_entry(uint64_t uID) { - if(ptChannel->uBufferSize + iAdditionalSize > ptChannel->uBufferCapacity) // grow + plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; + + plLogEntry* ptEntry = NULL; + + if(tPChannel->tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) { - char* pcOldBuffer = ptChannel->pcBuffer0; - uint64_t uNewCapacity = ptChannel->uBufferCapacity * 2; - if(uNewCapacity < ptChannel->uBufferSize + iAdditionalSize) - uNewCapacity = (ptChannel->uBufferSize + (uint64_t)iAdditionalSize) * 2; - ptChannel->pcBuffer0 = (char*)PL_LOG_ALLOC(uNewCapacity * 2); - memset(ptChannel->pcBuffer0, 0, uNewCapacity * 2); - memcpy(ptChannel->pcBuffer0, pcOldBuffer, ptChannel->uBufferCapacity); - ptChannel->uBufferCapacity = uNewCapacity; - ptChannel->pcBuffer1 = &ptChannel->pcBuffer0[uNewCapacity]; + ptEntry = &tPChannel->ptEntries[tPChannel->uNextEntry]; + tPChannel->uNextEntry++; + tPChannel->uNextEntry = tPChannel->uNextEntry % tPChannel->uEntryCapacity; + tPChannel->uEntryCount++; + if(tPChannel->uNextEntry == 0) + { + tPChannel->szBufferSize = 0; + tPChannel->szGeneration++; + } + } + else if(tPChannel->tType & PL_CHANNEL_TYPE_BUFFER) + { + + // check if overflow reallocation is needed + if(tPChannel->uEntryCount == tPChannel->uEntryCapacity) + { + plLogEntry* sbtOldEntries = tPChannel->ptEntries; + tPChannel->ptEntries = (plLogEntry*)PL_LOG_ALLOC(sizeof(plLogEntry) * tPChannel->uEntryCapacity * 2); + memset(tPChannel->ptEntries, 0, sizeof(plLogEntry) * tPChannel->uEntryCapacity * 2); + + // copy old values + memcpy(tPChannel->ptEntries, sbtOldEntries, sizeof(plLogEntry) * tPChannel->uEntryCapacity); + tPChannel->uEntryCapacity *= 2; + + PL_LOG_FREE(sbtOldEntries); + } + ptEntry = &tPChannel->ptEntries[tPChannel->uEntryCount]; + tPChannel->uEntryCount++; + } + return ptEntry; +} + +static inline void +pl__log_buffer_may_grow(plLogChannel* ptChannel, int iAdditionalSize) +{ + if(ptChannel->szBufferSize + iAdditionalSize > ptChannel->szBufferCapacity) // grow + { + char* pcOldBuffer = ptChannel->pcBuffer; + size_t uNewCapacity = ptChannel->szBufferCapacity * 2; + if(uNewCapacity < ptChannel->szBufferSize + iAdditionalSize) + uNewCapacity = (ptChannel->szBufferSize + (size_t)iAdditionalSize) * 2; + ptChannel->pcBuffer = (char*)PL_LOG_ALLOC(uNewCapacity * 2); + memset(ptChannel->pcBuffer, 0, uNewCapacity * 2); + memcpy(ptChannel->pcBuffer, pcOldBuffer, ptChannel->szBufferCapacity); + ptChannel->szBufferCapacity = uNewCapacity; PL_LOG_FREE(pcOldBuffer); } } @@ -680,22 +696,24 @@ static inline void pl__log_buffer_may_grow(plLogChannel* ptChannel, int iAdditio plLogContext* pl__create_log_context(void) { - plLogContext* tPContext = (plLogContext*)PL_LOG_ALLOC(sizeof(plLogContext)); - memset(tPContext, 0, sizeof(plLogContext)); - tPContext->uChannelCount = 0; - gptLogContext = tPContext; + static plLogContext gtContext = {0}; + gptLogContext = >Context; // setup log channels - pl_add_log_channel("Default", PL_CHANNEL_TYPE_CONSOLE | PL_CHANNEL_TYPE_BUFFER); + plLogChannelInit tLogInit = { + .tType = PL_CHANNEL_TYPE_CONSOLE | PL_CHANNEL_TYPE_BUFFER, + .uEntryCount = 1024 + }; + pl_add_log_channel("Default", tLogInit); - pl_log_trace_f("<- global enabled"); - pl_log_debug_f("<- global enabled"); - pl_log_info_f("<- global enabled"); - pl_log_warn_f("<- global enabled"); - pl_log_error_f("<- global enabled"); - pl_log_fatal_f("<- global enabled"); + pl_log_trace_f(0, "<- global enabled"); + pl_log_debug_f(0, "<- global enabled"); + pl_log_info_f(0, "<- global enabled"); + pl_log_warn_f(0, "<- global enabled"); + pl_log_error_f(0, "<- global enabled"); + pl_log_fatal_f(0, "<- global enabled"); - return tPContext; + return gptLogContext; } void @@ -704,26 +722,23 @@ pl__cleanup_log_context(void) PL_ASSERT(gptLogContext && "no global log context set"); if(gptLogContext) { - for(uint32_t i = 0; i < gptLogContext->uChannelCount; i++) + for(uint64_t i = 0; i < gptLogContext->uChannelCount; i++) { plLogChannel* ptChannel = &gptLogContext->atChannels[i]; - if(ptChannel->pcBuffer0) - PL_LOG_FREE(ptChannel->pcBuffer0); - if(ptChannel->bOverflowInUse) - PL_LOG_FREE(ptChannel->pEntries); - ptChannel->pEntries = NULL; - ptChannel->pcBuffer0 = NULL; - ptChannel->uBufferCapacity = 0; - ptChannel->uBufferSize = 0; - ptChannel->uEntryCapacity = 0; - ptChannel->uEntryCount = 0; - ptChannel->uLevel = 0; - ptChannel->tType = 0; - ptChannel->uID = 0; + if(ptChannel->pcBuffer) + PL_LOG_FREE(ptChannel->pcBuffer); + ptChannel->ptEntries = NULL; + ptChannel->pcBuffer = NULL; + ptChannel->szBufferCapacity = 0; + ptChannel->szBufferSize = 0; + ptChannel->uEntryCapacity = 0; + ptChannel->uEntryCount = 0; + ptChannel->uLevel = 0; + ptChannel->tType = 0; + ptChannel->uID = 0; } memset(gptLogContext->atChannels, 0, sizeof(plLogChannel) * PL_LOG_MAX_CHANNEL_COUNT); gptLogContext->uChannelCount = 0; - PL_LOG_FREE(gptLogContext); } gptLogContext = NULL; } @@ -735,39 +750,35 @@ pl__set_log_context(plLogContext* tPContext) gptLogContext = tPContext; } -plLogContext* -pl__get_log_context(void) +uint64_t +pl__add_log_channel(const char* pcName, plLogChannelInit tInit) { - PL_ASSERT(gptLogContext && "no global log context set"); - return gptLogContext; -} + uint64_t uID = gptLogContext->uChannelCount; -uint32_t -pl__add_log_channel(const char* pcName, plChannelType tType) -{ - uint32_t uID = gptLogContext->uChannelCount; + if(tInit.uEntryCount == 0) + tInit.uEntryCount = 1024; - if((tType & PL_CHANNEL_TYPE_BUFFER) && (tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER)) + if((tInit.tType & PL_CHANNEL_TYPE_BUFFER) && (tInit.tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER)) { PL_ASSERT(false && "Can't have PL_CHANNEL_TYPE_BUFFER and PL_CHANNEL_TYPE_CYCLIC_BUFFER together"); } plLogChannel* ptChannel = &gptLogContext->atChannels[uID]; ptChannel->pcName = pcName; - if(tType & PL_CHANNEL_TYPE_BUFFER) + if(tInit.tType & PL_CHANNEL_TYPE_BUFFER) { - ptChannel->pEntries = (plLogEntry*)PL_LOG_ALLOC(PL_LOG_INITIAL_LOG_SIZE * sizeof(plLogEntry)); - ptChannel->uEntryCapacity = PL_LOG_INITIAL_LOG_SIZE; + ptChannel->ptEntries = (plLogEntry*)PL_LOG_ALLOC(tInit.uEntryCount * sizeof(plLogEntry)); + ptChannel->uEntryCapacity = tInit.uEntryCount; + memset(ptChannel->ptEntries, 0, tInit.uEntryCount * sizeof(plLogEntry)); } - else if(tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) + else if(tInit.tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) { - ptChannel->pEntries = NULL; - ptChannel->uEntryCapacity = PL_LOG_CYCLIC_BUFFER_SIZE; - pl__log_buffer_may_grow(ptChannel, PL_LOG_MAX_LINE_SIZE); + ptChannel->ptEntries = (plLogEntry*)PL_LOG_ALLOC(tInit.uEntryCount * sizeof(plLogEntry)); + ptChannel->uEntryCapacity = tInit.uEntryCount; } else { - ptChannel->pEntries = NULL; + ptChannel->ptEntries = NULL; ptChannel->uEntryCapacity = 0; pl__log_buffer_may_grow(ptChannel, PL_LOG_MAX_LINE_SIZE); } @@ -775,78 +786,76 @@ pl__add_log_channel(const char* pcName, plChannelType tType) ptChannel->uEntryCount = 0; ptChannel->uNextEntry = 0; ptChannel->uLevel = 0; - ptChannel->tType = tType; + ptChannel->tType = tInit.tType; ptChannel->uID = uID; gptLogContext->uChannelCount++; return uID; } -uint32_t -pl__get_current_log_channel(void) -{ - return gptLogContext->uCurrentChannel; -} - void -pl__set_current_log_channel(uint32_t uID) -{ - PL_ASSERT(uID < gptLogContext->uChannelCount && "channel ID is not valid"); - gptLogContext->uCurrentChannel = uID; -} - -void -pl__set_log_level(uint32_t uID, uint32_t uLevel) +pl__set_log_level(uint64_t uID, uint64_t uLevel) { PL_ASSERT(uID < gptLogContext->uChannelCount && "channel ID is not valid"); gptLogContext->atChannels[uID].uLevel = uLevel; } void -pl__clear_log_channel(uint32_t uID) +pl__clear_log_channel(uint64_t uID) { PL_ASSERT(uID < gptLogContext->uChannelCount && "channel ID is not valid"); gptLogContext->atChannels[uID].uEntryCount = 0u; gptLogContext->atChannels[uID].uNextEntry = 0u; - if(gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) - memset(gptLogContext->atChannels[uID].atEntries, 0, sizeof(plLogEntry) * PL_LOG_CYCLIC_BUFFER_SIZE); - else if(gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_BUFFER) + if(gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER || gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_BUFFER) { - PL_LOG_FREE(gptLogContext->atChannels[uID].pEntries); - gptLogContext->atChannels[uID].pEntries = NULL; + PL_LOG_FREE(gptLogContext->atChannels[uID].ptEntries); + gptLogContext->atChannels[uID].ptEntries = NULL; gptLogContext->atChannels[uID].uEntryCapacity = 0; } } void -pl__reset_log_channel(uint32_t uID) +pl__reset_log_channel(uint64_t uID) { PL_ASSERT(uID < gptLogContext->uChannelCount && "channel ID is not valid"); gptLogContext->atChannels[uID].uEntryCount = 0u; gptLogContext->atChannels[uID].uNextEntry = 0u; - if(gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) - memset(gptLogContext->atChannels[uID].atEntries, 0, sizeof(plLogEntry) * PL_LOG_CYCLIC_BUFFER_SIZE); - else if(gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_BUFFER) - memset(gptLogContext->atChannels[uID].pEntries, 0, sizeof(plLogEntry) * gptLogContext->atChannels[uID].uEntryCapacity); + if(gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER || gptLogContext->atChannels[uID].tType & PL_CHANNEL_TYPE_BUFFER) + memset(gptLogContext->atChannels[uID].ptEntries, 0, sizeof(plLogEntry) * gptLogContext->atChannels[uID].uEntryCapacity); } -plLogEntry* -pl__get_log_entries(uint32_t uID, uint64_t* puEntryCount) +bool +pl__get_log_channel_info(uint64_t uID, plLogChannelInfo* ptOut) { - PL_ASSERT(uID < gptLogContext->uChannelCount && "channel ID is not valid"); - plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; - if(puEntryCount) - *puEntryCount = tPChannel->uEntryCount; - return tPChannel->pEntries; + if(uID >= gptLogContext->uChannelCount) + return false; + + ptOut->uID = uID; + ptOut->pcName = gptLogContext->atChannels[uID].pcName; + ptOut->tType = gptLogContext->atChannels[uID].tType; + ptOut->pcBuffer = gptLogContext->atChannels[uID].pcBuffer; + ptOut->uEntryCount = gptLogContext->atChannels[uID].uEntryCount; + ptOut->ptEntries = gptLogContext->atChannels[uID].ptEntries; + ptOut->uEntryCapacity = gptLogContext->atChannels[uID].uEntryCapacity; + return true; } -plLogChannel* -pl__get_log_channels(uint32_t* puChannelCount) +uint64_t +pl__get_log_channel_count(void) { - if(puChannelCount) - *puChannelCount = gptLogContext->uChannelCount; - return gptLogContext->atChannels; + return gptLogContext->uChannelCount; +} + +uint64_t +pl__get_log_channel_id(const char* pcName) +{ + for(uint64_t i = 0; i < gptLogContext->uChannelCount; i++) + { + if(strcmp(gptLogContext->atChannels[i].pcName, pcName) == 0) + return i; + } + return SIZE_MAX; } #define PL__LOG_LEVEL_MACRO(level, prefix, prefixSize) \ @@ -854,60 +863,76 @@ pl__get_log_channels(uint32_t* puChannelCount) if(tPChannel->uLevel < level + 1) \ { \ if(tPChannel->tType & PL_CHANNEL_TYPE_CONSOLE) \ - printf(prefix " (%s) %s\n", tPChannel->pcName, pcMessage); \ + printf("%s (%s) %s\n", prefix, tPChannel->pcName, pcMessage); \ if((tPChannel->tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) || (tPChannel->tType & PL_CHANNEL_TYPE_BUFFER)) \ { \ plLogEntry* ptEntry = pl__get_new_log_entry(uID); \ - const size_t szNewSize = strlen(pcMessage) + 10; \ + const size_t szNewSize = strlen(pcMessage) + prefixSize + 2; \ pl__log_buffer_may_grow(tPChannel, (int)szNewSize); \ - ptEntry->uOffset = tPChannel->uBufferSize; \ - char* cPDest = &tPChannel->pcBuffer0[tPChannel->uBufferSize + tPChannel->uBufferCapacity * (ptEntry->uGeneration % 2)]; \ + char* cPDest = &tPChannel->pcBuffer[tPChannel->szBufferSize + tPChannel->szBufferCapacity * (tPChannel->szGeneration % 2)]; \ + ptEntry->uOffset = tPChannel->szBufferSize + tPChannel->szBufferCapacity * (tPChannel->szGeneration % 2); \ ptEntry->uLevel = level; \ - tPChannel->uBufferSize += szNewSize; \ + tPChannel->szBufferSize += szNewSize; \ strcpy(cPDest, prefix); \ - cPDest += prefixSize; \ + cPDest[prefixSize] = ' '; \ + cPDest += prefixSize + 1; \ strcpy(cPDest, pcMessage); \ } \ } void -pl__log_trace(uint32_t uID, const char* pcMessage) +pl__log(const char* pcPrefix, int iPrefixSize, uint64_t uLevel, uint64_t uID, const char* pcMessage) { - PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_TRACE, "[TRACE] ", 8) + PL__LOG_LEVEL_MACRO(uLevel, pcPrefix, iPrefixSize) } void -pl__log_debug(uint32_t uID, const char* pcMessage) +pl__log_trace(uint64_t uID, const char* pcMessage) { - PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_DEBUG, "[DEBUG] ", 8) + PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_TRACE, "[TRACE]", 7) } void -pl__log_info(uint32_t uID, const char* pcMessage) +pl__log_debug(uint64_t uID, const char* pcMessage) { - PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_INFO, "[INFO ] ", 8) + PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_DEBUG, "[DEBUG]", 7) } void -pl__log_warn(uint32_t uID, const char* pcMessage) +pl__log_info(uint64_t uID, const char* pcMessage) { - PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_WARN, "[WARN ] ", 8) + PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_INFO, "[INFO ]", 7) } void -pl__log_error(uint32_t uID, const char* pcMessage) +pl__log_warn(uint64_t uID, const char* pcMessage) { - PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_ERROR, "[ERROR] ", 8) + PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_WARN, "[WARN ]", 7) } void -pl__log_fatal(uint32_t uID, const char* pcMessage) +pl__log_error(uint64_t uID, const char* pcMessage) { - PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_FATAL, "[FATAL] ", 8) + PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_ERROR, "[ERROR]", 7) } void -pl__log_trace_p(uint32_t uID, const char* cPFormat, ...) +pl__log_fatal(uint64_t uID, const char* pcMessage) +{ + PL__LOG_LEVEL_MACRO(PL_LOG_LEVEL_FATAL, "[FATAL]", 7) +} + +void +pl__log_p(const char* pcPrefix, int iPrefixSize, uint64_t uLevel, uint64_t uID, const char* cPFormat, ...) +{ + va_list argptr; + va_start(argptr, cPFormat); + pl__log_va(pcPrefix, iPrefixSize, uLevel, uID, cPFormat, argptr); + va_end(argptr); +} + +void +pl__log_trace_p(uint64_t uID, const char* cPFormat, ...) { va_list argptr; va_start(argptr, cPFormat); @@ -916,7 +941,7 @@ pl__log_trace_p(uint32_t uID, const char* cPFormat, ...) } void -pl__log_debug_p(uint32_t uID, const char* cPFormat, ...) +pl__log_debug_p(uint64_t uID, const char* cPFormat, ...) { va_list argptr; va_start(argptr, cPFormat); @@ -925,7 +950,7 @@ pl__log_debug_p(uint32_t uID, const char* cPFormat, ...) } void -pl__log_info_p(uint32_t uID, const char* cPFormat, ...) +pl__log_info_p(uint64_t uID, const char* cPFormat, ...) { va_list argptr; va_start(argptr, cPFormat); @@ -934,7 +959,7 @@ pl__log_info_p(uint32_t uID, const char* cPFormat, ...) } void -pl__log_warn_p(uint32_t uID, const char* cPFormat, ...) +pl__log_warn_p(uint64_t uID, const char* cPFormat, ...) { va_list argptr; va_start(argptr, cPFormat); @@ -943,7 +968,7 @@ pl__log_warn_p(uint32_t uID, const char* cPFormat, ...) } void -pl__log_error_p(uint32_t uID, const char* cPFormat, ...) +pl__log_error_p(uint64_t uID, const char* cPFormat, ...) { va_list argptr; va_start(argptr, cPFormat); @@ -952,7 +977,7 @@ pl__log_error_p(uint32_t uID, const char* cPFormat, ...) } void -pl__log_fatal_p(uint32_t uID, const char* cPFormat, ...) +pl__log_fatal_p(uint64_t uID, const char* cPFormat, ...) { va_list argptr; va_start(argptr, cPFormat); @@ -960,20 +985,20 @@ pl__log_fatal_p(uint32_t uID, const char* cPFormat, ...) va_end(argptr); } -#define PL__LOG_LEVEL_VA_BUFFER_MACRO(level, prefix) \ +#define PL__LOG_LEVEL_VA_BUFFER_MACRO(level, prefix, prefixSize) \ if((tPChannel->tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) || (tPChannel->tType & PL_CHANNEL_TYPE_BUFFER)) \ { \ va_list parm_copy; \ va_copy(parm_copy, args); \ plLogEntry* ptEntry = pl__get_new_log_entry(uID); \ - const int iNewSize = pl_vsnprintf(NULL, 0, cPFormat, parm_copy) + 9; \ + const int iNewSize = pl_vsnprintf(NULL, 0, cPFormat, parm_copy) + prefixSize + 2; \ va_end(parm_copy); \ pl__log_buffer_may_grow(tPChannel, iNewSize); \ - ptEntry->uOffset = tPChannel->uBufferSize; \ - char* cPDest = &tPChannel->pcBuffer0[tPChannel->uBufferSize + tPChannel->uBufferCapacity * (ptEntry->uGeneration % 2)]; \ - tPChannel->uBufferSize += iNewSize; \ + char* cPDest = &tPChannel->pcBuffer[tPChannel->szBufferSize + tPChannel->szBufferCapacity * (tPChannel->szGeneration % 2)]; \ + ptEntry->uOffset = tPChannel->szBufferSize + tPChannel->szBufferCapacity * (tPChannel->szGeneration % 2); \ + tPChannel->szBufferSize += iNewSize; \ ptEntry->uLevel = level; \ - cPDest += pl_snprintf(cPDest, 9, prefix); \ + cPDest += pl_snprintf(cPDest, prefixSize + 2, "%s ", prefix); \ va_list parm_copy2; \ va_copy(parm_copy2, args); \ pl_vsnprintf(cPDest, iNewSize, cPFormat, parm_copy2); \ @@ -981,7 +1006,44 @@ pl__log_fatal_p(uint32_t uID, const char* cPFormat, ...) } void -pl__log_trace_va(uint32_t uID, const char* cPFormat, va_list args) +pl__log_va(const char* pcPrefix, int iPrefixSize, uint64_t uLevel, uint64_t uID, const char* cPFormat, va_list args) +{ + plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; + + if(tPChannel->uLevel < uLevel + 1) + { + if(tPChannel->tType & PL_CHANNEL_TYPE_CONSOLE) + { + #ifdef PL_LOG_CUSTOM_BOLD + printf(PL_LOG_BOLD_CODE); + #endif + + #ifdef PL_LOG_CUSTOM_UNDERLINE + printf(PL_LOG_UNDERLINE_CODE); + #endif + + #ifdef PL_LOG_CUSTOM_FG_COLOR + printf(PL_LOG_CUSTOM_FG_COLOR); + #endif + + #ifdef PL_LOG_CUSTOM_BG_COLOR + printf(PL_LOG_CUSTOM_BG_COLOR); + #endif + + printf("%s (%s) ", pcPrefix, tPChannel->pcName); + char dest[PL_LOG_MAX_LINE_SIZE]; + va_list parm_copy; + va_copy(parm_copy, args); + pl_vsnprintf(dest, PL_LOG_MAX_LINE_SIZE, cPFormat, parm_copy); + printf("%s%s\n", dest, PL_LOG_POP_CODE); + va_end(parm_copy); + } + PL__LOG_LEVEL_VA_BUFFER_MACRO(uLevel, pcPrefix, iPrefixSize) + } +} + +void +pl__log_trace_va(uint64_t uID, const char* cPFormat, va_list args) { plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; @@ -1008,21 +1070,18 @@ pl__log_trace_va(uint32_t uID, const char* cPFormat, va_list args) printf("[TRACE] (%s) ", tPChannel->pcName); char dest[PL_LOG_MAX_LINE_SIZE]; - va_list parm_copy; va_copy(parm_copy, args); pl_vsnprintf(dest, PL_LOG_MAX_LINE_SIZE, cPFormat, parm_copy); printf("%s%s\n", dest, PL_LOG_POP_CODE); va_end(parm_copy); } - PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_TRACE, "[TRACE] ") - } - - + PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_TRACE, "[TRACE]", 7) + } } void -pl__log_debug_va(uint32_t uID, const char* cPFormat, va_list args) +pl__log_debug_va(uint64_t uID, const char* cPFormat, va_list args) { plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; @@ -1055,12 +1114,12 @@ pl__log_debug_va(uint32_t uID, const char* cPFormat, va_list args) printf("%s%s\n", dest, PL_LOG_POP_CODE); va_end(parm_copy); } - PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_DEBUG, "[DEBUG] ") + PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_DEBUG, "[DEBUG]", 7) } } void -pl__log_info_va(uint32_t uID, const char* cPFormat, va_list args) +pl__log_info_va(uint64_t uID, const char* cPFormat, va_list args) { plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; @@ -1093,12 +1152,12 @@ pl__log_info_va(uint32_t uID, const char* cPFormat, va_list args) printf("%s%s\n", dest, PL_LOG_POP_CODE); va_end(parm_copy); } - PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_INFO, "[INFO ] ") + PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_INFO, "[INFO ]", 7) } } void -pl__log_warn_va(uint32_t uID, const char* cPFormat, va_list args) +pl__log_warn_va(uint64_t uID, const char* cPFormat, va_list args) { plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; @@ -1131,12 +1190,12 @@ pl__log_warn_va(uint32_t uID, const char* cPFormat, va_list args) printf("%s%s\n", dest, PL_LOG_POP_CODE); va_end(parm_copy); } - PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_WARN, "[WARN ] ") + PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_WARN, "[WARN ]", 7) } } void -pl__log_error_va(uint32_t uID, const char* cPFormat, va_list args) +pl__log_error_va(uint64_t uID, const char* cPFormat, va_list args) { plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; @@ -1169,12 +1228,12 @@ pl__log_error_va(uint32_t uID, const char* cPFormat, va_list args) printf("%s%s\n", dest, PL_LOG_POP_CODE); va_end(parm_copy); } - PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_ERROR, "[ERROR] ") + PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_ERROR, "[ERROR]", 7) } } void -pl__log_fatal_va(uint32_t uID, const char* cPFormat, va_list args) +pl__log_fatal_va(uint64_t uID, const char* cPFormat, va_list args) { plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; @@ -1207,56 +1266,8 @@ pl__log_fatal_va(uint32_t uID, const char* cPFormat, va_list args) printf("%s%s\n", dest, PL_LOG_POP_CODE); va_end(parm_copy); } - PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_FATAL, "[FATAL] ") + PL__LOG_LEVEL_VA_BUFFER_MACRO(PL_LOG_LEVEL_FATAL, "[FATAL]", 7) } } -//----------------------------------------------------------------------------- -// [SECTION] internal api implementation -//----------------------------------------------------------------------------- - -static plLogEntry* -pl__get_new_log_entry(uint32_t uID) -{ - plLogChannel* tPChannel = &gptLogContext->atChannels[uID]; - - plLogEntry* ptEntry = NULL; - - if(tPChannel->tType & PL_CHANNEL_TYPE_CYCLIC_BUFFER) - { - ptEntry = &tPChannel->atEntries[tPChannel->uNextEntry]; - tPChannel->uNextEntry++; - tPChannel->uNextEntry = tPChannel->uNextEntry % PL_LOG_CYCLIC_BUFFER_SIZE; - tPChannel->uEntryCount++; - if(tPChannel->uNextEntry == 0) - { - tPChannel->uBufferSize = 0; - tPChannel->uGeneration++; - } - } - else if(tPChannel->tType & PL_CHANNEL_TYPE_BUFFER) - { - - // check if overflow reallocation is needed - if(tPChannel->uEntryCount == tPChannel->uEntryCapacity) - { - plLogEntry* sbtOldEntries = tPChannel->pEntries; - tPChannel->pEntries = (plLogEntry*)PL_LOG_ALLOC(sizeof(plLogEntry) * tPChannel->uEntryCapacity * 2); - memset(tPChannel->pEntries, 0, sizeof(plLogEntry) * tPChannel->uEntryCapacity * 2); - - // copy old values - memcpy(tPChannel->pEntries, sbtOldEntries, sizeof(plLogEntry) * tPChannel->uEntryCapacity); - tPChannel->uEntryCapacity *= 2; - - PL_LOG_FREE(sbtOldEntries); - } - - ptEntry = &tPChannel->pEntries[tPChannel->uEntryCount]; - tPChannel->uEntryCount++; - } - - ptEntry->uGeneration = tPChannel->uGeneration; - return ptEntry; -} - -#endif // PL_LOG_IMPLEMENTATION +#endif // PL_LOG_IMPLEMENTATION \ No newline at end of file diff --git a/pl_math.h b/pl_math.h index 95e05b2..40ce730 100644 --- a/pl_math.h +++ b/pl_math.h @@ -1,5 +1,6 @@ /* - pl_math.h, v0.6 (WIP) + pl_math.h + * simple math library Do this: #define PL_MATH_INCLUDE_FUNCTIONS @@ -12,9 +13,9 @@ #include "pl_math.h" */ -// library version -#define PL_MATH_VERSION "0.7.0" -#define PL_MATH_VERSION_NUM 00700 +// library version (format XYYZZ) +#define PL_MATH_VERSION "1.0.0" +#define PL_MATH_VERSION_NUM 10000 /* Index of this file: @@ -187,7 +188,11 @@ typedef struct _plAABB #include #include // bool #include // uint*_t -#include + +#ifndef PL_ASSERT + #include + #define PL_ASSERT(x) assert((x)) +#endif //----------------------------------------------------------------------------- // [SECTION] helpers @@ -239,92 +244,89 @@ static inline float pl_clamp01f(float fValue) { re static inline double pl_clamp01d(double dValue) { return pl_clampd(0.0, dValue, 1.0); } static inline size_t pl_align_up(size_t szValue, size_t szAlign) { return ((szValue + (szAlign - 1)) & ~(szAlign - 1)); } -#define PL__ALIGN_UP(num, align) (((num) + ((align)-1)) & ~((align)-1)) - //----------------------------------------------------------------------------- // [SECTION] vector ops //----------------------------------------------------------------------------- // unary ops -static inline float pl_length_sqr_vec2 (plVec2 tVec) { return pl_squaref(tVec.x) + pl_squaref(tVec.y); } -static inline float pl_length_sqr_vec3 (plVec3 tVec) { return pl_squaref(tVec.x) + pl_squaref(tVec.y) + pl_squaref(tVec.z); } -static inline float pl_length_sqr_vec4 (plVec4 tVec) { return pl_squaref(tVec.x) + pl_squaref(tVec.y) + pl_squaref(tVec.z) + pl_squaref(tVec.w); } -static inline float pl_length_vec2 (plVec2 tVec) { return sqrtf(pl_length_sqr_vec2(tVec)); } -static inline float pl_length_vec3 (plVec3 tVec) { return sqrtf(pl_length_sqr_vec3(tVec)); } -static inline float pl_length_vec4 (plVec4 tVec) { return sqrtf(pl_length_sqr_vec4(tVec)); } -static inline plVec2 pl_floor_vec2 (plVec2 tVec) { return pl_create_vec2(floorf(tVec.x), floorf(tVec.y));} -static inline plVec3 pl_floor_vec3 (plVec3 tVec) { return pl_create_vec3(floorf(tVec.x), floorf(tVec.y), floorf(tVec.z));} -static inline plVec4 pl_floor_vec4 (plVec4 tVec) { return pl_create_vec4(floorf(tVec.x), floorf(tVec.y), floorf(tVec.z), floorf(tVec.w));} +static inline float pl_length_sqr_vec2(plVec2 tVec) { return pl_squaref(tVec.x) + pl_squaref(tVec.y); } +static inline float pl_length_sqr_vec3(plVec3 tVec) { return pl_squaref(tVec.x) + pl_squaref(tVec.y) + pl_squaref(tVec.z); } +static inline float pl_length_sqr_vec4(plVec4 tVec) { return pl_squaref(tVec.x) + pl_squaref(tVec.y) + pl_squaref(tVec.z) + pl_squaref(tVec.w); } +static inline float pl_length_vec2 (plVec2 tVec) { return sqrtf(pl_length_sqr_vec2(tVec)); } +static inline float pl_length_vec3 (plVec3 tVec) { return sqrtf(pl_length_sqr_vec3(tVec)); } +static inline float pl_length_vec4 (plVec4 tVec) { return sqrtf(pl_length_sqr_vec4(tVec)); } +static inline plVec2 pl_floor_vec2 (plVec2 tVec) { return pl_create_vec2(floorf(tVec.x), floorf(tVec.y));} +static inline plVec3 pl_floor_vec3 (plVec3 tVec) { return pl_create_vec3(floorf(tVec.x), floorf(tVec.y), floorf(tVec.z));} +static inline plVec4 pl_floor_vec4 (plVec4 tVec) { return pl_create_vec4(floorf(tVec.x), floorf(tVec.y), floorf(tVec.z), floorf(tVec.w));} // binary ops +static inline plVec2 pl_lerp_vec2(plVec2 t0, plVec2 t1, float fAmount) { return pl_create_vec2(t0.x + (t1.x - t0.x) * fAmount, t0.y + (t1.y - t0.y) * fAmount);} +static inline plVec3 pl_lerp_vec3(plVec3 t0, plVec3 t1, float fAmount) { return pl_create_vec3(t0.x + (t1.x - t0.x) * fAmount, t0.y + (t1.y - t0.y) * fAmount, t0.z + (t1.z - t0.z) * fAmount);} +static inline plVec4 pl_lerp_vec4(plVec4 t0, plVec4 t1, float fAmount) { return pl_create_vec4(t0.x + (t1.x - t0.x) * fAmount, t0.y + (t1.y - t0.y) * fAmount, t0.z + (t1.z - t0.z) * fAmount, t0.w + (t1.w - t0.w) * fAmount);} -static inline plVec2 pl_lerp_vec2 (plVec2 t0, plVec2 t1, float fAmount) { return pl_create_vec2(t0.x + (t1.x - t0.x) * fAmount, t0.y + (t1.y - t0.y) * fAmount);} -static inline plVec3 pl_lerp_vec3 (plVec3 t0, plVec3 t1, float fAmount) { return pl_create_vec3(t0.x + (t1.x - t0.x) * fAmount, t0.y + (t1.y - t0.y) * fAmount, t0.z + (t1.z - t0.z) * fAmount);} -static inline plVec4 pl_lerp_vec4 (plVec4 t0, plVec4 t1, float fAmount) { return pl_create_vec4(t0.x + (t1.x - t0.x) * fAmount, t0.y + (t1.y - t0.y) * fAmount, t0.z + (t1.z - t0.z) * fAmount, t0.w + (t1.w - t0.w) * fAmount);} +static inline plVec2 pl_clamp_vec2(plVec2 tMin, plVec2 tValue, plVec2 tMax) { return pl_create_vec2(pl_clampf(tMin.x, tValue.x, tMax.x), pl_clampf(tMin.y, tValue.y, tMax.y));} +static inline plVec3 pl_clamp_vec3(plVec3 tMin, plVec3 tValue, plVec3 tMax) { return pl_create_vec3(pl_clampf(tMin.x, tValue.x, tMax.x), pl_clampf(tMin.y, tValue.y, tMax.y), pl_clampf(tMax.z, tValue.z, tMax.z));} +static inline plVec4 pl_clamp_vec4(plVec4 tMin, plVec4 tValue, plVec4 tMax) { return pl_create_vec4(pl_clampf(tMin.x, tValue.x, tMax.x), pl_clampf(tMin.y, tValue.y, tMax.y), pl_clampf(tMax.z, tValue.z, tMax.z), pl_clampf(tMax.w, tValue.w, tMax.w));} +static inline plVec2 pl_min_vec2(plVec2 tValue0, plVec2 tValue1) { return pl_create_vec2(pl_minf(tValue0.x, tValue1.x), pl_minf(tValue0.y, tValue1.y));} +static inline plVec3 pl_min_vec3(plVec3 tValue0, plVec3 tValue1) { return pl_create_vec3(pl_minf(tValue0.x, tValue1.x), pl_minf(tValue0.y, tValue1.y), pl_minf(tValue0.z, tValue1.z));} +static inline plVec4 pl_min_vec4(plVec4 tValue0, plVec4 tValue1) { return pl_create_vec4(pl_minf(tValue0.x, tValue1.x), pl_minf(tValue0.y, tValue1.y), pl_minf(tValue0.z, tValue1.z), pl_minf(tValue0.w, tValue1.w));} +static inline plVec2 pl_max_vec2(plVec2 tValue0, plVec2 tValue1) { return pl_create_vec2(pl_maxf(tValue0.x, tValue1.x), pl_maxf(tValue0.y, tValue1.y));} +static inline plVec3 pl_max_vec3(plVec3 tValue0, plVec3 tValue1) { return pl_create_vec3(pl_maxf(tValue0.x, tValue1.x), pl_maxf(tValue0.y, tValue1.y), pl_maxf(tValue0.z, tValue1.z));} +static inline plVec4 pl_max_vec4(plVec4 tValue0, plVec4 tValue1) { return pl_create_vec4(pl_maxf(tValue0.x, tValue1.x), pl_maxf(tValue0.y, tValue1.y), pl_maxf(tValue0.z, tValue1.z), pl_maxf(tValue0.w, tValue1.w));} -static inline plVec2 pl_clamp_vec2 (plVec2 tMin, plVec2 tValue, plVec2 tMax) { return pl_create_vec2(pl_clampf(tMin.x, tValue.x, tMax.x), pl_clampf(tMin.y, tValue.y, tMax.y));} -static inline plVec3 pl_clamp_vec3 (plVec3 tMin, plVec3 tValue, plVec3 tMax) { return pl_create_vec3(pl_clampf(tMin.x, tValue.x, tMax.x), pl_clampf(tMin.y, tValue.y, tMax.y), pl_clampf(tMax.z, tValue.z, tMax.z));} -static inline plVec4 pl_clamp_vec4 (plVec4 tMin, plVec4 tValue, plVec4 tMax) { return pl_create_vec4(pl_clampf(tMin.x, tValue.x, tMax.x), pl_clampf(tMin.y, tValue.y, tMax.y), pl_clampf(tMax.z, tValue.z, tMax.z), pl_clampf(tMax.w, tValue.w, tMax.w));} +static inline plVec3 pl_cross_vec3(plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.y * tVec2.z - tVec2.y * tVec1.z, tVec1.z * tVec2.x - tVec2.z * tVec1.x, tVec1.x * tVec2.y - tVec2.x * tVec1.y); } -static inline plVec2 pl_min_vec2 (plVec2 tValue0, plVec2 tValue1) { return pl_create_vec2(pl_minf(tValue0.x, tValue1.x), pl_minf(tValue0.y, tValue1.y));} -static inline plVec3 pl_min_vec3 (plVec3 tValue0, plVec3 tValue1) { return pl_create_vec3(pl_minf(tValue0.x, tValue1.x), pl_minf(tValue0.y, tValue1.y), pl_minf(tValue0.z, tValue1.z));} -static inline plVec4 pl_min_vec4 (plVec4 tValue0, plVec4 tValue1) { return pl_create_vec4(pl_minf(tValue0.x, tValue1.x), pl_minf(tValue0.y, tValue1.y), pl_minf(tValue0.z, tValue1.z), pl_minf(tValue0.w, tValue1.w));} -static inline plVec2 pl_max_vec2 (plVec2 tValue0, plVec2 tValue1) { return pl_create_vec2(pl_maxf(tValue0.x, tValue1.x), pl_maxf(tValue0.y, tValue1.y));} -static inline plVec3 pl_max_vec3 (plVec3 tValue0, plVec3 tValue1) { return pl_create_vec3(pl_maxf(tValue0.x, tValue1.x), pl_maxf(tValue0.y, tValue1.y), pl_maxf(tValue0.z, tValue1.z));} -static inline plVec4 pl_max_vec4 (plVec4 tValue0, plVec4 tValue1) { return pl_create_vec4(pl_maxf(tValue0.x, tValue1.x), pl_maxf(tValue0.y, tValue1.y), pl_maxf(tValue0.z, tValue1.z), pl_maxf(tValue0.w, tValue1.w));} +static inline float pl_dot_vec2(plVec2 tVec1, plVec2 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y; } +static inline float pl_dot_vec3(plVec3 tVec1, plVec3 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y + tVec1.z * tVec2.z; } +static inline float pl_dot_vec4(plVec4 tVec1, plVec4 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y + tVec1.z * tVec2.z + tVec1.w * tVec2.w; } -static inline float pl_dot_vec2 (plVec2 tVec1, plVec2 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y; } -static inline float pl_dot_vec3 (plVec3 tVec1, plVec3 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y + tVec1.z * tVec2.z; } -static inline float pl_dot_vec4 (plVec4 tVec1, plVec4 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y + tVec1.z * tVec2.z + tVec1.w * tVec2.w; } -static inline plVec3 pl_cross_vec3 (plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.y * tVec2.z - tVec2.y * tVec1.z, tVec1.z * tVec2.x - tVec2.z * tVec1.x, tVec1.x * tVec2.y - tVec2.x * tVec1.y); } +static inline plVec2 pl_add_vec2(plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x + tVec2.x, tVec1.y + tVec2.y); } +static inline plVec3 pl_add_vec3(plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x + tVec2.x, tVec1.y + tVec2.y, tVec1.z + tVec2.z); } +static inline plVec4 pl_add_vec4(plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x + tVec2.x, tVec1.y + tVec2.y, tVec1.z + tVec2.z, tVec1.w + tVec2.w); } -static inline plVec2 pl_add_vec2 (plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x + tVec2.x, tVec1.y + tVec2.y); } -static inline plVec3 pl_add_vec3 (plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x + tVec2.x, tVec1.y + tVec2.y, tVec1.z + tVec2.z); } -static inline plVec4 pl_add_vec4 (plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x + tVec2.x, tVec1.y + tVec2.y, tVec1.z + tVec2.z, tVec1.w + tVec2.w); } +static inline plVec2 pl_sub_vec2(plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x - tVec2.x, tVec1.y - tVec2.y); } +static inline plVec3 pl_sub_vec3(plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x - tVec2.x, tVec1.y - tVec2.y, tVec1.z - tVec2.z); } +static inline plVec4 pl_sub_vec4(plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x - tVec2.x, tVec1.y - tVec2.y, tVec1.z - tVec2.z, tVec1.w - tVec2.w) ;} -static inline plVec2 pl_sub_vec2 (plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x - tVec2.x, tVec1.y - tVec2.y); } -static inline plVec3 pl_sub_vec3 (plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x - tVec2.x, tVec1.y - tVec2.y, tVec1.z - tVec2.z); } -static inline plVec4 pl_sub_vec4 (plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x - tVec2.x, tVec1.y - tVec2.y, tVec1.z - tVec2.z, tVec1.w - tVec2.w) ;} +static inline plVec2 pl_mul_vec2(plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x * tVec2.x, tVec1.y * tVec2.y); } +static inline plVec3 pl_mul_vec3(plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x * tVec2.x, tVec1.y * tVec2.y, tVec1.z * tVec2.z); } +static inline plVec4 pl_mul_vec4(plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x * tVec2.x, tVec1.y * tVec2.y, tVec1.z * tVec2.z, tVec1.w * tVec2.w); } -static inline plVec2 pl_mul_vec2 (plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x * tVec2.x, tVec1.y * tVec2.y); } -static inline plVec3 pl_mul_vec3 (plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x * tVec2.x, tVec1.y * tVec2.y, tVec1.z * tVec2.z); } -static inline plVec4 pl_mul_vec4 (plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x * tVec2.x, tVec1.y * tVec2.y, tVec1.z * tVec2.z, tVec1.w * tVec2.w); } +static inline plVec2 pl_div_vec2(plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x / tVec2.x, tVec1.y / tVec2.y); } +static inline plVec3 pl_div_vec3(plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x / tVec2.x, tVec1.y / tVec2.y, tVec1.z / tVec2.z); } +static inline plVec4 pl_div_vec4(plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x / tVec2.x, tVec1.y / tVec2.y, tVec1.z / tVec2.z, tVec1.w / tVec2.w); } -static inline plVec2 pl_div_vec2 (plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(tVec1.x / tVec2.x, tVec1.y / tVec2.y); } -static inline plVec3 pl_div_vec3 (plVec3 tVec1, plVec3 tVec2) { return pl_create_vec3(tVec1.x / tVec2.x, tVec1.y / tVec2.y, tVec1.z / tVec2.z); } -static inline plVec4 pl_div_vec4 (plVec4 tVec1, plVec4 tVec2) { return pl_create_vec4(tVec1.x / tVec2.x, tVec1.y / tVec2.y, tVec1.z / tVec2.z, tVec1.w / tVec2.w); } +static inline plVec2 pl_mul_vec2_scalarf(plVec2 tVec, float fValue) { return pl_create_vec2(fValue * tVec.x, fValue * tVec.y); } +static inline plVec3 pl_mul_vec3_scalarf(plVec3 tVec, float fValue) { return pl_create_vec3(fValue * tVec.x, fValue * tVec.y, fValue * tVec.z); } +static inline plVec4 pl_mul_vec4_scalarf(plVec4 tVec, float fValue) { return pl_create_vec4(fValue * tVec.x, fValue * tVec.y, fValue * tVec.z, fValue * tVec.w); } -static inline plVec2 pl_mul_vec2_scalarf(plVec2 tVec, float fValue) { return pl_create_vec2(fValue * tVec.x, fValue * tVec.y); } -static inline plVec3 pl_mul_vec3_scalarf(plVec3 tVec, float fValue) { return pl_create_vec3(fValue * tVec.x, fValue * tVec.y, fValue * tVec.z); } -static inline plVec4 pl_mul_vec4_scalarf(plVec4 tVec, float fValue) { return pl_create_vec4(fValue * tVec.x, fValue * tVec.y, fValue * tVec.z, fValue * tVec.w); } +static inline plVec2 pl_div_vec2_scalarf(plVec2 tVec, float fValue) { return pl_create_vec2(tVec.x / fValue, tVec.y / fValue); } +static inline plVec3 pl_div_vec3_scalarf(plVec3 tVec, float fValue) { return pl_create_vec3(tVec.x / fValue, tVec.y / fValue, tVec.z / fValue); } +static inline plVec4 pl_div_vec4_scalarf(plVec4 tVec, float fValue) { return pl_create_vec4(tVec.x / fValue, tVec.y / fValue, tVec.z / fValue, tVec.w / fValue); } -static inline plVec2 pl_div_vec2_scalarf(plVec2 tVec, float fValue) { return pl_create_vec2(tVec.x / fValue, tVec.y / fValue); } -static inline plVec3 pl_div_vec3_scalarf(plVec3 tVec, float fValue) { return pl_create_vec3(tVec.x / fValue, tVec.y / fValue, tVec.z / fValue); } -static inline plVec4 pl_div_vec4_scalarf(plVec4 tVec, float fValue) { return pl_create_vec4(tVec.x / fValue, tVec.y / fValue, tVec.z / fValue, tVec.w / fValue); } +static inline plVec2 pl_div_scalarf_vec2(float fValue, plVec2 tVec) { return pl_create_vec2(fValue / tVec.x, fValue / tVec.y); } +static inline plVec3 pl_div_scalarf_vec3(float fValue, plVec3 tVec) { return pl_create_vec3(fValue / tVec.x, fValue / tVec.y, fValue / tVec.z); } +static inline plVec4 pl_div_scalarf_vec4(float fValue, plVec4 tVec) { return pl_create_vec4(fValue / tVec.x, fValue / tVec.y, fValue / tVec.z, fValue / tVec.w); } -static inline plVec2 pl_div_scalarf_vec2(float fValue, plVec2 tVec) { return pl_create_vec2(fValue / tVec.x, fValue / tVec.y); } -static inline plVec3 pl_div_scalarf_vec3(float fValue, plVec3 tVec) { return pl_create_vec3(fValue / tVec.x, fValue / tVec.y, fValue / tVec.z); } -static inline plVec4 pl_div_scalarf_vec4(float fValue, plVec4 tVec) { return pl_create_vec4(fValue / tVec.x, fValue / tVec.y, fValue / tVec.z, fValue / tVec.w); } - -static inline plVec2 pl_norm_vec2 (plVec2 tVec) { float fLength = pl_length_vec2(tVec); if(fLength > 0) fLength = 1.0f / fLength; return pl_mul_vec2_scalarf(tVec, fLength); } -static inline plVec3 pl_norm_vec3 (plVec3 tVec) { float fLength = pl_length_vec3(tVec); if(fLength > 0) fLength = 1.0f / fLength; return pl_mul_vec3_scalarf(tVec, fLength); } -static inline plVec4 pl_norm_vec4 (plVec4 tVec) { float fLength = pl_length_vec4(tVec); if(fLength > 0) fLength = 1.0f / fLength; return pl_mul_vec4_scalarf(tVec, fLength); } +static inline plVec2 pl_norm_vec2(plVec2 tVec) { float fLength = pl_length_vec2(tVec); if(fLength > 0) fLength = 1.0f / fLength; return pl_mul_vec2_scalarf(tVec, fLength); } +static inline plVec3 pl_norm_vec3(plVec3 tVec) { float fLength = pl_length_vec3(tVec); if(fLength > 0) fLength = 1.0f / fLength; return pl_mul_vec3_scalarf(tVec, fLength); } +static inline plVec4 pl_norm_vec4(plVec4 tVec) { float fLength = pl_length_vec4(tVec); if(fLength > 0) fLength = 1.0f / fLength; return pl_mul_vec4_scalarf(tVec, fLength); } //----------------------------------------------------------------------------- // [SECTION] matrix ops //----------------------------------------------------------------------------- // general ops -static inline float pl_mat4_get (const plMat4* ptMat, int iRow, int iCol) { return ptMat->col[iCol].d[iRow];} -static inline void pl_mat4_set (plMat4* ptMat, int iRow, int iCol, float fValue) { ptMat->col[iCol].d[iRow] = fValue;} -static inline plMat4 pl_identity_mat4 (void) { return pl_create_mat4_diag(1.0f, 1.0f, 1.0f, 1.0f);} -static inline plMat4 pl_mat4_transpose (const plMat4* ptMat) { plMat4 tResult = {0}; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) pl_mat4_set(&tResult, i, j, pl_mat4_get(ptMat, j, i)); return tResult;} -static inline plMat4 pl_mat4_invert (const plMat4* ptMat); -static inline plMat4 pl_mul_scalarf_mat4 (float fLeft, const plMat4* ptRight) { plMat4 tResult = {0}; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) pl_mat4_set(&tResult, i, j, fLeft * pl_mat4_get(ptRight, j, i)); return tResult;} -static inline plVec3 pl_mul_mat4_vec3 (const plMat4* ptLeft, plVec3 tRight); -static inline plVec4 pl_mul_mat4_vec4 (const plMat4* ptLeft, plVec4 tRight); -static inline plMat4 pl_mul_mat4 (const plMat4* ptLeft, const plMat4* ptRight); +static inline float pl_mat4_get (const plMat4* ptMat, int iRow, int iCol) { return ptMat->col[iCol].d[iRow];} +static inline void pl_mat4_set (plMat4* ptMat, int iRow, int iCol, float fValue) { ptMat->col[iCol].d[iRow] = fValue;} +static inline plMat4 pl_identity_mat4 (void) { return pl_create_mat4_diag(1.0f, 1.0f, 1.0f, 1.0f);} +static inline plMat4 pl_mat4_transpose (const plMat4* ptMat) { plMat4 tResult = {0}; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) pl_mat4_set(&tResult, i, j, pl_mat4_get(ptMat, j, i)); return tResult;} +static inline plMat4 pl_mat4_invert (const plMat4* ptMat); +static inline plMat4 pl_mul_scalarf_mat4(float fLeft, const plMat4* ptRight) { plMat4 tResult = {0}; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) pl_mat4_set(&tResult, i, j, fLeft * pl_mat4_get(ptRight, j, i)); return tResult;} +static inline plVec3 pl_mul_mat4_vec3 (const plMat4* ptLeft, plVec3 tRight); +static inline plVec4 pl_mul_mat4_vec4 (const plMat4* ptLeft, plVec4 tRight); +static inline plMat4 pl_mul_mat4 (const plMat4* ptLeft, const plMat4* ptRight); // translation, rotation, scaling static inline plMat4 pl_mat4_translate_xyz (float fX, float fY, float fZ) { plMat4 tResult = pl_create_mat4_diag(1.0f, 1.0f, 1.0f, 1.0f); tResult.x14 = fX; tResult.x24 = fY; tResult.x34 = fZ; return tResult;} @@ -337,8 +339,8 @@ static inline plMat4 pl_mat4_rotate_quat (plVec4 tQ); static inline plMat4 pl_rotation_translation_scale(plVec4 tQ, plVec3 tV, plVec3 tS); // transforms (optimized for orthogonal matrices) -static inline plMat4 pl_mat4t_invert (const plMat4* ptMat); -static inline plMat4 pl_mul_mat4t (const plMat4* ptLeft, const plMat4* ptRight); +static inline plMat4 pl_mat4t_invert(const plMat4* ptMat); +static inline plMat4 pl_mul_mat4t (const plMat4* ptLeft, const plMat4* ptRight); //----------------------------------------------------------------------------- // [SECTION] quaternion ops @@ -728,7 +730,7 @@ pl_decompose_matrix(const plMat4* ptM, plVec3* ptS, plVec4* ptQ, plVec3* ptT) } } - assert(!(ptQ->d[3] < 0.0f)); + PL_ASSERT(!(ptQ->d[3] < 0.0f)); } static inline plVec4 @@ -795,4 +797,4 @@ pl_quat_slerp(plVec4 tQ1, plVec4 tQ2, float fT) return tResult; } -#endif // PL_MATH_INCLUDE_FUNCTIONS +#endif // PL_MATH_INCLUDE_FUNCTIONS \ No newline at end of file diff --git a/pl_memory.h b/pl_memory.h index e87e15e..719aeda 100644 --- a/pl_memory.h +++ b/pl_memory.h @@ -107,9 +107,9 @@ void pl_stack_allocator_free_bottom_to_marker(plStackAllocator // Notes // - setting pBuffer to NULL, will set pszBufferSize to required buffer size -// so you can allocate a properly sized buffer for the szItemCount (then call function again) +// so you can allocate a properly sized buffer for the requested szItemCount (then call function again) // - to use a stack allocated buffer, first call the function with szItemCount = 0 & pszBufferSize -// set to size of the buffer; the function will return the number of items that can be support; +// set to size of the buffer; the function will return the number of items that can be supported; // call function again with this number size_t pl_pool_allocator_init (plPoolAllocator*, size_t szItemCount, size_t szItemSize, size_t szItemAlignment, size_t* pszBufferSize, void* pBuffer); diff --git a/pl_profile.h b/pl_profile.h index bca019e..9d99183 100644 --- a/pl_profile.h +++ b/pl_profile.h @@ -1,5 +1,6 @@ /* - pl_profile + pl_profile.h + * simple profiling library Do this: #define PL_PROFILE_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation. @@ -11,9 +12,9 @@ #include "pl_profile.h" */ -// library version -#define PL_PROFILE_VERSION "0.2.0" -#define PL_PROFILE_VERSION_NUM 00200 +// library version (format XYYZZ) +#define PL_PROFILE_VERSION "1.0.0" +#define PL_PROFILE_VERSION_NUM 10000 /* Index of this file: @@ -76,7 +77,7 @@ SAMPLING RETRIEVING RESULTS pl_get_last_frame_samples: - plProfileSample* pl_get_last_frame_samples(uint32_t* puSize); + plProfileSample* pl_get_last_frame_samples(uint32_t* puSizeOut); Returns samples from last frame. Call after "pl_end_profile_frame". @@ -105,8 +106,9 @@ COMPILE TIME OPTIONS //----------------------------------------------------------------------------- // forward declarations -typedef struct _plProfileSample plProfileSample; -typedef struct _plProfileContext plProfileContext; +typedef struct _plProfileSample plProfileSample; // single sample result +typedef struct _plProfileInit plProfileInit; // profile context init info +typedef struct _plProfileContext plProfileContext; // opaque type //----------------------------------------------------------------------------- // [SECTION] public api @@ -115,19 +117,19 @@ typedef struct _plProfileContext plProfileContext; #ifdef PL_PROFILE_ON // setup/shutdown -#define pl_create_profile_context(ptContext) pl__create_profile_context() -#define pl_cleanup_profile_context() pl__cleanup_profile_context() -#define pl_set_profile_context(ptContext) pl__set_profile_context((ptContext)) -#define pl_get_profile_context() pl__get_profile_context() +#define pl_create_profile_context(tInit) pl__create_profile_context((tInit)) +#define pl_cleanup_profile_context() pl__cleanup_profile_context() +#define pl_set_profile_context(ptContext) pl__set_profile_context((ptContext)) +#define pl_get_profile_context() pl__get_profile_context() // frames #define pl_begin_profile_frame() pl__begin_profile_frame() #define pl_end_profile_frame() pl__end_profile_frame() // samples -#define pl_begin_profile_sample(pcName) pl__begin_profile_sample((pcName)) -#define pl_end_profile_sample() pl__end_profile_sample() -#define pl_get_last_frame_samples(puSize) pl__get_last_frame_samples((puSize)) +#define pl_begin_profile_sample(uThreadIndex, pcName) pl__begin_profile_sample((uThreadIndex), (pcName)) +#define pl_end_profile_sample(uThreadIndex) pl__end_profile_sample((uThreadIndex)) +#define pl_get_last_frame_samples(uThreadIndex, puSize) pl__get_last_frame_samples((uThreadIndex), (puSize)) #endif // PL_PROFILE_ON @@ -143,24 +145,29 @@ typedef struct _plProfileSample uint32_t uDepth; } plProfileSample; +typedef struct _plProfileInit +{ + uint32_t uThreadCount; +} plProfileInit; + //----------------------------------------------------------------------------- // [SECTION] internal api //----------------------------------------------------------------------------- // setup/shutdown -plProfileContext* pl__create_profile_context (void); +plProfileContext* pl__create_profile_context (plProfileInit); void pl__cleanup_profile_context(void); -void pl__set_profile_context (plProfileContext* ptContext); +void pl__set_profile_context (plProfileContext*); plProfileContext* pl__get_profile_context (void); // frames -void pl__begin_profile_frame(void); -void pl__end_profile_frame (void); +void pl__begin_profile_frame(void); +void pl__end_profile_frame (void); // samples -void pl__begin_profile_sample(const char* pcName); -void pl__end_profile_sample (void); -plProfileSample* pl__get_last_frame_samples(uint32_t* puSize); +void pl__begin_profile_sample(uint32_t uThreadIndex, const char* pcName); +void pl__end_profile_sample (uint32_t uThreadIndex); +plProfileSample* pl__get_last_frame_samples(uint32_t uThreadIndex, uint32_t* puSizeOut); #ifndef PL_PROFILE_ON #define pl_create_profile_context(ptContext) NULL @@ -212,8 +219,10 @@ Index of this file: // [SECTION] includes //----------------------------------------------------------------------------- +#include // bool + #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN #include #elif defined(__APPLE__) #include // clock_gettime_nsec_np @@ -225,7 +234,7 @@ Index of this file: // [SECTION] global context //----------------------------------------------------------------------------- -plProfileContext* gTPProfileContext = NULL; +static plProfileContext* gptProfileContext = NULL; //----------------------------------------------------------------------------- // [SECTION] internal structs @@ -257,14 +266,20 @@ typedef struct _plProfileFrame uint32_t uOverflowSampleCapacity; } plProfileFrame; -typedef struct _plProfileContext +typedef struct _plProfileThreadData { - double dStartTime; - uint64_t ulFrame; plProfileFrame atFrames[2]; plProfileFrame* ptCurrentFrame; plProfileFrame* ptLastFrame; - void* pInternal; +} plProfileThreadData; + +typedef struct _plProfileContext +{ + double dStartTime; + uint64_t ulFrame; + plProfileThreadData* ptThreadData; + uint32_t uThreadCount; + void* pInternal; } plProfileContext; //----------------------------------------------------------------------------- @@ -286,7 +301,7 @@ pl__get_wall_clock(void) { double dResult = 0; #ifdef _WIN32 - INT64 slPerfFrequency = *(INT64*)gTPProfileContext->pInternal; + INT64 slPerfFrequency = *(INT64*)gptProfileContext->pInternal; INT64 slPerfCounter; QueryPerformanceCounter((LARGE_INTEGER*)&slPerfCounter); dResult = (double)slPerfCounter / (double)slPerfFrequency; @@ -296,7 +311,7 @@ pl__get_wall_clock(void) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); uint64_t nsec_count = ts.tv_nsec + ts.tv_sec * 1e9; - dResult = (double)nsec_count / *(double*)gTPProfileContext->pInternal; + dResult = (double)nsec_count / *(double*)gptProfileContext->pInternal; #endif return dResult; } @@ -306,17 +321,23 @@ pl__get_wall_clock(void) //----------------------------------------------------------------------------- plProfileContext* -pl__create_profile_context(void) +pl__create_profile_context(plProfileInit tInit) { // allocate context plProfileContext* ptContext = (plProfileContext*)PL_PROFILE_ALLOC(sizeof(plProfileContext)); memset(ptContext, 0, sizeof(plProfileContext)); - gTPProfileContext = ptContext; + gptProfileContext = ptContext; // clock setup #ifdef _WIN32 static INT64 slPerfFrequency = 0; - PL_ASSERT(QueryPerformanceFrequency((LARGE_INTEGER*)&slPerfFrequency)); + BOOL bResult = QueryPerformanceFrequency((LARGE_INTEGER*)&slPerfFrequency); + if(!bResult) + { + PL_PROFILE_FREE(gptProfileContext); + gptProfileContext = NULL; + return NULL; + } ptContext->pInternal = &slPerfFrequency; #elif defined(__APPLE__) // no setup required @@ -324,7 +345,10 @@ pl__create_profile_context(void) static struct timespec ts; if (clock_getres(CLOCK_MONOTONIC, &ts) != 0) { - PL_ASSERT(false && "clock_getres() failed"); + // PL_ASSERT(false && "clock_getres() failed"); + PL_PROFILE_FREE(gptProfileContext); + gptProfileContext = NULL; + return NULL; } static double dPerFrequency = 0.0; @@ -333,73 +357,88 @@ pl__create_profile_context(void) #endif ptContext->dStartTime = pl__get_wall_clock(); - ptContext->ptCurrentFrame = &ptContext->atFrames[0]; - ptContext->atFrames[0].uSampleCapacity = 256; - ptContext->atFrames[0].uSampleStackCapacity = 256; - ptContext->atFrames[1].uSampleCapacity = 256; - ptContext->atFrames[1].uSampleStackCapacity = 256; - ptContext->atFrames[0].ptSamples = ptContext->atFrames[0].atSamples; - ptContext->atFrames[1].ptSamples = ptContext->atFrames[1].atSamples; - ptContext->atFrames[0].puSampleStack = ptContext->atFrames[0].auSampleStack; - ptContext->atFrames[1].puSampleStack = ptContext->atFrames[1].auSampleStack; - ptContext->ptLastFrame = &ptContext->atFrames[0]; + ptContext->uThreadCount = tInit.uThreadCount; + ptContext->ptThreadData = (plProfileThreadData*)PL_PROFILE_ALLOC(sizeof(plProfileThreadData) * tInit.uThreadCount); + memset(ptContext->ptThreadData, 0, sizeof(plProfileThreadData) * tInit.uThreadCount); + for(uint32_t i = 0; i < tInit.uThreadCount; i++) + { + ptContext->ptThreadData[i].ptCurrentFrame = &ptContext->ptThreadData[i].atFrames[0]; + ptContext->ptThreadData[i].atFrames[0].uSampleCapacity = 256; + ptContext->ptThreadData[i].atFrames[0].uSampleStackCapacity = 256; + ptContext->ptThreadData[i].atFrames[1].uSampleCapacity = 256; + ptContext->ptThreadData[i].atFrames[1].uSampleStackCapacity = 256; + ptContext->ptThreadData[i].atFrames[0].ptSamples = ptContext->ptThreadData[i].atFrames[0].atSamples; + ptContext->ptThreadData[i].atFrames[1].ptSamples = ptContext->ptThreadData[i].atFrames[1].atSamples; + ptContext->ptThreadData[i].atFrames[0].puSampleStack = ptContext->ptThreadData[i].atFrames[0].auSampleStack; + ptContext->ptThreadData[i].atFrames[1].puSampleStack = ptContext->ptThreadData[i].atFrames[1].auSampleStack; + ptContext->ptThreadData[i].ptLastFrame = &ptContext->ptThreadData[i].atFrames[0]; + } return ptContext; } void pl__cleanup_profile_context(void) { - - for(uint32_t i = 0; i < 2; i++) + for(uint32_t i = 0; i < gptProfileContext->uThreadCount; i++) { - if(gTPProfileContext->atFrames[i].bOverflowInUse) - PL_PROFILE_FREE(gTPProfileContext->atFrames[i].ptSamples); + for(uint32_t j = 0; j < 2; j++) + { + + if(gptProfileContext->ptThreadData[i].atFrames[j].bOverflowInUse) + PL_PROFILE_FREE(gptProfileContext->ptThreadData[i].atFrames[j].ptSamples); - if(gTPProfileContext->atFrames[i].bSampleStackOverflowInUse) - PL_PROFILE_FREE(gTPProfileContext->atFrames[i].puSampleStack); + if(gptProfileContext->ptThreadData[i].atFrames[j].bSampleStackOverflowInUse) + PL_PROFILE_FREE(gptProfileContext->ptThreadData[i].atFrames[j].puSampleStack); + } } - PL_PROFILE_FREE(gTPProfileContext); - gTPProfileContext = NULL; + PL_PROFILE_FREE(gptProfileContext->ptThreadData); + PL_PROFILE_FREE(gptProfileContext); + gptProfileContext = NULL; } void pl__set_profile_context(plProfileContext* ptContext) { - PL_ASSERT(ptContext && "profile context is NULL"); - gTPProfileContext = ptContext; + gptProfileContext = ptContext; } plProfileContext* pl__get_profile_context(void) { - PL_ASSERT(gTPProfileContext && "no global log context set"); - return gTPProfileContext; + return gptProfileContext; } void pl__begin_profile_frame(void) { - gTPProfileContext->ulFrame++; - gTPProfileContext->ptCurrentFrame = &gTPProfileContext->atFrames[gTPProfileContext->ulFrame % 2]; - gTPProfileContext->ptCurrentFrame->dDuration = 0.0; - gTPProfileContext->ptCurrentFrame->dInternalDuration = 0.0; - gTPProfileContext->ptCurrentFrame->dStartTime = pl__get_wall_clock(); - gTPProfileContext->ptCurrentFrame->uTotalSampleSize = 0; + gptProfileContext->ulFrame++; + + for(uint32_t i = 0; i < gptProfileContext->uThreadCount; i++) + { + gptProfileContext->ptThreadData[i].ptCurrentFrame = &gptProfileContext->ptThreadData[i].atFrames[gptProfileContext->ulFrame % 2]; + gptProfileContext->ptThreadData[i].ptCurrentFrame->dDuration = 0.0; + gptProfileContext->ptThreadData[i].ptCurrentFrame->dInternalDuration = 0.0; + gptProfileContext->ptThreadData[i].ptCurrentFrame->dStartTime = pl__get_wall_clock(); + gptProfileContext->ptThreadData[i].ptCurrentFrame->uTotalSampleSize = 0; + } } void pl__end_profile_frame(void) { - gTPProfileContext->ptCurrentFrame->dDuration = pl__get_wall_clock() - gTPProfileContext->ptCurrentFrame->dStartTime; - gTPProfileContext->ptLastFrame = gTPProfileContext->ptCurrentFrame; + for(uint32_t i = 0; i < gptProfileContext->uThreadCount; i++) + { + gptProfileContext->ptThreadData[i].ptCurrentFrame->dDuration = pl__get_wall_clock() - gptProfileContext->ptThreadData[i].ptCurrentFrame->dStartTime; + gptProfileContext->ptThreadData[i].ptLastFrame = gptProfileContext->ptThreadData[i].ptCurrentFrame; + } } void -pl__begin_profile_sample(const char* pcName) +pl__begin_profile_sample(uint32_t uThreadIndex, const char* pcName) { const double dCurrentInternalTime = pl__get_wall_clock(); - plProfileFrame* ptCurrentFrame = gTPProfileContext->ptCurrentFrame; + plProfileFrame* ptCurrentFrame = gptProfileContext->ptThreadData[uThreadIndex].ptCurrentFrame; uint32_t uSampleIndex = ptCurrentFrame->uTotalSampleSize; plProfileSample* ptSample = pl__get_sample(ptCurrentFrame); @@ -414,10 +453,10 @@ pl__begin_profile_sample(const char* pcName) } void -pl__end_profile_sample(void) +pl__end_profile_sample(uint32_t uThreadIndex) { const double dCurrentInternalTime = pl__get_wall_clock(); - plProfileFrame* ptCurrentFrame = gTPProfileContext->ptCurrentFrame; + plProfileFrame* ptCurrentFrame = gptProfileContext->ptThreadData[uThreadIndex].ptCurrentFrame; plProfileSample* ptLastSample = &ptCurrentFrame->ptSamples[pl__pop_sample_stack(ptCurrentFrame)]; PL_ASSERT(ptLastSample && "Begin/end profile sample mismatch"); ptLastSample->dDuration = pl__get_wall_clock() - ptLastSample->dStartTime; @@ -426,9 +465,9 @@ pl__end_profile_sample(void) } plProfileSample* -pl__get_last_frame_samples(uint32_t* puSize) +pl__get_last_frame_samples(uint32_t uThreadIndex, uint32_t* puSize) { - plProfileFrame* ptFrame = gTPProfileContext->ptLastFrame; + plProfileFrame* ptFrame = gptProfileContext->ptThreadData[uThreadIndex].ptLastFrame; if(puSize) *puSize = ptFrame->uTotalSampleSize; diff --git a/pl_stl.h b/pl_stl.h index ffb88b0..f6e51b0 100644 --- a/pl_stl.h +++ b/pl_stl.h @@ -2,6 +2,16 @@ pl_stl.h * no dependencies * simple asci & binary stl parser + + Do this: + #define PL_STL_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define PL_STL_IMPLEMENTATION + #include "pl_stl.h" */ // library version (format XYYZZ) diff --git a/pl_test.h b/pl_test.h index dbd54d3..25f9aa9 100644 --- a/pl_test.h +++ b/pl_test.h @@ -1,5 +1,7 @@ /* pl_test.h + * simple test librsry + Do this: #define PL_TEST_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation.