From ec166e2a4383b13598e0204206321c9121c1bc70 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 10 May 2026 15:43:19 +0100 Subject: [PATCH] Update doc formatting --- base/Home.md | 269 +++++++++++++++++++----------------------------- common/Home.md | 194 +++++++++++++++++----------------- os/Home.md | 172 ++++++++++++------------------- prng/Home.md | 30 +++--- testing/Home.md | 38 +++---- uuid/Home.md | 60 ++++++----- 6 files changed, 339 insertions(+), 424 deletions(-) diff --git a/base/Home.md b/base/Home.md index a3cb0a6..4d1d65f 100644 --- a/base/Home.md +++ b/base/Home.md @@ -2,19 +2,17 @@ The `base` package provides core data structures and memory abstractions: dynamic arrays, doubly-linked lists, queues, strings, and a pluggable allocator interface. +```c +#include "wapp_base.h" +``` + **Dependencies:** common --- ## Allocator Interface -A pluggable allocator interface that abstracts memory allocation strategies. - -```c -#include "wapp_base.h" -``` - -### Allocator Struct +A pluggable allocator that abstracts memory allocation strategies. See os package for the arena-backed implementation. ```c typedef struct Allocator Allocator; @@ -33,22 +31,16 @@ struct Allocator { | Function | Description | |----------|-------------| | `wapp_mem_allocator_alloc(allocator, size)` | Allocates memory | -| `wapp_mem_allocator_alloc_aligned(allocator, size, alignment)` | Allocated aligned memory | +| `wapp_mem_allocator_alloc_aligned(allocator, size, alignment)` | Allocates aligned memory | | `wapp_mem_allocator_realloc(allocator, ptr, old_size, new_size)` | Reallocates memory | | `wapp_mem_allocator_realloc_aligned(allocator, ptr, old_size, new_size, alignment)` | Reallocates aligned memory | | `wapp_mem_allocator_free(allocator, ptr, size)` | Frees memory | -| `wapp_mem_allocator_invalid(allocator)` | Checks if an allocator is zero-initialised (invalid) | - -The `Allocator` struct holds function pointers and a context object. This allows different allocation strategies (malloc, arena, custom) to share the same interface. +| `wapp_mem_allocator_invalid(allocator)` | Checks whether an allocator is zero-initialised | --- ## Memory Utilities -```c -#include "wapp_base.h" -``` - | Function | Description | |----------|-------------| | `wapp_mem_util_align_forward(ptr, alignment)` | Aligns a pointer forward to the given alignment | @@ -57,82 +49,69 @@ The `Allocator` struct holds function pointers and a context object. This allows ## Array -A type-generic dynamic array with stack-allocated and allocator-backed variants. - -```c -#include "wapp_base.h" -``` +A type-generic dynamic array with both stack-allocated and allocator-backed variants. ### Typedefs -Convenience typedefs for common element types: - -`VoidPtrArray`, `C8Array`, `C16Array`, `C32Array`, `U8Array`, `U16Array`, `U32Array`, `U64Array`, `B8Array`, `I8Array`, `I16Array`, `I32Array`, `I64Array`, `F32Array`, `F64Array`, `F128Array`, `UptrArray`, `IptrArray`, `Str8Array` +`GenericArray`, `VoidPtrArray`, `C8Array`, `C16Array`, `C32Array`, `U8Array`, `U16Array`, `U32Array`, `U64Array`, `B8Array`, `I8Array`, `I16Array`, `I32Array`, `I64Array`, `F32Array`, `F64Array`, `F128Array`, `UptrArray`, `IptrArray`, `Str8Array` ### Creation | Macro | Description | |-------|-------------| -| `wapp_array(TYPE, ...)` | Creates a stack-allocated array with initial elements. Capacity rounds up to the next power of 2, with a minimum of 2x the element count. | -| `wapp_array_with_capacity(TYPE, CAPACITY, FLAGS)` | Creates a stack-allocated array with a specific capacity. `FLAGS` is a bitmask of `ArrayInitFlags`. | -| `wapp_array_alloc_capacity(TYPE, ALLOCATOR, CAPACITY, FLAGS)` | Creates an allocator-backed array with a specific capacity | +| `wapp_array(type, ...)` | Stack-allocated array with initial elements. Capacity rounds up to the next power of 2. | +| `wapp_array_with_capacity(type, capacity, flags)` | Stack-allocated array with a specific capacity. Use `ARRAY_INIT_NONE` or `ARRAY_INIT_FILLED`. | +| `wapp_array_alloc_capacity(type, allocator, capacity, flags)` | Allocator-backed array with a specific capacity | -### Element Operations +### Element Access & Mutation | Macro | Description | |-------|-------------| -| `wapp_array_count(ARRAY)` | Returns the current element count | -| `wapp_array_capacity(ARRAY)` | Returns the total capacity | -| `wapp_array_item_size(ARRAY)` | Returns the size of a single element | -| `wapp_array_set_count(ARRAY, COUNT)` | Sets the element count | -| `wapp_array_get(TYPE, ARRAY, INDEX)` | Returns a pointer to the element at `INDEX` | -| `wapp_array_set(TYPE, ARRAY, INDEX, VALUE_PTR)` | Sets the element at `INDEX` from `VALUE_PTR` | -| `wapp_array_pop(TYPE, ARRAY)` | Pops and returns the last element by value. Returns `0`/`{}` if empty. | +| `wapp_array_count(array)` | Current element count | +| `wapp_array_capacity(array)` | Total capacity | +| `wapp_array_item_size(array)` | Size of a single element | +| `wapp_array_set_count(array, count)` | Sets the element count | +| `wapp_array_get(type, array, index)` | Returns pointer to element at `index` | +| `wapp_array_set(type, array, index, value_ptr)` | Sets element at `index` from `value_ptr` | +| `wapp_array_pop(type, array)` | Pops and returns the last element by value (or `0`) | -### Mutation (Capped - no allocation) +### Capped Operations (no allocation) | Macro | Description | |-------|-------------| -| `wapp_array_append_capped(TYPE, ARRAY, VALUE_PTR)` | Appends an element within current capacity. Does not grow. | -| `wapp_array_extend_capped(TYPE, DST, SRC)` | Extends `DST` with elements from `SRC` within capacity. | -| `wapp_array_copy_capped(TYPE, DST, SRC)` | Copies `SRC` elements into `DST` within capacity. | -| `wapp_array_clear(TYPE, ARRAY)` | Resets the element count to 0 | +| `wapp_array_append_capped(type, array, value_ptr)` | Appends within current capacity | +| `wapp_array_extend_capped(type, dst, src)` | Extends `dst` with elements from `src` | +| `wapp_array_copy_capped(type, dst, src)` | Copies `src` into `dst` | +| `wapp_array_clear(type, array)` | Resets count to zero | -### Mutation (Allocator-backed - may reallocate) +### Allocator-backed Operations (may grow) | Macro | Description | |-------|-------------| -| `wapp_array_append_alloc(TYPE, ALLOCATOR, ARRAY, VALUE_PTR, FLAGS)` | Appends, growing via allocator if needed | -| `wapp_array_extend_alloc(TYPE, ALLOCATOR, DST, SRC, FLAGS)` | Extends, growing via allocator if needed | -| `wapp_array_copy_alloc(TYPE, ALLOCATOR, DST, SRC, FLAGS)` | Copies, growing via allocator if needed | +| `wapp_array_append_alloc(type, allocator, array, value_ptr, flags)` | Appends, growing via allocator | +| `wapp_array_extend_alloc(type, allocator, dst, src, flags)` | Extends, growing via allocator | +| `wapp_array_copy_alloc(type, allocator, dst, src, flags)` | Copies, growing via allocator | ### Other | Macro | Description | |-------|-------------| -| `wapp_array_calc_alloc_size(TYPE, CAPACITY)` | Calculates the allocation size needed for a given capacity | -| `wapp_array_from_preallcated_buffer(TYPE, BUFFER, BUFFER_SIZE)` | Creates an array from a pre-allocated buffer | - -### Initialization Flags - -| Flag | Description | -|------|-------------| -| `ARRAY_INIT_NONE` | No initialization (elements contain garbage) | -| `ARRAY_INIT_FILLED` | Zero-fill all elements on creation | +| `wapp_array_calc_alloc_size(type, capacity)` | Allocation size needed for a given capacity | +| `wapp_array_from_preallcated_buffer(type, buffer, buffer_size)` | Creates an array from a pre-allocated buffer | ### Example ```c -// Stack-allocated array with initial values +// Stack-allocated array I32Array arr = wapp_array(i32, 10, 20, 30); -wapp_array_count(&arr); // 3 -wapp_array_capacity(&arr); // 8 (next power of 2) +wapp_array_count(arr); // 3 +wapp_array_capacity(arr); // 8 // Append (capped) i32 val = 40; -wapp_array_append_capped(i32, &arr, &val); +wapp_array_append_capped(i32, arr, &val); -// Heap-allocated array with automatic growth via arena +// Allocator-backed with automatic growth Allocator arena = wapp_mem_arena_allocator_init(KiB(16)); I32Array dyn = wapp_array_alloc_capacity(i32, &arena, 4, ARRAY_INIT_NONE); wapp_array_append_alloc(i32, &arena, &dyn, &val, ARRAY_INIT_NONE); @@ -142,73 +121,52 @@ wapp_array_append_alloc(i32, &arena, &dyn, &val, ARRAY_INIT_NONE); ## Doubly-Linked List -A type-generic doubly-linked list with both stack-allocated (persistent) and allocator-backed nodes. - -```c -#include "wapp_base.h" -``` +A type-generic doubly-linked list with node-level operations. ### Typedefs -Convenience typedefs for common element types, both for lists and nodes: - -`VoidPtrList`, `C8List`, `C16List`, `C32List`, `U8List`, `U16List`, `U32List`, `U64List`, `B8List`, `I8List`, `I16List`, `I32List`, `I64List`, `F32List`, `F64List`, `F128List`, `UptrList`, `IptrList`, `Str8List` +`GenericList`, `GenericNode`, `VoidPtrList`, `U8List`, `U16List`, `U32List`, `U64List`, `B8List`, `I8List`, `I16List`, `I32List`, `I64List`, `F32List`, `F64List`, `F128List`, `UptrList`, `IptrList`, `Str8List` (and corresponding `*Node` types). ### Creation | Macro | Description | |-------|-------------| -| `wapp_dbl_list(TYPE)` | Creates an empty stack-allocated doubly-linked list | -| `wapp_dbl_list_alloc(TYPE, ALLOCATOR)` | Allocates a list using the given allocator | +| `wapp_dbl_list(type)` | Creates an empty stack-allocated list | +| `wapp_dbl_list_alloc(type, allocator)` | Allocates a list via allocator | ### Element Access | Macro | Description | |-------|-------------| -| `wapp_dbl_list_get(TYPE, LIST, INDEX)` | Returns a pointer to the element at `INDEX` (walks from nearest end) | -| `wapp_dbl_list_get_node(TYPE, LIST, INDEX)` | Returns the `GenericNode*` at `INDEX` | -| `wapp_dbl_list_get_node_item(TYPE, NODE)` | Returns a pointer to the item in a node | +| `wapp_dbl_list_get(type, list, index)` | Returns pointer to element at `index` | +| `wapp_dbl_list_get_node(type, list, index)` | Returns the `GenericNode*` at `index` | +| `wapp_dbl_list_get_node_item(type, node)` | Returns pointer to the item in a node | -### Mutation (Stack-allocated persistent nodes) +### Mutation | Macro | Description | |-------|-------------| -| `wapp_dbl_list_push_front(TYPE, LIST, ITEM_PTR)` | Inserts at the front | -| `wapp_dbl_list_push_back(TYPE, LIST, ITEM_PTR)` | Appends at the back | -| `wapp_dbl_list_insert(TYPE, LIST, ITEM_PTR, INDEX)` | Inserts at `INDEX` | -| `wapp_dbl_list_pop_front(TYPE, LIST)` | Removes and returns the front element (or `NULL`) | -| `wapp_dbl_list_pop_back(TYPE, LIST)` | Removes and returns the back element (or `NULL`) | -| `wapp_dbl_list_remove(TYPE, LIST, INDEX)` | Removes and returns the element at `INDEX` (or `NULL`) | -| `wapp_dbl_list_empty(TYPE, LIST)` | Removes all elements from the list | +| `wapp_dbl_list_push_front(type, list, item_ptr)` | Inserts at the front | +| `wapp_dbl_list_push_back(type, list, item_ptr)` | Appends at the back | +| `wapp_dbl_list_insert(type, list, item_ptr, index)` | Inserts at `index` | +| `wapp_dbl_list_pop_front(type, list)` | Removes and returns the front element | +| `wapp_dbl_list_pop_back(type, list)` | Removes and returns the back element | +| `wapp_dbl_list_remove(type, list, index)` | Removes and returns element at `index` | +| `wapp_dbl_list_empty(type, list)` | Removes all elements | -### Mutation (Allocator-backed nodes) - -| Macro | Description | -|-------|-------------| -| `wapp_dbl_list_push_front_alloc(TYPE, ALLOCATOR, LIST, ITEM_PTR)` | Inserts at front with allocated node | -| `wapp_dbl_list_push_back_alloc(TYPE, ALLOCATOR, LIST, ITEM_PTR)` | Appends at back with allocated node | -| `wapp_dbl_list_insert_alloc(TYPE, ALLOCATOR, LIST, ITEM_PTR, INDEX)` | Inserts at `INDEX` with allocated node | - -### Node-Level Operations - -| Macro | Description | -|-------|-------------| -| `wapp_dbl_list_pop_front_node(TYPE, LIST)` | Removes and returns the front `GenericNode*` (or `NULL`) | -| `wapp_dbl_list_pop_back_node(TYPE, LIST)` | Removes and returns the back `GenericNode*` (or `NULL`) | -| `wapp_dbl_list_remove_node(TYPE, LIST, INDEX)` | Removes and returns the `GenericNode*` at `INDEX` (or `NULL`) | +Allocation-backed variants (`_push_front_alloc`, `_push_back_alloc`, `_insert_alloc`) accept an `allocator` parameter for node allocation. Node-level variants (`_pop_front_node`, `_pop_back_node`, `_remove_node`) return the `GenericNode*` directly. ### Example ```c Str8List list = wapp_dbl_list(Str8); - Str8 s1 = wapp_str8_lit("hello"); Str8 s2 = wapp_str8_lit("world"); wapp_dbl_list_push_back(Str8, &list, &s1); wapp_dbl_list_push_back(Str8, &list, &s2); -Str8 *item = wapp_dbl_list_get(Str8, &list, 0); // pointer to s1 +Str8 *item = wapp_dbl_list_get(Str8, &list, 0); ``` --- @@ -217,51 +175,41 @@ Str8 *item = wapp_dbl_list_get(Str8, &list, 0); // pointer to s1 A type-generic circular queue (FIFO) backed by a dynamic array. -```c -#include "wapp_base.h" -``` - ### Typedefs -Convenience typedefs: `VoidPtrQueue`, `C8Queue`, `C16Queue`, `C32Queue`, `U8Queue`, `U16Queue`, `U32Queue`, `U64Queue`, `B8Queue`, `I8Queue`, `I32Queue`, `I64Queue`, `F32Queue`, `F64Queue`, `F128Queue`, `UptrQueue`, `IptrQueue`, `Str8Queue` +`GenericQueue`, `VoidPtrQueue`, `U8Queue`, `U16Queue`, `U32Queue`, `U64Queue`, `I8Queue`, `I16Queue`, `I32Queue`, `I64Queue`, `F32Queue`, `F64Queue`, `F128Queue`, `UptrQueue`, `IptrQueue`, `Str8Queue` ### Creation | Macro | Description | |-------|-------------| -| `wapp_queue(TYPE, CAPACITY)` | Creates a stack-allocated queue with the given capacity | -| `wapp_queue_alloc(TYPE, ALLOCATOR, CAPACITY)` | Creates an allocator-backed queue | +| `wapp_queue(type, capacity)` | Stack-allocated queue | +| `wapp_queue_alloc(type, allocator, capacity)` | Allocator-backed queue | ### Operations | Macro | Description | |-------|-------------| -| `wapp_queue_push(TYPE, QUEUE, VALUE_PTR)` | Pushes an item to the back. Fails if full. | -| `wapp_queue_push_alloc(TYPE, ALLOCATOR, QUEUE, VALUE_PTR)` | Pushes, growing the backing array via allocator if full | -| `wapp_queue_pop(TYPE, QUEUE)` | Pops and returns a pointer to the front item | -| `wapp_queue_capacity(QUEUE)` | Returns the current capacity | -| `wapp_queue_item_size(QUEUE)` | Returns the size of a single element | +| `wapp_queue_push(type, queue, value_ptr)` | Pushes to the back (fails if full) | +| `wapp_queue_push_alloc(type, allocator, queue, value_ptr)` | Pushes, growing via allocator | +| `wapp_queue_pop(type, queue)` | Pops and returns pointer to the front item | +| `wapp_queue_capacity(queue)` | Current capacity | +| `wapp_queue_item_size(queue)` | Size of a single element | ### Example ```c I32Queue queue = wapp_queue(i32, 8); - i32 val = 42; wapp_queue_push(i32, &queue, &val); - -i32 *result = wapp_queue_pop(i32, &queue); // pointer to 42 +i32 *result = wapp_queue_pop(i32, &queue); ``` --- ## Str8 -A length-tracked, mutable string type. - -```c -#include "wapp_base.h" -``` +A length-tracked mutable string type. ### Type @@ -278,97 +226,90 @@ typedef const Str8 Str8RO; // read-only view ### Printf Helpers -| Macro | Description | -|-------|-------------| -| `WAPP_STR8_SPEC` | Format specifier (`"%.*s"`) for printf | -| `wapp_str8_varg(STRING)` | Expands to `(int)(STRING).size, (STRING).buf` for use with `WAPP_STR8_SPEC` | - ```c +#define WAPP_STR8_SPEC "%.*s" +#define wapp_str8_varg(s) (int)((s).size), (s).buf + printf("Value: " WAPP_STR8_SPEC "\n", wapp_str8_varg(my_str)); ``` -### Creation - Stack +### Creation (Stack) | Macro | Description | |-------|-------------| -| `wapp_str8_buf(CAPACITY)` | Creates an empty string buffer (zeroed) | -| `wapp_str8_lit(STRING)` | Creates a mutable copy of a string literal (capacity = 2x length) | -| `wapp_str8_lit_ro(STRING)` | Creates a read-only view of a string literal | -| `wapp_str8_lit_ro_initialiser_list(STRING)` | For use in static initialisers when compound literals aren't supported | +| `wapp_str8_buf(capacity)` | Zeroed empty buffer | +| `wapp_str8_lit(string)` | Mutable copy (capacity = 2x length) | +| `wapp_str8_lit_ro(string)` | Read-only view of a string literal | +| `wapp_str8_lit_ro_initialiser_list(string)` | For use in static initialisers | -### Creation - Allocator +### Creation (Allocator) | Function | Description | |----------|-------------| -| `wapp_str8_alloc_buf(allocator, capacity)` | Allocates an empty string buffer via allocator | -| `wapp_str8_alloc_and_fill_buf(allocator, capacity)` | Allocates and zero-fills | -| `wapp_str8_alloc_cstr(allocator, cstr)` | Copies a C string into an allocated Str8 | -| `wapp_str8_alloc_str8(allocator, str)` | Copies a Str8 into an allocated Str8 | -| `wapp_str8_alloc_substr(allocator, str, start, end)` | Copies a substring range | -| `wapp_str8_alloc_concat(allocator, dst, src)` | Concatenates and returns a new allocated Str8 | -| `wapp_str8_dealloc_buf(allocator, str)` | Frees an allocated Str8 | +| `wapp_str8_alloc_buf(allocator, capacity)` | Empty buffer via allocator | +| `wapp_str8_alloc_and_fill_buf(allocator, capacity)` | Zero-filled buffer | +| `wapp_str8_alloc_cstr(allocator, cstr)` | Copy a C string | +| `wapp_str8_alloc_str8(allocator, str)` | Copy a Str8 | +| `wapp_str8_alloc_substr(allocator, str, start, end)` | Copy a substring | +| `wapp_str8_alloc_concat(allocator, dst, src)` | Concatenate into new allocation | +| `wapp_str8_dealloc_buf(allocator, str)` | Free an allocated Str8 | -### Element Access & Mutation +### Access & Mutation | Function | Description | |----------|-------------| -| `wapp_str8_get(str, index)` | Gets character at `index`. Returns `'\0'` if out of bounds. | -| `wapp_str8_set(str, index, c)` | Sets character at `index` | -| `wapp_str8_push_back(str, c)` | Appends a single character | +| `wapp_str8_get(str, index)` | Character at `index` (or `'\0'` if out of bounds) | +| `wapp_str8_set(str, index, c)` | Set character at `index` | +| `wapp_str8_push_back(str, c)` | Append a single character | ### Comparison & Search | Function | Description | |----------|-------------| -| `wapp_str8_equal(s1, s2)` | Full string equality | -| `wapp_str8_equal_to_count(s1, s2, count)` | Equality limited to the first `count` characters | -| `wapp_str8_find(str, substr)` | Forward search. Returns index or `-1`. | -| `wapp_str8_rfind(str, substr)` | Reverse search. Returns index or `-1`. | +| `wapp_str8_equal(s1, s2)` | Full equality | +| `wapp_str8_equal_to_count(s1, s2, n)` | Equality limited to first `n` characters | +| `wapp_str8_find(str, substr)` | Forward search (returns index or `-1`) | +| `wapp_str8_rfind(str, substr)` | Reverse search (returns index or `-1`) | ### Content Manipulation | Function | Description | |----------|-------------| -| `wapp_str8_slice(str, start, end)` | Returns a read-only substring view | -| `wapp_str8_concat_capped(dst, src)` | Concatenates within `dst` capacity | -| `wapp_str8_copy_cstr_capped(dst, cstr)` | Copies a C string into a Str8 | -| `wapp_str8_copy_str8_capped(dst, src)` | Copies a Str8 into another Str8 | -| `wapp_str8_copy_to_cstr(dst, src, dst_capacity)` | Copies Str8 content to a C string buffer | -| `wapp_str8_format(dst, format, ...)` | printf-style formatting into a Str8 | -| `wapp_str8_to_lower(dst, src)` | Converts to lowercase | -| `wapp_str8_to_upper(dst, src)` | Converts to uppercase | -| `wapp_str8_from_bytes(dst, src)` | Converts a `U8Array` of bytes into a Str8 | +| `wapp_str8_slice(str, start, end)` | Read-only substring view | +| `wapp_str8_concat_capped(dst, src)` | Concatenate within capacity | +| `wapp_str8_copy_cstr_capped(dst, cstr)` | Copy C string into Str8 | +| `wapp_str8_copy_str8_capped(dst, src)` | Copy Str8 into Str8 | +| `wapp_str8_copy_to_cstr(dst, src, dst_capacity)` | Copy to C string buffer | +| `wapp_str8_format(dst, format, ...)` | printf-style formatting | +| `wapp_str8_to_lower(dst, src)` | Convert to lowercase | +| `wapp_str8_to_upper(dst, src)` | Convert to uppercase | +| `wapp_str8_from_bytes(dst, src)` | Convert `U8Array` bytes to Str8 | -### Split and Join +### Split & Join | Function | Description | |----------|-------------| -| `wapp_str8_split(allocator, str, delimiter)` | Splits forward into a `Str8List` (all parts) | -| `wapp_str8_split_with_max(allocator, str, delimiter, max_splits)` | Splits forward with a maximum number of splits | -| `wapp_str8_rsplit(allocator, str, delimiter)` | Splits in reverse | -| `wapp_str8_rsplit_with_max(allocator, str, delimiter, max_splits)` | Splits in reverse with a maximum | -| `wapp_str8_join(allocator, list, delimiter)` | Joins a `Str8List` with a delimiter | +| `wapp_str8_split(allocator, str, delimiter)` | Split into `Str8List` | +| `wapp_str8_split_with_max(allocator, str, delimiter, max_splits)` | Split with maximum parts | +| `wapp_str8_rsplit(allocator, str, delimiter)` | Reverse split | +| `wapp_str8_rsplit_with_max(allocator, str, delimiter, max_splits)` | Reverse split with maximum | +| `wapp_str8_join(allocator, list, delimiter)` | Join a `Str8List` with delimiter | | `wapp_str8_list_total_size(list)` | Sum of all string sizes in a list | ### Example ```c Str8 s = wapp_str8_lit("Hello, World!"); -printf(WAPP_STR8_SPEC "\n", wapp_str8_varg(s)); // prints "Hello, World!" - -Str8 buf = wapp_str8_buf(256); -wapp_str8_copy_cstr_capped(&buf, "Hello"); -wapp_str8_push_back(&buf, '!'); +printf(WAPP_STR8_SPEC "\n", wapp_str8_varg(s)); // Formatting +Str8 buf = wapp_str8_buf(256); wapp_str8_format(&buf, "Value: %d", 42); -// Split +// Split and join Allocator arena = wapp_mem_arena_allocator_init(KiB(16)); Str8 data = wapp_str8_lit("a,b,c"); Str8 delim = wapp_str8_lit_ro(","); Str8List *parts = wapp_str8_split(&arena, &data, &delim); - -// Join Str8 *joined = wapp_str8_join(&arena, parts, &delim); ``` diff --git a/common/Home.md b/common/Home.md index 998f744..ae5f824 100644 --- a/common/Home.md +++ b/common/Home.md @@ -1,106 +1,109 @@ # common -The `common` package provides foundational type definitions, platform detection, assertion macros, and miscellaneous utilities used by all other packages. - -**Dependencies:** None - ---- - -## Aliases - -Convenient typedefs for primitive types and qualifiers. +The `common` package provides foundational type definitions, platform detection, assertion macros, and miscellaneous utilities used across the entire library. ```c #include "wapp_common.h" ``` -### Integer Types +**Dependencies:** None -| Type | Underlying | -|------|-----------| -| `u8`, `u16`, `u32`, `u64` | `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t` | -| `i8`, `i16`, `i32`, `i64` | `int8_t`, `int16_t`, `int32_t`, `int64_t` | -| `b8` | `uint8_t` (boolean) | -| `uptr`, `iptr` | `uintptr_t`, `intptr_t` | +--- -### Character Types +## Type Aliases -| Type | Description | -|------|-------------| -| `c8` | UTF-8 code unit (`uint8_t` or `char8_t`) | -| `c16` | UTF-16 code unit (`uint16_t` or `char16_t`) | -| `c32` | UTF-32 code unit (`uint32_t` or `char32_t`) | +Convenient typedefs for primitive types. -### Floating-Point Types +```c +// Integer types +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; +typedef uint8_t b8; // boolean +typedef uintptr_t uptr; +typedef intptr_t iptr; -| Type | Description | -|------|-------------| -| `f32` | 32-bit float | -| `f64` | 64-bit double | -| `f128` | 80+ bit long double | +// Character types +typedef uint8_t c8; // UTF-8 code unit +typedef uint16_t c16; // UTF-16 code unit +typedef uint32_t c32; // UTF-32 code unit + +// Floating-point types +typedef float f32; +typedef double f64; +typedef long double f128; +``` + +Where available, `c8`/`c16`/`c32` map to `char8_t`/`char16_t`/`char32_t`. ### Boolean Macros (C only) -In C, `true` and `false` are defined as `(b8)1` and `(b8)0` respectively when unavailable. +In C, `true` and `false` are defined as `(b8)1` and `(b8)0` when not already available. ### Qualifier Macros -| Macro | Expands To | Description | -|-------|-----------|-------------| -| `wapp_extern` | `extern` | External linkage | -| `wapp_intern` | `static` | Internal linkage | -| `wapp_persist` | `static` | Persistent storage duration | -| `wapp_class_mem` | `static` | Class-level static (C++ only) | +| Macro | Description | +|-------|-------------| +| `wapp_extern` | External linkage (`extern`) | +| `wapp_intern` | Internal linkage (`static`) | +| `wapp_persist` | Persistent storage (`static`) | +| `wapp_class_mem` | Class-level static (C++ only) | ### C/C++ Interop ```c -BEGIN_C_LINKAGE // extern "C" { (C++ only) -END_C_LINKAGE // } (C++ only) +BEGIN_C_LINKAGE // extern "C" { (C++ only) +END_C_LINKAGE // } (C++ only) ``` --- ## Platform Detection -The library auto-detects the target platform and defines the appropriate macros. +The library auto-detects the target platform and language version at compile time. -### Platform Macros +```c +#include "wapp_common.h" +``` -**OS Family:** -- `WAPP_PLATFORM_POSIX` - Any POSIX-compliant system -- `WAPP_PLATFORM_WINDOWS` - Any Windows system (including Cygwin) -- `WAPP_PLATFORM_UNIX` - Traditional Unix systems +### Operating Systems -**Specific Platforms:** -- `WAPP_PLATFORM_LINUX` - Linux -- `WAPP_PLATFORM_MACOS` - macOS -- `WAPP_PLATFORM_IOS` - iOS -- `WAPP_PLATFORM_ANDROID` - Android -- `WAPP_PLATFORM_FREE_BSD` - FreeBSD -- `WAPP_PLATFORM_NET_BSD` - NetBSD -- `WAPP_PLATFORM_OPEN_BSD` - OpenBSD -- `WAPP_PLATFORM_DRAGON_FLY` - DragonFly BSD -- `WAPP_PLATFORM_GNU` - GNU/Hurd -- `WAPP_PLATFORM_CYGWIN` - Cygwin -- `WAPP_PLATFORM_WINDOWS64` - 64-bit Windows -- `WAPP_PLATFORM_WINDOWS32` - 32-bit Windows -- `WAPP_PLATFORM_APPLE` - Any Apple platform +| Macro | Targets | +|-------|---------| +| `WAPP_PLATFORM_POSIX` | All POSIX-compliant systems | +| `WAPP_PLATFORM_LINUX` | Linux | +| `WAPP_PLATFORM_MACOS` | macOS | +| `WAPP_PLATFORM_IOS` | iOS | +| `WAPP_PLATFORM_ANDROID` | Android | +| `WAPP_PLATFORM_FREE_BSD` | FreeBSD | +| `WAPP_PLATFORM_NET_BSD` | NetBSD | +| `WAPP_PLATFORM_OPEN_BSD` | OpenBSD | +| `WAPP_PLATFORM_DRAGON_FLY` | DragonFly BSD | +| `WAPP_PLATFORM_GNU` | GNU/Hurd | +| `WAPP_PLATFORM_CYGWIN` | Cygwin | +| `WAPP_PLATFORM_WINDOWS` | All Windows (32-bit, 64-bit, Cygwin) | +| `WAPP_PLATFORM_APPLE` | All Apple platforms | -### Language Version Macros +### Language Version -**C Language:** -- `WAPP_PLATFORM_C` - Defined when compiling as C -- `WAPP_PLATFORM_C89`, `WAPP_PLATFORM_C99`, `WAPP_PLATFORM_C11`, `WAPP_PLATFORM_C17`, `WAPP_PLATFORM_C23` - -**C++ Language:** -- `WAPP_PLATFORM_CPP` - Defined when compiling as C++ -- `WAPP_PLATFORM_CPP98`, `WAPP_PLATFORM_CPP11`, `WAPP_PLATFORM_CPP14`, `WAPP_PLATFORM_CPP17`, `WAPP_PLATFORM_CPP20`, `WAPP_PLATFORM_CPP23` +| Macro | Defined When | +|-------|-------------| +| `WAPP_PLATFORM_C` | Compiling as C | +| `WAPP_PLATFORM_C99`, `WAPP_PLATFORM_C11`, `WAPP_PLATFORM_C17`, `WAPP_PLATFORM_C23` | Specific C standard versions | +| `WAPP_PLATFORM_CPP` | Compiling as C++ | +| `WAPP_PLATFORM_CPP11`, `WAPP_PLATFORM_CPP14`, `WAPP_PLATFORM_CPP17`, `WAPP_PLATFORM_CPP20`, `WAPP_PLATFORM_CPP23` | Specific C++ standard versions | --- ## Assertions +Runtime and compile-time assertion macros with configurable behaviour. + ```c #include "wapp_common.h" ``` @@ -109,11 +112,16 @@ The library auto-detects the target platform and defines the appropriate macros. | Macro | Description | |-------|-------------| -| `wapp_static_assert(EXPR, MSG)` | Compile-time assertion using `extern char` trick | -| `wapp_runtime_assert(EXPR, MSG)` | Runtime assertion (disabled by `WAPP_NO_RUNTIME_ASSERT`) | -| `wapp_debug_assert(EXPR, MSG)` | Runtime assertion, only active when `WAPP_DEBUG_ASSERT` is defined | +| `wapp_static_assert(expr, msg)` | Compile-time assertion via `extern char` trick | +| `wapp_runtime_assert(expr, msg)` | Runtime check; aborts with file/line/function info on failure | +| `wapp_debug_assert(expr, msg)` | Like `wapp_runtime_assert`, but only active when `WAPP_DEBUG_ASSERT` is defined | -On failure, assertions print the file, line, function, expression value, and diagnostic message to `stderr`, then call `abort()`. +On failure, the diagnostic includes the file name, line number, function name, expression value, and message: + +``` +src/foo.c:42 (In function `load_config`): Assertion failed (1) +Diagnostic: config should not be NULL +``` ### Build Configuration @@ -121,7 +129,7 @@ On failure, assertions print the file, line, function, expression value, and dia // Enable debug assertions during development #define WAPP_DEBUG_ASSERT -// Disable all runtime assertions for release +// Disable all runtime assertions for release builds #define WAPP_NO_RUNTIME_ASSERT ``` @@ -129,6 +137,8 @@ On failure, assertions print the file, line, function, expression value, and dia ## Misc Utilities +Helper macros for size literals, alignment, and bit operations. + ```c #include "wapp_common.h" ``` @@ -137,32 +147,28 @@ On failure, assertions print the file, line, function, expression value, and dia Binary (IEC) prefixes: -| Macro | Formula | -|-------|---------| -| `KiB(SIZE)` | `SIZE << 10` | -| `MiB(SIZE)` | `SIZE << 20` | -| `GiB(SIZE)` | `SIZE << 30` | -| `TiB(SIZE)` | `SIZE << 40` | -| `PiB(SIZE)` | `SIZE << 50` | -| `EiB(SIZE)` | `SIZE << 60` | +| Macro | Expands To | +|-------|-----------| +| `KiB(n)` | `n << 10` | +| `MiB(n)` | `n << 20` | +| `GiB(n)` | `n << 30` | +| `TiB(n)` | `n << 40` | Decimal (SI) prefixes: -| Macro | Formula | -|-------|---------| -| `KB(SIZE)` | `SIZE * 1000` | -| `MB(SIZE)` | `KB(SIZE) * 1000` | -| `GB(SIZE)` | `MB(SIZE) * 1000` | -| `TB(SIZE)` | `GB(SIZE) * 1000` | -| `PB(SIZE)` | `TB(SIZE) * 1000` | -| `EB(SIZE)` | `PB(SIZE) * 1000` | +| Macro | Expands To | +|-------|-----------| +| `KB(n)` | `n * 1000` | +| `MB(n)` | `KB(n) * 1000` | +| `GB(n)` | `MB(n) * 1000` | +| `TB(n)` | `GB(n) * 1000` | -### Utility Macros +### Other Utilities -| Macro | Description | -|-------|-------------| -| `wapp_misc_utils_reserve_padding(SIZE)` | Inserts padding bytes to align a struct field to pointer size | -| `wapp_misc_utils_u64_round_up_pow2(X)` | Rounds `X` up to the nearest power of 2 | -| `wapp_is_power_of_two(NUM)` | Checks if `NUM` is a power of 2 | -| `wapp_pointer_offset(PTR, OFFSET)` | Adds a byte offset to a pointer | -| `wapp_misc_utils_va_args_count(T, ...)` | Returns the number of variadic arguments of type `T` | +| Macro / Function | Description | +|------------------|-------------| +| `wapp_misc_utils_reserve_padding(size)` | Inserts padding to align a struct field to pointer size | +| `wapp_misc_utils_u64_round_up_pow2(x)` | Rounds `x` up to the nearest power of 2 | +| `wapp_is_power_of_two(n)` | Tests whether `n` is a power of 2 | +| `wapp_pointer_offset(ptr, offset)` | Adds a byte offset to a pointer | +| `wapp_misc_utils_va_args_count(t, ...)` | Returns the number of variadic arguments of type `t` | diff --git a/os/Home.md b/os/Home.md index abe2b7e..fb16c10 100644 --- a/os/Home.md +++ b/os/Home.md @@ -1,6 +1,10 @@ # os -The `os` package provides OS-level abstractions: file I/O, memory-mapped arena allocators, shell command execution, terminal colour output, and path manipulation. +The `os` package provides OS-level abstractions: virtual memory, arena allocators, file I/O, shell command execution, terminal colour output, and path manipulation. + +```c +#include "wapp_os.h" +``` **Dependencies:** common, base @@ -10,17 +14,13 @@ The `os` package provides OS-level abstractions: file I/O, memory-mapped arena a Low-level virtual memory allocation. -```c -#include "wapp_os.h" -``` - ### Types -| Type | Description | -|------|-------------| -| `MemAccess` | Memory access permissions: `WAPP_MEM_ACCESS_NONE`, `WAPP_MEM_ACCESS_READ_ONLY`, `WAPP_MEM_ACCESS_EXEC_ONLY`, `WAPP_MEM_ACCESS_READ_WRITE`, `WAPP_MEM_ACCESS_READ_EXEC`, `WAPP_MEM_ACCESS_READ_WRITE_EXEC` | -| `MemAllocFlags` | Allocation flags: `WAPP_MEM_ALLOC_RESERVE`, `WAPP_MEM_ALLOC_COMMIT` | -| `MemInitType` | Initialization: `WAPP_MEM_INIT_UNINITIALISED`, `WAPP_MEM_INIT_INITIALISED` | +| Type | Values | +|------|--------| +| `MemAccess` | `WAPP_MEM_ACCESS_NONE`, `WAPP_MEM_ACCESS_READ_ONLY`, `WAPP_MEM_ACCESS_EXEC_ONLY`, `WAPP_MEM_ACCESS_READ_WRITE`, `WAPP_MEM_ACCESS_READ_EXEC`, `WAPP_MEM_ACCESS_READ_WRITE_EXEC` | +| `MemAllocFlags` | `WAPP_MEM_ALLOC_RESERVE`, `WAPP_MEM_ALLOC_COMMIT` | +| `MemInitType` | `WAPP_MEM_INIT_UNINITIALISED`, `WAPP_MEM_INIT_INITIALISED` | ### Functions @@ -33,37 +33,35 @@ Low-level virtual memory allocation. On POSIX, `wapp_os_mem_alloc` wraps `mmap` and `wapp_os_mem_free` wraps `munmap`. On Windows they wrap `VirtualAlloc` and `VirtualFree`. -POSIX uses `MAP_POPULATE` (Linux/GNU) or `MAP_PREFAULT_READ` (FreeBSD) for the commit flag. Other POSIX platforms (BSD, Apple) set both flags to `0`, relying on lazy mapping. - -On Windows, `WAPP_MEM_ALLOC_RESERVE` maps to `MEM_RESERVE` and `WAPP_MEM_ALLOC_COMMIT` maps to `MEM_COMMIT`. +The commit flag behaviour varies by platform: +- Linux/GNU: `WAPP_MEM_ALLOC_COMMIT` maps to `MAP_POPULATE` +- FreeBSD: `WAPP_MEM_ALLOC_COMMIT` maps to `MAP_PREFAULT_READ` +- Other BSD/Apple/Unix: both flags are `0` (lazy mapping) +- Windows: `WAPP_MEM_ALLOC_RESERVE` = `MEM_RESERVE`, `WAPP_MEM_ALLOC_COMMIT` = `MEM_COMMIT` --- ## Arena Allocator -A bump allocator backed by OS virtual memory (or a user-provided buffer). Provides fast, sequential allocations with temporary allocation scoping (memory stacking). - -```c -#include "wapp_os.h" -``` +A bump allocator backed by OS virtual memory (or a user-provided buffer). Provides fast sequential allocations with temporary scope support. ### Initialization | Function / Macro | Description | |------------------|-------------| -| `wapp_mem_arena_init_allocated(arena, base_capacity)` | Initialises an arena with reserved OS memory | -| `wapp_mem_arena_init_allocated_commit(arena, base_capacity)` | Reserves and commits OS memory | -| `wapp_mem_arena_init_allocated_zero(arena, base_capacity)` | Reserves and zeroes OS memory | -| `wapp_mem_arena_init_allocated_commit_and_zero(arena, base_capacity)` | Reserves, commits, and zeroes | -| `wapp_mem_arena_init_allocated_custom(arena, base_capacity, flags, zero)` | Full control over initialization | -| `wapp_mem_arena_init_buffer(arena, buffer, buffer_size)` | Initialises an arena from a pre-existing buffer | +| `wapp_mem_arena_init_allocated(arena, base_capacity)` | Arena backed by reserved OS memory | +| `wapp_mem_arena_init_allocated_commit(arena, base_capacity)` | Reserved and committed | +| `wapp_mem_arena_init_allocated_zero(arena, base_capacity)` | Reserved and zeroed | +| `wapp_mem_arena_init_allocated_commit_and_zero(arena, base_capacity)` | Reserved, committed, and zeroed | +| `wapp_mem_arena_init_allocated_custom(arena, base_capacity, flags, zero)` | Full control | +| `wapp_mem_arena_init_buffer(arena, buffer, buffer_size)` | Arena from a pre-existing buffer | ### Allocation | Function | Description | |----------|-------------| -| `wapp_mem_arena_alloc(arena, size)` | Bump-allocates memory | -| `wapp_mem_arena_alloc_aligned(arena, size, alignment)` | Bump-allocates aligned memory | +| `wapp_mem_arena_alloc(arena, size)` | Bump allocates memory | +| `wapp_mem_arena_alloc_aligned(arena, size, alignment)` | Bump allocates aligned memory | | `wapp_mem_arena_realloc(arena, ptr, old_size, new_size)` | Reallocates within the arena | | `wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment)` | Reallocates aligned | @@ -71,10 +69,10 @@ A bump allocator backed by OS virtual memory (or a user-provided buffer). Provid | Function | Description | |----------|-------------| -| `wapp_mem_arena_temp_begin(arena)` | Saves the current position (start of temp scope) | -| `wapp_mem_arena_temp_end(arena)` | Rewinds to the saved position (ends temp scope) | +| `wapp_mem_arena_temp_begin(arena)` | Saves current position | +| `wapp_mem_arena_temp_end(arena)` | Rewinds to saved position (ends temporary scope) | | `wapp_mem_arena_clear(arena)` | Zeroes all arena memory | -| `wapp_mem_arena_destroy(arena)` | Frees the arena and sets pointer to `NULL` | +| `wapp_mem_arena_destroy(arena)` | Frees arena and sets pointer to `NULL` | ### Example @@ -84,7 +82,7 @@ wapp_mem_arena_init_allocated(&arena, MiB(1)); i32 *numbers = wapp_mem_arena_alloc(arena, 100 * sizeof(i32)); -// Temporary scope +// Temporary allocation scope wapp_mem_arena_temp_begin(arena); // ... temporary allocations ... wapp_mem_arena_temp_end(arena); // memory rewound @@ -94,15 +92,11 @@ wapp_mem_arena_destroy(&arena); // arena is now NULL ### Arena-backed Allocator -Wraps an `Arena` in the `Allocator` interface (from base). - -```c -#include "wapp_os.h" -``` +Wraps an `Arena` in the `Allocator` interface from base. | Function / Macro | Description | |------------------|-------------| -| `wapp_mem_arena_allocator_init(capacity)` | Creates an `Allocator` backed by a new arena | +| `wapp_mem_arena_allocator_init(capacity)` | `Allocator` backed by a new arena | | `wapp_mem_arena_allocator_init_commit(capacity)` | With committed memory | | `wapp_mem_arena_allocator_init_zero(capacity)` | With zeroed memory | | `wapp_mem_arena_allocator_init_commit_and_zero(capacity)` | With committed and zeroed memory | @@ -113,7 +107,7 @@ Wraps an `Arena` in the `Allocator` interface (from base). | `wapp_mem_arena_allocator_clear(allocator)` | Clear arena | | `wapp_mem_arena_allocator_destroy(allocator)` | Destroy arena | -**Note:** The arena allocator only supports `alloc` and `alloc_aligned`. `realloc`, `realloc_aligned`, and `free` are not implemented (individual frees are unsupported by arenas). +> **Note:** The arena allocator only supports `alloc` and `alloc_aligned`. `realloc`, `realloc_aligned`, and `free` are not implemented (arenas do not support individual frees). ```c Allocator allocator = wapp_mem_arena_allocator_init(KiB(16)); @@ -125,32 +119,28 @@ wapp_mem_arena_allocator_destroy(&allocator); ## File I/O -Cross-platform file operations. - -```c -#include "wapp_os.h" -``` +Cross-platform file operations with array-level read/write support. ### Types | Type | Description | |------|-------------| | `WFile` | Opaque file handle | -| `FileAccessMode` | Access mode enum | -| `FileSeekOrigin` | Seek origin enum | +| `FileAccessMode` | Access mode (see below) | +| `FileSeekOrigin` | Seek origin | ### File Access Modes -| Mode | Description | -|------|-------------| -| `WAPP_ACCESS_READ` | Read-only (`r`) | -| `WAPP_ACCESS_WRITE` | Write-only, truncates (`w`) | -| `WAPP_ACCESS_APPEND` | Append (`a`) | -| `WAPP_ACCESS_READ_EX` | Read/write (`r+`) | -| `WAPP_ACCESS_WRITE_EX` | Read/write, truncates (`w+`) | -| `WAPP_ACCESS_APPEND_EX` | Read/append (`a+`) | -| `WAPP_ACCESS_WRITE_FAIL_ON_EXIST` | Write, fail if exists (`wx`) | -| `WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX` | Read/write, fail if exists (`wx+`) | +| Mode | stdio Equivalent | Description | +|------|-----------------|-------------| +| `WAPP_ACCESS_READ` | `r` | Read-only | +| `WAPP_ACCESS_WRITE` | `w` | Write-only, truncates | +| `WAPP_ACCESS_APPEND` | `a` | Append | +| `WAPP_ACCESS_READ_EX` | `r+` | Read/write | +| `WAPP_ACCESS_WRITE_EX` | `w+` | Read/write, truncates | +| `WAPP_ACCESS_APPEND_EX` | `a+` | Read/append | +| `WAPP_ACCESS_WRITE_FAIL_ON_EXIST` | `wx` | Write, fail if exists | +| `WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX` | `wx+` | Read/write, fail if exists | ### Seek Origins @@ -166,24 +156,20 @@ Cross-platform file operations. |----------|-------------| | `wapp_file_open(allocator, filepath, mode)` | Opens a file | | `wapp_file_close(file)` | Closes a file | -| `wapp_file_read(buffer, file, byte_count)` | Reads raw bytes. Returns bytes read. | -| `wapp_file_write(buffer, file, byte_count)` | Writes raw bytes. Returns bytes written or negative on error. | +| `wapp_file_read(buf, file, byte_count)` | Reads raw bytes. Returns bytes read. | +| `wapp_file_write(buf, file, byte_count)` | Writes raw bytes. Returns count or negative on error. | | `wapp_file_read_array(dst_array, file, item_count)` | Reads array elements from file | | `wapp_file_write_array(src_array, file, item_count)` | Writes array elements to file | -| `wapp_file_seek(file, offset, origin)` | Seeks to a position. Returns the new position or negative on error. | -| `wapp_file_get_current_position(file)` | Returns the current file cursor position or negative on error | -| `wapp_file_get_length(file)` | Returns the file size in bytes | +| `wapp_file_seek(file, offset, origin)` | Seeks to position. Returns new position or negative. | +| `wapp_file_get_current_position(file)` | Current file cursor position | +| `wapp_file_get_length(file)` | File size in bytes | | `wapp_file_flush(file)` | Flushes file buffers | | `wapp_file_rename(old_path, new_path)` | Renames a file | | `wapp_file_remove(path)` | Deletes a file | ### Platform Notes -On POSIX, `WFile` stores an `i32 fd` (file descriptor) and all operations wrap POSIX system calls (`open`, `read`, `write`, `lseek`, `ftruncate`, `close`, `rename`, `unlink`). - -On Windows, `WFile` stores a `HANDLE` and operations wrap Win32 API calls (`CreateFile`, `ReadFile`, `WriteFile`, `SetFilePointerEx`, `GetFileSizeEx`, `FlushFileBuffers`, `CloseHandle`, `MoveFileEx`, `DeleteFile`). - -Newline convention: `END_OF_LINE` is `"\n"` on POSIX and `"\r\n"` on Windows. +On POSIX, `WFile` wraps an `i32 fd` and operations use POSIX system calls (`open`, `read`, `write`, `lseek`, `close`, `rename`, `unlink`). On Windows, `WFile` wraps a `HANDLE` and operations use Win32 API (`CreateFile`, `ReadFile`, `WriteFile`, `SetFilePointerEx`, `CloseHandle`, `MoveFileEx`, `DeleteFile`). ### Example @@ -198,10 +184,9 @@ I32Array arr = wapp_array_from_preallcated_buffer(i32, data, sizeof(data)); wapp_file_write_array(arr, f, 3); wapp_file_close(f); -// Read +// Read back f = wapp_file_open(&arena, &filename, WAPP_ACCESS_READ); i64 len = wapp_file_get_length(f); -// ... read into buffer ... wapp_file_close(f); wapp_file_remove(&filename); ``` @@ -212,10 +197,6 @@ wapp_file_remove(&filename); Execute shell commands and capture or discard their output. -```c -#include "wapp_os.h" -``` - ### Types ```c @@ -245,26 +226,23 @@ typedef struct CMDResult { | Function | Description | |----------|-------------| -| `wapp_shell_commander_execute(out_handling, out_buf, cmd)` | Executes a command. When `out_handling` is `SHELL_OUTPUT_CAPTURE`, `out_buf` must point to a `Str8` buffer. | +| `wapp_shell_commander_execute(out_handling, out_buf, cmd)` | Executes a command. Requires a `Str8` buffer when using `SHELL_OUTPUT_CAPTURE`. | ### Example ```c -// Build command Str8List cmd = wapp_dbl_list(Str8); Str8 prog = wapp_str8_lit("echo"); Str8 arg = wapp_str8_lit("hello world"); wapp_dbl_list_push_back(Str8, &cmd, &prog); wapp_dbl_list_push_back(Str8, &cmd, &arg); -// Execute and discard output -CMDResult result = wapp_shell_commander_execute(SHELL_OUTPUT_DISCARD, NULL, &cmd); -// result.exited == true, result.exit_code == 0 +// Discard output +CMDResult r = wapp_shell_commander_execute(SHELL_OUTPUT_DISCARD, NULL, &cmd); -// Execute and capture output +// Capture output Str8 buf = wapp_str8_buf(64); -result = wapp_shell_commander_execute(SHELL_OUTPUT_CAPTURE, &buf, &cmd); -// buf contains "hello world\n" +r = wapp_shell_commander_execute(SHELL_OUTPUT_CAPTURE, &buf, &cmd); ``` --- @@ -273,39 +251,27 @@ result = wapp_shell_commander_execute(SHELL_OUTPUT_CAPTURE, &buf, &cmd); Print coloured text to the terminal. -```c -#include "wapp_os.h" -``` - ### Colour Values -| Colour | Description | -|--------|-------------| -| `WAPP_TERM_COLOUR_FG_BLACK` through `WAPP_TERM_COLOUR_FG_WHITE` | Standard foreground colours | -| `WAPP_TERM_COLOUR_FG_BR_BLACK` through `WAPP_TERM_COLOUR_FG_BR_WHITE` | Bright foreground variants | -| `WAPP_TERM_COLOUR_CLEAR` | Reset to default | +Available colours: `WAPP_TERM_COLOUR_FG_BLACK`, `WAPP_TERM_COLOUR_FG_RED`, `WAPP_TERM_COLOUR_FG_GREEN`, `WAPP_TERM_COLOUR_FG_BLUE`, `WAPP_TERM_COLOUR_FG_CYAN`, `WAPP_TERM_COLOUR_FG_MAGENTA`, `WAPP_TERM_COLOUR_FG_YELLOW`, `WAPP_TERM_COLOUR_FG_WHITE`, plus bright variants (`WAPP_TERM_COLOUR_FG_BR_*`) and `WAPP_TERM_COLOUR_CLEAR`. ### Functions | Function | Description | |----------|-------------| | `wapp_shell_termcolour_print_text(text, colour)` | Prints text in the specified colour | -| `wapp_shell_termcolour_clear_colour()` | Resets terminal colours to default | +| `wapp_shell_termcolour_clear_colour()` | Resets to default terminal colours | --- ## CPath -Cross-platform path manipulation utilities. - -```c -#include "wapp_os.h" -``` +Cross-platform path manipulation. ### Constants -| Constant | Value | -|----------|-------| +| Constant | Description | +|----------|-------------| | `WAPP_PATH_SEP` | Platform path separator (`'/'` or `'\\'`) | | `WAPP_PATH_MAX` | Maximum path length | @@ -313,16 +279,19 @@ Cross-platform path manipulation utilities. | Function | Description | |----------|-------------| -| `wapp_cpath_join_path(dst, parts)` | Joins a `Str8List` of path components into a `Str8`. Returns an error code: `CPATH_JOIN_SUCCESS` (0), `CPATH_JOIN_INVALID_ARGS`, `CPATH_JOIN_EMPTY_PARTS`, `CPATH_JOIN_INSUFFICIENT_DST_CAPACITY`. Handles separator insertion automatically. | -| `wapp_cpath_dirname(allocator, path)` | Returns the parent directory (equivalent to `dirup(path, 1)`) | +| `wapp_cpath_join_path(dst, parts)` | Joins a `Str8List` of path components into a `Str8`. Returns `CPATH_JOIN_SUCCESS` (0) or an error code. Handles separator insertion automatically. | +| `wapp_cpath_dirname(allocator, path)` | Returns the parent directory | | `wapp_cpath_dirup(allocator, path, count)` | Returns the directory `count` levels up | +### Error Codes + +`CPATH_JOIN_SUCCESS`, `CPATH_JOIN_INVALID_ARGS`, `CPATH_JOIN_EMPTY_PARTS`, `CPATH_JOIN_INSUFFICIENT_DST_CAPACITY` + ### Example ```c Allocator arena = wapp_mem_arena_allocator_init(KiB(16)); -// Join path components Str8List parts = wapp_dbl_list(Str8); Str8 root = wapp_str8_lit("/"); Str8 home = wapp_str8_lit("home"); @@ -332,9 +301,8 @@ wapp_dbl_list_push_back(Str8, &parts, &home); wapp_dbl_list_push_back(Str8, &parts, &user); Str8 out = wapp_str8_buf(256); -wapp_cpath_join_path(&out, &parts); // out = "/home/user" +wapp_cpath_join_path(&out, &parts); // "/home/user" -// Parent directory Str8 dir = wapp_str8_lit("/home/user/docs"); Str8 *parent = wapp_cpath_dirname(&arena, &dir); // "/home/user" Str8 *grandparent = wapp_cpath_dirup(&arena, &dir, 2); // "/home" @@ -346,10 +314,6 @@ Str8 *grandparent = wapp_cpath_dirup(&arena, &dir, 2); // "/home" Cross-platform wrappers for `popen`/`pclose`. -```c -#include "wapp_os.h" -``` - | Macro | POSIX | Windows | |-------|-------|---------| | `wapp_shell_utils_popen` | `popen` | `_popen` | diff --git a/prng/Home.md b/prng/Home.md index edae012..c25a4cd 100644 --- a/prng/Home.md +++ b/prng/Home.md @@ -1,6 +1,10 @@ # prng -The `prng` package provides a **Xorshift256** pseudo-random number generator (PRNG). It uses a SplitMix64 seeding strategy initialised from the system clock. +The `prng` package provides a **Xorshift256** pseudo-random number generator. It uses a SplitMix64 seeding strategy initialised from the system clock. + +```c +#include "wapp_prng.h" +``` **Dependencies:** common @@ -8,11 +12,7 @@ The `prng` package provides a **Xorshift256** pseudo-random number generator (PR ## Xorshift256 -A fast, non-cryptographic PRNG with a 256-bit state. - -```c -#include "wapp_prng.h" -``` +A fast, non-cryptographic PRNG with a 256-bit state. Three variants are available with different trade-offs between speed and statistical quality. ### State @@ -30,19 +30,21 @@ struct XOR256State { | Function | Description | |----------|-------------| -| `wapp_prng_xorshift_init_state()` | Seeds and returns a new `XOR256State`. The OS generator is seeded once globally from the system clock (CLOCK_MONOTONIC_RAW on POSIX, `timespec_get` or `time` otherwise). A SplitMix64 generator then expands this into the 4 x 64-bit state. | -| `wapp_prng_xorshift_256(state)` | Standard xorshift256 variant. Returns a `u64`. | -| `wapp_prng_xorshift_256ss(state)` | xorshift256 with "scrambled" output (`rol64(z * 5, 7) * 9`). Passes BigCrush. | -| `wapp_prng_xorshift_256p(state)` | xorshift256 with "+" output (`w + x`). Passes BigCrush. | +| `wapp_prng_xorshift_init_state()` | Seeds a new `XOR256State` from the system clock using SplitMix64 expansion | +| `wapp_prng_xorshift_256(state)` | Standard xorshift256. Fastest variant. | +| `wapp_prng_xorshift_256ss(state)` | Scrambled output: `rol64(z * 5, 7) * 9`. Passes BigCrush. | +| `wapp_prng_xorshift_256p(state)` | Plus output: `w + x`. Passes BigCrush. | + +The state is seeded once globally from the system clock (`CLOCK_MONOTONIC_RAW` on POSIX, `timespec_get` or `time` otherwise), then expanded via SplitMix64 into four 64-bit state words. ### Example ```c XOR256State state = wapp_prng_xorshift_init_state(); -u64 r1 = wapp_prng_xorshift_256(&state); -u64 r2 = wapp_prng_xorshift_256ss(&state); -u64 r3 = wapp_prng_xorshift_256p(&state); +u64 r1 = wapp_prng_xorshift_256(&state); // fast +u64 r2 = wapp_prng_xorshift_256ss(&state); // high quality (BigCrush) +u64 r3 = wapp_prng_xorshift_256p(&state); // high quality (BigCrush) ``` -The state is passed by pointer and mutated on each call. The `_ss` and `_p` variants provide better statistical quality and pass the BigCrush test suite, while the standard `_256` variant is faster but has known weaknesses. +> The `_256ss` and `_256p` variants provide better statistical quality and pass the BigCrush test suite. The standard `_256` variant is faster but has known statistical weaknesses. diff --git a/testing/Home.md b/testing/Home.md index 496a566..18d4f17 100644 --- a/testing/Home.md +++ b/testing/Home.md @@ -1,6 +1,10 @@ # testing -The `testing` package provides a lightweight test runner that uses terminal colours for pass/fail output. +The `testing` package provides a lightweight test runner with coloured pass/fail output. It is designed for the library's own test suite but can be used in any C/C++ project. + +```c +#include "wapp_testing.h" +``` **Dependencies:** common, os, base @@ -8,11 +12,7 @@ The `testing` package provides a lightweight test runner that uses terminal colo ## Tester -A simple test framework. Each test is a function that returns a `TestFuncResult`. Tests are registered by passing their function pointers to `wapp_tester_run_tests`. - -```c -#include "wapp_testing.h" -``` +Each test is a function that returns a `TestFuncResult`. Tests are registered by passing their function pointers to `wapp_tester_run_tests`. ### Types @@ -23,29 +23,22 @@ struct TestFuncResult { b8 passed; }; -// Test function signature: typedef TestFuncResult(TestFunc)(void); ``` -### Test Result Helper +### Macros | Macro | Description | |-------|-------------| -| `wapp_tester_result(PASSED)` | Creates a `TestFuncResult` with the current function's name via `__func__` | - -### Test Runner - -| Macro / Function | Description | -|------------------|-------------| -| `wapp_tester_run_tests(func1, func2, ..., funcN)` | Runs all listed test functions. Must be NULL-terminated (the varargs macro automatically appends `NULL`). | -| `run_tests(func1, ...)` | Underlying function (varargs, NULL-terminated) | +| `wapp_tester_result(passed)` | Creates a `TestFuncResult` using `__func__` as the test name | +| `wapp_tester_run_tests(...)` | Runs all listed test functions (NULL-terminated automatically) | ### Behaviour -- Each test runs sequentially in declaration order. +- Tests run sequentially in declaration order. - Passing tests are shown in green (`[PASSED]`), failing tests in red (`[FAILED]`). -- Output uses terminal colours via `wapp_shell_termcolour_print_text`. - On the first failure, the runner calls `exit(EXIT_FAILURE)` immediately. +- Output uses terminal colours via the os package's `wapp_shell_termcolour_print_text`. ### Example @@ -72,6 +65,7 @@ int main(void) { ``` Output: + ``` [PASSED] test_addition [PASSED] test_subtraction @@ -80,8 +74,8 @@ Output: ### Writing Tests Each test function must: -1. Have the signature `TestFuncResult test_name(void)` -2. Return `wapp_tester_result(condition)` where `condition` is `true` for pass, `false` for fail -3. Not take any parameters +- Have the signature `TestFuncResult test_name(void)` +- Return `wapp_tester_result(condition)` where `condition` is `true` for pass, `false` for fail +- Take no parameters -Tests that share state (e.g. a file handle or an arena) can use `wapp_intern` (file-level `static`) variables to persist state across sequentially run tests. +Tests that share state (e.g. a file handle or arena) can use `wapp_persist` (file-level `static`) variables to persist state across sequentially run tests. diff --git a/uuid/Home.md b/uuid/Home.md index bd41319..7c73a5a 100644 --- a/uuid/Home.md +++ b/uuid/Home.md @@ -2,67 +2,75 @@ The `uuid` package provides **UUID v4** generation as specified by RFC 4122. UUIDs are generated using the library's Xorshift256 PRNG and formatted as 36-character strings. +```c +#include "wapp_uuid.h" +``` + **Dependencies:** common, base, prng --- ## UUID v4 -```c -#include "wapp_uuid.h" -``` - ### Type ```c typedef struct WUUID WUUID; struct WUUID { - Str8 uuid; // The UUID string representation + Str8 uuid; // The UUID string representation }; ``` ### Constants -| Constant | Description | -|----------|-------------| -| `UUID_BUF_LENGTH` | `48` - recommended buffer size for UUID strings | -| `WAPP_UUID_SPEC` | `WAPP_STR8_SPEC` - for printf formatting | -| `wapp_uuid_varg(wuuid)` | Expands to `wapp_str8_varg((WUUID).uuid)` for printf | +| Constant | Value | +|----------|-------| +| `UUID_BUF_LENGTH` | `48` | +| `WAPP_UUID_SPEC` | `WAPP_STR8_SPEC` | -### Convenience Macro +### Printf Helpers -| Macro | Description | -|-------|-------------| -| `wapp_uuid_gen_uuid4()` | One-shot UUID v4 generation. Creates a buffer and returns a fully initialised `WUUID` in a single expression - no variables needed. | +```c +#define wapp_uuid_varg(wuuid) wapp_str8_varg((WUUID).uuid) + +printf(WAPP_UUID_SPEC "\n", wapp_uuid_varg(u)); +``` + +### One-shot Generation + +```c +WUUID u = wapp_uuid_gen_uuid4(); +``` + +Creates a buffer and returns a fully initialised `WUUID` in a single expression. ### Low-Level API -| Function | Description | -|----------|-------------| -| `wapp_uuid_create()` | Creates an empty `WUUID` with a zeroed buffer of `UUID_BUF_LENGTH` capacity | -| `wapp_uuid_init_uuid4(uuid)` | Fills a `WUUID` with a randomly generated UUID v4. Returns the same pointer for chaining. | +| Function / Macro | Description | +|------------------|-------------| +| `wapp_uuid_create()` | Creates an empty `WUUID` with a zeroed buffer | +| `wapp_uuid_init_uuid4(uuid)` | Fills a `WUUID` with a randomly generated UUID v4. Returns the same pointer. | ### Example ```c -// One-shot generation (most common usage) +// One-shot WUUID uuid = wapp_uuid_gen_uuid4(); printf(WAPP_UUID_SPEC "\n", wapp_uuid_varg(uuid)); -// Example output: "f47ac10b-58cc-4372-a567-0e02b2c3d479" -// Two-step (low-level) +// Two-step WUUID u = wapp_uuid_create(); wapp_uuid_init_uuid4(&u); -printf(WAPP_UUID_SPEC "\n", wapp_uuid_varg(u)); ``` ### UUID Format -The generated UUID follows RFC 4122: +Generated UUIDs follow RFC 4122: + ``` xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx ``` -Where: + - The `4` identifies version 4 (random) -- `y` is one of `8`, `9`, `a`, or `b` (the variant field) -- All other digits are randomly generated via `wapp_prng_xorshift_256` +- `y` is one of `8`, `9`, `a`, or `b` (the RFC 4122 variant field) +- All other hex digits are generated via `wapp_prng_xorshift_256`