192 lines
5.1 KiB
Markdown
192 lines
5.1 KiB
Markdown
# Utility Library
|
|
|
|
Source: `src/dusk/util/`
|
|
|
|
All C code in the project must use these utilities instead of their
|
|
standard library equivalents. Do not use `malloc`, `free`, `strcmp`,
|
|
`strcpy`, `memcpy`, `memset`, etc. directly.
|
|
|
|
---
|
|
|
|
## Memory (`memory.h`)
|
|
|
|
```c
|
|
void *memoryAllocate(size_t size);
|
|
void *memoryAlign(size_t alignment, size_t size); // aligned alloc
|
|
void memoryFree(void *ptr);
|
|
void memoryCopy(void *dest, const void *src, size_t size);
|
|
void memoryZero(void *dest, size_t size);
|
|
errorret_t memoryCompare(const void *a, const void *b, size_t size);
|
|
|
|
size_t memoryGetAllocatedCount(void);
|
|
// Returns the number of live allocations. Must be 0 at test teardown.
|
|
|
|
void memoryTrack(void *ptr);
|
|
// Register a pointer that was malloc'd outside the engine (e.g. by a
|
|
// third-party library) so it counts toward the allocation tracker.
|
|
```
|
|
|
|
`MEMORY_POINTERS_IN_USE` is a file-scope static tracking the live count.
|
|
It is incremented by `memoryAllocate` / `memoryTrack` and decremented by
|
|
`memoryFree`. Tests assert this is 0 at teardown to catch leaks.
|
|
|
|
---
|
|
|
|
## String (`string.h`)
|
|
|
|
Use these instead of `<string.h>` / `<ctype.h>` functions:
|
|
|
|
```c
|
|
void stringCopy(char_t *dest, const char_t *src, size_t destSize);
|
|
int stringCompare(const char_t *a, const char_t *b);
|
|
bool_t stringEquals(const char_t *a, const char_t *b);
|
|
int stringCompareInsensitive(const char_t *a, const char_t *b);
|
|
size_t stringLength(const char_t *str);
|
|
void stringTrim(char_t *str);
|
|
bool_t stringIsWhitespace(char_t c);
|
|
bool_t stringStartsWith(const char_t *str, const char_t *prefix);
|
|
bool_t stringEndsWith(const char_t *str, const char_t *suffix);
|
|
bool_t stringContains(const char_t *haystack, const char_t *needle);
|
|
char_t *stringFind(const char_t *haystack, const char_t *needle);
|
|
void stringFormat(char_t *dest, size_t destSize, const char_t *fmt, ...);
|
|
int32_t stringToInt(const char_t *str);
|
|
float_t stringToFloat(const char_t *str);
|
|
void stringFromInt(char_t *dest, size_t destSize, int32_t value);
|
|
void stringFromFloat(char_t *dest, size_t destSize, float_t value);
|
|
```
|
|
|
|
`destSize` in `stringCopy` / `stringFormat` is the buffer capacity
|
|
**excluding** the null terminator.
|
|
|
|
---
|
|
|
|
## Math (`math.h`)
|
|
|
|
```c
|
|
#define MATH_PI M_PI
|
|
|
|
#define mathMax(a, b)
|
|
#define mathMin(a, b)
|
|
#define mathClamp(x, lower, upper)
|
|
#define mathAbs(amt)
|
|
|
|
uint32_t mathNextPowTwo(uint32_t value);
|
|
float_t mathModFloat(float_t x, float_t y); // always non-negative
|
|
float_t mathLerp(float_t a, float_t b, float_t t);
|
|
// plus additional trig / remap helpers
|
|
```
|
|
|
|
The project uses **cglm** for vector and matrix math (`vec3`, `mat4`,
|
|
`glm_vec3_*`, `glm_mat4_*`, etc.). `math.h` provides scalar helpers
|
|
that complement cglm.
|
|
|
|
---
|
|
|
|
## Endian (`endian.h`)
|
|
|
|
GameCube and Wii are big-endian. Any binary data format (asset files,
|
|
network packets) must use the endian utilities when reading multi-byte
|
|
values.
|
|
|
|
```c
|
|
bool_t isHostLittleEndian(void);
|
|
uint16_t endianLittleToHost16(uint16_t value);
|
|
uint32_t endianLittleToHost32(uint32_t value);
|
|
uint64_t endianLittleToHost64(uint64_t value);
|
|
float_t endianLittleToHostFloat(float_t value);
|
|
```
|
|
|
|
If neither `DUSK_PLATFORM_ENDIAN_LITTLE` nor `DUSK_PLATFORM_ENDIAN_BIG`
|
|
is defined, the implementation falls back to a runtime check
|
|
(`ENDIAN_MAGIC` probe). Prefer setting the compile-time macro for new
|
|
platform targets.
|
|
|
|
---
|
|
|
|
## Reference counting (`ref.h`)
|
|
|
|
`ref_t` is a generic reference-counted handle with optional lock /
|
|
unlock / all-unlocked callbacks.
|
|
|
|
```c
|
|
void refInit(
|
|
ref_t *ref,
|
|
void *data,
|
|
refcallback_t onLock,
|
|
refcallback_t onUnlock,
|
|
refcallback_t onAllUnlocked // called when count -> 0; do cleanup here
|
|
);
|
|
|
|
void refLock(ref_t *ref); // increment count
|
|
bool_t refUnlock(ref_t *ref); // decrement; returns true if count == 0
|
|
```
|
|
|
|
The asset entry system uses `ref_t` internally to track how many
|
|
subsystems have locked a loaded asset.
|
|
|
|
---
|
|
|
|
## Array (`array.h`)
|
|
|
|
```c
|
|
void arrayReverse(void *array, size_t count, size_t elementSize);
|
|
```
|
|
|
|
Generic in-place reverse using the element stride.
|
|
|
|
---
|
|
|
|
## Sort (`sort.h`)
|
|
|
|
Use these instead of `qsort` for portability across all platforms.
|
|
|
|
```c
|
|
typedef int_t (*sortcompare_t)(const void *, const void *);
|
|
|
|
void sortBubble(
|
|
void *array,
|
|
const size_t count,
|
|
const size_t size,
|
|
const sortcompare_t compare
|
|
);
|
|
|
|
void sortQuick(
|
|
void *array,
|
|
const size_t count,
|
|
const size_t size,
|
|
const sortcompare_t compare
|
|
);
|
|
|
|
#define sort sortQuick // preferred; use this in new code
|
|
```
|
|
|
|
Typed convenience helpers for `uint8_t` arrays:
|
|
|
|
```c
|
|
int sortArrayU8Compare(const void *a, const void *b);
|
|
void sortArrayU8(uint8_t *array, const size_t count);
|
|
```
|
|
|
|
---
|
|
|
|
## Crypt (`crypt.h`)
|
|
|
|
CRC32 checksum for save file integrity. Not cryptographically secure --
|
|
do not use for security purposes.
|
|
|
|
```c
|
|
// One-shot checksum:
|
|
uint32_t cryptCRC32(const void *data, const size_t size);
|
|
|
|
// Streaming (incremental) CRC32:
|
|
uint32_t cryptCRC32Begin(void);
|
|
void cryptCRC32Update(
|
|
uint32_t *crc, const void *data, const size_t size
|
|
);
|
|
uint32_t cryptCRC32End(const uint32_t crc);
|
|
```
|
|
|
|
The streaming API allows computing a checksum across multiple buffers
|
|
or while interleaving other reads -- the save system uses this to
|
|
verify the whole save slot in a single pass.
|