This commit is contained in:
parent
95454b54f7
commit
aebd939d7d
46
README.md
Normal file
46
README.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
## Pilot Light Libraries
|
||||||
|
|
||||||
|
Single-file MIT licensed libraries for C/C++. These are "STB" style libraries (more info [here](https://github.com/nothings/stb)).
|
||||||
|
|
||||||
|
|
||||||
|
### Libraries
|
||||||
|
|
||||||
|
Library | Lastest Version | Category | Lines of Code | Description
|
||||||
|
--------------------- | ---- | -------- | --- | --------------------------------
|
||||||
|
**[pl_ds.h](pl_ds.h)** | 1.0 | utility | 691 | typesafe dynamic array and hash tables for C
|
||||||
|
**[pl_json.h](pl_json.h)** | 1.0 | parsing | 2067 | json reading & writing for C
|
||||||
|
**[pl_log.h](pl_log.h)** | 1.0 | utility | 1295 | small logging library for C
|
||||||
|
**[pl_math.h](pl_math.h)** | 1.0 | math | 800 | small math library for C (vectors, matrices, quaternions, etc.)
|
||||||
|
**[pl_memory.h](pl_memory.h)** | 1.0 | utility | 699 | various memory allocators for C
|
||||||
|
**[pl_profile.h](pl_profile.h)** | 1.0 | utility | 551 | small profiling library for C
|
||||||
|
**[pl_stl.h](pl_stl.h)** | 1.0 | parsing | 340 | small STL file parser
|
||||||
|
**[pl_string.h](pl_string.h)** | 1.0 | utility | 439 | string utilities for C
|
||||||
|
**[pl_test.h](pl_test.h)** | 1.0 | misc | 543 | small testing library for C
|
||||||
|
|
||||||
|
Total libraries: 9
|
||||||
|
Total lines of C code: 7425
|
||||||
|
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### How do I use these libraries?
|
||||||
|
|
||||||
|
The idea behind single-header file libraries is that they're easy to distribute and deploy
|
||||||
|
because all the code is contained in a single file. By default, the .h files in here act as
|
||||||
|
their own header files, i.e. they declare the functions contained in the file but don't
|
||||||
|
actually result in any code getting compiled.
|
||||||
|
|
||||||
|
So in addition, you should select _exactly one_ C/C++ source file that actually instantiates
|
||||||
|
the code, preferably a file you're not editing frequently. This file should define a
|
||||||
|
specific macro (this is documented per-library) to actually enable the function definitions.
|
||||||
|
For example, to use pl_log, you should have exactly one C/C++ file that doesn't
|
||||||
|
include pl_log.h regularly, but instead does
|
||||||
|
|
||||||
|
#define PL_LOG_IMPLEMENTATION
|
||||||
|
#include "pl_log.h"
|
||||||
|
|
||||||
|
The right macro to define is pointed out right at the top of each of these libraries.
|
||||||
|
|
||||||
|
|
||||||
|
### Where is the documentation?
|
||||||
|
The documentation is included at the top of each file.
|
242
pl_ds.h
242
pl_ds.h
@ -3,9 +3,9 @@
|
|||||||
* data structures
|
* data structures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library version
|
// library version (format XYYZZ)
|
||||||
#define PL_DS_VERSION "0.5.2"
|
#define PL_DS_VERSION "1.0.0"
|
||||||
#define PL_DS_VERSION_NUM 00502
|
#define PL_DS_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
@ -15,8 +15,8 @@ Index of this file:
|
|||||||
// [SECTION] forward declarations
|
// [SECTION] forward declarations
|
||||||
// [SECTION] public api (stretchy buffer)
|
// [SECTION] public api (stretchy buffer)
|
||||||
// [SECTION] public api (hashmap)
|
// [SECTION] public api (hashmap)
|
||||||
// [SECTION] internal
|
// [SECTION] internal (stretchy buffer)
|
||||||
// [SECTION] public api implementation (hashmap)
|
// [SECTION] internal (hashmap)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -125,16 +125,16 @@ HASHMAPS
|
|||||||
uint64_t pl_hm_hash(const void* pData, size_t szDataSize, uint64_t uSeed);
|
uint64_t pl_hm_hash(const void* pData, size_t szDataSize, uint64_t uSeed);
|
||||||
Returns the CRC64 hash of some arbitrary data.
|
Returns the CRC64 hash of some arbitrary data.
|
||||||
|
|
||||||
pl__hm_resize:
|
pl_hm_resize:
|
||||||
void pl__hm_resize(plHashMap*, uint32_t);
|
void pl_hm_resize(plHashMap*, uint32_t);
|
||||||
Resizes the hashmap or frees it if zero is used.
|
Resizes the hashmap or frees it if zero is used.
|
||||||
|
|
||||||
pl_hm_free:
|
pl_hm_free:
|
||||||
void pl_hm_free(plHashMap*);
|
void pl_hm_free(plHashMap*);
|
||||||
Frees the hashmap internal memory.
|
Frees the hashmap internal memory.
|
||||||
|
|
||||||
pl__hm_insert:
|
pl_hm_insert:
|
||||||
void pl__hm_insert(plHashMap*, uint64_t ulKey, uint64_t ulValue);
|
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
|
Adds an entry to the hashmap where ulKey is a hashed key (usually a string) and
|
||||||
ulValue is the index into the value array.
|
ulValue is the index into the value array.
|
||||||
|
|
||||||
@ -158,8 +158,8 @@ HASHMAPS
|
|||||||
bool pl_hm_has_key(plHashMap*, const char*);
|
bool pl_hm_has_key(plHashMap*, const char*);
|
||||||
Same as pl_hm_has_key but performs the hash for you.
|
Same as pl_hm_has_key but performs the hash for you.
|
||||||
|
|
||||||
pl__hm_insert_str:
|
pl_hm_insert_str:
|
||||||
void pl__hm_insert_str(plHashMap*, const char* pcKey, uint64_t ulValue);
|
void pl_hm_insert_str(plHashMap*, const char* pcKey, uint64_t ulValue);
|
||||||
Same as pl__hm_insert but performs the hash for you.
|
Same as pl__hm_insert but performs the hash for you.
|
||||||
|
|
||||||
pl_hm_lookup_str:
|
pl_hm_lookup_str:
|
||||||
@ -173,10 +173,12 @@ HASHMAPS
|
|||||||
COMPILE TIME OPTIONS
|
COMPILE TIME OPTIONS
|
||||||
|
|
||||||
* Change allocators by defining both:
|
* Change allocators by defining both:
|
||||||
PL_LOG_ALLOC(x)
|
PL_DS_ALLOC(x)
|
||||||
PL_LOG_FREE(x)
|
PL_DS_FREE(x)
|
||||||
* Change initial hashmap size:
|
* Change initial hashmap size:
|
||||||
PL_DS_HASHMAP_INITIAL_SIZE (default is 256)
|
PL_DS_HASHMAP_INITIAL_SIZE (default is 256) // should be power of 2
|
||||||
|
* Change assert by defining:
|
||||||
|
PL_DS_ASSERT(x)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -215,25 +217,11 @@ COMPILE TIME OPTIONS
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <stdint.h> // uint32_t
|
#include <stdint.h> // uint32_t
|
||||||
#include <stdlib.h> // malloc, free
|
|
||||||
#include <string.h> // memset, memmove
|
#include <string.h> // memset, memmove
|
||||||
#include <stdbool.h> // bool
|
#include <stdbool.h> // bool
|
||||||
#include <stdarg.h> // arg vars
|
#include <stdarg.h> // arg vars
|
||||||
#include <stdio.h> // vsprintf
|
#include <stdio.h> // vsprintf
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// [SECTION] documentation
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef struct _plHashMap
|
|
||||||
{
|
|
||||||
uint32_t _uItemCount;
|
|
||||||
uint32_t _uBucketCount;
|
|
||||||
uint64_t* _aulKeys; // stored keys used for rehashing during growth
|
|
||||||
uint64_t* _aulValueIndices; // indices into value array (user held)
|
|
||||||
uint64_t* _sbulFreeIndices; // free list of available indices
|
|
||||||
} plHashMap;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] public api (stretchy buffer)
|
// [SECTION] public api (stretchy buffer)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -312,30 +300,43 @@ typedef struct _plHashMap
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define pl_hm_resize(ptHashMap, uBucketCount) \
|
#define pl_hm_resize(ptHashMap, uBucketCount) \
|
||||||
pl__hm_resize(ptHashMap, uBucketCount, __FILE__, __LINE__)
|
pl__hm_resize(&(ptHashMap), (uBucketCount), __FILE__, __LINE__)
|
||||||
|
|
||||||
#define pl_hm_insert(ptHashMap, ulKey, ulValue) \
|
#define pl_hm_insert(ptHashMap, ulKey, ulValue) \
|
||||||
pl__hm_insert(ptHashMap, ulKey, ulValue, __FILE__, __LINE__)
|
pl__hm_insert(&(ptHashMap), (ulKey), (ulValue), __FILE__, __LINE__)
|
||||||
|
|
||||||
|
#define pl_hm_free(ptHashMap) \
|
||||||
|
pl__hm_free(&(ptHashMap))
|
||||||
|
|
||||||
|
#define pl_hm_remove(ptHashMap, ulKey) \
|
||||||
|
pl__hm_remove(&(ptHashMap), (ulKey))
|
||||||
|
|
||||||
|
#define pl_hm_remove_str(ptHashMap, pcKey) \
|
||||||
|
pl_hm_remove((ptHashMap), pl_hm_hash_str((pcKey)))
|
||||||
|
|
||||||
|
#define pl_hm_lookup(ptHashMap, ulKey) \
|
||||||
|
pl__hm_lookup(&(ptHashMap), (ulKey))
|
||||||
|
|
||||||
|
#define pl_hm_get_free_index(ptHashMap) \
|
||||||
|
pl__hm_get_free_index(&(ptHashMap))
|
||||||
|
|
||||||
|
#define pl_hm_has_key(ptHashMap, ulKey) \
|
||||||
|
pl__hm_has_key(&(ptHashMap), (ulKey))
|
||||||
|
|
||||||
|
#define pl_hm_has_key_str(ptHashMap, pcKey) \
|
||||||
|
pl_hm_has_key((ptHashMap), pl_hm_hash_str((pcKey)))
|
||||||
|
|
||||||
|
#define pl_hm_lookup_str(ptHashMap, pcKey) \
|
||||||
|
pl_hm_lookup((ptHashMap), pl_hm_hash_str((pcKey)))
|
||||||
|
|
||||||
#define pl_hm_insert_str(ptHashMap, pcKey, ulValue) \
|
#define pl_hm_insert_str(ptHashMap, pcKey, ulValue) \
|
||||||
pl__hm_insert_str(ptHashMap, pcKey, ulValue, __FILE__, __LINE__)
|
pl_hm_insert((ptHashMap), pl_hm_hash_str((pcKey)), (ulValue))
|
||||||
|
|
||||||
static inline void pl__hm_resize (plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, int iLine);
|
static inline uint64_t pl_hm_hash_str(const char* pcKey);
|
||||||
static inline void pl_hm_free (plHashMap* ptHashMap) { pl__hm_resize(ptHashMap, 0, "", 0);}
|
static inline uint64_t pl_hm_hash (const void* pData, size_t szDataSize, uint64_t uSeed);
|
||||||
static inline void pl__hm_insert (plHashMap* ptHashMap, uint64_t ulKey, uint64_t ulValue, const char* pcFile, int iLine);
|
|
||||||
static inline void pl_hm_remove (plHashMap* ptHashMap, uint64_t ulKey);
|
|
||||||
static inline uint64_t pl_hm_lookup (plHashMap* ptHashMap, uint64_t ulKey);
|
|
||||||
static inline uint64_t pl_hm_get_free_index(plHashMap* ptHashMap);
|
|
||||||
static inline bool pl_hm_has_key (plHashMap* ptHashMap, uint64_t ulKey);
|
|
||||||
static inline uint64_t pl_hm_hash_str (const char* pcKey);
|
|
||||||
static inline uint64_t pl_hm_hash (const void* pData, size_t szDataSize, uint64_t uSeed);
|
|
||||||
static inline void pl__hm_insert_str (plHashMap* ptHashMap, const char* pcKey, uint64_t ulValue, const char* pcFile, int iLine);
|
|
||||||
static inline void pl_hm_remove_str (plHashMap* ptHashMap, const char* pcKey);
|
|
||||||
static inline uint64_t pl_hm_lookup_str (plHashMap* ptHashMap, const char* pcKey);
|
|
||||||
static inline bool pl_hm_has_key_str (plHashMap* ptHashMap, const char* pcKey);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] internal
|
// [SECTION] internal (stretchy buffer)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define pl__sb_header(buf) ((plSbHeader_*)(((char*)(buf)) - sizeof(plSbHeader_)))
|
#define pl__sb_header(buf) ((plSbHeader_*)(((char*)(buf)) - sizeof(plSbHeader_)))
|
||||||
@ -413,17 +414,60 @@ pl__sb_sprintf(char** ppcBuffer, const char* pcFormat, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] public api implementation (hashmap)
|
// [SECTION] internal (hashmap)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static inline void
|
typedef struct plHashMap
|
||||||
pl__hm_resize(plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, int iLine)
|
|
||||||
{
|
{
|
||||||
|
int _iMemoryOwned; // did we allocate this
|
||||||
|
uint32_t _uItemCount;
|
||||||
|
uint32_t _uBucketCount;
|
||||||
|
uint64_t* _aulKeys; // stored keys used for rehashing during growth
|
||||||
|
uint64_t* _aulValueIndices; // indices into value array (user held)
|
||||||
|
uint64_t* _sbulFreeIndices; // free list of available indices
|
||||||
|
} plHashMap;
|
||||||
|
|
||||||
|
static inline uint64_t pl__hm_lookup (plHashMap** ptHashMap, uint64_t ulKey);
|
||||||
|
static inline uint64_t pl__hm_get_free_index(plHashMap** ptHashMap);
|
||||||
|
static inline bool pl__hm_has_key (plHashMap** pptHashMap, uint64_t ulKey);
|
||||||
|
static inline void pl__hm_resize (plHashMap** pptHashMap, uint32_t uBucketCount, const char* pcFile, int iLine);
|
||||||
|
static inline void pl__hm_free (plHashMap** pptHashMap) { pl__hm_resize(pptHashMap, 0, "", 0);}
|
||||||
|
static inline void pl__hm_insert (plHashMap** pptHashMap, uint64_t ulKey, uint64_t ulValue, const char* pcFile, int iLine);
|
||||||
|
static inline void pl__hm_remove (plHashMap** pptHashMap, uint64_t ulKey);
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
pl__ds_get_next_power_of_2(size_t n)
|
||||||
|
{
|
||||||
|
size_t ulResult = 1;
|
||||||
|
if (n && !(n & (n - 1)))
|
||||||
|
ulResult = n;
|
||||||
|
while (ulResult < n)
|
||||||
|
ulResult <<= 1;
|
||||||
|
return ulResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
pl__hm_resize(plHashMap** pptHashMap, uint32_t uBucketCount, const char* pcFile, int iLine)
|
||||||
|
{
|
||||||
|
plHashMap* ptHashMap = *pptHashMap;
|
||||||
|
|
||||||
|
if(ptHashMap == NULL && uBucketCount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(ptHashMap == NULL)
|
||||||
|
{
|
||||||
|
ptHashMap = PL_DS_ALLOC(sizeof(plHashMap));
|
||||||
|
memset(ptHashMap, 0, sizeof(plHashMap));
|
||||||
|
ptHashMap->_iMemoryOwned = 1;
|
||||||
|
*pptHashMap = ptHashMap;
|
||||||
|
}
|
||||||
const uint32_t uOldBucketCount = ptHashMap->_uBucketCount;
|
const uint32_t uOldBucketCount = ptHashMap->_uBucketCount;
|
||||||
uint64_t* sbulOldValueIndices = ptHashMap->_aulValueIndices;
|
uint64_t* sbulOldValueIndices = ptHashMap->_aulValueIndices;
|
||||||
uint64_t* aulOldKeys = ptHashMap->_aulKeys;
|
uint64_t* aulOldKeys = ptHashMap->_aulKeys;
|
||||||
|
|
||||||
ptHashMap->_uBucketCount = uBucketCount < PL_DS_HASHMAP_INITIAL_SIZE ? PL_DS_HASHMAP_INITIAL_SIZE : uBucketCount;
|
|
||||||
|
ptHashMap->_uBucketCount = uBucketCount < PL_DS_HASHMAP_INITIAL_SIZE ? PL_DS_HASHMAP_INITIAL_SIZE : (uint32_t)pl__ds_get_next_power_of_2(uBucketCount);
|
||||||
|
|
||||||
if(uBucketCount > 0)
|
if(uBucketCount > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -432,18 +476,20 @@ pl__hm_resize(plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, i
|
|||||||
memset(ptHashMap->_aulValueIndices, 0xff, sizeof(uint64_t) * ptHashMap->_uBucketCount);
|
memset(ptHashMap->_aulValueIndices, 0xff, sizeof(uint64_t) * ptHashMap->_uBucketCount);
|
||||||
memset(ptHashMap->_aulKeys, 0xff, sizeof(uint64_t) * ptHashMap->_uBucketCount);
|
memset(ptHashMap->_aulKeys, 0xff, sizeof(uint64_t) * ptHashMap->_uBucketCount);
|
||||||
|
|
||||||
|
uint64_t mask = uOldBucketCount - 1;
|
||||||
|
|
||||||
for(uint32_t i = 0; i < uOldBucketCount; i++)
|
for(uint32_t i = 0; i < uOldBucketCount; i++)
|
||||||
{
|
{
|
||||||
const uint64_t ulKey = aulOldKeys[i];
|
const uint64_t ulKey = aulOldKeys[i];
|
||||||
uint64_t ulOldModKey = ulKey % uOldBucketCount;
|
uint64_t ulOldModKey = ulKey & mask;
|
||||||
|
|
||||||
|
|
||||||
while(aulOldKeys[ulOldModKey] != ulKey && aulOldKeys[ulOldModKey] != UINT64_MAX)
|
while(aulOldKeys[ulOldModKey] != ulKey && aulOldKeys[ulOldModKey] != UINT64_MAX)
|
||||||
ulOldModKey = (ulOldModKey + 1) % uOldBucketCount;
|
ulOldModKey = (ulOldModKey + 1) & mask;
|
||||||
|
|
||||||
const uint64_t ulValue = sbulOldValueIndices[ulOldModKey];
|
const uint64_t ulValue = sbulOldValueIndices[ulOldModKey];
|
||||||
ptHashMap->_uItemCount--;
|
ptHashMap->_uItemCount--;
|
||||||
pl__hm_insert(ptHashMap, ulKey, ulValue, pcFile, iLine);
|
pl__hm_insert(pptHashMap, ulKey, ulValue, pcFile, iLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -452,6 +498,11 @@ pl__hm_resize(plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, i
|
|||||||
ptHashMap->_aulKeys = NULL;
|
ptHashMap->_aulKeys = NULL;
|
||||||
pl_sb_free(ptHashMap->_sbulFreeIndices);
|
pl_sb_free(ptHashMap->_sbulFreeIndices);
|
||||||
ptHashMap->_uItemCount = 0;
|
ptHashMap->_uItemCount = 0;
|
||||||
|
if(ptHashMap->_iMemoryOwned)
|
||||||
|
{
|
||||||
|
PL_DS_FREE(ptHashMap);
|
||||||
|
*pptHashMap = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sbulOldValueIndices)
|
if(sbulOldValueIndices)
|
||||||
@ -465,18 +516,29 @@ pl__hm_resize(plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
pl__hm_insert(plHashMap* ptHashMap, uint64_t ulKey, uint64_t ulValue, const char* pcFile, int iLine)
|
pl__hm_insert(plHashMap** pptHashMap, uint64_t ulKey, uint64_t ulValue, const char* pcFile, int iLine)
|
||||||
{
|
{
|
||||||
if(ptHashMap->_uBucketCount == 0)
|
plHashMap* ptHashMap = *pptHashMap;
|
||||||
pl__hm_resize(ptHashMap, PL_DS_HASHMAP_INITIAL_SIZE, pcFile, iLine);
|
|
||||||
else if(((float)ptHashMap->_uItemCount / (float)ptHashMap->_uBucketCount) > 0.60f)
|
|
||||||
pl__hm_resize(ptHashMap, ptHashMap->_uBucketCount * 2, pcFile, iLine);
|
|
||||||
|
|
||||||
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
|
if(ptHashMap == NULL)
|
||||||
|
{
|
||||||
|
ptHashMap = PL_DS_ALLOC_INDIRECT(sizeof(plHashMap), pcFile, iLine);
|
||||||
|
memset(ptHashMap, 0, sizeof(plHashMap));
|
||||||
|
ptHashMap->_iMemoryOwned = 1;
|
||||||
|
*pptHashMap = ptHashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ptHashMap->_uBucketCount == 0)
|
||||||
|
pl__hm_resize(pptHashMap, PL_DS_HASHMAP_INITIAL_SIZE, pcFile, iLine);
|
||||||
|
else if(((float)ptHashMap->_uItemCount / (float)ptHashMap->_uBucketCount) > 0.60f)
|
||||||
|
pl__hm_resize(pptHashMap, ptHashMap->_uBucketCount * 2, pcFile, iLine);
|
||||||
|
|
||||||
|
uint64_t mask = ptHashMap->_uBucketCount - 1;
|
||||||
|
uint64_t ulModKey = ulKey & mask;
|
||||||
|
|
||||||
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
||||||
{
|
{
|
||||||
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
|
ulModKey = (ulModKey + 1) & mask;
|
||||||
if(ptHashMap->_aulKeys[ulModKey] == UINT64_MAX - 1)
|
if(ptHashMap->_aulKeys[ulModKey] == UINT64_MAX - 1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -487,14 +549,16 @@ pl__hm_insert(plHashMap* ptHashMap, uint64_t ulKey, uint64_t ulValue, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
pl_hm_remove(plHashMap* ptHashMap, uint64_t ulKey)
|
pl__hm_remove(plHashMap** pptHashMap, uint64_t ulKey)
|
||||||
{
|
{
|
||||||
|
plHashMap* ptHashMap = *pptHashMap;
|
||||||
PL_DS_ASSERT(ptHashMap->_uBucketCount > 0 && "hashmap has no items");
|
PL_DS_ASSERT(ptHashMap->_uBucketCount > 0 && "hashmap has no items");
|
||||||
|
|
||||||
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
|
uint64_t mask = ptHashMap->_uBucketCount - 1;
|
||||||
|
uint64_t ulModKey = ulKey & mask;
|
||||||
|
|
||||||
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
||||||
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
|
ulModKey = (ulModKey + 1) & mask;
|
||||||
|
|
||||||
const uint64_t ulValue = ptHashMap->_aulValueIndices[ulModKey];
|
const uint64_t ulValue = ptHashMap->_aulValueIndices[ulModKey];
|
||||||
pl_sb_push(ptHashMap->_sbulFreeIndices, ulValue);
|
pl_sb_push(ptHashMap->_sbulFreeIndices, ulValue);
|
||||||
@ -568,15 +632,20 @@ pl_hm_hash(const void* pData, size_t szDataSize, uint64_t uSeed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
pl_hm_lookup(plHashMap* ptHashMap, uint64_t ulKey)
|
pl__hm_lookup(plHashMap** pptHashMap, uint64_t ulKey)
|
||||||
{
|
{
|
||||||
|
plHashMap* ptHashMap = *pptHashMap;
|
||||||
|
|
||||||
|
if(ptHashMap == NULL)
|
||||||
|
return UINT64_MAX;
|
||||||
if(ptHashMap->_uBucketCount == 0)
|
if(ptHashMap->_uBucketCount == 0)
|
||||||
return UINT64_MAX;
|
return UINT64_MAX;
|
||||||
|
|
||||||
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
|
uint64_t mask = ptHashMap->_uBucketCount - 1;
|
||||||
|
uint64_t ulModKey = ulKey & mask;
|
||||||
|
|
||||||
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
||||||
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
|
ulModKey = (ulModKey + 1) & mask;
|
||||||
|
|
||||||
if(ptHashMap->_aulKeys[ulModKey] == UINT64_MAX)
|
if(ptHashMap->_aulKeys[ulModKey] == UINT64_MAX)
|
||||||
return UINT64_MAX;
|
return UINT64_MAX;
|
||||||
@ -585,8 +654,12 @@ pl_hm_lookup(plHashMap* ptHashMap, uint64_t ulKey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
pl_hm_get_free_index(plHashMap* ptHashMap)
|
pl__hm_get_free_index(plHashMap** pptHashMap)
|
||||||
{
|
{
|
||||||
|
plHashMap* ptHashMap = *pptHashMap;
|
||||||
|
|
||||||
|
if(ptHashMap == NULL)
|
||||||
|
return UINT64_MAX;
|
||||||
uint64_t ulResult = UINT64_MAX;
|
uint64_t ulResult = UINT64_MAX;
|
||||||
if(pl_sb_size(ptHashMap->_sbulFreeIndices) > 0)
|
if(pl_sb_size(ptHashMap->_sbulFreeIndices) > 0)
|
||||||
{
|
{
|
||||||
@ -595,43 +668,24 @@ pl_hm_get_free_index(plHashMap* ptHashMap)
|
|||||||
return ulResult;
|
return ulResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
pl__hm_insert_str(plHashMap* ptHashMap, const char* pcKey, uint64_t ulValue, const char* pcFile, int iLine)
|
|
||||||
{
|
|
||||||
pl__hm_insert(ptHashMap, pl_hm_hash_str(pcKey), ulValue, pcFile, iLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
pl_hm_remove_str(plHashMap* ptHashMap, const char* pcKey)
|
|
||||||
{
|
|
||||||
pl_hm_remove(ptHashMap, pl_hm_hash_str(pcKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t
|
|
||||||
pl_hm_lookup_str(plHashMap* ptHashMap, const char* pcKey)
|
|
||||||
{
|
|
||||||
return pl_hm_lookup(ptHashMap, pl_hm_hash_str(pcKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
pl_hm_has_key(plHashMap* ptHashMap, uint64_t ulKey)
|
pl__hm_has_key(plHashMap** pptHashMap, uint64_t ulKey)
|
||||||
{
|
{
|
||||||
|
plHashMap* ptHashMap = *pptHashMap;
|
||||||
|
|
||||||
|
if(ptHashMap == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
if(ptHashMap->_uItemCount == 0)
|
if(ptHashMap->_uItemCount == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
|
uint64_t mask = ptHashMap->_uBucketCount - 1;
|
||||||
|
uint64_t ulModKey = ulKey & mask;
|
||||||
|
|
||||||
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
|
||||||
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
|
ulModKey = (ulModKey + 1) & mask;
|
||||||
|
|
||||||
return ptHashMap->_aulKeys[ulModKey] != UINT64_MAX;
|
return ptHashMap->_aulKeys[ulModKey] != UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
pl_hm_has_key_str(plHashMap* ptHashMap, const char* pcKey)
|
|
||||||
{
|
|
||||||
return pl_hm_has_key(ptHashMap, pl_hm_hash_str(pcKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // PL_DS_H
|
#endif // PL_DS_H
|
||||||
|
|
||||||
|
163
pl_math.h
163
pl_math.h
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
pl_math.h, v0.6 (WIP)
|
pl_math.h
|
||||||
|
* simple math library
|
||||||
|
|
||||||
Do this:
|
Do this:
|
||||||
#define PL_MATH_INCLUDE_FUNCTIONS
|
#define PL_MATH_INCLUDE_FUNCTIONS
|
||||||
@ -12,9 +13,9 @@
|
|||||||
#include "pl_math.h"
|
#include "pl_math.h"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library version
|
// library version (format XYYZZ)
|
||||||
#define PL_MATH_VERSION "0.7.0"
|
#define PL_MATH_VERSION "1.0.0"
|
||||||
#define PL_MATH_VERSION_NUM 00700
|
#define PL_MATH_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
@ -29,6 +30,7 @@ Index of this file:
|
|||||||
// [SECTION] matrix ops
|
// [SECTION] matrix ops
|
||||||
// [SECTION] quaternion ops
|
// [SECTION] quaternion ops
|
||||||
// [SECTION] rect ops
|
// [SECTION] rect ops
|
||||||
|
// [SECTION] colors
|
||||||
// [SECTION] implementations
|
// [SECTION] implementations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -187,7 +189,11 @@ typedef struct _plAABB
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h> // bool
|
#include <stdbool.h> // bool
|
||||||
#include <stdint.h> // uint*_t
|
#include <stdint.h> // uint*_t
|
||||||
#include <assert.h>
|
|
||||||
|
#ifndef PL_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#define PL_ASSERT(x) assert((x))
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] helpers
|
// [SECTION] helpers
|
||||||
@ -239,92 +245,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 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)); }
|
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
|
// [SECTION] vector ops
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// unary 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_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_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_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_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_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 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 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 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 plVec4 pl_floor_vec4 (plVec4 tVec) { return pl_create_vec4(floorf(tVec.x), floorf(tVec.y), floorf(tVec.z), floorf(tVec.w));}
|
||||||
|
|
||||||
// binary ops
|
// 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 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_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 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_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 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_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 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 float pl_dot_vec2(plVec2 tVec1, plVec2 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.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 float pl_dot_vec3(plVec3 tVec1, plVec3 tVec2) { return tVec1.x * tVec2.x + tVec1.y * tVec2.y + tVec1.z * tVec2.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 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 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 plVec2 pl_add_vec2(plVec2 tVec1, plVec2 tVec2) { return pl_create_vec2(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 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 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 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 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 plVec2 pl_sub_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 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_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 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 plVec2 pl_mul_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 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_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 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 plVec2 pl_div_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 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_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 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 plVec2 pl_mul_vec2_scalarf(plVec2 tVec, float fValue) { return pl_create_vec2(fValue * tVec.x, fValue * tVec.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 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_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 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 plVec2 pl_div_vec2_scalarf(plVec2 tVec, float fValue) { return pl_create_vec2(tVec.x / fValue, tVec.y / fValue); }
|
||||||
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 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_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 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 plVec2 pl_div_scalarf_vec2(float fValue, plVec2 tVec) { return pl_create_vec2(fValue / tVec.x, fValue / tVec.y); }
|
||||||
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 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_vec4_scalarf(plVec4 tVec, float fValue) { return pl_create_vec4(tVec.x / fValue, tVec.y / fValue, tVec.z / fValue, tVec.w / fValue); }
|
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 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_div_scalarf_vec3(float fValue, plVec3 tVec) { return pl_create_vec3(fValue / tVec.x, fValue / tVec.y, fValue / tVec.z); }
|
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_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 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
|
// [SECTION] matrix ops
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// general ops
|
// general ops
|
||||||
static inline float pl_mat4_get (const plMat4* ptMat, int iRow, int iCol) { return ptMat->col[iCol].d[iRow];}
|
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 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_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_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_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 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 plVec3 pl_mul_mat4_vec3 (const plMat4* ptLeft, plVec3 tRight);
|
||||||
static inline plVec4 pl_mul_mat4_vec4 (const plMat4* ptLeft, plVec4 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 plMat4 pl_mul_mat4 (const plMat4* ptLeft, const plMat4* ptRight);
|
||||||
|
|
||||||
// translation, rotation, scaling
|
// 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;}
|
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 +340,8 @@ static inline plMat4 pl_mat4_rotate_quat (plVec4 tQ);
|
|||||||
static inline plMat4 pl_rotation_translation_scale(plVec4 tQ, plVec3 tV, plVec3 tS);
|
static inline plMat4 pl_rotation_translation_scale(plVec4 tQ, plVec3 tV, plVec3 tS);
|
||||||
|
|
||||||
// transforms (optimized for orthogonal matrices)
|
// transforms (optimized for orthogonal matrices)
|
||||||
static inline plMat4 pl_mat4t_invert (const plMat4* ptMat);
|
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_mul_mat4t (const plMat4* ptLeft, const plMat4* ptRight);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] quaternion ops
|
// [SECTION] quaternion ops
|
||||||
@ -385,6 +388,28 @@ static inline plRect pl_rect_move_start (const plRect* ptRect, float fX, floa
|
|||||||
static inline plRect pl_rect_move_start_x (const plRect* ptRect, float fX) { const plRect tResult = { { fX, ptRect->tMin.y}, { fX + ptRect->tMax.x - ptRect->tMin.x, ptRect->tMax.y} }; return tResult;}
|
static inline plRect pl_rect_move_start_x (const plRect* ptRect, float fX) { const plRect tResult = { { fX, ptRect->tMin.y}, { fX + ptRect->tMax.x - ptRect->tMin.x, ptRect->tMax.y} }; return tResult;}
|
||||||
static inline plRect pl_rect_move_start_y (const plRect* ptRect, float fY) { const plRect tResult = {{ ptRect->tMin.x, fY}, { ptRect->tMax.x, fY + ptRect->tMax.y - ptRect->tMin.y}}; return tResult;}
|
static inline plRect pl_rect_move_start_y (const plRect* ptRect, float fY) { const plRect tResult = {{ ptRect->tMin.x, fY}, { ptRect->tMax.x, fY + ptRect->tMax.y - ptRect->tMin.y}}; return tResult;}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] colors
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// creates packed 32-bit encoded colors
|
||||||
|
#define PL_COLOR_32_RGBA(R, G, B, A) ((uint32_t)(255.0f * (R) + 0.5f) | (uint32_t) (255.0f * (G) + 0.5f) << 8 | (uint32_t) (255.0f * (B) + 0.5f) << 16 | (uint32_t) (255.0f * (A) + 0.5f) << 24)
|
||||||
|
#define PL_COLOR_32_VEC4(X) ((uint32_t)(255.0f * (X).r + 0.5f) | (uint32_t) (255.0f * (X).g + 0.5f) << 8 | (uint32_t) (255.0f * (X).b + 0.5f) << 16 | (uint32_t) (255.0f * (X).a + 0.5f) << 24)
|
||||||
|
#define PL_COLOR_32_RGB(R, G, B) ((uint32_t)(255.0f * (R) + 0.5f) | (uint32_t) (255.0f * (G) + 0.5f) << 8 | (uint32_t) (255.0f * (B) + 0.5f) << 16 | (uint32_t) (255.5f) << 24)
|
||||||
|
#define PL_COLOR_32_VEC3(X) ((uint32_t)(255.0f * (X).r + 0.5f) | (uint32_t) (255.0f * (X).g + 0.5f) << 8 | (uint32_t) (255.0f * (X).b + 0.5f) << 16 | (uint32_t) (255.5f) << 24)
|
||||||
|
#define PL_COLOR_32_WHITE UINT32_MAX
|
||||||
|
#define PL_COLOR_32_BLACK 0x00
|
||||||
|
#define PL_COLOR_32_RED 0xFF0000FF
|
||||||
|
#define PL_COLOR_32_BLUE 0xFFFF0000
|
||||||
|
#define PL_COLOR_32_DARK_BLUE 0xFF8B0000
|
||||||
|
#define PL_COLOR_32_GREEN 0xFF00FF00
|
||||||
|
#define PL_COLOR_32_YELLOW 0xFF00FFFF
|
||||||
|
#define PL_COLOR_32_ORANGE 0xFF00A5FF
|
||||||
|
#define PL_COLOR_32_MAGENTA 0xFFFF00FF
|
||||||
|
#define PL_COLOR_32_CYAN 0xFFFFFF00
|
||||||
|
#define PL_COLOR_32_GREY 0xFF808080
|
||||||
|
#define PL_COLOR_32_LIGHT_GREY 0xFFD3D3D3
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] implementations
|
// [SECTION] implementations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -728,7 +753,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
|
static inline plVec4
|
||||||
|
304
pl_memory.h
304
pl_memory.h
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
pl_memory
|
pl_memory.h
|
||||||
* no dependencies
|
* no dependencies
|
||||||
* simple
|
* simple memory allocators
|
||||||
|
|
||||||
Do this:
|
Do this:
|
||||||
#define PL_MEMORY_IMPLEMENTATION
|
#define PL_MEMORY_IMPLEMENTATION
|
||||||
@ -19,9 +19,9 @@
|
|||||||
* override assert by defining PL_ASSERT(x)
|
* override assert by defining PL_ASSERT(x)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library version
|
// library version (format XYYZZ)
|
||||||
#define PL_MEMORY_VERSION "0.5.0"
|
#define PL_MEMORY_VERSION "1.0.0"
|
||||||
#define PL_MEMORY_VERSION_NUM 00500
|
#define PL_MEMORY_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
@ -53,18 +53,16 @@ Index of this file:
|
|||||||
// [SECTION] includes
|
// [SECTION] includes
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <stdint.h> // uint*_t
|
|
||||||
#include <stddef.h> // size_t
|
#include <stddef.h> // size_t
|
||||||
#include <stdbool.h> // bool
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] forward declarations & basic types
|
// [SECTION] forward declarations & basic types
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct _plTempAllocator plTempAllocator;
|
// basic types
|
||||||
typedef struct _plStackAllocator plStackAllocator;
|
typedef struct _plTempAllocator plTempAllocator;
|
||||||
typedef struct _plPoolAllocator plPoolAllocator;
|
typedef struct _plStackAllocator plStackAllocator;
|
||||||
typedef struct _plPoolAllocatorNode plPoolAllocatorNode;
|
typedef struct _plPoolAllocator plPoolAllocator;
|
||||||
|
|
||||||
typedef size_t plStackAllocatorMarker;
|
typedef size_t plStackAllocatorMarker;
|
||||||
|
|
||||||
@ -74,65 +72,57 @@ typedef size_t plStackAllocatorMarker;
|
|||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~general purpose allocation~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~general purpose allocation~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
void* pl_aligned_alloc(size_t szAlignment, size_t szSize);
|
void* pl_aligned_alloc(size_t szAlignment, size_t);
|
||||||
void pl_aligned_free (void* pBuffer);
|
void pl_aligned_free (void*);
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~virtual memory system~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
// Notes
|
|
||||||
// - API subject to change slightly
|
|
||||||
// - additional error checks needs to be added
|
|
||||||
// - committed memory does not necessarily mean the memory has been mapped to physical
|
|
||||||
// memory. This is happens when the memory is actually touched. Even so, on Windows
|
|
||||||
// you can not commit more memmory then you have in your page file.
|
|
||||||
// - uncommitted memory does not necessarily mean the memory will be immediately
|
|
||||||
// evicted. It is up to the OS.
|
|
||||||
|
|
||||||
size_t pl_get_page_size (void); // returns memory page size
|
|
||||||
void* pl_virtual_alloc (void* pAddress, size_t szSize); // reserves & commits a block of memory. pAddress is starting address or use NULL to have system choose. szSize must be a multiple of memory page size.
|
|
||||||
void* pl_virtual_reserve (void* pAddress, size_t szSize); // reserves a block of memory. pAddress is starting address or use NULL to have system choose. szSize must be a multiple of memory page size.
|
|
||||||
void* pl_virtual_commit (void* pAddress, size_t szSize); // commits a block of reserved memory. szSize must be a multiple of memory page size.
|
|
||||||
void pl_virtual_uncommit(void* pAddress, size_t szSize); // uncommits a block of committed memory.
|
|
||||||
void pl_virtual_free (void* pAddress, size_t szSize); // frees a block of previously reserved/committed memory. Must be the starting address returned from "pl_virtual_reserve()" or "pl_virtual_alloc()"
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~temporary allocator~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~temporary allocator~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
void* pl_temp_allocator_alloc (plTempAllocator* ptAllocator, size_t szSize);
|
void* pl_temp_allocator_alloc (plTempAllocator*, size_t);
|
||||||
void pl_temp_allocator_reset (plTempAllocator* ptAllocator);
|
void pl_temp_allocator_reset (plTempAllocator*);
|
||||||
void pl_temp_allocator_free (plTempAllocator* ptAllocator);
|
void pl_temp_allocator_free (plTempAllocator*);
|
||||||
char* pl_temp_allocator_sprintf(plTempAllocator* ptAllocator, const char* cPFormat, ...);
|
char* pl_temp_allocator_sprintf(plTempAllocator*, const char* cPFormat, ...);
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~stack allocators~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~stack allocators~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
// common
|
// common
|
||||||
void pl_stack_allocator_init (plStackAllocator* ptAllocator, size_t szSize, void* pBuffer);
|
void pl_stack_allocator_init(plStackAllocator*, size_t, void*);
|
||||||
|
|
||||||
// single stack
|
// single stack
|
||||||
void* pl_stack_allocator_alloc (plStackAllocator* ptAllocator, size_t szSize);
|
void* pl_stack_allocator_alloc (plStackAllocator*, size_t);
|
||||||
void* pl_stack_allocator_aligned_alloc (plStackAllocator* ptAllocator, size_t szSize, size_t szAlignment);
|
void* pl_stack_allocator_aligned_alloc (plStackAllocator*, size_t, size_t szAlignment);
|
||||||
plStackAllocatorMarker pl_stack_allocator_marker (plStackAllocator* ptAllocator);
|
plStackAllocatorMarker pl_stack_allocator_marker (plStackAllocator*);
|
||||||
void pl_stack_allocator_free_to_marker(plStackAllocator* ptAllocator, plStackAllocatorMarker tMarker);
|
void pl_stack_allocator_free_to_marker(plStackAllocator*, plStackAllocatorMarker);
|
||||||
void pl_stack_allocator_reset (plStackAllocator* ptAllocator);
|
void pl_stack_allocator_reset (plStackAllocator*);
|
||||||
|
|
||||||
// double sided stack
|
// double sided stack
|
||||||
void* pl_stack_allocator_aligned_alloc_bottom (plStackAllocator* ptAllocator, size_t szSize, size_t szAlignment);
|
void* pl_stack_allocator_aligned_alloc_bottom (plStackAllocator*, size_t, size_t szAlignment);
|
||||||
plStackAllocatorMarker pl_stack_allocator_top_marker (plStackAllocator* ptAllocator);
|
plStackAllocatorMarker pl_stack_allocator_top_marker (plStackAllocator*);
|
||||||
plStackAllocatorMarker pl_stack_allocator_bottom_marker (plStackAllocator* ptAllocator);
|
plStackAllocatorMarker pl_stack_allocator_bottom_marker (plStackAllocator*);
|
||||||
void* pl_stack_allocator_alloc_bottom (plStackAllocator* ptAllocator, size_t szSize);
|
void* pl_stack_allocator_alloc_bottom (plStackAllocator*, size_t);
|
||||||
void* pl_stack_allocator_alloc_top (plStackAllocator* ptAllocator, size_t szSize);
|
void* pl_stack_allocator_alloc_top (plStackAllocator*, size_t);
|
||||||
void pl_stack_allocator_free_top_to_marker (plStackAllocator* ptAllocator, plStackAllocatorMarker tMarker);
|
void pl_stack_allocator_free_top_to_marker (plStackAllocator*, plStackAllocatorMarker);
|
||||||
void pl_stack_allocator_free_bottom_to_marker(plStackAllocator* ptAllocator, plStackAllocatorMarker tMarker);
|
void pl_stack_allocator_free_bottom_to_marker(plStackAllocator*, plStackAllocatorMarker);
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pool allocator~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~pool allocator~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
void pl_pool_allocator_init (plPoolAllocator* ptAllocator, size_t szItemCount, size_t szItemSize, size_t szItemAlignment, size_t* pszBufferSize, void* pBuffer);
|
// Notes
|
||||||
void* pl_pool_allocator_alloc(plPoolAllocator* ptAllocator);
|
// - setting pBuffer to NULL, will set pszBufferSize to required buffer size
|
||||||
void pl_pool_allocator_free (plPoolAllocator* ptAllocator, void* pItem);
|
// 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 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);
|
||||||
|
void* pl_pool_allocator_alloc(plPoolAllocator*);
|
||||||
|
void pl_pool_allocator_free (plPoolAllocator*, void* pItem);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] structs
|
// [SECTION] structs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// the details of the following structures don't matter to you, but they must
|
||||||
|
// be visible so you can handle the memory allocations for them
|
||||||
|
|
||||||
typedef struct _plTempAllocator
|
typedef struct _plTempAllocator
|
||||||
{
|
{
|
||||||
size_t szSize;
|
size_t szSize;
|
||||||
@ -142,6 +132,8 @@ typedef struct _plTempAllocator
|
|||||||
char** ppcMemoryBlocks;
|
char** ppcMemoryBlocks;
|
||||||
size_t szMemoryBlockCount;
|
size_t szMemoryBlockCount;
|
||||||
size_t szMemoryBlockCapacity;
|
size_t szMemoryBlockCapacity;
|
||||||
|
size_t szCurrentBlockSizes;
|
||||||
|
size_t szNextBlockSizes;
|
||||||
} plTempAllocator;
|
} plTempAllocator;
|
||||||
|
|
||||||
typedef struct _plStackAllocator
|
typedef struct _plStackAllocator
|
||||||
@ -152,6 +144,7 @@ typedef struct _plStackAllocator
|
|||||||
size_t szTopOffset;
|
size_t szTopOffset;
|
||||||
} plStackAllocator;
|
} plStackAllocator;
|
||||||
|
|
||||||
|
typedef struct _plPoolAllocatorNode plPoolAllocatorNode;
|
||||||
typedef struct _plPoolAllocatorNode
|
typedef struct _plPoolAllocatorNode
|
||||||
{
|
{
|
||||||
plPoolAllocatorNode* ptNextNode;
|
plPoolAllocatorNode* ptNextNode;
|
||||||
@ -179,7 +172,6 @@ Index of this file:
|
|||||||
// [SECTION] defines
|
// [SECTION] defines
|
||||||
// [SECTION] internal api
|
// [SECTION] internal api
|
||||||
// [SECTION] public api implementation
|
// [SECTION] public api implementation
|
||||||
// [SECTION] internal api implementation
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -198,40 +190,23 @@ Index of this file:
|
|||||||
|
|
||||||
#ifndef PL_MEMORY_ALLOC
|
#ifndef PL_MEMORY_ALLOC
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#define PL_MEMORY_ALLOC(x) malloc(x)
|
#define PL_MEMORY_ALLOC(x) malloc(x)
|
||||||
#define PL_MEMORY_FREE(x) free(x)
|
#define PL_MEMORY_FREE(x) free(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef PL_ASSERT
|
#ifndef PL_ASSERT
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#define PL_ASSERT(x) assert((x))
|
#define PL_ASSERT(x) assert((x))
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PL_MEMORY_TEMP_STACK_BLOCK_SIZE
|
|
||||||
#define PL_MEMORY_TEMP_BLOCK_SIZE 4194304
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h> // VirtualAlloc, VirtualFree
|
|
||||||
#include <sysinfoapi.h> // page size
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#else // linux
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PL__ALIGN_UP(num, align) (((num) + ((align)-1)) & ~((align)-1))
|
#define PL__ALIGN_UP(num, align) (((num) + ((align)-1)) & ~((align)-1))
|
||||||
|
|
||||||
#ifndef pl_vnsprintf
|
#ifndef pl_vnsprintf
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define pl_vnsprintf vnsprintf
|
#define pl_vnsprintf vsnprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h> // varargs
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] internal api
|
// [SECTION] internal api
|
||||||
@ -270,96 +245,18 @@ pl__align_forward_size(size_t szPtr, size_t szAlign)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] public api implementation
|
// [SECTION] public api implementation
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
size_t
|
|
||||||
pl_get_page_size(void)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
SYSTEM_INFO tInfo = {0};
|
|
||||||
GetSystemInfo(&tInfo);
|
|
||||||
return (size_t)tInfo.dwPageSize;
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return (size_t)getpagesize();
|
|
||||||
#else // linux
|
|
||||||
return (size_t)getpagesize();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
pl_virtual_alloc(void* pAddress, size_t szSize)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
return VirtualAlloc(pAddress, szSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
void* pResult = mmap(pAddress, szSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
||||||
return pResult;
|
|
||||||
#else // linux
|
|
||||||
void* pResult = mmap(pAddress, szSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
||||||
return pResult;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
pl_virtual_reserve(void* pAddress, size_t szSize)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
return VirtualAlloc(pAddress, szSize, MEM_RESERVE, PAGE_READWRITE);
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
void* pResult = mmap(pAddress, szSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
||||||
return pResult;
|
|
||||||
#else // linux
|
|
||||||
void* pResult = mmap(pAddress, szSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
||||||
return pResult;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
pl_virtual_commit(void* pAddress, size_t szSize)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
return VirtualAlloc(pAddress, szSize, MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
mprotect(pAddress, szSize, PROT_READ | PROT_WRITE);
|
|
||||||
return pAddress;
|
|
||||||
#else // linux
|
|
||||||
mprotect(pAddress, szSize, PROT_READ | PROT_WRITE);
|
|
||||||
return pAddress;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pl_virtual_free(void* pAddress, size_t szSize)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
PL_ASSERT(VirtualFree(pAddress, szSize, MEM_RELEASE));
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
PL_ASSERT(munmap(pAddress, szSize) == 0);
|
|
||||||
#else // linux
|
|
||||||
PL_ASSERT(munmap(pAddress, szSize) == 0); //-V586
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pl_virtual_uncommit(void* pAddress, size_t szSize)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
PL_ASSERT(VirtualFree(pAddress, szSize, MEM_DECOMMIT));
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
mprotect(pAddress, szSize, PROT_NONE);
|
|
||||||
#else // linux
|
|
||||||
mprotect(pAddress, szSize, PROT_NONE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
void*
|
||||||
pl_aligned_alloc(size_t szAlignment, size_t szSize)
|
pl_aligned_alloc(size_t szAlignment, size_t szSize)
|
||||||
{
|
{
|
||||||
void* pBuffer = NULL;
|
void* pBuffer = NULL;
|
||||||
|
|
||||||
|
if(szAlignment == 0)
|
||||||
|
szAlignment = pl__get_next_power_of_2(szSize);
|
||||||
|
|
||||||
// ensure power of 2
|
// ensure power of 2
|
||||||
PL_ASSERT((szAlignment & (szAlignment -1)) == 0 && "alignment must be a power of 2");
|
PL_ASSERT((szAlignment & (szAlignment -1)) == 0 && "alignment must be a power of 2");
|
||||||
|
|
||||||
@ -406,6 +303,8 @@ pl_temp_allocator_alloc(plTempAllocator* ptAllocator, size_t szSize)
|
|||||||
ptAllocator->szSize = PL_MEMORY_TEMP_STACK_SIZE;
|
ptAllocator->szSize = PL_MEMORY_TEMP_STACK_SIZE;
|
||||||
ptAllocator->pcBuffer = ptAllocator->acStackBuffer;
|
ptAllocator->pcBuffer = ptAllocator->acStackBuffer;
|
||||||
ptAllocator->szOffset = 0;
|
ptAllocator->szOffset = 0;
|
||||||
|
ptAllocator->szCurrentBlockSizes = PL_MEMORY_TEMP_STACK_SIZE * 2;
|
||||||
|
ptAllocator->szNextBlockSizes = PL_MEMORY_TEMP_STACK_SIZE * 2;
|
||||||
memset(ptAllocator->acStackBuffer, 0, PL_MEMORY_TEMP_STACK_SIZE);
|
memset(ptAllocator->acStackBuffer, 0, PL_MEMORY_TEMP_STACK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +313,6 @@ pl_temp_allocator_alloc(plTempAllocator* ptAllocator, size_t szSize)
|
|||||||
// not enough room is available
|
// not enough room is available
|
||||||
if(szSize > ptAllocator->szSize - ptAllocator->szOffset)
|
if(szSize > ptAllocator->szSize - ptAllocator->szOffset)
|
||||||
{
|
{
|
||||||
PL_ASSERT(szSize < PL_MEMORY_TEMP_BLOCK_SIZE);
|
|
||||||
if(ptAllocator->szMemoryBlockCapacity == 0) // first overflow
|
if(ptAllocator->szMemoryBlockCapacity == 0) // first overflow
|
||||||
{
|
{
|
||||||
// allocate block array
|
// allocate block array
|
||||||
@ -422,30 +320,61 @@ pl_temp_allocator_alloc(plTempAllocator* ptAllocator, size_t szSize)
|
|||||||
ptAllocator->ppcMemoryBlocks = (char**)PL_MEMORY_ALLOC(sizeof(char*) * ptAllocator->szMemoryBlockCapacity);
|
ptAllocator->ppcMemoryBlocks = (char**)PL_MEMORY_ALLOC(sizeof(char*) * ptAllocator->szMemoryBlockCapacity);
|
||||||
memset(ptAllocator->ppcMemoryBlocks, 0, (sizeof(char*) * ptAllocator->szMemoryBlockCapacity));
|
memset(ptAllocator->ppcMemoryBlocks, 0, (sizeof(char*) * ptAllocator->szMemoryBlockCapacity));
|
||||||
|
|
||||||
|
size_t szNewBlockSize = ptAllocator->szCurrentBlockSizes;
|
||||||
|
if(szSize > szNewBlockSize)
|
||||||
|
{
|
||||||
|
ptAllocator->szNextBlockSizes = szSize;
|
||||||
|
szNewBlockSize = szSize;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate first block
|
// allocate first block
|
||||||
ptAllocator->ppcMemoryBlocks[0] = (char*)PL_MEMORY_ALLOC(PL_MEMORY_TEMP_BLOCK_SIZE);
|
ptAllocator->ppcMemoryBlocks[0] = (char*)PL_MEMORY_ALLOC(szNewBlockSize);
|
||||||
ptAllocator->szSize = PL_MEMORY_TEMP_BLOCK_SIZE;
|
ptAllocator->szSize = szNewBlockSize;
|
||||||
ptAllocator->szOffset = 0;
|
ptAllocator->szOffset = 0;
|
||||||
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[0];
|
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[0];
|
||||||
}
|
}
|
||||||
else if(ptAllocator->szMemoryBlockCount == ptAllocator->szMemoryBlockCapacity) // grow memory block storage
|
else if(ptAllocator->szMemoryBlockCount == ptAllocator->szMemoryBlockCapacity) // grow memory block storage
|
||||||
{
|
{
|
||||||
|
|
||||||
|
size_t szNewBlockSize = ptAllocator->szCurrentBlockSizes;
|
||||||
|
if(szSize > szNewBlockSize)
|
||||||
|
{
|
||||||
|
ptAllocator->szNextBlockSizes = szSize;
|
||||||
|
szNewBlockSize = szSize;
|
||||||
|
}
|
||||||
|
|
||||||
char** ppcOldBlocks = ptAllocator->ppcMemoryBlocks;
|
char** ppcOldBlocks = ptAllocator->ppcMemoryBlocks;
|
||||||
ptAllocator->ppcMemoryBlocks = (char**)PL_MEMORY_ALLOC(sizeof(char*) * (ptAllocator->szMemoryBlockCapacity + 1));
|
ptAllocator->ppcMemoryBlocks = (char**)PL_MEMORY_ALLOC(sizeof(char*) * (ptAllocator->szMemoryBlockCapacity + 1));
|
||||||
memset(ptAllocator->ppcMemoryBlocks, 0, (sizeof(char*) * (ptAllocator->szMemoryBlockCapacity + 1)));
|
memset(ptAllocator->ppcMemoryBlocks, 0, (sizeof(char*) * (ptAllocator->szMemoryBlockCapacity + 1)));
|
||||||
memcpy(ptAllocator->ppcMemoryBlocks, ppcOldBlocks, sizeof(char*) * ptAllocator->szMemoryBlockCapacity);
|
memcpy(ptAllocator->ppcMemoryBlocks, ppcOldBlocks, sizeof(char*) * ptAllocator->szMemoryBlockCapacity);
|
||||||
ptAllocator->szMemoryBlockCapacity++;
|
ptAllocator->szMemoryBlockCapacity++;
|
||||||
ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount] = (char*)PL_MEMORY_ALLOC(PL_MEMORY_TEMP_BLOCK_SIZE);
|
ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount] = (char*)PL_MEMORY_ALLOC(szNewBlockSize);
|
||||||
ptAllocator->szSize = PL_MEMORY_TEMP_BLOCK_SIZE;
|
ptAllocator->szSize = szNewBlockSize;
|
||||||
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount];
|
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount];
|
||||||
ptAllocator->szOffset = 0;
|
ptAllocator->szOffset = 0;
|
||||||
}
|
}
|
||||||
else // block is available
|
else if(szSize <= ptAllocator->szCurrentBlockSizes) // block available & small enough
|
||||||
{
|
{
|
||||||
ptAllocator->szSize = PL_MEMORY_TEMP_BLOCK_SIZE;
|
ptAllocator->szSize = ptAllocator->szCurrentBlockSizes;
|
||||||
ptAllocator->szOffset = 0;
|
ptAllocator->szOffset = 0;
|
||||||
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount];
|
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount];
|
||||||
}
|
}
|
||||||
|
else // block available but too small
|
||||||
|
{
|
||||||
|
size_t szNewBlockSize = ptAllocator->szCurrentBlockSizes;
|
||||||
|
ptAllocator->szNextBlockSizes = szSize;
|
||||||
|
szNewBlockSize = szSize;
|
||||||
|
|
||||||
|
char** ppcOldBlocks = ptAllocator->ppcMemoryBlocks;
|
||||||
|
ptAllocator->ppcMemoryBlocks = (char**)PL_MEMORY_ALLOC(sizeof(char*) * (ptAllocator->szMemoryBlockCapacity + 1));
|
||||||
|
memset(ptAllocator->ppcMemoryBlocks, 0, (sizeof(char*) * (ptAllocator->szMemoryBlockCapacity + 1)));
|
||||||
|
memcpy(ptAllocator->ppcMemoryBlocks, ppcOldBlocks, sizeof(char*) * ptAllocator->szMemoryBlockCapacity);
|
||||||
|
ptAllocator->szMemoryBlockCapacity++;
|
||||||
|
ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount] = (char*)PL_MEMORY_ALLOC(szNewBlockSize);
|
||||||
|
ptAllocator->szSize = szNewBlockSize;
|
||||||
|
ptAllocator->pcBuffer = ptAllocator->ppcMemoryBlocks[ptAllocator->szMemoryBlockCount];
|
||||||
|
ptAllocator->szOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ptAllocator->szMemoryBlockCount++;
|
ptAllocator->szMemoryBlockCount++;
|
||||||
}
|
}
|
||||||
@ -462,6 +391,17 @@ pl_temp_allocator_reset(plTempAllocator* ptAllocator)
|
|||||||
ptAllocator->szOffset = 0;
|
ptAllocator->szOffset = 0;
|
||||||
ptAllocator->szMemoryBlockCount = 0;
|
ptAllocator->szMemoryBlockCount = 0;
|
||||||
ptAllocator->pcBuffer = ptAllocator->acStackBuffer;
|
ptAllocator->pcBuffer = ptAllocator->acStackBuffer;
|
||||||
|
|
||||||
|
if(ptAllocator->szCurrentBlockSizes != ptAllocator->szNextBlockSizes)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < ptAllocator->szMemoryBlockCapacity; i++)
|
||||||
|
{
|
||||||
|
PL_MEMORY_FREE(ptAllocator->ppcMemoryBlocks[i]);
|
||||||
|
ptAllocator->ppcMemoryBlocks[i] = (char*)PL_MEMORY_ALLOC(ptAllocator->szNextBlockSizes);
|
||||||
|
memset(ptAllocator->ppcMemoryBlocks[i], 0, ptAllocator->szNextBlockSizes);
|
||||||
|
}
|
||||||
|
ptAllocator->szCurrentBlockSizes = ptAllocator->szNextBlockSizes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -530,7 +470,8 @@ pl_stack_allocator_alloc(plStackAllocator* ptAllocator, size_t szSize)
|
|||||||
{
|
{
|
||||||
size_t szOffset = ptAllocator->szBottomOffset + szSize;
|
size_t szOffset = ptAllocator->szBottomOffset + szSize;
|
||||||
|
|
||||||
PL_ASSERT(szOffset < ptAllocator->szTopOffset && "stack allocator full");
|
if(szOffset >= ptAllocator->szTopOffset)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// update offset
|
// update offset
|
||||||
void* pBuffer = ptAllocator->pucBuffer + ptAllocator->szBottomOffset;
|
void* pBuffer = ptAllocator->pucBuffer + ptAllocator->szBottomOffset;
|
||||||
@ -549,7 +490,8 @@ pl_stack_allocator_aligned_alloc(plStackAllocator* ptAllocator, size_t szSize, s
|
|||||||
uintptr_t pOffset = pl__align_forward_uintptr(pCurrentPointer, szAlignment);
|
uintptr_t pOffset = pl__align_forward_uintptr(pCurrentPointer, szAlignment);
|
||||||
pOffset -= (uintptr_t)ptAllocator->pucBuffer;
|
pOffset -= (uintptr_t)ptAllocator->pucBuffer;
|
||||||
|
|
||||||
PL_ASSERT(pOffset + szSize <= ptAllocator->szTopOffset && "linear allocator full");
|
if(pOffset + szSize > ptAllocator->szTopOffset)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// check if allocator has enough space left
|
// check if allocator has enough space left
|
||||||
if(pOffset + szSize <= ptAllocator->szSize)
|
if(pOffset + szSize <= ptAllocator->szSize)
|
||||||
@ -579,7 +521,8 @@ pl_stack_allocator_aligned_alloc_top(plStackAllocator* ptAllocator, size_t szSiz
|
|||||||
uintptr_t pOffset = pl__align_forward_uintptr(pCurrentPointer, szAlignment);
|
uintptr_t pOffset = pl__align_forward_uintptr(pCurrentPointer, szAlignment);
|
||||||
pOffset -= (uintptr_t)ptAllocator->pucBuffer;
|
pOffset -= (uintptr_t)ptAllocator->pucBuffer;
|
||||||
|
|
||||||
PL_ASSERT(pOffset + szSize <= ptAllocator->szTopOffset && "linear allocator full");
|
if(pOffset + szSize > ptAllocator->szTopOffset)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// check if allocator has enough space left
|
// check if allocator has enough space left
|
||||||
if(pOffset + szSize <= ptAllocator->szSize)
|
if(pOffset + szSize <= ptAllocator->szSize)
|
||||||
@ -604,7 +547,8 @@ pl_stack_allocator_alloc_top(plStackAllocator* ptAllocator, size_t szSize)
|
|||||||
{
|
{
|
||||||
size_t szOffset = ptAllocator->szTopOffset - szSize;
|
size_t szOffset = ptAllocator->szTopOffset - szSize;
|
||||||
|
|
||||||
PL_ASSERT(szOffset > ptAllocator->szBottomOffset && szOffset < ptAllocator->szTopOffset && "stack allocator full");
|
if(szOffset < ptAllocator->szBottomOffset || szOffset > ptAllocator->szTopOffset)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// update offset
|
// update offset
|
||||||
void* pBuffer = ptAllocator->pucBuffer + szOffset;
|
void* pBuffer = ptAllocator->pucBuffer + szOffset;
|
||||||
@ -674,24 +618,36 @@ pl_stack_allocator_reset(plStackAllocator* ptAllocator)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
size_t
|
||||||
pl_pool_allocator_init(plPoolAllocator* ptAllocator, size_t szItemCount, size_t szItemSize, size_t szItemAlignment, size_t* pszBufferSize, void* pBuffer)
|
pl_pool_allocator_init(plPoolAllocator* ptAllocator, size_t szItemCount, size_t szItemSize, size_t szItemAlignment, size_t* pszBufferSize, void* pBuffer)
|
||||||
{
|
{
|
||||||
PL_ASSERT(ptAllocator);
|
PL_ASSERT(ptAllocator);
|
||||||
PL_ASSERT(szItemCount > 0);
|
|
||||||
PL_ASSERT(szItemSize > 0);
|
PL_ASSERT(szItemSize > 0);
|
||||||
PL_ASSERT(pszBufferSize);
|
PL_ASSERT(pszBufferSize);
|
||||||
|
|
||||||
if(szItemAlignment == 0)
|
// gotta have room for node in unused blocks
|
||||||
|
if(szItemSize < sizeof(plPoolAllocatorNode))
|
||||||
{
|
{
|
||||||
|
szItemSize = sizeof(plPoolAllocatorNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let us calculate alignment
|
||||||
|
if(szItemAlignment == 0)
|
||||||
szItemAlignment = pl__get_next_power_of_2(szItemSize);
|
szItemAlignment = pl__get_next_power_of_2(szItemSize);
|
||||||
|
|
||||||
|
// let us calculate number of items
|
||||||
|
if(szItemCount == 0 && *pszBufferSize > 0)
|
||||||
|
{
|
||||||
|
size_t szAlignedItemSize = pl__align_forward_size(szItemSize, szItemAlignment);
|
||||||
|
szItemCount = (*pszBufferSize - szItemAlignment) / (szAlignedItemSize);
|
||||||
|
return szItemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pBuffer == NULL)
|
if(pBuffer == NULL)
|
||||||
{
|
{
|
||||||
size_t szAlignedItemSize = pl__align_forward_size(szItemSize, szItemAlignment);
|
size_t szAlignedItemSize = pl__align_forward_size(szItemSize, szItemAlignment);
|
||||||
*pszBufferSize = szAlignedItemSize * szItemCount + szItemAlignment;
|
*pszBufferSize = szAlignedItemSize * szItemCount + szItemAlignment;
|
||||||
return;
|
return szItemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptAllocator->szFreeItems = szItemCount;
|
ptAllocator->szFreeItems = szItemCount;
|
||||||
@ -705,7 +661,6 @@ pl_pool_allocator_init(plPoolAllocator* ptAllocator, size_t szItemCount, size_t
|
|||||||
uintptr_t pStart = pl__align_forward_uintptr(pInitialStart, (uintptr_t)szItemAlignment);
|
uintptr_t pStart = pl__align_forward_uintptr(pInitialStart, (uintptr_t)szItemAlignment);
|
||||||
ptAllocator->szUsableSize -= (size_t)(pStart - pInitialStart);
|
ptAllocator->szUsableSize -= (size_t)(pStart - pInitialStart);
|
||||||
|
|
||||||
PL_ASSERT(ptAllocator->szItemSize >= sizeof(plPoolAllocatorNode) && "pool allocator item size too small");
|
|
||||||
PL_ASSERT(ptAllocator->szUsableSize >= ptAllocator->szItemSize * szItemCount && "pool allocator buffer size too small");
|
PL_ASSERT(ptAllocator->szUsableSize >= ptAllocator->szItemSize * szItemCount && "pool allocator buffer size too small");
|
||||||
|
|
||||||
unsigned char* pUsableBuffer = (unsigned char*)pStart;
|
unsigned char* pUsableBuffer = (unsigned char*)pStart;
|
||||||
@ -716,6 +671,7 @@ pl_pool_allocator_init(plPoolAllocator* ptAllocator, size_t szItemCount, size_t
|
|||||||
pNode0->ptNextNode = pNode1;
|
pNode0->ptNextNode = pNode1;
|
||||||
}
|
}
|
||||||
ptAllocator->pFreeList = (plPoolAllocatorNode*)pUsableBuffer;
|
ptAllocator->pFreeList = (plPoolAllocatorNode*)pUsableBuffer;
|
||||||
|
return szItemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
@ -740,4 +696,4 @@ pl_pool_allocator_free(plPoolAllocator* ptAllocator, void* pItem)
|
|||||||
ptAllocator->pFreeList->ptNextNode = pOldFreeNode;
|
ptAllocator->pFreeList->ptNextNode = pOldFreeNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // PL_MEMORY_IMPLEMENTATION
|
200
pl_profile.h
200
pl_profile.h
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
pl_profile
|
pl_profile.h
|
||||||
|
* simple profiling library
|
||||||
Do this:
|
Do this:
|
||||||
#define PL_PROFILE_IMPLEMENTATION
|
#define PL_PROFILE_IMPLEMENTATION
|
||||||
before you include this file in *one* C or C++ file to create the implementation.
|
before you include this file in *one* C or C++ file to create the implementation.
|
||||||
@ -11,9 +12,9 @@
|
|||||||
#include "pl_profile.h"
|
#include "pl_profile.h"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library version
|
// library version (format XYYZZ)
|
||||||
#define PL_PROFILE_VERSION "0.2.0"
|
#define PL_PROFILE_VERSION "1.0.0"
|
||||||
#define PL_PROFILE_VERSION_NUM 00200
|
#define PL_PROFILE_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
@ -76,7 +77,7 @@ SAMPLING
|
|||||||
RETRIEVING RESULTS
|
RETRIEVING RESULTS
|
||||||
|
|
||||||
pl_get_last_frame_samples:
|
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".
|
Returns samples from last frame. Call after "pl_end_profile_frame".
|
||||||
|
|
||||||
|
|
||||||
@ -105,8 +106,9 @@ COMPILE TIME OPTIONS
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
typedef struct _plProfileSample plProfileSample;
|
typedef struct _plProfileSample plProfileSample; // single sample result
|
||||||
typedef struct _plProfileContext plProfileContext;
|
typedef struct _plProfileInit plProfileInit; // profile context init info
|
||||||
|
typedef struct _plProfileContext plProfileContext; // opaque type
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] public api
|
// [SECTION] public api
|
||||||
@ -115,19 +117,19 @@ typedef struct _plProfileContext plProfileContext;
|
|||||||
#ifdef PL_PROFILE_ON
|
#ifdef PL_PROFILE_ON
|
||||||
|
|
||||||
// setup/shutdown
|
// setup/shutdown
|
||||||
#define pl_create_profile_context(ptContext) pl__create_profile_context()
|
#define pl_create_profile_context(tInit) pl__create_profile_context((tInit))
|
||||||
#define pl_cleanup_profile_context() pl__cleanup_profile_context()
|
#define pl_cleanup_profile_context() pl__cleanup_profile_context()
|
||||||
#define pl_set_profile_context(ptContext) pl__set_profile_context((ptContext))
|
#define pl_set_profile_context(ptContext) pl__set_profile_context((ptContext))
|
||||||
#define pl_get_profile_context() pl__get_profile_context()
|
#define pl_get_profile_context() pl__get_profile_context()
|
||||||
|
|
||||||
// frames
|
// frames
|
||||||
#define pl_begin_profile_frame() pl__begin_profile_frame()
|
#define pl_begin_profile_frame() pl__begin_profile_frame()
|
||||||
#define pl_end_profile_frame() pl__end_profile_frame()
|
#define pl_end_profile_frame() pl__end_profile_frame()
|
||||||
|
|
||||||
// samples
|
// samples
|
||||||
#define pl_begin_profile_sample(pcName) pl__begin_profile_sample((pcName))
|
#define pl_begin_profile_sample(uThreadIndex, pcName) pl__begin_profile_sample((uThreadIndex), (pcName))
|
||||||
#define pl_end_profile_sample() pl__end_profile_sample()
|
#define pl_end_profile_sample(uThreadIndex) pl__end_profile_sample((uThreadIndex))
|
||||||
#define pl_get_last_frame_samples(puSize) pl__get_last_frame_samples((puSize))
|
#define pl_get_last_frame_samples(uThreadIndex, puSize) pl__get_last_frame_samples((uThreadIndex), (puSize))
|
||||||
|
|
||||||
#endif // PL_PROFILE_ON
|
#endif // PL_PROFILE_ON
|
||||||
|
|
||||||
@ -143,35 +145,41 @@ typedef struct _plProfileSample
|
|||||||
uint32_t uDepth;
|
uint32_t uDepth;
|
||||||
} plProfileSample;
|
} plProfileSample;
|
||||||
|
|
||||||
|
typedef struct _plProfileInit
|
||||||
|
{
|
||||||
|
uint32_t uThreadCount;
|
||||||
|
} plProfileInit;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] internal api
|
// [SECTION] internal api
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// setup/shutdown
|
// setup/shutdown
|
||||||
plProfileContext* pl__create_profile_context (void);
|
plProfileContext* pl__create_profile_context (plProfileInit);
|
||||||
void pl__cleanup_profile_context(void);
|
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);
|
plProfileContext* pl__get_profile_context (void);
|
||||||
|
|
||||||
// frames
|
// frames
|
||||||
void pl__begin_profile_frame(void);
|
void pl__begin_profile_frame (void);
|
||||||
void pl__end_profile_frame (void);
|
void pl__end_profile_frame (void);
|
||||||
|
|
||||||
// samples
|
// samples
|
||||||
void pl__begin_profile_sample(const char* pcName);
|
void pl__begin_profile_sample(uint32_t uThreadIndex, const char* pcName);
|
||||||
void pl__end_profile_sample (void);
|
void pl__end_profile_sample (uint32_t uThreadIndex);
|
||||||
plProfileSample* pl__get_last_frame_samples(uint32_t* puSize);
|
plProfileSample* pl__get_last_frame_samples(uint32_t uThreadIndex, uint32_t* puSizeOut);
|
||||||
|
|
||||||
#ifndef PL_PROFILE_ON
|
#ifndef PL_PROFILE_ON
|
||||||
#define pl_create_profile_context(ptContext) NULL
|
#define pl_create_profile_context(ptContext) NULL
|
||||||
#define pl_cleanup_profile_context() //
|
#define pl_cleanup_profile_context() //
|
||||||
#define pl_set_profile_context(ptContext) //
|
#define pl_set_profile_context(ptContext) //
|
||||||
#define pl_get_profile_context() NULL
|
#define pl_get_profile_context() NULL
|
||||||
#define pl_begin_profile_frame(ulFrame) //
|
#define pl_begin_profile_frame() //
|
||||||
#define pl_end_profile_frame() //
|
#define pl_end_profile_frame() //
|
||||||
#define pl_begin_profile_sample(pcName) //
|
#define pl_begin_profile_sampleuThreadIndex(uThreadIndex, pcName) //
|
||||||
#define pl_end_profile_sample() //
|
#define pl_end_profile_sample(uThreadIndex) //
|
||||||
#define pl_get_last_frame_samples(puSize) NULL
|
#define pl_get_last_frame_samples(uThreadIndex, puSize) NULL
|
||||||
|
#define pl_get_profile_overhead() 0.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // PL_PROFILE_H
|
#endif // PL_PROFILE_H
|
||||||
@ -212,8 +220,11 @@ Index of this file:
|
|||||||
// [SECTION] includes
|
// [SECTION] includes
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdbool.h> // bool
|
||||||
|
#include <string.h> // memset
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include <time.h> // clock_gettime_nsec_np
|
#include <time.h> // clock_gettime_nsec_np
|
||||||
@ -225,7 +236,7 @@ Index of this file:
|
|||||||
// [SECTION] global context
|
// [SECTION] global context
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
plProfileContext* gTPProfileContext = NULL;
|
static plProfileContext* gptProfileContext = NULL;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] internal structs
|
// [SECTION] internal structs
|
||||||
@ -257,14 +268,20 @@ typedef struct _plProfileFrame
|
|||||||
uint32_t uOverflowSampleCapacity;
|
uint32_t uOverflowSampleCapacity;
|
||||||
} plProfileFrame;
|
} plProfileFrame;
|
||||||
|
|
||||||
typedef struct _plProfileContext
|
typedef struct _plProfileThreadData
|
||||||
{
|
{
|
||||||
double dStartTime;
|
|
||||||
uint64_t ulFrame;
|
|
||||||
plProfileFrame atFrames[2];
|
plProfileFrame atFrames[2];
|
||||||
plProfileFrame* ptCurrentFrame;
|
plProfileFrame* ptCurrentFrame;
|
||||||
plProfileFrame* ptLastFrame;
|
plProfileFrame* ptLastFrame;
|
||||||
void* pInternal;
|
} plProfileThreadData;
|
||||||
|
|
||||||
|
typedef struct _plProfileContext
|
||||||
|
{
|
||||||
|
double dStartTime;
|
||||||
|
uint64_t ulFrame;
|
||||||
|
plProfileThreadData* ptThreadData;
|
||||||
|
uint32_t uThreadCount;
|
||||||
|
void* pInternal;
|
||||||
} plProfileContext;
|
} plProfileContext;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -286,7 +303,7 @@ pl__get_wall_clock(void)
|
|||||||
{
|
{
|
||||||
double dResult = 0;
|
double dResult = 0;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
INT64 slPerfFrequency = *(INT64*)gTPProfileContext->pInternal;
|
INT64 slPerfFrequency = *(INT64*)gptProfileContext->pInternal;
|
||||||
INT64 slPerfCounter;
|
INT64 slPerfCounter;
|
||||||
QueryPerformanceCounter((LARGE_INTEGER*)&slPerfCounter);
|
QueryPerformanceCounter((LARGE_INTEGER*)&slPerfCounter);
|
||||||
dResult = (double)slPerfCounter / (double)slPerfFrequency;
|
dResult = (double)slPerfCounter / (double)slPerfFrequency;
|
||||||
@ -296,7 +313,7 @@ pl__get_wall_clock(void)
|
|||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
uint64_t nsec_count = ts.tv_nsec + ts.tv_sec * 1e9;
|
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
|
#endif
|
||||||
return dResult;
|
return dResult;
|
||||||
}
|
}
|
||||||
@ -306,17 +323,23 @@ pl__get_wall_clock(void)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
plProfileContext*
|
plProfileContext*
|
||||||
pl__create_profile_context(void)
|
pl__create_profile_context(plProfileInit tInit)
|
||||||
{
|
{
|
||||||
// allocate context
|
// allocate context
|
||||||
plProfileContext* ptContext = (plProfileContext*)PL_PROFILE_ALLOC(sizeof(plProfileContext));
|
plProfileContext* ptContext = (plProfileContext*)PL_PROFILE_ALLOC(sizeof(plProfileContext));
|
||||||
memset(ptContext, 0, sizeof(plProfileContext));
|
memset(ptContext, 0, sizeof(plProfileContext));
|
||||||
gTPProfileContext = ptContext;
|
gptProfileContext = ptContext;
|
||||||
|
|
||||||
// clock setup
|
// clock setup
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static INT64 slPerfFrequency = 0;
|
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;
|
ptContext->pInternal = &slPerfFrequency;
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// no setup required
|
// no setup required
|
||||||
@ -324,7 +347,10 @@ pl__create_profile_context(void)
|
|||||||
static struct timespec ts;
|
static struct timespec ts;
|
||||||
if (clock_getres(CLOCK_MONOTONIC, &ts) != 0)
|
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;
|
static double dPerFrequency = 0.0;
|
||||||
@ -333,73 +359,97 @@ pl__create_profile_context(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ptContext->dStartTime = pl__get_wall_clock();
|
ptContext->dStartTime = pl__get_wall_clock();
|
||||||
ptContext->ptCurrentFrame = &ptContext->atFrames[0];
|
ptContext->uThreadCount = tInit.uThreadCount;
|
||||||
ptContext->atFrames[0].uSampleCapacity = 256;
|
ptContext->ptThreadData = (plProfileThreadData*)PL_PROFILE_ALLOC(sizeof(plProfileThreadData) * tInit.uThreadCount);
|
||||||
ptContext->atFrames[0].uSampleStackCapacity = 256;
|
memset(ptContext->ptThreadData, 0, sizeof(plProfileThreadData) * tInit.uThreadCount);
|
||||||
ptContext->atFrames[1].uSampleCapacity = 256;
|
for(uint32_t i = 0; i < tInit.uThreadCount; i++)
|
||||||
ptContext->atFrames[1].uSampleStackCapacity = 256;
|
{
|
||||||
ptContext->atFrames[0].ptSamples = ptContext->atFrames[0].atSamples;
|
ptContext->ptThreadData[i].ptCurrentFrame = &ptContext->ptThreadData[i].atFrames[0];
|
||||||
ptContext->atFrames[1].ptSamples = ptContext->atFrames[1].atSamples;
|
ptContext->ptThreadData[i].atFrames[0].uSampleCapacity = 256;
|
||||||
ptContext->atFrames[0].puSampleStack = ptContext->atFrames[0].auSampleStack;
|
ptContext->ptThreadData[i].atFrames[0].uSampleStackCapacity = 256;
|
||||||
ptContext->atFrames[1].puSampleStack = ptContext->atFrames[1].auSampleStack;
|
ptContext->ptThreadData[i].atFrames[1].uSampleCapacity = 256;
|
||||||
ptContext->ptLastFrame = &ptContext->atFrames[0];
|
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;
|
return ptContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pl__cleanup_profile_context(void)
|
pl__cleanup_profile_context(void)
|
||||||
{
|
{
|
||||||
|
for(uint32_t i = 0; i < gptProfileContext->uThreadCount; i++)
|
||||||
for(uint32_t i = 0; i < 2; i++)
|
|
||||||
{
|
{
|
||||||
if(gTPProfileContext->atFrames[i].bOverflowInUse)
|
for(uint32_t j = 0; j < 2; j++)
|
||||||
PL_PROFILE_FREE(gTPProfileContext->atFrames[i].ptSamples);
|
{
|
||||||
|
|
||||||
if(gTPProfileContext->atFrames[i].bSampleStackOverflowInUse)
|
if(gptProfileContext->ptThreadData[i].atFrames[j].bOverflowInUse)
|
||||||
PL_PROFILE_FREE(gTPProfileContext->atFrames[i].puSampleStack);
|
PL_PROFILE_FREE(gptProfileContext->ptThreadData[i].atFrames[j].ptSamples);
|
||||||
|
|
||||||
|
if(gptProfileContext->ptThreadData[i].atFrames[j].bSampleStackOverflowInUse)
|
||||||
|
PL_PROFILE_FREE(gptProfileContext->ptThreadData[i].atFrames[j].puSampleStack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PL_PROFILE_FREE(gTPProfileContext);
|
PL_PROFILE_FREE(gptProfileContext->ptThreadData);
|
||||||
gTPProfileContext = NULL;
|
PL_PROFILE_FREE(gptProfileContext);
|
||||||
|
gptProfileContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pl__set_profile_context(plProfileContext* ptContext)
|
pl__set_profile_context(plProfileContext* ptContext)
|
||||||
{
|
{
|
||||||
PL_ASSERT(ptContext && "profile context is NULL");
|
gptProfileContext = ptContext;
|
||||||
gTPProfileContext = ptContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plProfileContext*
|
plProfileContext*
|
||||||
pl__get_profile_context(void)
|
pl__get_profile_context(void)
|
||||||
{
|
{
|
||||||
PL_ASSERT(gTPProfileContext && "no global log context set");
|
return gptProfileContext;
|
||||||
return gTPProfileContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pl__begin_profile_frame(void)
|
pl__begin_profile_frame(void)
|
||||||
{
|
{
|
||||||
gTPProfileContext->ulFrame++;
|
|
||||||
gTPProfileContext->ptCurrentFrame = &gTPProfileContext->atFrames[gTPProfileContext->ulFrame % 2];
|
if(gptProfileContext == NULL)
|
||||||
gTPProfileContext->ptCurrentFrame->dDuration = 0.0;
|
{
|
||||||
gTPProfileContext->ptCurrentFrame->dInternalDuration = 0.0;
|
plProfileInit tInit = {
|
||||||
gTPProfileContext->ptCurrentFrame->dStartTime = pl__get_wall_clock();
|
.uThreadCount = 1
|
||||||
gTPProfileContext->ptCurrentFrame->uTotalSampleSize = 0;
|
};
|
||||||
|
pl__create_profile_context(tInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
pl__end_profile_frame(void)
|
pl__end_profile_frame(void)
|
||||||
{
|
{
|
||||||
gTPProfileContext->ptCurrentFrame->dDuration = pl__get_wall_clock() - gTPProfileContext->ptCurrentFrame->dStartTime;
|
for(uint32_t i = 0; i < gptProfileContext->uThreadCount; i++)
|
||||||
gTPProfileContext->ptLastFrame = gTPProfileContext->ptCurrentFrame;
|
{
|
||||||
|
gptProfileContext->ptThreadData[i].ptCurrentFrame->dDuration = pl__get_wall_clock() - gptProfileContext->ptThreadData[i].ptCurrentFrame->dStartTime;
|
||||||
|
gptProfileContext->ptThreadData[i].ptLastFrame = gptProfileContext->ptThreadData[i].ptCurrentFrame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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();
|
const double dCurrentInternalTime = pl__get_wall_clock();
|
||||||
plProfileFrame* ptCurrentFrame = gTPProfileContext->ptCurrentFrame;
|
plProfileFrame* ptCurrentFrame = gptProfileContext->ptThreadData[uThreadIndex].ptCurrentFrame;
|
||||||
|
|
||||||
uint32_t uSampleIndex = ptCurrentFrame->uTotalSampleSize;
|
uint32_t uSampleIndex = ptCurrentFrame->uTotalSampleSize;
|
||||||
plProfileSample* ptSample = pl__get_sample(ptCurrentFrame);
|
plProfileSample* ptSample = pl__get_sample(ptCurrentFrame);
|
||||||
@ -414,10 +464,10 @@ pl__begin_profile_sample(const char* pcName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pl__end_profile_sample(void)
|
pl__end_profile_sample(uint32_t uThreadIndex)
|
||||||
{
|
{
|
||||||
const double dCurrentInternalTime = pl__get_wall_clock();
|
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)];
|
plProfileSample* ptLastSample = &ptCurrentFrame->ptSamples[pl__pop_sample_stack(ptCurrentFrame)];
|
||||||
PL_ASSERT(ptLastSample && "Begin/end profile sample mismatch");
|
PL_ASSERT(ptLastSample && "Begin/end profile sample mismatch");
|
||||||
ptLastSample->dDuration = pl__get_wall_clock() - ptLastSample->dStartTime;
|
ptLastSample->dDuration = pl__get_wall_clock() - ptLastSample->dStartTime;
|
||||||
@ -426,9 +476,9 @@ pl__end_profile_sample(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
plProfileSample*
|
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)
|
if(puSize)
|
||||||
*puSize = ptFrame->uTotalSampleSize;
|
*puSize = ptFrame->uTotalSampleSize;
|
||||||
|
35
pl_stl.h
35
pl_stl.h
@ -1,15 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
pl_stl.h
|
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
|
// library version (format XYYZZ)
|
||||||
#define PL_STL_VERSION "0.2.0"
|
#define PL_STL_VERSION "1.0.0"
|
||||||
#define PL_STL_VERSION_NUM 00200
|
#define PL_STL_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
// [SECTION] header mess
|
// [SECTION] header mess
|
||||||
// [SECTION] includes
|
|
||||||
// [SECTION] forward declarations & basic types
|
// [SECTION] forward declarations & basic types
|
||||||
// [SECTION] public api
|
// [SECTION] public api
|
||||||
// [SECTION] structs
|
// [SECTION] structs
|
||||||
@ -23,12 +34,6 @@ Index of this file:
|
|||||||
#ifndef PL_STL_H
|
#ifndef PL_STL_H
|
||||||
#define PL_STL_H
|
#define PL_STL_H
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// [SECTION] includes
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] forward declarations & basic types
|
// [SECTION] forward declarations & basic types
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -50,7 +55,7 @@ typedef struct _plStlInfo
|
|||||||
size_t szPositionStreamSize;
|
size_t szPositionStreamSize;
|
||||||
size_t szNormalStreamSize;
|
size_t szNormalStreamSize;
|
||||||
size_t szIndexBufferSize;
|
size_t szIndexBufferSize;
|
||||||
bool bPreloaded;
|
int iPreloaded;
|
||||||
} plStlInfo;
|
} plStlInfo;
|
||||||
|
|
||||||
#endif // PL_STL_H
|
#endif // PL_STL_H
|
||||||
@ -104,11 +109,11 @@ pl_load_stl(const char* pcData, size_t szDataSize, float* afPositionStream, floa
|
|||||||
ptInfoOut = &_tInternalInfo;
|
ptInfoOut = &_tInternalInfo;
|
||||||
|
|
||||||
bool bAsci = strncmp(pcData, "solid", 5) == 0;
|
bool bAsci = strncmp(pcData, "solid", 5) == 0;
|
||||||
size_t szFacetCount = ptInfoOut->bPreloaded ? ptInfoOut->szIndexBufferSize / 3 : 0;
|
size_t szFacetCount = ptInfoOut->iPreloaded ? ptInfoOut->szIndexBufferSize / 3 : 0;
|
||||||
size_t szCurrentCursor = 0;
|
size_t szCurrentCursor = 0;
|
||||||
size_t szVertexCount = ptInfoOut->bPreloaded ? ptInfoOut->szIndexBufferSize : 0;
|
size_t szVertexCount = ptInfoOut->iPreloaded ? ptInfoOut->szIndexBufferSize : 0;
|
||||||
|
|
||||||
if(!ptInfoOut->bPreloaded)
|
if(!ptInfoOut->iPreloaded)
|
||||||
{
|
{
|
||||||
|
|
||||||
// find number of vertices & facets
|
// find number of vertices & facets
|
||||||
@ -131,7 +136,7 @@ pl_load_stl(const char* pcData, size_t szDataSize, float* afPositionStream, floa
|
|||||||
szVertexCount = szFacetCount * 3;
|
szVertexCount = szFacetCount * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptInfoOut->bPreloaded = true;
|
ptInfoOut->iPreloaded = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptInfoOut->szIndexBufferSize = szFacetCount * 3;
|
ptInfoOut->szIndexBufferSize = szFacetCount * 3;
|
||||||
|
75
pl_string.h
75
pl_string.h
@ -1,5 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
pl_string
|
pl_string.h
|
||||||
|
* no dependencies
|
||||||
|
* simple string ops
|
||||||
|
|
||||||
Do this:
|
Do this:
|
||||||
#define PL_STRING_IMPLEMENTATION
|
#define PL_STRING_IMPLEMENTATION
|
||||||
before you include this file in *one* C or C++ file to create the implementation.
|
before you include this file in *one* C or C++ file to create the implementation.
|
||||||
@ -11,9 +14,9 @@
|
|||||||
#include "pl_string.h"
|
#include "pl_string.h"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library version
|
// library version (format XYYZZ)
|
||||||
#define PL_STRING_VERSION "0.2.0"
|
#define PL_STRING_VERSION "1.0.0"
|
||||||
#define PL_STRING_VERSION_NUM 00200
|
#define PL_STRING_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
@ -47,10 +50,10 @@ uint32_t pl_str_hash_data(const void* pData, size_t szDataSize, uint32_t uSee
|
|||||||
uint32_t pl_str_hash (const char* pcData, size_t szDataSize, uint32_t uSeed);
|
uint32_t pl_str_hash (const char* pcData, size_t szDataSize, uint32_t uSeed);
|
||||||
|
|
||||||
// file/path string ops
|
// file/path string ops
|
||||||
const char* pl_str_get_file_extension(const char* pcFilePath, char* pcExtensionOut);
|
const char* pl_str_get_file_extension(const char* pcFilePath, char* pcExtensionOut, size_t szOutSize);
|
||||||
const char* pl_str_get_file_name (const char* pcFilePath, char* pcFileOut);
|
const char* pl_str_get_file_name (const char* pcFilePath, char* pcFileOut, size_t szOutSize);
|
||||||
const char* pl_str_get_file_name_only(const char* pcFilePath, char* pcFileOut);
|
bool pl_str_get_file_name_only(const char* pcFilePath, char* pcFileOut, size_t szOutSize);
|
||||||
void pl_str_get_directory (const char* pcFilePath, char* pcDirectoryOut);
|
bool pl_str_get_directory (const char* pcFilePath, char* pcDirectoryOut, size_t szOutSize);
|
||||||
|
|
||||||
// misc. opts
|
// misc. opts
|
||||||
bool pl_str_concatenate (const char* pcStr0, const char* pcStr1, char* pcStringOut, size_t szDataSize);
|
bool pl_str_concatenate (const char* pcStr0, const char* pcStr1, char* pcStringOut, size_t szDataSize);
|
||||||
@ -165,7 +168,7 @@ pl_str_hash(const char* pcData, size_t szDataSize, uint32_t uSeed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
pl_str_get_file_extension(const char* pcFilePath, char* pcExtensionOut)
|
pl_str_get_file_extension(const char* pcFilePath, char* pcExtensionOut, size_t szOutSize)
|
||||||
{
|
{
|
||||||
const char* pcResult = NULL;
|
const char* pcResult = NULL;
|
||||||
const size_t szLen = strlen(pcFilePath);
|
const size_t szLen = strlen(pcFilePath);
|
||||||
@ -194,7 +197,8 @@ pl_str_get_file_extension(const char* pcFilePath, char* pcExtensionOut)
|
|||||||
char c = pcFilePath[szLen - i - 1];
|
char c = pcFilePath[szLen - i - 1];
|
||||||
if(c == '.')
|
if(c == '.')
|
||||||
{
|
{
|
||||||
if(pcExtensionOut) strcpy(pcExtensionOut, &pcFilePath[szLen - i]);
|
if(pcExtensionOut)
|
||||||
|
strncpy(pcExtensionOut, &pcFilePath[szLen - i], szOutSize);
|
||||||
pcResult = &pcFilePath[szLen - i];
|
pcResult = &pcFilePath[szLen - i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -202,14 +206,15 @@ pl_str_get_file_extension(const char* pcFilePath, char* pcExtensionOut)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(pcExtensionOut) memset(pcExtensionOut, 0, 1);
|
if(pcExtensionOut)
|
||||||
|
memset(pcExtensionOut, 0, szOutSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcResult;
|
return pcResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
pl_str_get_file_name(const char* pcFilePath, char* pcFileOut)
|
pl_str_get_file_name(const char* pcFilePath, char* pcFileOut, size_t szOutSize)
|
||||||
{
|
{
|
||||||
const char* pcResult = pcFilePath;
|
const char* pcResult = pcFilePath;
|
||||||
const size_t szLen = strlen(pcFilePath);
|
const size_t szLen = strlen(pcFilePath);
|
||||||
@ -233,7 +238,8 @@ pl_str_get_file_name(const char* pcFilePath, char* pcFileOut)
|
|||||||
|
|
||||||
if(uSlashCount == 0)
|
if(uSlashCount == 0)
|
||||||
{
|
{
|
||||||
if(pcFileOut) strcpy(pcFileOut, &pcFilePath[i + 1]);
|
if(pcFileOut)
|
||||||
|
strncpy(pcFileOut, &pcFilePath[i + 1], szOutSize);
|
||||||
pcResult = &pcFilePath[i + 1];
|
pcResult = &pcFilePath[i + 1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -241,16 +247,26 @@ pl_str_get_file_name(const char* pcFilePath, char* pcFileOut)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(pcFileOut) memcpy(pcFileOut, pcFilePath, szLen + 1);
|
if(pcFileOut)
|
||||||
|
{
|
||||||
|
size_t szCopySize = szLen + 1;
|
||||||
|
if(szCopySize > szOutSize)
|
||||||
|
szCopySize = szOutSize;
|
||||||
|
memcpy(pcFileOut, pcFilePath, szCopySize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcResult;
|
return pcResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
bool
|
||||||
pl_str_get_file_name_only(const char* pcFilePath, char* pcFileOut)
|
pl_str_get_file_name_only(const char* pcFilePath, char* pcFileOut, size_t szOutSize)
|
||||||
{
|
{
|
||||||
const char* pcResult = pcFilePath;
|
PL_ASSERT(pcFileOut && "pl_str_get_file_name_only requires pcFileOut to be valid pointer");
|
||||||
|
|
||||||
|
if(pcFileOut == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
const size_t szLen = strlen(pcFilePath);
|
const size_t szLen = strlen(pcFilePath);
|
||||||
|
|
||||||
// check if string includes directory
|
// check if string includes directory
|
||||||
@ -272,19 +288,20 @@ pl_str_get_file_name_only(const char* pcFilePath, char* pcFileOut)
|
|||||||
|
|
||||||
if(uSlashCount == 0)
|
if(uSlashCount == 0)
|
||||||
{
|
{
|
||||||
if(pcFileOut) strcpy(pcFileOut, &pcFilePath[i + 1]);
|
strncpy(pcFileOut, &pcFilePath[i + 1], szOutSize);
|
||||||
pcResult = &pcFilePath[i + 1];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(pcFileOut) memcpy(pcFileOut, pcFilePath, szLen + 1);
|
if(szLen + 1 > szOutSize)
|
||||||
|
return false;
|
||||||
|
memcpy(pcFileOut, pcFilePath, szLen + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t szOutLen = strlen(pcFileOut);
|
if(szLen > szOutSize)
|
||||||
|
return false;
|
||||||
bool bPeriodReached = false;
|
bool bPeriodReached = false;
|
||||||
for(size_t i = 0; i < szLen; i++)
|
for(size_t i = 0; i < szLen; i++)
|
||||||
{
|
{
|
||||||
@ -299,15 +316,17 @@ pl_str_get_file_name_only(const char* pcFilePath, char* pcFileOut)
|
|||||||
pcFileOut[i] = 0;
|
pcFileOut[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return pcResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
pl_str_get_directory(const char* pcFilePath, char* pcDirectoryOut)
|
pl_str_get_directory(const char* pcFilePath, char* pcDirectoryOut, size_t szOutSize)
|
||||||
{
|
{
|
||||||
size_t szLen = strlen(pcFilePath);
|
size_t szLen = strlen(pcFilePath);
|
||||||
strcpy(pcDirectoryOut, pcFilePath);
|
strncpy(pcDirectoryOut, pcFilePath, szOutSize);
|
||||||
|
|
||||||
|
if(szLen > szOutSize || szOutSize < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
while(szLen > 0)
|
while(szLen > 0)
|
||||||
{
|
{
|
||||||
@ -323,6 +342,7 @@ pl_str_get_directory(const char* pcFilePath, char* pcDirectoryOut)
|
|||||||
pcDirectoryOut[0] = '.';
|
pcDirectoryOut[0] = '.';
|
||||||
pcDirectoryOut[1] = '/';
|
pcDirectoryOut[1] = '/';
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -333,7 +353,6 @@ pl_str_concatenate(const char* pcStr0, const char* pcStr1, char* pcStringOut, si
|
|||||||
|
|
||||||
if(szLen0 + szLen1 > szDataSize)
|
if(szLen0 + szLen1 > szDataSize)
|
||||||
{
|
{
|
||||||
PL_ASSERT(false && "buffer provided not big enough");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
308
pl_test.h
308
pl_test.h
@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
pl_test
|
pl_test.h
|
||||||
|
* simple test librsry
|
||||||
|
|
||||||
Do this:
|
Do this:
|
||||||
#define PL_TEST_IMPLEMENTATION
|
#define PL_TEST_IMPLEMENTATION
|
||||||
before you include this file in *one* C or C++ file to create the implementation.
|
before you include this file in *one* C or C++ file to create the implementation.
|
||||||
@ -9,17 +11,22 @@
|
|||||||
#include ...
|
#include ...
|
||||||
#define PL_TEST_IMPLEMENTATION
|
#define PL_TEST_IMPLEMENTATION
|
||||||
#include "pl_test.h"
|
#include "pl_test.h"
|
||||||
|
Notes:
|
||||||
|
* for console color output on windows, define "PL_TEST_WIN32_COLOR" before
|
||||||
|
including the implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library version
|
// library version (format XYYZZ)
|
||||||
#define PL_TEST_VERSION "0.1.0"
|
#define PL_TEST_VERSION "1.0.0"
|
||||||
#define PL_TEST_VERSION_NUM 00100
|
#define PL_TEST_VERSION_NUM 10000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Index of this file:
|
Index of this file:
|
||||||
// [SECTION] header mess
|
// [SECTION] header mess
|
||||||
// [SECTION] includes
|
// [SECTION] includes
|
||||||
// [SECTION] public api
|
// [SECTION] public api
|
||||||
|
// [SECTION] structs
|
||||||
|
// [SECTION] private
|
||||||
// [SECTION] c file
|
// [SECTION] c file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -34,8 +41,8 @@ Index of this file:
|
|||||||
// [SECTION] includes
|
// [SECTION] includes
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h> // bool
|
||||||
#include <stdint.h>
|
#include <stdint.h> // uint32_t
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] forward declarations & basic types
|
// [SECTION] forward declarations & basic types
|
||||||
@ -43,6 +50,7 @@ Index of this file:
|
|||||||
|
|
||||||
// forward declarations
|
// forward declarations
|
||||||
typedef struct _plTestContext plTestContext;
|
typedef struct _plTestContext plTestContext;
|
||||||
|
typedef struct _plTestOptions plTestOptions;
|
||||||
|
|
||||||
typedef void (*PL_TEST_FUNCTION)(void*);
|
typedef void (*PL_TEST_FUNCTION)(void*);
|
||||||
|
|
||||||
@ -52,26 +60,29 @@ typedef void (*PL_TEST_FUNCTION)(void*);
|
|||||||
|
|
||||||
#define pl_test_register_test(TEST, DATA) pl__test_register_test((TEST), (DATA), #TEST)
|
#define pl_test_register_test(TEST, DATA) pl__test_register_test((TEST), (DATA), #TEST)
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] public api
|
// [SECTION] public api
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
plTestContext* pl_create_test_context(void);
|
plTestContext* pl_create_test_context(plTestOptions);
|
||||||
|
|
||||||
// tests
|
// tests
|
||||||
void pl__test_register_test(PL_TEST_FUNCTION tTest, void* pData, const char* pcName);
|
void pl_test_run_suite(const char* pcSuiteName);
|
||||||
bool pl_test_run(void);
|
bool pl_test_finish(void);
|
||||||
|
|
||||||
// booleans
|
// booleans
|
||||||
bool pl_test_expect_true (bool bValue, const char* pcMsg);
|
bool pl_test_expect_true (bool bValue, const char* pcMsg);
|
||||||
bool pl_test_expect_false(bool bValue, const char* pcMsg);
|
bool pl_test_expect_false(bool bValue, const char* pcMsg);
|
||||||
|
|
||||||
// numbers
|
// integers
|
||||||
bool pl_test_expect_int_equal (int iValue0, int iValue1, const char* pcMsg);
|
bool pl_test_expect_int_equal (int iValue0, int iValue1, const char* pcMsg);
|
||||||
bool pl_test_expect_int_not_equal (int iValue0, int iValue1, const char* pcMsg);
|
bool pl_test_expect_int_not_equal (int iValue0, int iValue1, const char* pcMsg);
|
||||||
bool pl_test_expect_unsigned_equal (uint32_t uValue0, uint32_t uValue1, const char* pcMsg);
|
bool pl_test_expect_uint32_equal (uint32_t uValue0, uint32_t uValue1, const char* pcMsg);
|
||||||
bool pl_test_expect_unsigned_not_equal (uint32_t uValue0, uint32_t uValue1, const char* pcMsg);
|
bool pl_test_expect_uint32_not_equal(uint32_t uValue0, uint32_t uValue1, const char* pcMsg);
|
||||||
|
bool pl_test_expect_uint64_equal (uint64_t uValue0, uint64_t uValue1, const char* pcMsg);
|
||||||
|
bool pl_test_expect_uint64_not_equal(uint64_t uValue0, uint64_t uValue1, const char* pcMsg);
|
||||||
|
|
||||||
|
// floating point
|
||||||
bool pl_test_expect_float_near_equal (float fValue0, float fValue1, float fError, const char* pcMsg);
|
bool pl_test_expect_float_near_equal (float fValue0, float fValue1, float fError, const char* pcMsg);
|
||||||
bool pl_test_expect_float_near_not_equal (float fValue0, float fValue1, float fError, const char* pcMsg);
|
bool pl_test_expect_float_near_not_equal (float fValue0, float fValue1, float fError, const char* pcMsg);
|
||||||
bool pl_test_expect_double_near_equal (double dValue0, double dValue1, double dError, const char* pcMsg);
|
bool pl_test_expect_double_near_equal (double dValue0, double dValue1, double dError, const char* pcMsg);
|
||||||
@ -81,6 +92,23 @@ bool pl_test_expect_double_near_not_equal(double dValue0, double dValue1, double
|
|||||||
bool pl_test_expect_string_equal (const char* pcValue0, const char* pcValue1, const char* pcMsg);
|
bool pl_test_expect_string_equal (const char* pcValue0, const char* pcValue1, const char* pcMsg);
|
||||||
bool pl_test_expect_string_not_equal(const char* pcValue0, const char* pcValue1, const char* pcMsg);
|
bool pl_test_expect_string_not_equal(const char* pcValue0, const char* pcValue1, const char* pcMsg);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] structs
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef struct _plTestOptions
|
||||||
|
{
|
||||||
|
bool bPrintSuiteResults;
|
||||||
|
bool bPrintAllPassedChecks;
|
||||||
|
bool bPrintColor;
|
||||||
|
} plTestOptions;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// [SECTION] private
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void pl__test_register_test(PL_TEST_FUNCTION tTest, void* pData, const char* pcName);
|
||||||
|
|
||||||
#endif // PL_TEST_H
|
#endif // PL_TEST_H
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -100,6 +128,14 @@ Index of this file:
|
|||||||
|
|
||||||
#ifdef PL_TEST_IMPLEMENTATION
|
#ifdef PL_TEST_IMPLEMENTATION
|
||||||
|
|
||||||
|
#if defined(PL_TEST_WIN32_COLOR) && defined(_WIN32)
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
static DWORD gtOriginalMode = 0;
|
||||||
|
static HANDLE gtStdOutHandle = 0;
|
||||||
|
static bool gbActiveColor = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] includes
|
// [SECTION] includes
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -130,12 +166,15 @@ typedef struct _plTest
|
|||||||
|
|
||||||
typedef struct _plTestContext
|
typedef struct _plTestContext
|
||||||
{
|
{
|
||||||
plTest* atTests;
|
plTest* atTests;
|
||||||
plTest* ptCurrentTest;
|
plTest* ptCurrentTest;
|
||||||
uint32_t uTestSize;
|
uint32_t uTestSize;
|
||||||
uint32_t uTestCapacity;
|
uint32_t uTestCapacity;
|
||||||
uint32_t uFailedTest;
|
uint32_t uFailedTest;
|
||||||
bool bPrintPasses;
|
plTestOptions tOptions;
|
||||||
|
|
||||||
|
uint32_t uTotalPassedTests;
|
||||||
|
uint32_t uTotalFailedTests;
|
||||||
} plTestContext;
|
} plTestContext;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -149,12 +188,30 @@ plTestContext* gptTestContext = NULL;
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
plTestContext*
|
plTestContext*
|
||||||
pl_create_test_context(void)
|
pl_create_test_context(plTestOptions tOptions)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if defined(PL_TEST_WIN32_COLOR) && defined(_WIN32)
|
||||||
|
DWORD tCurrentMode = 0;
|
||||||
|
gbActiveColor = true;
|
||||||
|
gtStdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if(gtStdOutHandle == INVALID_HANDLE_VALUE)
|
||||||
|
gbActiveColor = false;
|
||||||
|
else if(!GetConsoleMode(gtStdOutHandle, &tCurrentMode))
|
||||||
|
gbActiveColor = false;
|
||||||
|
gtOriginalMode = tCurrentMode;
|
||||||
|
tCurrentMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; // enable ANSI escape codes
|
||||||
|
if(!SetConsoleMode(gtStdOutHandle, tCurrentMode))
|
||||||
|
gbActiveColor = false;
|
||||||
|
|
||||||
|
if(!gbActiveColor)
|
||||||
|
tOptions.bPrintColor = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
gptTestContext = (plTestContext*)malloc(sizeof(plTestContext));
|
gptTestContext = (plTestContext*)malloc(sizeof(plTestContext));
|
||||||
memset(gptTestContext, 0, sizeof(plTestContext));
|
memset(gptTestContext, 0, sizeof(plTestContext));
|
||||||
gptTestContext->uTestCapacity = 64;
|
gptTestContext->uTestCapacity = 64;
|
||||||
gptTestContext->bPrintPasses = false;
|
gptTestContext->tOptions = tOptions;
|
||||||
gptTestContext->atTests = (plTest*)malloc(gptTestContext->uTestCapacity * sizeof(plTest));
|
gptTestContext->atTests = (plTest*)malloc(gptTestContext->uTestCapacity * sizeof(plTest));
|
||||||
memset(gptTestContext->atTests, 0, sizeof(gptTestContext->uTestCapacity * sizeof(plTest)));
|
memset(gptTestContext->atTests, 0, sizeof(gptTestContext->uTestCapacity * sizeof(plTest)));
|
||||||
return gptTestContext;
|
return gptTestContext;
|
||||||
@ -179,30 +236,70 @@ pl__test_register_test(PL_TEST_FUNCTION tTest, void* pData, const char* pcName)
|
|||||||
gptTestContext->atTests[gptTestContext->uTestSize - 1].pData = pData;
|
gptTestContext->atTests[gptTestContext->uTestSize - 1].pData = pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
pl_test_run(void)
|
pl_test_run_suite(const char* pcSuiteName)
|
||||||
{
|
{
|
||||||
|
printf("\n------%s suite------\n\n", pcSuiteName);
|
||||||
|
|
||||||
for(uint32_t i = 0; i < gptTestContext->uTestSize; i++)
|
for(uint32_t i = 0; i < gptTestContext->uTestSize; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
gptTestContext->ptCurrentTest = &gptTestContext->atTests[i];
|
gptTestContext->ptCurrentTest = &gptTestContext->atTests[i];
|
||||||
gptTestContext->ptCurrentTest->bFailureOccured = false;
|
gptTestContext->ptCurrentTest->bFailureOccured = false;
|
||||||
|
|
||||||
printf("-----------------------------------\n");
|
printf("running -> \"%s\"\n", gptTestContext->ptCurrentTest->pcName);
|
||||||
printf("\"%s\" running...\n\n", gptTestContext->ptCurrentTest->pcName);
|
|
||||||
gptTestContext->ptCurrentTest->tTest(gptTestContext->ptCurrentTest->pData);
|
gptTestContext->ptCurrentTest->tTest(gptTestContext->ptCurrentTest->pData);
|
||||||
|
|
||||||
if(gptTestContext->ptCurrentTest->bFailureOccured)
|
if(gptTestContext->ptCurrentTest->bFailureOccured)
|
||||||
{
|
{
|
||||||
pl__test_print_red("\n\n\"%s\" failed", NULL, gptTestContext->ptCurrentTest->pcName);
|
pl__test_print_red("%s", NULL, " -> failed");
|
||||||
gptTestContext->uFailedTest++;
|
gptTestContext->uFailedTest++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("\n\n\"%s\" passed\n\n", gptTestContext->ptCurrentTest->pcName);
|
pl__test_print_green("%s", NULL, " passed");
|
||||||
printf("-----------------------------------\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gptTestContext->uFailedTest == 0;
|
if(gptTestContext->tOptions.bPrintSuiteResults)
|
||||||
|
{
|
||||||
|
printf("\nPassed: ");
|
||||||
|
pl__test_print_green("%u", NULL, gptTestContext->uTestSize - gptTestContext->uFailedTest);
|
||||||
|
|
||||||
|
printf("Failed: ");
|
||||||
|
pl__test_print_red("%u", NULL, gptTestContext->uFailedTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("\n------End tests------\n\n");
|
||||||
|
|
||||||
|
// reset context
|
||||||
|
gptTestContext->uTotalPassedTests += gptTestContext->uTestSize - gptTestContext->uFailedTest;
|
||||||
|
gptTestContext->uTotalFailedTests += gptTestContext->uFailedTest;
|
||||||
|
gptTestContext->uTestSize = 0;
|
||||||
|
gptTestContext->uFailedTest = 0;
|
||||||
|
gptTestContext->ptCurrentTest = NULL;
|
||||||
|
memset(gptTestContext->atTests, 0, sizeof(plTest) * gptTestContext->uTestCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pl_test_finish(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("\n------Results------\n");
|
||||||
|
|
||||||
|
printf("\nTests passed: ");
|
||||||
|
pl__test_print_green("%u", NULL, gptTestContext->uTotalPassedTests);
|
||||||
|
|
||||||
|
printf("Tests failed: ");
|
||||||
|
pl__test_print_red("%u", NULL, gptTestContext->uTotalFailedTests);
|
||||||
|
|
||||||
|
#if defined(PL_TEST_WIN32_COLOR) && defined(_WIN32)
|
||||||
|
if(gbActiveColor)
|
||||||
|
{
|
||||||
|
if(!SetConsoleMode(gtStdOutHandle, gtOriginalMode))
|
||||||
|
exit(GetLastError());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return gptTestContext->uTotalFailedTests == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -210,7 +307,8 @@ pl_test_expect_true(bool bValue, const char* pcMsg)
|
|||||||
{
|
{
|
||||||
if(bValue)
|
if(bValue)
|
||||||
{
|
{
|
||||||
pl__test_print_green("Value: true | Expected Value: true", pcMsg);
|
if(gptTestContext->tOptions.bPrintAllPassedChecks)
|
||||||
|
pl__test_print_green("Value: true | Expected Value: true", pcMsg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,64 +327,67 @@ pl_test_expect_false(bool bValue, const char* pcMsg)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl__test_print_green("Value: false | Expected Value: false", pcMsg);
|
if(gptTestContext->tOptions.bPrintAllPassedChecks)
|
||||||
|
pl__test_print_green("Value: false | Expected Value: false", pcMsg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define pl__test_expect_equal(value0, value1, pcMsg, format) \
|
||||||
|
if((value0) == (value1)) \
|
||||||
|
{ \
|
||||||
|
if(gptTestContext->tOptions.bPrintAllPassedChecks) \
|
||||||
|
pl__test_print_green(format " equals " format " | Equality Expected", (pcMsg), (value0), (value1)); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
pl__test_print_red(format " does not equal " format " | Equality Expected", (pcMsg), (value0), (value1)); \
|
||||||
|
gptTestContext->ptCurrentTest->bFailureOccured = true; \
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#define pl__test_expect_not_equal(value0, value1, pcMsg, format) \
|
||||||
|
if((value0) == (value1)) \
|
||||||
|
{ \
|
||||||
|
pl__test_print_red(format " equals " format " | Equality Not Expected", (pcMsg), (value0), (value1)); \
|
||||||
|
gptTestContext->ptCurrentTest->bFailureOccured = true; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
if(gptTestContext->tOptions.bPrintAllPassedChecks) \
|
||||||
|
pl__test_print_green(format " does not equal " format " | Equality Expected", (pcMsg), (value0), (value1)); \
|
||||||
|
return true;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pl_test_expect_int_equal(int iValue0, int iValue1, const char* pcMsg)
|
pl_test_expect_int_equal(int iValue0, int iValue1, const char* pcMsg)
|
||||||
{
|
{
|
||||||
if(iValue0 == iValue1)
|
pl__test_expect_equal(iValue0, iValue1, pcMsg, "%i");
|
||||||
{
|
|
||||||
pl__test_print_green("%i equals %i | Equality Expected", pcMsg, iValue0, iValue1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl__test_print_red("%i does not equal %i | Equality Expected", pcMsg, iValue0, iValue1);
|
|
||||||
gptTestContext->ptCurrentTest->bFailureOccured = true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pl_test_expect_int_not_equal(int iValue0, int iValue1, const char* pcMsg)
|
pl_test_expect_int_not_equal(int iValue0, int iValue1, const char* pcMsg)
|
||||||
{
|
{
|
||||||
if(iValue0 == iValue1)
|
pl__test_expect_not_equal(iValue0, iValue1, pcMsg, "%i");
|
||||||
{
|
|
||||||
pl__test_print_red("%i equals %i | Equality Not Expected", pcMsg, iValue0, iValue1);
|
|
||||||
gptTestContext->ptCurrentTest->bFailureOccured = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl__test_print_green("%i does not equal %i | Equality Not Expected", pcMsg, iValue0, iValue1);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pl_test_expect_unsigned_equal(uint32_t uValue0, uint32_t uValue1, const char* pcMsg)
|
pl_test_expect_uint64_equal(uint64_t uValue0, uint64_t uValue1, const char* pcMsg)
|
||||||
{
|
{
|
||||||
if(uValue0 == uValue1)
|
pl__test_expect_equal(uValue0, uValue1, pcMsg, "%llu");
|
||||||
{
|
|
||||||
pl__test_print_green("%u equals %u | Equality Expected", pcMsg, uValue0, uValue1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl__test_print_red("%u does not equal %u | Equality Expected", pcMsg, uValue0, uValue1);
|
|
||||||
gptTestContext->ptCurrentTest->bFailureOccured = true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pl_test_expect_unsigned_not_equal(uint32_t uValue0, uint32_t uValue1, const char* pcMsg)
|
pl_test_expect_uint64_not_equal(uint64_t uValue0, uint64_t uValue1, const char* pcMsg)
|
||||||
{
|
{
|
||||||
if(uValue0 == uValue1)
|
pl__test_expect_not_equal(uValue0, uValue1, pcMsg, "%llu");
|
||||||
{
|
}
|
||||||
pl__test_print_red("%u equals %u | Equality Not Expected", pcMsg, uValue0, uValue1);
|
|
||||||
gptTestContext->ptCurrentTest->bFailureOccured = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl__test_print_green("%u does not equal %u | Equality Not Expected", pcMsg, uValue0, uValue1);
|
bool
|
||||||
return true;
|
pl_test_expect_uint32_equal(uint32_t uValue0, uint32_t uValue1, const char* pcMsg)
|
||||||
|
{
|
||||||
|
pl__test_expect_equal(uValue0, uValue1, pcMsg, "%u");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
pl_test_expect_uint32_not_equal(uint32_t uValue0, uint32_t uValue1, const char* pcMsg)
|
||||||
|
{
|
||||||
|
pl__test_expect_not_equal(uValue0, uValue1, pcMsg, "%u");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -306,7 +407,8 @@ pl_test_expect_double_near_equal(double dValue0, double dValue1, double dError,
|
|||||||
{
|
{
|
||||||
if(dValue0 >= dValue1 - dError && dValue0 <= dValue1 + dError)
|
if(dValue0 >= dValue1 - dError && dValue0 <= dValue1 + dError)
|
||||||
{
|
{
|
||||||
pl__test_print_green("%0.6f equals %0.6f | Equality Expected within %0.6f", pcMsg, dValue0, dValue1, dError);
|
if(gptTestContext->tOptions.bPrintAllPassedChecks)
|
||||||
|
pl__test_print_green("%0.6f equals %0.6f | Equality Expected within %0.6f", pcMsg, dValue0, dValue1, dError);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +427,8 @@ pl_test_expect_double_near_not_equal(double dValue0, double dValue1, double dErr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl__test_print_green("%0.6f does not equal %0.6f | Equality Not Expected within %0.6f", pcMsg, dValue0, dValue1, dError);
|
if(gptTestContext->tOptions.bPrintAllPassedChecks)
|
||||||
|
pl__test_print_green("%0.6f does not equal %0.6f | Equality Not Expected within %0.6f", pcMsg, dValue0, dValue1, dError);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +437,8 @@ pl_test_expect_string_equal(const char* pcValue0, const char* pcValue1, const ch
|
|||||||
{
|
{
|
||||||
if(strcmp(pcValue0, pcValue1) == 0)
|
if(strcmp(pcValue0, pcValue1) == 0)
|
||||||
{
|
{
|
||||||
pl__test_print_green("\"%s\" equals \"%s\" | Equality Expected", pcMsg, pcValue0, pcValue1);
|
if(gptTestContext->tOptions.bPrintAllPassedChecks)
|
||||||
|
pl__test_print_green("\"%s\" equals \"%s\" | Equality Expected", pcMsg, pcValue0, pcValue1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +452,8 @@ pl_test_expect_string_not_equal(const char* pcValue0, const char* pcValue1, cons
|
|||||||
{
|
{
|
||||||
if(strcmp(pcValue0, pcValue1) == 0)
|
if(strcmp(pcValue0, pcValue1) == 0)
|
||||||
{
|
{
|
||||||
pl__test_print_green("\"%s\" equals \"%s\" | Equality Not Expected", pcMsg, pcValue0, pcValue1);
|
if(gptTestContext->tOptions.bPrintAllPassedChecks)
|
||||||
|
pl__test_print_green("\"%s\" equals \"%s\" | Equality Not Expected", pcMsg, pcValue0, pcValue1);
|
||||||
gptTestContext->ptCurrentTest->bFailureOccured = true;
|
gptTestContext->ptCurrentTest->bFailureOccured = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -374,11 +479,14 @@ pl__test_print_va(const char* cPFormat, va_list args)
|
|||||||
void static
|
void static
|
||||||
pl__test_print_red(const char* cPFormat, const char* pcMsg, ...)
|
pl__test_print_red(const char* cPFormat, const char* pcMsg, ...)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
if(gptTestContext->tOptions.bPrintColor)
|
||||||
printf("[91m");
|
{
|
||||||
#else
|
#ifdef _WIN32
|
||||||
printf("\033[91m");
|
printf("[91m");
|
||||||
#endif
|
#else
|
||||||
|
printf("\033[91m");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, pcMsg);
|
va_start(argptr, pcMsg);
|
||||||
@ -390,24 +498,27 @@ pl__test_print_red(const char* cPFormat, const char* pcMsg, ...)
|
|||||||
else
|
else
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
#ifdef _WIN32
|
if(gptTestContext->tOptions.bPrintColor)
|
||||||
printf("[0m");
|
{
|
||||||
#else
|
#ifdef _WIN32
|
||||||
printf("\033[0m");
|
printf("[0m");
|
||||||
#endif
|
#else
|
||||||
|
printf("\033[0m");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pl__test_print_green(const char* cPFormat, const char* pcMsg, ...)
|
pl__test_print_green(const char* cPFormat, const char* pcMsg, ...)
|
||||||
{
|
{
|
||||||
if(!gptTestContext->bPrintPasses)
|
if(gptTestContext->tOptions.bPrintColor)
|
||||||
return;
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
#ifdef _WIN32
|
printf("[92m");
|
||||||
printf("[92m");
|
#else
|
||||||
#else
|
printf("\033[92m");
|
||||||
printf("\033[92m");
|
#endif
|
||||||
#endif
|
}
|
||||||
|
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, pcMsg);
|
va_start(argptr, pcMsg);
|
||||||
@ -419,11 +530,14 @@ pl__test_print_green(const char* cPFormat, const char* pcMsg, ...)
|
|||||||
else
|
else
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
#ifdef _WIN32
|
if(gptTestContext->tOptions.bPrintColor)
|
||||||
printf("[0m");
|
{
|
||||||
#else
|
#ifdef _WIN32
|
||||||
printf("\033[0m");
|
printf("[0m");
|
||||||
#endif
|
#else
|
||||||
|
printf("\033[0m");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PL_TEST_IMPLEMENTATION
|
#endif // PL_TEST_IMPLEMENTATION
|
@ -1,26 +1,51 @@
|
|||||||
#include "pl_ds_tests.h"
|
#include "pl_ds_tests.h"
|
||||||
#include "pl_json_tests.h"
|
#include "pl_json_tests.h"
|
||||||
|
#include "pl_memory_tests.h"
|
||||||
|
#include "pl_string_tests.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
plTestContext* ptTestContext = pl_create_test_context();
|
// create test context
|
||||||
|
plTestOptions tOptions = {
|
||||||
|
.bPrintSuiteResults = true,
|
||||||
|
.bPrintColor = true
|
||||||
|
};
|
||||||
|
plTestContext* ptTestContext = pl_create_test_context(tOptions);
|
||||||
|
|
||||||
// data structure tests
|
// pl_json.h tests
|
||||||
pl_test_register_test(hashmap_test_0, NULL);
|
pl_json_tests(NULL);
|
||||||
|
pl_test_run_suite("pl_json.h");
|
||||||
|
|
||||||
// json tests
|
// pl_memory.h tests
|
||||||
pl_test_register_test(json_test_0, NULL);
|
pl_memory_tests(NULL);
|
||||||
|
pl_test_run_suite("pl_memory.h");
|
||||||
|
|
||||||
if(!pl_test_run())
|
// pl_ds.h tests
|
||||||
|
pl_ds_tests(NULL);
|
||||||
|
pl_test_run_suite("pl_ds.h");
|
||||||
|
|
||||||
|
// pl_string.h tests
|
||||||
|
pl_string_tests(NULL);
|
||||||
|
pl_test_run_suite("pl_string.h");
|
||||||
|
|
||||||
|
bool bResult = pl_test_finish();
|
||||||
|
|
||||||
|
if(!bResult)
|
||||||
{
|
{
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PL_TEST_IMPLEMENTATION
|
|
||||||
#include "pl_test.h"
|
|
||||||
|
|
||||||
#define PL_JSON_IMPLEMENTATION
|
#define PL_JSON_IMPLEMENTATION
|
||||||
#include "pl_json.h"
|
#include "pl_json.h"
|
||||||
|
|
||||||
|
#define PL_MEMORY_IMPLEMENTATION
|
||||||
|
#include "pl_memory.h"
|
||||||
|
|
||||||
|
#define PL_STRING_IMPLEMENTATION
|
||||||
|
#include "pl_string.h"
|
||||||
|
|
||||||
|
#define PL_TEST_WIN32_COLOR
|
||||||
|
#define PL_TEST_IMPLEMENTATION
|
||||||
|
#include "pl_test.h"
|
@ -6,97 +6,104 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "pl_ds.h"
|
#include "pl_ds.h"
|
||||||
|
|
||||||
static void
|
void
|
||||||
hashmap_test_0(void* pData)
|
hashmap_test_0(void* pData)
|
||||||
{
|
{
|
||||||
// hashmap 0
|
plHashMap* ptHashMap = NULL;
|
||||||
|
|
||||||
|
int* sbiValues = NULL;
|
||||||
|
pl_sb_push(sbiValues, 0);
|
||||||
|
pl_sb_push(sbiValues, 69);
|
||||||
|
pl_hm_insert(ptHashMap, pl_hm_hash_str("Dirty Number"), pl_sb_size(sbiValues) - 1);
|
||||||
|
pl_sb_push(sbiValues, 117);
|
||||||
|
pl_hm_insert(ptHashMap, pl_hm_hash_str("Spartan Number"), pl_sb_size(sbiValues) - 1);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < 3000; i++)
|
||||||
{
|
{
|
||||||
plHashMap tHashMap = {0};
|
pl_sb_push(sbiValues, i);
|
||||||
|
pl_hm_insert(ptHashMap, pl_hm_hash("Spartan Number2", strlen("Spartan Number2"), i), pl_sb_size(sbiValues) - 1);
|
||||||
int* sbiValues = NULL;
|
|
||||||
pl_sb_push(sbiValues, 0);
|
|
||||||
pl_sb_push(sbiValues, 69);
|
|
||||||
pl_hm_insert(&tHashMap, pl_hm_hash_str("Dirty Number"), pl_sb_size(sbiValues) - 1);
|
|
||||||
pl_sb_push(sbiValues, 117);
|
|
||||||
pl_hm_insert(&tHashMap, pl_hm_hash_str("Spartan Number"), pl_sb_size(sbiValues) - 1);
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < 3000; i++)
|
|
||||||
{
|
|
||||||
pl_sb_push(sbiValues, i);
|
|
||||||
pl_hm_insert(&tHashMap, pl_hm_hash("Spartan Number2", strlen("Spartan Number2"), i), pl_sb_size(sbiValues) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(&tHashMap, pl_hm_hash_str("Dirty Number"))], 69, NULL);
|
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(&tHashMap, pl_hm_hash_str("Spartan Number"))], 117, NULL);
|
|
||||||
|
|
||||||
pl_hm_remove(&tHashMap, pl_hm_hash_str("Dirty Number"));
|
|
||||||
|
|
||||||
uint64_t ulFreeIndex = pl_hm_get_free_index(&tHashMap);
|
|
||||||
if(ulFreeIndex == UINT64_MAX)
|
|
||||||
{
|
|
||||||
pl_sb_add(sbiValues);
|
|
||||||
ulFreeIndex = pl_sb_size(sbiValues) - 1;
|
|
||||||
}
|
|
||||||
sbiValues[ulFreeIndex] = 666999;
|
|
||||||
pl_hm_insert(&tHashMap, pl_hm_hash_str("Extra dirty number"), ulFreeIndex);
|
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(&tHashMap, pl_hm_hash_str("Extra dirty number"))], 666999, NULL);
|
|
||||||
|
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(&tHashMap, pl_hm_hash_str("Extra dirty number"))], 666999, NULL);
|
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(&tHashMap, pl_hm_hash_str("Spartan Number"))], 117, NULL);
|
|
||||||
|
|
||||||
pl_hm_free(&tHashMap);
|
|
||||||
pl_sb_free(sbiValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashmap 1
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(ptHashMap, pl_hm_hash_str("Dirty Number"))], 69, NULL);
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(ptHashMap, pl_hm_hash_str("Spartan Number"))], 117, NULL);
|
||||||
|
|
||||||
|
pl_hm_remove(ptHashMap, pl_hm_hash_str("Dirty Number"));
|
||||||
|
|
||||||
|
uint64_t ulFreeIndex = pl_hm_get_free_index(ptHashMap);
|
||||||
|
if(ulFreeIndex == UINT64_MAX)
|
||||||
{
|
{
|
||||||
plHashMap tHashMap = {0};
|
pl_sb_add(sbiValues);
|
||||||
|
ulFreeIndex = pl_sb_size(sbiValues) - 1;
|
||||||
pl_hm_insert(&tHashMap, pl_hm_hash_str("Dirty Number"), 69);
|
|
||||||
pl_hm_insert(&tHashMap, pl_hm_hash_str("Spartan Number"), 117);
|
|
||||||
|
|
||||||
pl_test_expect_int_equal((int)pl_hm_lookup(&tHashMap, pl_hm_hash_str("Dirty Number")), 69, NULL);
|
|
||||||
pl_test_expect_int_equal((int)pl_hm_lookup(&tHashMap, pl_hm_hash_str("Spartan Number")), 117, NULL);
|
|
||||||
|
|
||||||
pl_hm_free(&tHashMap);
|
|
||||||
}
|
}
|
||||||
|
sbiValues[ulFreeIndex] = 666999;
|
||||||
|
pl_hm_insert(ptHashMap, pl_hm_hash_str("Extra dirty number"), ulFreeIndex);
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(ptHashMap, pl_hm_hash_str("Extra dirty number"))], 666999, NULL);
|
||||||
|
|
||||||
// hashmap 2
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(ptHashMap, pl_hm_hash_str("Extra dirty number"))], 666999, NULL);
|
||||||
{
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup(ptHashMap, pl_hm_hash_str("Spartan Number"))], 117, NULL);
|
||||||
plHashMap tHashMap = {0};
|
|
||||||
|
|
||||||
int* sbiValues = NULL;
|
pl_hm_free(ptHashMap);
|
||||||
pl_sb_push(sbiValues, 0);
|
pl_sb_free(sbiValues);
|
||||||
pl_sb_push(sbiValues, 69);
|
}
|
||||||
pl_hm_insert_str(&tHashMap, "Dirty Number", pl_sb_size(sbiValues) - 1);
|
|
||||||
pl_sb_push(sbiValues, 117);
|
void
|
||||||
pl_hm_insert_str(&tHashMap, "Spartan Number", pl_sb_size(sbiValues) - 1);
|
hashmap_test_1(void* pData)
|
||||||
|
{
|
||||||
for(uint32_t i = 0; i < 79; i++)
|
plHashMap* ptHashMap = NULL;
|
||||||
{
|
|
||||||
pl_sb_push(sbiValues, 118);
|
pl_hm_insert(ptHashMap, pl_hm_hash_str("Dirty Number"), 69);
|
||||||
pl_hm_insert_str(&tHashMap, "Spartan Number2", pl_sb_size(sbiValues) - 1);
|
pl_hm_insert(ptHashMap, pl_hm_hash_str("Spartan Number"), 117);
|
||||||
}
|
|
||||||
|
pl_test_expect_int_equal((int)pl_hm_lookup(ptHashMap, pl_hm_hash_str("Dirty Number")), 69, NULL);
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(&tHashMap, "Dirty Number")], 69, NULL);
|
pl_test_expect_int_equal((int)pl_hm_lookup(ptHashMap, pl_hm_hash_str("Spartan Number")), 117, NULL);
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(&tHashMap, "Spartan Number")], 117, NULL);
|
|
||||||
|
pl_hm_free(ptHashMap);
|
||||||
pl_hm_remove_str(&tHashMap, "Dirty Number");
|
}
|
||||||
|
|
||||||
uint64_t ulFreeIndex = pl_hm_get_free_index(&tHashMap);
|
void
|
||||||
if(ulFreeIndex == UINT64_MAX)
|
hashmap_test_2(void* pData)
|
||||||
{
|
{
|
||||||
pl_sb_add(sbiValues);
|
plHashMap* ptHashMap = NULL;
|
||||||
ulFreeIndex = pl_sb_size(sbiValues) - 1;
|
|
||||||
}
|
int* sbiValues = NULL;
|
||||||
sbiValues[ulFreeIndex] = 666999;
|
pl_sb_push(sbiValues, 0);
|
||||||
pl_hm_insert_str(&tHashMap, "Extra dirty number", ulFreeIndex);
|
pl_sb_push(sbiValues, 69);
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(&tHashMap, "Extra dirty number")], 666999, NULL);
|
pl_hm_insert_str(ptHashMap, "Dirty Number", pl_sb_size(sbiValues) - 1);
|
||||||
|
pl_sb_push(sbiValues, 117);
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(&tHashMap, "Extra dirty number")], 666999, NULL);
|
pl_hm_insert_str(ptHashMap, "Spartan Number", pl_sb_size(sbiValues) - 1);
|
||||||
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(&tHashMap, "Spartan Number")], 117, NULL);
|
|
||||||
|
for(uint32_t i = 0; i < 79; i++)
|
||||||
pl_hm_free(&tHashMap);
|
{
|
||||||
pl_sb_free(sbiValues);
|
pl_sb_push(sbiValues, 118);
|
||||||
}
|
pl_hm_insert_str(ptHashMap, "Spartan Number2", pl_sb_size(sbiValues) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(ptHashMap, "Dirty Number")], 69, NULL);
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(ptHashMap, "Spartan Number")], 117, NULL);
|
||||||
|
|
||||||
|
pl_hm_remove_str(ptHashMap, "Dirty Number");
|
||||||
|
|
||||||
|
uint64_t ulFreeIndex = pl_hm_get_free_index(ptHashMap);
|
||||||
|
if(ulFreeIndex == UINT64_MAX)
|
||||||
|
{
|
||||||
|
pl_sb_add(sbiValues);
|
||||||
|
ulFreeIndex = pl_sb_size(sbiValues) - 1;
|
||||||
|
}
|
||||||
|
sbiValues[ulFreeIndex] = 666999;
|
||||||
|
pl_hm_insert_str(ptHashMap, "Extra dirty number", ulFreeIndex);
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(ptHashMap, "Extra dirty number")], 666999, NULL);
|
||||||
|
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(ptHashMap, "Extra dirty number")], 666999, NULL);
|
||||||
|
pl_test_expect_int_equal(sbiValues[pl_hm_lookup_str(ptHashMap, "Spartan Number")], 117, NULL);
|
||||||
|
|
||||||
|
pl_hm_free(ptHashMap);
|
||||||
|
pl_sb_free(sbiValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pl_ds_tests(void* pData)
|
||||||
|
{
|
||||||
|
pl_test_register_test(hashmap_test_0, NULL);
|
||||||
|
pl_test_register_test(hashmap_test_1, NULL);
|
||||||
|
pl_test_register_test(hashmap_test_2, NULL);
|
||||||
}
|
}
|
@ -6,166 +6,176 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "pl_json.h"
|
#include "pl_json.h"
|
||||||
|
|
||||||
static void
|
void
|
||||||
json_test_0(void* pData)
|
write_json_test(void* pData)
|
||||||
{
|
{
|
||||||
|
|
||||||
char* pcBuffer = NULL;
|
char** ppcBuffer = pData;
|
||||||
|
|
||||||
// write json
|
// root object
|
||||||
{
|
plJsonObject* ptRootJsonObject = pl_json_new_root_object("ROOT");
|
||||||
|
pl_json_add_string_member(ptRootJsonObject, "first name", "John");
|
||||||
|
pl_json_add_string_member(ptRootJsonObject, "last name", "Doe");
|
||||||
|
pl_json_add_int_member(ptRootJsonObject, "age", 40);
|
||||||
|
pl_json_add_bool_member(ptRootJsonObject, "tall", false);
|
||||||
|
pl_json_add_bool_member(ptRootJsonObject, "hungry", true);
|
||||||
|
int aScores[] = {100, 86, 46};
|
||||||
|
pl_json_add_int_array(ptRootJsonObject, "scores", aScores, 3);
|
||||||
|
|
||||||
// root object
|
char* aPets[] = {"Riley", "Luna", "Chester"};
|
||||||
plJsonObject tRootJsonObject = {0};
|
pl_json_add_string_array(ptRootJsonObject, "pets", aPets, 3);
|
||||||
pl_json_add_string_member(&tRootJsonObject, "first name", "John");
|
|
||||||
pl_json_add_string_member(&tRootJsonObject, "last name", "Doe");
|
|
||||||
pl_json_add_int_member(&tRootJsonObject, "age", 40);
|
|
||||||
pl_json_add_bool_member(&tRootJsonObject, "tall", false);
|
|
||||||
pl_json_add_bool_member(&tRootJsonObject, "hungry", true);
|
|
||||||
int aScores[] = {100, 86, 46};
|
|
||||||
pl_json_add_int_array(&tRootJsonObject, "scores", aScores, 3);
|
|
||||||
|
|
||||||
char* aPets[] = {"Riley", "Luna", "Chester"};
|
// member object
|
||||||
pl_json_add_string_array(&tRootJsonObject, "pets", aPets, 3);
|
|
||||||
|
|
||||||
// member object
|
plJsonObject* ptBestFriend = pl_json_add_member(ptRootJsonObject, "best friend");
|
||||||
plJsonObject tBestFriend = {0};
|
pl_json_add_string_member(ptBestFriend, "first name", "John");
|
||||||
pl_json_add_string_member(&tBestFriend, "first name", "John");
|
pl_json_add_string_member(ptBestFriend, "last name", "Doe");
|
||||||
pl_json_add_string_member(&tBestFriend, "last name", "Doe");
|
pl_json_add_int_member(ptBestFriend, "age", 40);
|
||||||
pl_json_add_int_member(&tBestFriend, "age", 40);
|
pl_json_add_bool_member(ptBestFriend, "tall", false);
|
||||||
pl_json_add_bool_member(&tBestFriend, "tall", false);
|
pl_json_add_bool_member(ptBestFriend, "hungry", true);
|
||||||
pl_json_add_bool_member(&tBestFriend, "hungry", true);
|
pl_json_add_string_array(ptBestFriend, "pets", aPets, 3);
|
||||||
pl_json_add_string_array(&tBestFriend, "pets", aPets, 3);
|
pl_json_add_int_array(ptBestFriend, "scores", aScores, 3);
|
||||||
pl_json_add_int_array(&tBestFriend, "scores", aScores, 3);
|
|
||||||
|
|
||||||
pl_json_add_member(&tRootJsonObject, "best friend", &tBestFriend);
|
// friend member object
|
||||||
|
plJsonObject* ptFriends = pl_json_add_member_array(ptRootJsonObject, "friends", 2);
|
||||||
|
|
||||||
// friend member object
|
plJsonObject* ptFriend0 = pl_json_member_by_index(ptFriends, 0);
|
||||||
plJsonObject atFriends[2] = {0};
|
int aScores0[] = {88, 86, 100};
|
||||||
int aScores0[] = {88, 86, 100};
|
pl_json_add_string_member(ptFriend0, "first name", "Jacob");
|
||||||
pl_json_add_string_member(&atFriends[0], "first name", "Jacob");
|
pl_json_add_string_member(ptFriend0, "last name", "Smith");
|
||||||
pl_json_add_string_member(&atFriends[0], "last name", "Smith");
|
pl_json_add_int_member(ptFriend0, "age", 23);
|
||||||
pl_json_add_int_member(&atFriends[0], "age", 23);
|
pl_json_add_bool_member(ptFriend0, "tall", true);
|
||||||
pl_json_add_bool_member(&atFriends[0], "tall", true);
|
pl_json_add_bool_member(ptFriend0, "hungry", false);
|
||||||
pl_json_add_bool_member(&atFriends[0], "hungry", false);
|
pl_json_add_int_array(ptFriend0, "scores", aScores0, 3);
|
||||||
pl_json_add_int_array(&atFriends[0], "scores", aScores0, 3);
|
|
||||||
|
|
||||||
int aScores1[] = {80, 80, 100};
|
plJsonObject* ptFriend1 = pl_json_member_by_index(ptFriends, 1);
|
||||||
pl_json_add_string_member(&atFriends[1], "first name", "Chance");
|
int aScores1[] = {80, 80, 100};
|
||||||
pl_json_add_string_member(&atFriends[1], "last name", "Dale");
|
pl_json_add_string_member(ptFriend1, "first name", "Chance");
|
||||||
pl_json_add_int_member(&atFriends[1], "age", 48);
|
pl_json_add_string_member(ptFriend1, "last name", "Dale");
|
||||||
pl_json_add_bool_member(&atFriends[1], "tall", true);
|
pl_json_add_int_member(ptFriend1, "age", 48);
|
||||||
pl_json_add_bool_member(&atFriends[1], "hungry", true);
|
pl_json_add_bool_member(ptFriend1, "tall", true);
|
||||||
pl_json_add_int_array(&atFriends[1], "scores", aScores1, 3);
|
pl_json_add_bool_member(ptFriend1, "hungry", true);
|
||||||
|
pl_json_add_int_array(ptFriend1, "scores", aScores1, 3);
|
||||||
|
|
||||||
pl_json_add_member_array(&tRootJsonObject, "friends", atFriends, 2);
|
uint32_t uBufferSize = 0;
|
||||||
|
pl_write_json(ptRootJsonObject, NULL, &uBufferSize);
|
||||||
|
|
||||||
uint32_t uBufferSize = 0;
|
*ppcBuffer = malloc(uBufferSize + 1);
|
||||||
pl_write_json(&tRootJsonObject, NULL, &uBufferSize);
|
memset(*ppcBuffer, 0, uBufferSize + 1);
|
||||||
|
pl_write_json(ptRootJsonObject, *ppcBuffer, &uBufferSize);
|
||||||
|
|
||||||
pcBuffer = malloc(uBufferSize + 1);
|
pl_unload_json(&ptRootJsonObject);
|
||||||
memset(pcBuffer, 0, uBufferSize + 1);
|
}
|
||||||
pl_write_json(&tRootJsonObject, pcBuffer, &uBufferSize);
|
|
||||||
|
void
|
||||||
pl_unload_json(&tRootJsonObject);
|
read_json_test(void* pData)
|
||||||
}
|
{
|
||||||
|
|
||||||
// read json
|
char** ppcBuffer = pData;
|
||||||
{
|
|
||||||
|
plJsonObject* ptRootJsonObject = NULL;
|
||||||
plJsonObject tRootJsonObject = {0};
|
pl_load_json(*ppcBuffer, &ptRootJsonObject);
|
||||||
pl_load_json(pcBuffer, &tRootJsonObject);
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~reading~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~reading~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
// check root members
|
||||||
// check root members
|
{
|
||||||
{
|
int aiScores[3] = {0};
|
||||||
int aiScores[3] = {0};
|
pl_json_int_array_member(ptRootJsonObject, "scores", aiScores, NULL);
|
||||||
pl_json_int_array_member(&tRootJsonObject, "scores", aiScores, NULL);
|
pl_test_expect_int_equal(aiScores[0], 100, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[0], 100, NULL);
|
pl_test_expect_int_equal(aiScores[1], 86, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[1], 86, NULL);
|
pl_test_expect_int_equal(aiScores[2], 46, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[2], 46, NULL);
|
}
|
||||||
}
|
{
|
||||||
{
|
char acPet0[64] = {0};
|
||||||
char acPet0[64] = {0};
|
char acPet1[64] = {0};
|
||||||
char acPet1[64] = {0};
|
char acPet2[64] = {0};
|
||||||
char acPet2[64] = {0};
|
char* aacPets[3] = {acPet0, acPet1, acPet2};
|
||||||
char* aacPets[3] = {acPet0, acPet1, acPet2};
|
uint32_t auLengths[3] = {64, 64, 64};
|
||||||
uint32_t auLengths[3] = {64, 64, 64};
|
pl_json_string_array_member(ptRootJsonObject, "pets", aacPets, NULL, auLengths);
|
||||||
pl_json_string_array_member(&tRootJsonObject, "pets", aacPets, NULL, auLengths);
|
pl_test_expect_string_equal(acPet0, "Riley", NULL);
|
||||||
pl_test_expect_string_equal(acPet0, "Riley", NULL);
|
pl_test_expect_string_equal(acPet1, "Luna", NULL);
|
||||||
pl_test_expect_string_equal(acPet1, "Luna", NULL);
|
pl_test_expect_string_equal(acPet2, "Chester", NULL);
|
||||||
pl_test_expect_string_equal(acPet2, "Chester", NULL);
|
}
|
||||||
}
|
|
||||||
|
char acFirstName[64] = {0};
|
||||||
char acFirstName[64] = {0};
|
char acLastName[64] = {0};
|
||||||
char acLastName[64] = {0};
|
pl_test_expect_string_equal(pl_json_string_member(ptRootJsonObject, "first name", acFirstName, 64), "John", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(&tRootJsonObject, "first name", acFirstName, 64), "John", NULL);
|
pl_test_expect_string_equal(pl_json_string_member(ptRootJsonObject, "last name", acLastName, 64), "Doe", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(&tRootJsonObject, "last name", acLastName, 64), "Doe", NULL);
|
pl_test_expect_int_equal(pl_json_int_member(ptRootJsonObject, "age", 0), 40, NULL);
|
||||||
pl_test_expect_int_equal(pl_json_int_member(&tRootJsonObject, "age", 0), 40, NULL);
|
pl_test_expect_false(pl_json_bool_member(ptRootJsonObject, "tall", false), NULL);
|
||||||
pl_test_expect_false(pl_json_bool_member(&tRootJsonObject, "tall", false), NULL);
|
pl_test_expect_true(pl_json_bool_member(ptRootJsonObject, "hungry", false), NULL);
|
||||||
pl_test_expect_true(pl_json_bool_member(&tRootJsonObject, "hungry", false), NULL);
|
|
||||||
|
// check child members
|
||||||
// check child members
|
plJsonObject* ptBestFriend = pl_json_member(ptRootJsonObject, "best friend");
|
||||||
plJsonObject* ptBestFriend = pl_json_member(&tRootJsonObject, "best friend");
|
{
|
||||||
{
|
int aiScores[3] = {0};
|
||||||
int aiScores[3] = {0};
|
pl_json_int_array_member(ptBestFriend, "scores", aiScores, NULL);
|
||||||
pl_json_int_array_member(ptBestFriend, "scores", aiScores, NULL);
|
pl_test_expect_int_equal(aiScores[0], 100, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[0], 100, NULL);
|
pl_test_expect_int_equal(aiScores[1], 86, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[1], 86, NULL);
|
pl_test_expect_int_equal(aiScores[2], 46, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[2], 46, NULL);
|
}
|
||||||
}
|
{
|
||||||
{
|
char acPet0[64] = {0};
|
||||||
char acPet0[64] = {0};
|
char acPet1[64] = {0};
|
||||||
char acPet1[64] = {0};
|
char acPet2[64] = {0};
|
||||||
char acPet2[64] = {0};
|
char* aacPets[3] = {acPet0, acPet1, acPet2};
|
||||||
char* aacPets[3] = {acPet0, acPet1, acPet2};
|
uint32_t auLengths[3] = {64, 64, 64};
|
||||||
uint32_t auLengths[3] = {64, 64, 64};
|
pl_json_string_array_member(ptBestFriend, "pets", aacPets, NULL, auLengths);
|
||||||
pl_json_string_array_member(ptBestFriend, "pets", aacPets, NULL, auLengths);
|
pl_test_expect_string_equal(acPet0, "Riley", NULL);
|
||||||
pl_test_expect_string_equal(acPet0, "Riley", NULL);
|
pl_test_expect_string_equal(acPet1, "Luna", NULL);
|
||||||
pl_test_expect_string_equal(acPet1, "Luna", NULL);
|
pl_test_expect_string_equal(acPet2, "Chester", NULL);
|
||||||
pl_test_expect_string_equal(acPet2, "Chester", NULL);
|
}
|
||||||
}
|
|
||||||
|
pl_test_expect_string_equal(pl_json_string_member(ptBestFriend, "first name", acFirstName, 64), "John", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(ptBestFriend, "first name", acFirstName, 64), "John", NULL);
|
pl_test_expect_string_equal(pl_json_string_member(ptBestFriend, "last name", acLastName, 64), "Doe", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(ptBestFriend, "last name", acLastName, 64), "Doe", NULL);
|
pl_test_expect_int_equal(pl_json_int_member(ptBestFriend, "age", 0), 40, NULL);
|
||||||
pl_test_expect_int_equal(pl_json_int_member(ptBestFriend, "age", 0), 40, NULL);
|
pl_test_expect_false(pl_json_bool_member(ptBestFriend, "tall", false), NULL);
|
||||||
pl_test_expect_false(pl_json_bool_member(ptBestFriend, "tall", false), NULL);
|
pl_test_expect_true(pl_json_bool_member(ptBestFriend, "hungry", false), NULL);
|
||||||
pl_test_expect_true(pl_json_bool_member(ptBestFriend, "hungry", false), NULL);
|
|
||||||
|
uint32_t uFriendCount = 0;
|
||||||
uint32_t uFriendCount = 0;
|
plJsonObject* ptFriends = pl_json_array_member(ptRootJsonObject, "friends", &uFriendCount);
|
||||||
plJsonObject* sbtFriends = pl_json_array_member(&tRootJsonObject, "friends", &uFriendCount);
|
|
||||||
|
plJsonObject* ptFriend0 = pl_json_member_by_index(ptFriends, 0);
|
||||||
plJsonObject* ptFriend0 = &sbtFriends[0];
|
plJsonObject* ptFriend1 = pl_json_member_by_index(ptFriends, 1);
|
||||||
plJsonObject* ptFriend1 = &sbtFriends[1];
|
{
|
||||||
{
|
int aiScores[3] = {0};
|
||||||
int aiScores[3] = {0};
|
pl_json_int_array_member(ptFriend0, "scores", aiScores, NULL);
|
||||||
pl_json_int_array_member(ptFriend0, "scores", aiScores, NULL);
|
pl_test_expect_int_equal(aiScores[0], 88, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[0], 88, NULL);
|
pl_test_expect_int_equal(aiScores[1], 86, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[1], 86, NULL);
|
pl_test_expect_int_equal(aiScores[2], 100, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[2], 100, NULL);
|
}
|
||||||
}
|
|
||||||
|
{
|
||||||
{
|
int aiScores[3] = {0};
|
||||||
int aiScores[3] = {0};
|
pl_json_int_array_member(ptFriend1, "scores", aiScores, NULL);
|
||||||
pl_json_int_array_member(ptFriend1, "scores", aiScores, NULL);
|
pl_test_expect_int_equal(aiScores[0], 80, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[0], 80, NULL);
|
pl_test_expect_int_equal(aiScores[1], 80, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[1], 80, NULL);
|
pl_test_expect_int_equal(aiScores[2], 100, NULL);
|
||||||
pl_test_expect_int_equal(aiScores[2], 100, NULL);
|
}
|
||||||
}
|
|
||||||
|
pl_test_expect_string_equal(pl_json_string_member(ptFriend0, "first name", acFirstName, 64), "Jacob", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(ptFriend0, "first name", acFirstName, 64), "Jacob", NULL);
|
pl_test_expect_string_equal(pl_json_string_member(ptFriend0, "last name", acLastName, 64), "Smith", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(ptFriend0, "last name", acLastName, 64), "Smith", NULL);
|
pl_test_expect_int_equal(pl_json_int_member(ptFriend0, "age", 0), 23, NULL);
|
||||||
pl_test_expect_int_equal(pl_json_int_member(ptFriend0, "age", 0), 23, NULL);
|
pl_test_expect_true(pl_json_bool_member(ptFriend0, "tall", false), NULL);
|
||||||
pl_test_expect_true(pl_json_bool_member(ptFriend0, "tall", false), NULL);
|
pl_test_expect_false(pl_json_bool_member(ptFriend0, "hungry", false), NULL);
|
||||||
pl_test_expect_false(pl_json_bool_member(ptFriend0, "hungry", false), NULL);
|
|
||||||
|
pl_test_expect_string_equal(pl_json_string_member(ptFriend1, "first name", acFirstName, 64), "Chance", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(ptFriend1, "first name", acFirstName, 64), "Chance", NULL);
|
pl_test_expect_string_equal(pl_json_string_member(ptFriend1, "last name", acLastName, 64), "Dale", NULL);
|
||||||
pl_test_expect_string_equal(pl_json_string_member(ptFriend1, "last name", acLastName, 64), "Dale", NULL);
|
pl_test_expect_int_equal(pl_json_int_member(ptFriend1, "age", 0), 48, NULL);
|
||||||
pl_test_expect_int_equal(pl_json_int_member(ptFriend1, "age", 0), 48, NULL);
|
pl_test_expect_true(pl_json_bool_member(ptFriend1, "tall", false), NULL);
|
||||||
pl_test_expect_true(pl_json_bool_member(ptFriend1, "tall", false), NULL);
|
pl_test_expect_true(pl_json_bool_member(ptFriend1, "hungry", false), NULL);
|
||||||
pl_test_expect_true(pl_json_bool_member(ptFriend1, "hungry", false), NULL);
|
|
||||||
|
pl_unload_json(&ptRootJsonObject);
|
||||||
pl_unload_json(&tRootJsonObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
pl_json_tests(void* pData)
|
||||||
|
{
|
||||||
|
static char* pcBuffer = NULL;
|
||||||
|
|
||||||
|
pl_test_register_test(write_json_test, &pcBuffer);
|
||||||
|
pl_test_register_test(read_json_test, &pcBuffer);
|
||||||
}
|
}
|
157
tests/pl_memory_tests.h
Normal file
157
tests/pl_memory_tests.h
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#include "pl_test.h"
|
||||||
|
#include "pl_memory.h"
|
||||||
|
#include <string.h> // memset
|
||||||
|
|
||||||
|
typedef struct _plTestStruct
|
||||||
|
{
|
||||||
|
const char* pcName;
|
||||||
|
int iAge;
|
||||||
|
} plTestStruct;
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_test_aligned_alloc(void* pData)
|
||||||
|
{
|
||||||
|
int* iBuffer0 = pl_aligned_alloc(0, sizeof(int));
|
||||||
|
pl_test_expect_uint64_equal(((uint64_t)iBuffer0) % 4, 0, NULL);
|
||||||
|
pl_aligned_free(iBuffer0);
|
||||||
|
|
||||||
|
int* iBuffer1 = pl_aligned_alloc(16, sizeof(int));
|
||||||
|
pl_test_expect_uint64_equal(((uint64_t)iBuffer1) % 16, 0, NULL);
|
||||||
|
pl_aligned_free(iBuffer1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_test_pool_allocator_0(void* pData)
|
||||||
|
{
|
||||||
|
// here we are testing standard usage
|
||||||
|
|
||||||
|
plPoolAllocator tAllocator = {0};
|
||||||
|
|
||||||
|
// let library tell use required buffer size
|
||||||
|
size_t szRequiredBufferSize = 0;
|
||||||
|
pl_pool_allocator_init(&tAllocator, 5, sizeof(int), 0, &szRequiredBufferSize, NULL);
|
||||||
|
|
||||||
|
int* iBuffer = malloc(szRequiredBufferSize);
|
||||||
|
memset(iBuffer, 0, szRequiredBufferSize);
|
||||||
|
pl_pool_allocator_init(&tAllocator, 5, sizeof(int), 0, &szRequiredBufferSize, iBuffer);
|
||||||
|
|
||||||
|
int* iItem0 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
int* iItem1 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
int* iItem2 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
int* iItem3 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
int* iItem4 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
int* iItem5 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
|
||||||
|
*iItem0 = 0;
|
||||||
|
*iItem1 = 1;
|
||||||
|
*iItem2 = 2;
|
||||||
|
*iItem3 = 3;
|
||||||
|
*iItem4 = 4;
|
||||||
|
|
||||||
|
pl_test_expect_int_equal(*iItem0, 0, NULL);
|
||||||
|
pl_test_expect_int_equal(*iItem1, 1, NULL);
|
||||||
|
pl_test_expect_int_equal(*iItem2, 2, NULL);
|
||||||
|
pl_test_expect_int_equal(*iItem3, 3, NULL);
|
||||||
|
pl_test_expect_int_equal(*iItem4, 4, NULL);
|
||||||
|
pl_test_expect_uint64_equal(((uint64_t)iItem5), 0, NULL);
|
||||||
|
free(iBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_test_pool_allocator_1(void* pData)
|
||||||
|
{
|
||||||
|
// here we are testing usage with stack allocated memory
|
||||||
|
|
||||||
|
plPoolAllocator tAllocator = {0};
|
||||||
|
|
||||||
|
plTestStruct atData[5] = {0};
|
||||||
|
|
||||||
|
// let library tell use required buffer size
|
||||||
|
size_t szRequiredBufferSize = sizeof(atData);
|
||||||
|
size_t szItemCount = pl_pool_allocator_init(&tAllocator, 0, sizeof(plTestStruct), 0, &szRequiredBufferSize, atData);
|
||||||
|
pl_pool_allocator_init(&tAllocator, szItemCount, sizeof(plTestStruct), 0, &szRequiredBufferSize, atData);
|
||||||
|
|
||||||
|
pl_test_expect_int_equal((int)szItemCount, 4, NULL);
|
||||||
|
|
||||||
|
plTestStruct* ptData0 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
plTestStruct* ptData1 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
plTestStruct* ptData2 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
plTestStruct* ptData3 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
plTestStruct* ptData4 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
|
||||||
|
ptData0->iAge = 0;
|
||||||
|
ptData1->iAge = 1;
|
||||||
|
ptData2->iAge = 2;
|
||||||
|
ptData3->iAge = 3;
|
||||||
|
|
||||||
|
ptData0->pcName = "John";
|
||||||
|
ptData1->pcName = "James";
|
||||||
|
ptData2->pcName = "Mark";
|
||||||
|
ptData3->pcName = "Matt";
|
||||||
|
|
||||||
|
pl_test_expect_int_equal(ptData0->iAge, 0, NULL);
|
||||||
|
pl_test_expect_int_equal(ptData1->iAge, 1, NULL);
|
||||||
|
pl_test_expect_int_equal(ptData2->iAge, 2, NULL);
|
||||||
|
pl_test_expect_int_equal(ptData3->iAge, 3, NULL);
|
||||||
|
|
||||||
|
pl_test_expect_string_equal(ptData0->pcName, "John", NULL);
|
||||||
|
pl_test_expect_string_equal(ptData1->pcName, "James", NULL);
|
||||||
|
pl_test_expect_string_equal(ptData2->pcName, "Mark", NULL);
|
||||||
|
pl_test_expect_string_equal(ptData3->pcName, "Matt", NULL);
|
||||||
|
pl_test_expect_uint64_equal(((uint64_t)ptData4), 0, NULL);
|
||||||
|
|
||||||
|
pl_pool_allocator_free(&tAllocator, ptData1);
|
||||||
|
plTestStruct* ptData5 = pl_pool_allocator_alloc(&tAllocator);
|
||||||
|
pl_test_expect_uint64_not_equal(((uint64_t)ptData5), 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_test_stack_allocator_0(void* pData)
|
||||||
|
{
|
||||||
|
char acBuffer[1024] = {0};
|
||||||
|
plStackAllocator tAllocator = {0};
|
||||||
|
pl_stack_allocator_init(&tAllocator, 1024, acBuffer);
|
||||||
|
|
||||||
|
plTestStruct* ptData0 = pl_stack_allocator_alloc(&tAllocator, sizeof(plTestStruct));
|
||||||
|
ptData0->pcName = "John";
|
||||||
|
ptData0->iAge = 31;
|
||||||
|
|
||||||
|
plStackAllocatorMarker tMarker0 = pl_stack_allocator_marker(&tAllocator);
|
||||||
|
|
||||||
|
plTestStruct* ptData1 = pl_stack_allocator_alloc(&tAllocator, sizeof(plTestStruct));
|
||||||
|
ptData0->pcName = "Rachael";
|
||||||
|
ptData0->iAge = 32;
|
||||||
|
|
||||||
|
pl_stack_allocator_free_to_marker(&tAllocator, tMarker0);
|
||||||
|
|
||||||
|
plTestStruct* ptData2 = pl_stack_allocator_alloc(&tAllocator, sizeof(plTestStruct));
|
||||||
|
ptData0->pcName = "Charlie";
|
||||||
|
ptData0->iAge = 4;
|
||||||
|
|
||||||
|
pl_test_expect_uint64_equal((uint64_t)ptData1, (uint64_t)ptData2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memory_test_temp_allocator_0(void* pData)
|
||||||
|
{
|
||||||
|
plTempAllocator tAllocator = {0};
|
||||||
|
|
||||||
|
char* pcBuffer0 = pl_temp_allocator_alloc(&tAllocator, 256);
|
||||||
|
char* pcBuffer1 = pl_temp_allocator_alloc(&tAllocator, 256);
|
||||||
|
char* pcBuffer2 = pl_temp_allocator_alloc(&tAllocator, 256);
|
||||||
|
char* pcBuffer3 = pl_temp_allocator_alloc(&tAllocator, 256);
|
||||||
|
char* pcBuffer4 = pl_temp_allocator_alloc(&tAllocator, 256);
|
||||||
|
|
||||||
|
|
||||||
|
pl_temp_allocator_free(&tAllocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pl_memory_tests(void* pData)
|
||||||
|
{
|
||||||
|
pl_test_register_test(memory_test_aligned_alloc, NULL);
|
||||||
|
pl_test_register_test(memory_test_pool_allocator_0, NULL);
|
||||||
|
pl_test_register_test(memory_test_pool_allocator_1, NULL);
|
||||||
|
pl_test_register_test(memory_test_stack_allocator_0, NULL);
|
||||||
|
pl_test_register_test(memory_test_temp_allocator_0, NULL);
|
||||||
|
}
|
78
tests/pl_string_tests.h
Normal file
78
tests/pl_string_tests.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "pl_test.h"
|
||||||
|
#include "pl_string.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
string_test_0(void* pData)
|
||||||
|
{
|
||||||
|
const char* pcFilePath0 = "C:/Users/hoffstadt/file1.txt";
|
||||||
|
const char* pcFilePath1 = "C:\\Users\\hoffstadt\\file1.txt";
|
||||||
|
const char* pcFilePath2 = "C:\\Users/hoffstadt\\file1.txt";
|
||||||
|
const char* pcFilePath3 = "file1.txt";
|
||||||
|
const char* pcFilePath4 = "file1";
|
||||||
|
|
||||||
|
const char* pcExt0 = pl_str_get_file_extension(pcFilePath0, NULL, 0);
|
||||||
|
const char* pcExt1 = pl_str_get_file_extension(pcFilePath1, NULL, 0);
|
||||||
|
const char* pcExt2 = pl_str_get_file_extension(pcFilePath2, NULL, 0);
|
||||||
|
const char* pcExt3 = pl_str_get_file_extension(pcFilePath3, NULL, 0);
|
||||||
|
const char* pcExt4 = pl_str_get_file_extension(pcFilePath4, NULL, 0);
|
||||||
|
|
||||||
|
pl_test_expect_string_equal(pcExt0, "txt", NULL);
|
||||||
|
pl_test_expect_string_equal(pcExt1, "txt", NULL);
|
||||||
|
pl_test_expect_string_equal(pcExt2, "txt", NULL);
|
||||||
|
pl_test_expect_string_equal(pcExt3, "txt", NULL);
|
||||||
|
pl_test_expect_uint64_equal(((uint64_t)pcExt4), 0, NULL);
|
||||||
|
|
||||||
|
const char* pcFile0 = pl_str_get_file_name(pcFilePath0, NULL, 0);
|
||||||
|
const char* pcFile1 = pl_str_get_file_name(pcFilePath1, NULL, 0);
|
||||||
|
const char* pcFile2 = pl_str_get_file_name(pcFilePath2, NULL, 0);
|
||||||
|
const char* pcFile3 = pl_str_get_file_name(pcFilePath3, NULL, 0);
|
||||||
|
const char* pcFile4 = pl_str_get_file_name(pcFilePath4, NULL, 0);
|
||||||
|
|
||||||
|
pl_test_expect_string_equal(pcFile0, "file1.txt", "pl_str_get_file_name");
|
||||||
|
pl_test_expect_string_equal(pcFile1, "file1.txt", "pl_str_get_file_name");
|
||||||
|
pl_test_expect_string_equal(pcFile2, "file1.txt", "pl_str_get_file_name");
|
||||||
|
pl_test_expect_string_equal(pcFile3, "file1.txt", "pl_str_get_file_name");
|
||||||
|
pl_test_expect_string_equal(pcFile4, "file1", "pl_str_get_file_name");
|
||||||
|
|
||||||
|
char acFileName0[256] = {0};
|
||||||
|
char acFileName1[256] = {0};
|
||||||
|
char acFileName2[256] = {0};
|
||||||
|
char acFileName3[256] = {0};
|
||||||
|
char acFileName4[256] = {0};
|
||||||
|
pl_str_get_file_name_only(pcFilePath0, acFileName0, 256);
|
||||||
|
pl_str_get_file_name_only(pcFilePath1, acFileName1, 256);
|
||||||
|
pl_str_get_file_name_only(pcFilePath2, acFileName2, 256);
|
||||||
|
pl_str_get_file_name_only(pcFilePath3, acFileName3, 256);
|
||||||
|
pl_str_get_file_name_only(pcFilePath4, acFileName4, 256);
|
||||||
|
|
||||||
|
pl_test_expect_string_equal(acFileName0, "file1", "pl_str_get_file_name_only");
|
||||||
|
pl_test_expect_string_equal(acFileName1, "file1", "pl_str_get_file_name_only");
|
||||||
|
pl_test_expect_string_equal(acFileName2, "file1", "pl_str_get_file_name_only");
|
||||||
|
pl_test_expect_string_equal(acFileName3, "file1", "pl_str_get_file_name_only");
|
||||||
|
pl_test_expect_string_equal(acFileName4, "file1", "pl_str_get_file_name_only");
|
||||||
|
|
||||||
|
char acDirectory0[128] = {0};
|
||||||
|
char acDirectory1[128] = {0};
|
||||||
|
char acDirectory2[128] = {0};
|
||||||
|
char acDirectory3[128] = {0};
|
||||||
|
char acDirectory4[128] = {0};
|
||||||
|
|
||||||
|
pl_str_get_directory(pcFilePath0, acDirectory0, 128);
|
||||||
|
pl_str_get_directory(pcFilePath1, acDirectory1, 128);
|
||||||
|
pl_str_get_directory(pcFilePath2, acDirectory2, 128);
|
||||||
|
pl_str_get_directory(pcFilePath3, acDirectory3, 128);
|
||||||
|
pl_str_get_directory(pcFilePath4, acDirectory4, 128);
|
||||||
|
|
||||||
|
pl_test_expect_string_equal(acDirectory0, "C:/Users/hoffstadt/", NULL);
|
||||||
|
pl_test_expect_string_equal(acDirectory1, "C:\\Users\\hoffstadt\\", NULL);
|
||||||
|
pl_test_expect_string_equal(acDirectory2, "C:\\Users/hoffstadt\\", NULL);
|
||||||
|
pl_test_expect_string_equal(acDirectory3, "./", NULL);
|
||||||
|
pl_test_expect_string_equal(acDirectory4, "./", NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pl_string_tests(void* pData)
|
||||||
|
{
|
||||||
|
pl_test_register_test(string_test_0, NULL);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user