feature: add mkdocs-material documentation site with CI deployment
Generate comprehensive documentation for all 173 source units and integrate mkdocs-material into the build toolchain. Documentation covers kernel core, x86 architecture, drivers, applications, and all subsystems with a tabbed navigation structure. - Add mkdocs.yml with material theme, mermaid support, and tabbed nav - Add doc/index.md landing page - Generate doc/src/ markdown for every Pascal unit in src/ - Reorganize planning docs into doc/planning/ - Add compat, lvglh, and toolchain doc sections - Update Dockerfile to install python3 and mkdocs-material (pinned <2) - Replace pasdoc-based compile_docs.sh with mkdocs build --strict - Add compile_docs.sh to the main build pipeline in compile.sh - Add deploy-docs step in .drone.yml with host volume mount to nginx - Add site/.gitkeep for build output directory
This commit is contained in:
1 parent
7157a57513
commit
26e2fd947e
209 files changed
+16996
-13
No files matched your search
@@ -0,0 +1,95 @@
|
||||
# core.panic
|
||||
|
||||
Architecture-agnostic kernel panic (BSOD) engine.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.panic` implements a graphical and serial kernel panic handler for the Asuro kernel. When a fatal condition is detected anywhere in the kernel, `panic` is called with a fault identifier, a human-readable description, and an optional CPU register snapshot. The unit outputs the fault information to the serial syslog for headless debugging and, if LVGL has been initialised, displays a graphical Blue Screen of Death (BSOD).
|
||||
|
||||
The BSOD screen and all its LVGL widgets are pre-allocated at `init` time so that no dynamic LVGL allocation is needed when a panic fires. At panic time only label text is updated via `lv_label_set_text`, the pre-built screen is loaded, and a single render pass is forced. Text formatting uses static heap buffers and avoids calling any string library routines that might themselves fault.
|
||||
|
||||
Architecture-specific code is responsible for registering a CPU halt routine with `registerHaltProc` before any panic can occur. If no halt procedure is registered, the default fallback loops forever.
|
||||
|
||||
If `init` has not been called before a panic (early boot panic), the unit gracefully falls back to syslog-only output.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `io.syslog` — serial fault output
|
||||
- `debug.tracer` — call-stack capture and freeze
|
||||
- `driver.video` — frame buffer flush
|
||||
- `memory.heap` — buffer allocation
|
||||
- `driver.video.lvgl` — LVGL widget creation and rendering
|
||||
- `core.version` — version constants for the system info panel
|
||||
- `proc.mgr` — current process information
|
||||
- `proc.types` — process state enumeration
|
||||
- `core.fmt.targa` — teapot TGA image decoding
|
||||
- `core.gfx.texture` — pixel buffer type
|
||||
|
||||
## Constants
|
||||
|
||||
### MAX_REGISTER_ENTRIES
|
||||
Maximum number of register name/value pairs an architecture can supply in a `TRegisterSnapshot`. Value: `32`.
|
||||
|
||||
### PANIC_TEXT_BUF_SIZE
|
||||
Size in bytes of the pre-allocated text buffers used to format register, trace, process, and system information. Value: `2048`.
|
||||
|
||||
## Types
|
||||
|
||||
### TRegisterEntry
|
||||
```pascal
|
||||
TRegisterEntry = record
|
||||
Name : pchar;
|
||||
Value : uint32;
|
||||
end;
|
||||
```
|
||||
A single name/value pair representing one CPU register. `Name` must be a static string literal or a pointer that remains valid for the kernel lifetime.
|
||||
|
||||
### TRegisterSnapshot / PRegisterSnapshot
|
||||
```pascal
|
||||
TRegisterSnapshot = record
|
||||
Count : uint32;
|
||||
Entries : array[0..MAX_REGISTER_ENTRIES-1] of TRegisterEntry;
|
||||
end;
|
||||
```
|
||||
A snapshot of CPU register state at the time of a fault. `Count` specifies how many entries in `Entries` are valid.
|
||||
|
||||
### THaltProc
|
||||
```pascal
|
||||
THaltProc = procedure;
|
||||
```
|
||||
Procedure type for the architecture-specific CPU halt routine.
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### init
|
||||
```pascal
|
||||
procedure init;
|
||||
```
|
||||
Creates the hidden BSOD LVGL screen and pre-allocates all widget objects and text buffers. Must be called once after LVGL has been initialised. Subsequent calls to `panic` will display the graphical BSOD only if `init` has been called first.
|
||||
|
||||
### panic
|
||||
```pascal
|
||||
procedure panic(fault : pchar; info : pchar; regs : PRegisterSnapshot);
|
||||
```
|
||||
Triggers a kernel panic. Freezes the call-stack tracer, dumps fault information to syslog, and (if the BSOD screen is ready) displays the graphical panic screen. Then calls the registered halt procedure. Re-entrant calls are detected by a guard flag; if `panic` is called while a panic is already in progress, the system halts immediately without further output.
|
||||
|
||||
Parameters:
|
||||
- `fault` — short fault identifier string, e.g. `'arch.x86.fault.gpf'`.
|
||||
- `info` — human-readable description of the fault.
|
||||
- `regs` — pointer to a `TRegisterSnapshot`, or `nil` if register state is unavailable.
|
||||
|
||||
### registerHaltProc
|
||||
```pascal
|
||||
procedure registerHaltProc(proc : THaltProc);
|
||||
```
|
||||
Registers the architecture-specific halt procedure. Must be called before any panic can occur. If not called, a fallback infinite loop is used.
|
||||
|
||||
## Notes
|
||||
|
||||
The BSOD layout consists of a top banner (teapot TGA image beside title text) and a two-column content area. The left column contains Fault Details, CPU Registers, Process Info, and System Info cards. The right column contains the full-height Call Stack card.
|
||||
|
||||
The teapot image is loaded from a TGA binary linked into the kernel image via an assembly `incbin` stub (`_panic_tga_start` / `_panic_tga_size`). The image is decoded once at `init` time and stored in a pre-built LVGL image descriptor.
|
||||
|
||||
All text formatting in the panic path uses a set of internal buffer-writing helpers (`writeHexToBuffer`, `writeStrToBuffer`, `writeIntToBuffer`) that do not call the kernel string library, making the panic path robust against faults in those subsystems.
|
||||
|
||||
A compile-time switch `BSOD_ENABLE` gates the display path; if disabled, `panic` only writes to syslog and halts.
|
||||
@@ -0,0 +1,45 @@
|
||||
# core.rand
|
||||
|
||||
Pseudo-random number generator for the kernel.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.rand` implements a linear congruential generator (LCG) using the classic glibc constants (multiplier 1103515245, increment 12345) to produce pseudo-random values of 8, 16, and 32-bit widths. A single global state variable is maintained. The unit is intended for non-cryptographic use cases such as randomised data placement, simple simulations, or test data generation.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### rand32
|
||||
```pascal
|
||||
function rand32 : uint32;
|
||||
```
|
||||
Returns a 32-bit pseudo-random value formed by combining two successive 15-bit LCG outputs in the high and low 16-bit halves.
|
||||
|
||||
### rand16
|
||||
```pascal
|
||||
function rand16 : uint16;
|
||||
```
|
||||
Returns a 16-bit pseudo-random value (low 16 bits of a `rand32` call).
|
||||
|
||||
### rand8
|
||||
```pascal
|
||||
function rand8 : uint8;
|
||||
```
|
||||
Returns an 8-bit pseudo-random value (low 8 bits of a `rand32` call).
|
||||
|
||||
### srand
|
||||
```pascal
|
||||
procedure srand(seed : uint32);
|
||||
```
|
||||
Seeds the generator by adding `seed` to the current internal state. The seed is added rather than assigned, so successive calls accumulate entropy rather than resetting the sequence to a fixed point.
|
||||
|
||||
## Notes
|
||||
|
||||
The generator is not cryptographically secure and must not be used for security-sensitive purposes such as key generation or nonce selection.
|
||||
|
||||
The internal `rand` function returns values in the range 0–32767 (15 bits), following the classic C `rand()` output convention. `rand32` combines two calls to produce a 32-bit value.
|
||||
|
||||
Because `srand` adds to the existing state, the output sequence cannot be exactly reproduced by setting a known seed after the generator has been called. Seed before first use for reproducible sequences.
|
||||
@@ -0,0 +1,131 @@
|
||||
# core.strings
|
||||
|
||||
Null-terminated string manipulation library for the kernel.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.strings` provides a comprehensive set of routines for working with null-terminated (`pchar`) strings in a bare-metal environment. Because the kernel cannot use the Free Pascal runtime library string support, all allocation is performed through the kernel heap (`kalloc`/`kfree`) and all operations work on raw pointer-based C-style strings. The unit covers string creation, copying, comparison, searching, case conversion, concatenation, substring extraction, replacement, and conversion to and from integer types. A built-in `UnitTest` procedure exercises the full API and reports results via syslog.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.util` — `memcpy`, `memset`, `HexCharToDecimal`
|
||||
- `arch.x86.util` — architecture-level utilities
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.ds.lists` — transitively required
|
||||
- `io.syslog` — test output (implementation section only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### stringNew
|
||||
```pascal
|
||||
function stringNew(size : uint32) : pchar;
|
||||
```
|
||||
Allocates a new zero-initialised string buffer of `size` bytes plus a null terminator. Returns a pointer to the buffer.
|
||||
|
||||
### stringCopy
|
||||
```pascal
|
||||
function stringCopy(str : pchar) : pchar;
|
||||
```
|
||||
Allocates and returns a heap copy of `str`.
|
||||
|
||||
### stringSize
|
||||
```pascal
|
||||
function stringSize(str : pchar) : uint32;
|
||||
```
|
||||
Returns the length of `str` in characters, excluding the null terminator. Returns 0 for `nil`.
|
||||
|
||||
### stringEquals
|
||||
```pascal
|
||||
function stringEquals(str1, str2 : pchar) : boolean;
|
||||
```
|
||||
Returns `true` if `str1` and `str2` have identical length and content.
|
||||
|
||||
### stringToUpper
|
||||
```pascal
|
||||
function stringToUpper(str : pchar) : pchar;
|
||||
```
|
||||
Returns a heap-allocated copy of `str` with all lowercase ASCII letters converted to uppercase.
|
||||
|
||||
### stringToLower
|
||||
```pascal
|
||||
function stringToLower(str : pchar) : pchar;
|
||||
```
|
||||
Returns a heap-allocated copy of `str` with all uppercase ASCII letters converted to lowercase.
|
||||
|
||||
### stringConcat
|
||||
```pascal
|
||||
function stringConcat(str1, str2 : pchar) : pchar;
|
||||
```
|
||||
Returns a heap-allocated string containing `str1` followed by `str2`.
|
||||
|
||||
### stringTrim
|
||||
```pascal
|
||||
function stringTrim(str : pchar; length : uint32) : pchar;
|
||||
```
|
||||
Returns a heap-allocated copy of `str` truncated to at most `length` characters. If `length` exceeds the string length, the full string is copied.
|
||||
|
||||
### stringSub
|
||||
```pascal
|
||||
function stringSub(str : pchar; start, size : uint32) : pchar;
|
||||
```
|
||||
Returns a heap-allocated substring of `str` beginning at byte offset `start` with at most `size` characters. Returns an empty string if `start` is past the end. If `start + size` exceeds the string length, the result is clamped to the end.
|
||||
|
||||
### stringMatchAt
|
||||
```pascal
|
||||
function stringMatchAt(str : pchar; pos : uint32; find : pchar) : boolean;
|
||||
```
|
||||
Returns `true` if `find` matches the characters in `str` starting at position `pos`. An empty `find` always returns `true`.
|
||||
|
||||
### stringIndexOf
|
||||
```pascal
|
||||
function stringIndexOf(str, find : pchar) : sint32;
|
||||
```
|
||||
Returns the zero-based index of the first occurrence of `find` within `str`, or `-1` if not found. An empty `find` returns `0`.
|
||||
|
||||
### stringContains
|
||||
```pascal
|
||||
function stringContains(str : pchar; sub : pchar) : boolean;
|
||||
```
|
||||
Returns `true` if `sub` appears anywhere within `str`.
|
||||
|
||||
### stringReplace
|
||||
```pascal
|
||||
function stringReplace(str, find, replace : pchar) : pchar;
|
||||
```
|
||||
Returns a heap-allocated copy of `str` with the first occurrence of `find` replaced by `replace`. If `find` is not present, a copy of `str` is returned unchanged.
|
||||
|
||||
### stringToInt
|
||||
```pascal
|
||||
function stringToInt(str : pchar) : uint32;
|
||||
```
|
||||
Parses a decimal integer string and returns its `uint32` value. Non-digit characters are ignored.
|
||||
|
||||
### intToString
|
||||
```pascal
|
||||
function intToString(i : uint32) : pchar;
|
||||
```
|
||||
Returns a heap-allocated decimal string representation of `i`.
|
||||
|
||||
### hexStringToInt
|
||||
```pascal
|
||||
function hexStringToInt(str : pchar) : uint32;
|
||||
```
|
||||
Parses a hexadecimal string (no `0x` prefix) and returns its `uint32` value.
|
||||
|
||||
### boolToString
|
||||
```pascal
|
||||
function boolToString(b : boolean; ext : boolean) : pchar;
|
||||
```
|
||||
Returns a heap-allocated string for the boolean `b`. When `ext` is `true`, returns `'true'` or `'false'`; when `false`, returns `'1'` or `'0'`.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the complete string function test suite and logs a pass/fail summary to syslog under the `'STRINGS'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
All functions returning `pchar` return newly heap-allocated strings. Callers are responsible for freeing the result with `kfree` when it is no longer needed.
|
||||
|
||||
`stringReplace` replaces only the first occurrence of `find`. There is no bulk-replace variant.
|
||||
@@ -0,0 +1,11 @@
|
||||
# core.types
|
||||
|
||||
Dummy compatibility unit providing a named home for the `core.types` identifier.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.types` is an intentionally empty unit whose sole purpose is to satisfy the Free Pascal unit dependency resolver when a virtual machine build environment requires a unit named `core.types` to be present. It contains no type definitions, constants, or routines. Actual shared type definitions used by Asuro modules are declared in the units that own them, or in `core.ds.types` for data structure types.
|
||||
|
||||
## Notes
|
||||
|
||||
This unit should not be used as a dependency in new code. It exists purely for VM build-system compatibility and exports no symbols.
|
||||
@@ -0,0 +1,91 @@
|
||||
# core.util
|
||||
|
||||
Portable data manipulation utilities with no architecture-specific dependencies.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.util` provides low-level helpers that operate on raw integers and memory without relying on any x86 assembly. It covers byte and nibble extraction, endian byte-order swapping, flat memory operations (`memset`/`memcpy`), BCD-to-integer conversion, hex character parsing, and a branchless absolute value. These primitives are used throughout the kernel wherever portable, assembly-free data manipulation is required.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### hi
|
||||
```pascal
|
||||
function hi(b : uint8) : uint8;
|
||||
```
|
||||
Returns the high nibble (bits 7–4) of a byte, shifted into the low four bits of the result. Exported with the alias `util_hi`.
|
||||
|
||||
### lo
|
||||
```pascal
|
||||
function lo(b : uint8) : uint8;
|
||||
```
|
||||
Returns the low nibble (bits 3–0) of a byte. Exported with the alias `util_lo`.
|
||||
|
||||
### switchendian
|
||||
```pascal
|
||||
function switchendian(b : uint8) : uint8;
|
||||
```
|
||||
Swaps the two nibbles of a byte (equivalent to a 4-bit rotate). Exported with the alias `util_switchendian`.
|
||||
|
||||
### switchendian16
|
||||
```pascal
|
||||
function switchendian16(b : uint16) : uint16;
|
||||
```
|
||||
Reverses the byte order of a 16-bit value, converting between big-endian and little-endian representations.
|
||||
|
||||
### switchendian32
|
||||
```pascal
|
||||
function switchendian32(b : uint32) : uint32;
|
||||
```
|
||||
Reverses the byte order of a 32-bit value for endian conversion.
|
||||
|
||||
### getWord
|
||||
```pascal
|
||||
function getWord(i : uint32; hi : boolean) : uint16;
|
||||
```
|
||||
Extracts the high or low 16-bit word from a 32-bit value. Returns bits 31–16 when `hi` is `true`; bits 15–0 otherwise.
|
||||
|
||||
### getByte
|
||||
```pascal
|
||||
function getByte(i : uint32; index : uint8) : uint8;
|
||||
```
|
||||
Extracts a single byte from a 32-bit value by zero-based byte index (0 = least significant byte).
|
||||
|
||||
### memset
|
||||
```pascal
|
||||
procedure memset(location : uint32; value : uint8; size : uint32);
|
||||
```
|
||||
Fills `size` bytes starting at address `location` with the byte `value`. Does nothing if `size` is zero.
|
||||
|
||||
### memcpy
|
||||
```pascal
|
||||
procedure memcpy(source : uint32; dest : uint32; size : uint32);
|
||||
```
|
||||
Copies `size` bytes from address `source` to address `dest` byte by byte. Behaviour is undefined if the regions overlap.
|
||||
|
||||
### BCDToUint8
|
||||
```pascal
|
||||
function BCDToUint8(bcd : uint8) : uint8;
|
||||
```
|
||||
Converts a Binary-Coded Decimal byte to its unsigned integer equivalent. The high nibble is the tens digit; the low nibble is the units digit.
|
||||
|
||||
### HexCharToDecimal
|
||||
```pascal
|
||||
function HexCharToDecimal(hex : char) : uint8;
|
||||
```
|
||||
Converts a single hexadecimal character (`0`–`9`, `a`–`f`, `A`–`F`) to its decimal value 0–15. Returns 0 for unrecognised characters.
|
||||
|
||||
### abs
|
||||
```pascal
|
||||
function abs(x : sint32) : uint32;
|
||||
```
|
||||
Returns the absolute value of a signed 32-bit integer using a branchless arithmetic technique based on sign-extension, XOR, and subtraction. The result type is `uint32`.
|
||||
|
||||
## Notes
|
||||
|
||||
`memcpy` is a simple byte loop and does not handle overlapping source and destination regions correctly. Callers must ensure regions do not overlap, or copy in the appropriate direction manually.
|
||||
|
||||
The `hi`, `lo`, and `switchendian` functions carry stable C-compatible export aliases (`util_hi`, `util_lo`, `util_switchendian`) for use from assembly or interop stubs.
|
||||
@@ -0,0 +1,62 @@
|
||||
# core.version
|
||||
|
||||
Auto-generated kernel version and build metadata constants.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.version` is a generated unit updated by the build system on every compilation. It provides string and integer constants describing the current kernel version, build toolchain versions, source statistics, and the build timestamp. Other units reference these constants for display in boot messages, the kernel panic screen, and any context where version identification is required.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
## Constants
|
||||
|
||||
### VERSION
|
||||
Full dotted version string with release label: `'1.1.3-alpha-176-g63b67f58'`.
|
||||
|
||||
### VERSION_MAJOR
|
||||
Major version component string: `'1'`.
|
||||
|
||||
### VERSION_MINOR
|
||||
Minor version component string: `'1'`.
|
||||
|
||||
### VERSION_SUB
|
||||
Sub-version (patch) component string: `'3'`.
|
||||
|
||||
### REVISION
|
||||
Short Git commit hash of HEAD at compile time: `'63b67f58'`.
|
||||
|
||||
### RELEASE
|
||||
Git-describe release tag including commit distance and hash: `'alpha-176-g63b67f58'`.
|
||||
|
||||
### LINE_COUNT
|
||||
Total source lines counted at compile time: `99538`.
|
||||
|
||||
### FILE_COUNT
|
||||
Total source files counted at compile time: `175`.
|
||||
|
||||
### DRIVER_COUNT
|
||||
Number of driver units counted at compile time: `69`.
|
||||
|
||||
### FPC_VERSION
|
||||
Free Pascal Compiler version used to build the kernel: `'3.2.2'`.
|
||||
|
||||
### NASM_VERSION
|
||||
NASM assembler version used to assemble architecture-specific stubs: `'2.16.01'`.
|
||||
|
||||
### MAKE_VERSION
|
||||
GNU Make version used to drive the build: `'4.3'`.
|
||||
|
||||
### COMPILE_DATE
|
||||
Compilation date in MM/DD/YY format: `'08/03/26'`.
|
||||
|
||||
### COMPILE_TIME
|
||||
Compilation time in HH:MM:SS format: `'17:23:28'`.
|
||||
|
||||
### CHECKSUM
|
||||
MD5 checksum of the compiled kernel image computed by the build system: `'c30f33c48e462403420808146b9075e1'`.
|
||||
|
||||
## Notes
|
||||
|
||||
This file is regenerated on every build. Manual edits will be overwritten. The unit has no implementation section.
|
||||
@@ -0,0 +1,59 @@
|
||||
# core.ds.bheap
|
||||
|
||||
Shared binary heap engine for min-heap, max-heap, and priority queue implementations.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.bheap` provides the core binary heap machinery used by `core.ds.minh`, `core.ds.maxh`, and `core.ds.prio`. It stores element data inline in a flat buffer with index-array indirection: a separate `Indices` array maps heap positions to data slot indices, so swaps during sift-up and sift-down exchange only 32-bit indices rather than copying full element data. Freed data slots are recycled via a free-slot stack, avoiding fragmentation. The buffer grows automatically by doubling when capacity is exhausted.
|
||||
|
||||
The heap can operate in either min-heap mode (root holds the lowest priority value) or max-heap mode (root holds the highest priority value), controlled by the `IsMinHeap` field set at creation time.
|
||||
|
||||
This unit is not intended to be used directly. Use the typed wrappers `core.ds.minh`, `core.ds.maxh`, or `core.ds.prio` instead.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.ds.types` — `TBinaryHeap`, `PBinaryHeap`
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.util` — `memcpy`, `memset`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### BHeap_New
|
||||
```pascal
|
||||
function BHeap_New(ElementSize : uint32; InitialCapacity : uint32;
|
||||
MinHeap : boolean) : PBinaryHeap;
|
||||
```
|
||||
Allocates and initialises a new binary heap. `ElementSize` is the size in bytes of each data element (not including the priority field). `InitialCapacity` is the starting number of slots. `MinHeap` selects ordering: `true` for min-heap, `false` for max-heap.
|
||||
|
||||
### BHeap_Insert
|
||||
```pascal
|
||||
procedure BHeap_Insert(Heap : PBinaryHeap; Priority : uint32; Data : void);
|
||||
```
|
||||
Inserts a new element with the given `Priority`. The element data pointed to by `Data` is copied into the heap's internal buffer. Grows the heap automatically if capacity is exhausted.
|
||||
|
||||
### BHeap_ExtractRoot
|
||||
```pascal
|
||||
function BHeap_ExtractRoot(Heap : PBinaryHeap; OutData : void) : boolean;
|
||||
```
|
||||
Removes and copies the root element's data into `OutData`. The root's data slot is returned to the free-slot stack. Returns `true` if an element was extracted; `false` if the heap was empty.
|
||||
|
||||
### BHeap_PeekRoot
|
||||
```pascal
|
||||
function BHeap_PeekRoot(Heap : PBinaryHeap) : void;
|
||||
```
|
||||
Returns a direct pointer to the root element's data without removing it. Returns `nil` if the heap is empty. The pointer is invalidated by any subsequent insertion or extraction.
|
||||
|
||||
### BHeap_Free
|
||||
```pascal
|
||||
procedure BHeap_Free(Heap : PBinaryHeap);
|
||||
```
|
||||
Frees all three internal buffers (`Data`, `Indices`, `FreeSlots`) and the heap structure itself.
|
||||
|
||||
## Notes
|
||||
|
||||
The data slot layout is: `[uint32 priority][ElementSize bytes of element data]`. The `NodeStride` field equals `sizeof(uint32) + ElementSize`.
|
||||
|
||||
Swaps during sift-up and sift-down exchange entries in the `Indices` array only, so the cost of a swap is always O(1) regardless of element size.
|
||||
|
||||
When the heap is full, `BHeap_Grow` doubles all three buffers and copies existing data. This is an O(n) operation.
|
||||
@@ -0,0 +1,65 @@
|
||||
# core.ds.bloom
|
||||
|
||||
Probabilistic set-membership filter using double hashing.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.bloom` implements a Bloom filter — a space-efficient probabilistic data structure for testing whether an element is a member of a set. Insertions and membership tests run in O(k) time where k is the number of hash functions. Double hashing is used to derive k independent bit positions from two base hash functions (FNV-1a 32-bit and DJB2 32-bit), avoiding the need to store or compute k separate functions.
|
||||
|
||||
False positives are possible at a rate determined by the filter size and the number of hash functions. False negatives are not possible: if `Bloom_Test` returns `false`, the element was definitely not inserted.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.ds.types` — `TBloomFilter`, `PBloomFilter`
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.util` — `memset`
|
||||
- `core.enc.fnv1a` — `Hash_FNV1a32`
|
||||
- `core.enc.djb2` — `Hash_DJB2_32`
|
||||
- `io.syslog` — test output
|
||||
- `core.strings` — test output formatting
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### Bloom_New
|
||||
```pascal
|
||||
function Bloom_New(BitCount : uint32; HashCount : uint32) : PBloomFilter;
|
||||
```
|
||||
Creates a new Bloom filter with `BitCount` bits and `HashCount` hash functions per element. The bit buffer is zero-initialised. Returns `nil` on allocation failure.
|
||||
|
||||
A common sizing guideline: `m = -n * ln(p) / (ln(2)^2)` for `n` expected elements and target false-positive rate `p`. Optimal `k = (m/n) * ln(2)`.
|
||||
|
||||
### Bloom_Add
|
||||
```pascal
|
||||
procedure Bloom_Add(Filter : PBloomFilter; Data : void; DataLen : uint32);
|
||||
```
|
||||
Inserts `DataLen` bytes pointed to by `Data` into the filter by setting the k bit positions derived from double hashing. Increments `Filter^.Count`.
|
||||
|
||||
### Bloom_Test
|
||||
```pascal
|
||||
function Bloom_Test(Filter : PBloomFilter; Data : void; DataLen : uint32) : boolean;
|
||||
```
|
||||
Tests whether `Data` (of `DataLen` bytes) was probably inserted. Returns `true` if all k bit positions are set, `false` if any bit is clear (definite non-member).
|
||||
|
||||
### Bloom_Clear
|
||||
```pascal
|
||||
procedure Bloom_Clear(Filter : PBloomFilter);
|
||||
```
|
||||
Resets all bits to zero and sets `Count` to zero without freeing the filter structure or bit buffer.
|
||||
|
||||
### Bloom_Free
|
||||
```pascal
|
||||
procedure Bloom_Free(Filter : PBloomFilter);
|
||||
```
|
||||
Frees the bit buffer and the filter structure. After this call the pointer is invalid.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the Bloom filter test suite and logs a pass/fail summary to syslog under the `'BLOOM'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
The second hash `h2` is forced to be odd (`h2 := h2 or 1`) before use. This guarantees full period coverage of the bit array when stepping by `h2`, because an odd step and a power-of-two (or arbitrary) modulus are coprime.
|
||||
|
||||
`Bloom_Free` does not check for `nil` on the bit buffer pointer; callers should not call it on a partially initialised filter.
|
||||
@@ -0,0 +1,78 @@
|
||||
# core.ds.cfifo
|
||||
|
||||
Array-backed contiguous FIFO queue with lazy compaction and automatic growth.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.cfifo` implements a First-In First-Out queue that stores elements in a flat contiguous buffer rather than a linked list. This avoids per-element heap allocation overhead and improves cache locality. The buffer doubles in size when it becomes full. A lazy compaction strategy is used: instead of shifting elements on every dequeue, the `Head` index is simply advanced. When `Head` passes half the capacity, all remaining elements are shifted back to index 0 in a single compaction pass.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.ds.types` — `TCFIFOQueue`, `PCFIFOQueue`
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.util` — `memcpy`, `memset`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### CFIFO_New
|
||||
```pascal
|
||||
function CFIFO_New(ElementSize : uint32; InitialCapacity : uint32) : PCFIFOQueue;
|
||||
```
|
||||
Creates a new contiguous FIFO queue. `ElementSize` is the size in bytes of each element. `InitialCapacity` is the starting number of element slots; the buffer grows automatically as needed.
|
||||
|
||||
### CFIFO_Enqueue
|
||||
```pascal
|
||||
procedure CFIFO_Enqueue(Queue : PCFIFOQueue; Data : void);
|
||||
```
|
||||
Copies `ElementSize` bytes from `Data` into the back of the queue. Grows the buffer if all slots are consumed. Triggers a compaction pass if there is no room at the tail despite available slots (due to head advancement).
|
||||
|
||||
### CFIFO_Dequeue
|
||||
```pascal
|
||||
function CFIFO_Dequeue(Queue : PCFIFOQueue; Data : void) : boolean;
|
||||
```
|
||||
Copies the front element into `Data` and advances `Head`. Triggers a lazy compaction when `Head` passes half the capacity. Resets `Head` to 0 when the queue becomes empty. Returns `false` if the queue is empty.
|
||||
|
||||
### CFIFO_Peek
|
||||
```pascal
|
||||
function CFIFO_Peek(Queue : PCFIFOQueue) : void;
|
||||
```
|
||||
Returns a direct pointer to the front element without removing it. Returns `nil` if the queue is empty. The pointer is invalidated by any subsequent enqueue or dequeue that triggers compaction or growth.
|
||||
|
||||
### CFIFO_Size
|
||||
```pascal
|
||||
function CFIFO_Size(Queue : PCFIFOQueue) : uint32;
|
||||
```
|
||||
Returns the number of elements currently in the queue.
|
||||
|
||||
### CFIFO_IsEmpty
|
||||
```pascal
|
||||
function CFIFO_IsEmpty(Queue : PCFIFOQueue) : boolean;
|
||||
```
|
||||
Returns `true` if the queue contains no elements.
|
||||
|
||||
### CFIFO_Capacity
|
||||
```pascal
|
||||
function CFIFO_Capacity(Queue : PCFIFOQueue) : uint32;
|
||||
```
|
||||
Returns the current allocated capacity in number of element slots.
|
||||
|
||||
### CFIFO_Free
|
||||
```pascal
|
||||
procedure CFIFO_Free(Queue : PCFIFOQueue);
|
||||
```
|
||||
Frees the element buffer and the queue structure.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the CFIFO test suite and logs a pass/fail summary to syslog under the `'CFIFO'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
Compaction uses `memcpy` to shift elements, which is safe here because the destination is always at a lower address than the source when `Head > 0`.
|
||||
|
||||
The buffer capacity never shrinks automatically. Use `CFIFO_Free` and `CFIFO_New` to reclaim memory after draining a large queue.
|
||||
@@ -0,0 +1,79 @@
|
||||
# core.ds.cfifols
|
||||
|
||||
Dynamic list of contiguous FIFO queue pointers.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.cfifols` implements a growable ordered list of `PCFIFOQueue` pointers. It is used to group and manage a variable number of related contiguous FIFO queues under a single handle. The list stores only pointer references; the referenced queues are owned and managed by the caller unless `CFIFOLS_FreeAll` is used.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.ds.types` — `TCFIFOList`, `PCFIFOList`
|
||||
- `core.ds.cfifo` — `CFIFO_Free` (used by `CFIFOLS_FreeAll`)
|
||||
- `core.util` — `memcpy`, `memset`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### CFIFOLS_New
|
||||
```pascal
|
||||
function CFIFOLS_New(InitialCapacity : uint32) : PCFIFOList;
|
||||
```
|
||||
Creates a new contiguous FIFO list with `InitialCapacity` pointer slots. The slot buffer grows automatically when the capacity is exceeded.
|
||||
|
||||
### CFIFOLS_Add
|
||||
```pascal
|
||||
procedure CFIFOLS_Add(List : PCFIFOList; Queue : PCFIFOQueue);
|
||||
```
|
||||
Appends the queue pointer `Queue` to the end of the list. Grows the slot buffer by doubling if capacity is exhausted.
|
||||
|
||||
### CFIFOLS_Get
|
||||
```pascal
|
||||
function CFIFOLS_Get(List : PCFIFOList; Index : uint32) : PCFIFOQueue;
|
||||
```
|
||||
Returns the queue pointer at zero-based `Index`. Returns `nil` if `Index` is out of range.
|
||||
|
||||
### CFIFOLS_Remove
|
||||
```pascal
|
||||
function CFIFOLS_Remove(List : PCFIFOList; Index : uint32) : boolean;
|
||||
```
|
||||
Removes the pointer at `Index` by shifting subsequent entries left. The referenced queue is not freed; ownership is retained by the caller. Returns `false` if `Index` is out of range.
|
||||
|
||||
### CFIFOLS_Count
|
||||
```pascal
|
||||
function CFIFOLS_Count(List : PCFIFOList) : uint32;
|
||||
```
|
||||
Returns the number of queue pointers currently in the list.
|
||||
|
||||
### CFIFOLS_IsEmpty
|
||||
```pascal
|
||||
function CFIFOLS_IsEmpty(List : PCFIFOList) : boolean;
|
||||
```
|
||||
Returns `true` if the list holds no pointers.
|
||||
|
||||
### CFIFOLS_Free
|
||||
```pascal
|
||||
procedure CFIFOLS_Free(List : PCFIFOList);
|
||||
```
|
||||
Frees the pointer slot buffer and the list structure. Does not free the referenced queues.
|
||||
|
||||
### CFIFOLS_FreeAll
|
||||
```pascal
|
||||
procedure CFIFOLS_FreeAll(List : PCFIFOList);
|
||||
```
|
||||
Calls `CFIFO_Free` on every queue in the list, then frees the slot buffer and the list structure.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the CFIFOLS test suite and logs a pass/fail summary to syslog under the `'CFIFOLS'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
`CFIFOLS_Remove` shifts remaining entries using `memcpy`, which is safe because the destination is always at a lower address than the source.
|
||||
|
||||
The list does not track queue ownership; callers must decide whether to use `CFIFOLS_Free` (preserving queues) or `CFIFOLS_FreeAll` (destroying queues).
|
||||
@@ -0,0 +1,78 @@
|
||||
# core.ds.circ
|
||||
|
||||
Fixed-capacity ring-buffer queue.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.circ` implements a circular (ring-buffer) FIFO queue with a fixed maximum capacity set at creation time. Elements are stored in a flat pre-allocated buffer. Head and tail indices advance with modulo arithmetic to wrap around the buffer, eliminating the need for compaction or shifting. Enqueue is rejected when the buffer is full.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.ds.types` — `TCircularQueue`, `PCircularQueue`
|
||||
- `core.util` — `memcpy`, `memset`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### circ_New
|
||||
```pascal
|
||||
function circ_New(Capacity : uint32; ElementSize : uint32) : PCircularQueue;
|
||||
```
|
||||
Creates a new circular queue with exactly `Capacity` element slots. `ElementSize` is the size in bytes of each element. The buffer is zero-initialised.
|
||||
|
||||
### circ_Enqueue
|
||||
```pascal
|
||||
function circ_Enqueue(Queue : PCircularQueue; Data : void) : boolean;
|
||||
```
|
||||
Copies `ElementSize` bytes from `Data` into the next free slot and advances the tail index. Returns `false` if the queue is full and the element is rejected.
|
||||
|
||||
### circ_Dequeue
|
||||
```pascal
|
||||
function circ_Dequeue(Queue : PCircularQueue; Data : void) : boolean;
|
||||
```
|
||||
Copies the front element into `Data` and advances the head index. Returns `false` if the queue is empty.
|
||||
|
||||
### circ_Peek
|
||||
```pascal
|
||||
function circ_Peek(Queue : PCircularQueue) : void;
|
||||
```
|
||||
Returns a direct pointer to the front element without removing it. Returns `nil` if the queue is empty.
|
||||
|
||||
### circ_Size
|
||||
```pascal
|
||||
function circ_Size(Queue : PCircularQueue) : uint32;
|
||||
```
|
||||
Returns the number of elements currently in the queue.
|
||||
|
||||
### circ_IsFull
|
||||
```pascal
|
||||
function circ_IsFull(Queue : PCircularQueue) : boolean;
|
||||
```
|
||||
Returns `true` if the queue has reached its maximum capacity.
|
||||
|
||||
### circ_IsEmpty
|
||||
```pascal
|
||||
function circ_IsEmpty(Queue : PCircularQueue) : boolean;
|
||||
```
|
||||
Returns `true` if the queue contains no elements.
|
||||
|
||||
### circ_Free
|
||||
```pascal
|
||||
procedure circ_Free(Queue : PCircularQueue);
|
||||
```
|
||||
Frees the element buffer and the queue structure.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the circular queue test suite and logs a pass/fail summary to syslog under the `'CIRC'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
The capacity is fixed at creation. Unlike `core.ds.cfifo`, the circular queue never grows. Callers must choose a capacity sufficient for their maximum concurrent element count.
|
||||
|
||||
The pointer returned by `circ_Peek` is invalidated by any subsequent enqueue or dequeue that moves the head index.
|
||||
@@ -0,0 +1,70 @@
|
||||
# core.ds.fifo
|
||||
|
||||
Linked-list backed First-In First-Out queue.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.fifo` implements a FIFO queue using a singly-linked list of heap-allocated nodes. Each enqueued element is copied into a new node; each dequeue copies the data out and frees the node. The linked-list design allows unbounded growth with no compaction or shifting, at the cost of one heap allocation per element. For use cases requiring better cache locality and lower allocation overhead, see `core.ds.cfifo`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.util` — `memcpy`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
- `core.ds.types` — `TFIFOQueue`, `PFIFOQueue`, `TQueueNode`, `PQueueNode`
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### FIFO_New
|
||||
```pascal
|
||||
function FIFO_New(ElementSize : uint32) : PFIFOQueue;
|
||||
```
|
||||
Creates and returns a new empty FIFO queue. `ElementSize` is the size in bytes of each element.
|
||||
|
||||
### FIFO_Enqueue
|
||||
```pascal
|
||||
procedure FIFO_Enqueue(Queue : PFIFOQueue; Data : void);
|
||||
```
|
||||
Allocates a new node, copies `ElementSize` bytes from `Data` into it, and appends it to the tail of the queue.
|
||||
|
||||
### FIFO_Dequeue
|
||||
```pascal
|
||||
function FIFO_Dequeue(Queue : PFIFOQueue; Data : void) : boolean;
|
||||
```
|
||||
Copies the front element's data into `Data`, removes the head node, and frees it. Returns `false` if the queue is empty.
|
||||
|
||||
### FIFO_Peek
|
||||
```pascal
|
||||
function FIFO_Peek(Queue : PFIFOQueue) : void;
|
||||
```
|
||||
Returns a direct pointer to the front element's data without removing the node. Returns `nil` if the queue is empty. The pointer is invalidated if the head node is dequeued.
|
||||
|
||||
### FIFO_Size
|
||||
```pascal
|
||||
function FIFO_Size(Queue : PFIFOQueue) : uint32;
|
||||
```
|
||||
Returns the number of elements currently in the queue.
|
||||
|
||||
### FIFO_IsEmpty
|
||||
```pascal
|
||||
function FIFO_IsEmpty(Queue : PFIFOQueue) : boolean;
|
||||
```
|
||||
Returns `true` if the queue contains no elements.
|
||||
|
||||
### FIFO_Free
|
||||
```pascal
|
||||
procedure FIFO_Free(Queue : PFIFOQueue);
|
||||
```
|
||||
Frees all nodes and their data buffers, then frees the queue structure.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the FIFO queue test suite and logs a pass/fail summary to syslog under the `'FIFO'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
Each enqueue causes two heap allocations (node structure and element data buffer). For high-frequency queuing, prefer `core.ds.cfifo` which batches allocations into a single growing buffer.
|
||||
@@ -0,0 +1,109 @@
|
||||
# core.ds.hashmap
|
||||
|
||||
String-keyed hash map with chained collision resolution and automatic rehashing.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.hashmap` provides a general-purpose hash map that maps null-terminated string keys to opaque `void` pointers. Collisions are resolved by chaining (linked lists per bucket). When the load factor threshold is exceeded, the table doubles in size and all existing entries are re-distributed. Key strings are heap-copied on insertion so callers do not need to keep the original key alive.
|
||||
|
||||
The hash function used is FNV-1a 32-bit, replacing an earlier MD5-based scheme.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.enc.fnv1a` — `Hash_FNV1a32`
|
||||
- `core.strings` — `stringEquals`, `stringCopy`, `stringSize`
|
||||
- `io.syslog` — `printMap` debug output
|
||||
- `debug.tracer` — call-stack tracing
|
||||
- `core.util` — `memcpy`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
|
||||
## Constants
|
||||
|
||||
### HASHMAP_DEFAULT_SIZE
|
||||
Default initial bucket count: `16`.
|
||||
|
||||
### HASHMAP_DEFAULT_LOADFACTOR
|
||||
Default load factor threshold for rehashing: `0.75`.
|
||||
|
||||
## Types
|
||||
|
||||
### THashItem / PHashItem / DPHashItem
|
||||
```pascal
|
||||
THashItem = record
|
||||
Next : PHashItem;
|
||||
Key : pchar;
|
||||
Hash : uint32;
|
||||
Data : void;
|
||||
end;
|
||||
```
|
||||
A single hash map entry. `Next` links to the next entry in the same bucket (collision chain). `Key` is a heap-allocated copy of the key string. `Hash` caches the computed key hash. `Data` is the caller-supplied value pointer.
|
||||
|
||||
### THashMap / PHashMap
|
||||
```pascal
|
||||
THashMap = record
|
||||
Size : uint32;
|
||||
LoadFactor : Single;
|
||||
Count : uint32;
|
||||
Table : DPHashItem;
|
||||
end;
|
||||
```
|
||||
The map header. `Size` is the current bucket count. `Table` is the bucket array (an array of `PHashItem` pointers). `Count` tracks the total number of entries across all buckets.
|
||||
|
||||
### THashForEachCb
|
||||
```pascal
|
||||
THashForEachCb = procedure(key: pchar; data: void; ud: void);
|
||||
```
|
||||
Callback type for the `forEach` iterator. `key` is the entry's key string, `data` is the stored value, and `ud` is the caller-supplied user data pointer passed to `forEach`.
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### new
|
||||
```pascal
|
||||
function new : PHashMap;
|
||||
```
|
||||
Creates a new hash map with `HASHMAP_DEFAULT_SIZE` buckets and `HASHMAP_DEFAULT_LOADFACTOR`.
|
||||
|
||||
### newEx
|
||||
```pascal
|
||||
function newEx(size : uint32; loadFactor : Single) : PHashMap;
|
||||
```
|
||||
Creates a new hash map with the specified initial bucket count and load factor.
|
||||
|
||||
### add
|
||||
```pascal
|
||||
procedure add(map : PHashMap; key : pchar; value : void);
|
||||
```
|
||||
Inserts or updates an entry for `key` with value `value`. If the key already exists, its value is replaced. The key string is heap-copied. Triggers a rehash if the load factor is exceeded after insertion.
|
||||
|
||||
### get
|
||||
```pascal
|
||||
function get(map : PHashMap; key : pchar) : void;
|
||||
```
|
||||
Returns the value associated with `key`, or `nil` if not found.
|
||||
|
||||
### delete
|
||||
```pascal
|
||||
procedure delete(map : PHashMap; key : pchar; freeItem : boolean);
|
||||
```
|
||||
Removes the entry for `key`. The key string's heap copy is always freed. If `freeItem` is `true`, the stored `Data` pointer is also freed with `kfree`.
|
||||
|
||||
### forEach
|
||||
```pascal
|
||||
procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
||||
```
|
||||
Iterates over all entries in the map (in unspecified bucket order) and calls `cb` for each one. `ud` is passed through to the callback unchanged.
|
||||
|
||||
### printMap
|
||||
```pascal
|
||||
procedure printMap(map : PHashMap);
|
||||
```
|
||||
Writes a debug representation of all buckets and their collision chains to syslog. Intended for development use only.
|
||||
|
||||
## Notes
|
||||
|
||||
The `add` procedure increments `Count` on every call, including for key updates (overwrites). This means `Count` may overcount if the same key is added multiple times. Callers should use `get` to check for an existing key before calling `add` if accurate counting matters.
|
||||
|
||||
Rehashing allocates a new bucket array and re-inserts all existing items without copying their key or data — only the item pointers are moved. The old bucket array is freed.
|
||||
|
||||
There is no `free` procedure exported for the map. Callers managing map lifetime should iterate with `forEach` to free values, then call `kfree` on the table and the map structure directly, or arrange for the heap to be torn down wholesale.
|
||||
@@ -0,0 +1,70 @@
|
||||
# core.ds.lifo
|
||||
|
||||
Linked-list backed Last-In First-Out stack.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.lifo` implements a LIFO stack using a singly-linked list of heap-allocated nodes. Each pushed element is copied into a new node prepended to the head of the list. Each pop copies the data out and frees the top node. The linked-list design allows unbounded growth with no pre-allocation, at the cost of one heap allocation per element.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.util` — `memcpy`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
- `core.ds.types` — `TLIFOStack`, `PLIFOStack`, `TQueueNode`, `PQueueNode`
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### lifo_New
|
||||
```pascal
|
||||
function lifo_New(ElementSize : uint32) : PLIFOStack;
|
||||
```
|
||||
Creates and returns a new empty LIFO stack. `ElementSize` is the size in bytes of each element.
|
||||
|
||||
### lifo_Push
|
||||
```pascal
|
||||
procedure lifo_Push(Stack : PLIFOStack; Data : void);
|
||||
```
|
||||
Allocates a new node, copies `ElementSize` bytes from `Data` into it, and prepends the node to the top of the stack.
|
||||
|
||||
### lifo_Pop
|
||||
```pascal
|
||||
function lifo_Pop(Stack : PLIFOStack; Data : void) : boolean;
|
||||
```
|
||||
Copies the top element's data into `Data`, removes the top node, and frees it. Returns `false` if the stack is empty.
|
||||
|
||||
### lifo_Peek
|
||||
```pascal
|
||||
function lifo_Peek(Stack : PLIFOStack) : void;
|
||||
```
|
||||
Returns a direct pointer to the top element's data without removing the node. Returns `nil` if the stack is empty. The pointer is invalidated if the top node is popped.
|
||||
|
||||
### lifo_Size
|
||||
```pascal
|
||||
function lifo_Size(Stack : PLIFOStack) : uint32;
|
||||
```
|
||||
Returns the number of elements currently on the stack.
|
||||
|
||||
### lifo_IsEmpty
|
||||
```pascal
|
||||
function lifo_IsEmpty(Stack : PLIFOStack) : boolean;
|
||||
```
|
||||
Returns `true` if the stack contains no elements.
|
||||
|
||||
### lifo_Free
|
||||
```pascal
|
||||
procedure lifo_Free(Stack : PLIFOStack);
|
||||
```
|
||||
Pops and frees all nodes and their data buffers, then frees the stack structure.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the LIFO stack test suite and logs a pass/fail summary to syslog under the `'LIFO'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
Each push causes two heap allocations (node structure and element data buffer). The stack does not expose an array-backed variant; if cache efficiency matters, consider using `core.ds.cfifo` reversed or a custom stack on a pre-allocated buffer.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,67 @@
|
||||
# core.ds.maxh
|
||||
|
||||
Max-heap: extracts the element with the highest priority value first.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.maxh` is a thin typed wrapper over `core.ds.bheap` that creates a max-heap. In a max-heap, `maxh_ExtractMax` always yields the element whose `Priority` value is the largest among all inserted elements. This is suitable for applications such as scheduling where the most urgent (highest-valued) item should be processed first.
|
||||
|
||||
All heap mechanics (index-array indirection, free-slot recycling, automatic growth) are handled by the underlying `core.ds.bheap` engine.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.ds.types` — `TBinaryHeap`, `PBinaryHeap`
|
||||
- `core.ds.bheap` — heap engine
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
- `memory.heap` — `kfree` (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### maxh_New
|
||||
```pascal
|
||||
function maxh_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap;
|
||||
```
|
||||
Creates a new max-heap. `ElementSize` is the size in bytes of each data element. `InitialCapacity` is the starting number of slots (grows automatically).
|
||||
|
||||
### maxh_Insert
|
||||
```pascal
|
||||
procedure maxh_Insert(Heap : PBinaryHeap; Priority : uint32; Data : void);
|
||||
```
|
||||
Inserts an element with the given priority. Higher priority values are extracted first.
|
||||
|
||||
### maxh_ExtractMax
|
||||
```pascal
|
||||
function maxh_ExtractMax(Heap : PBinaryHeap; Data : void) : boolean;
|
||||
```
|
||||
Removes and copies the element with the highest priority into `Data`. Returns `false` if the heap is empty.
|
||||
|
||||
### maxh_PeekMax
|
||||
```pascal
|
||||
function maxh_PeekMax(Heap : PBinaryHeap) : void;
|
||||
```
|
||||
Returns a direct pointer to the highest-priority element's data without removing it. Returns `nil` if the heap is empty.
|
||||
|
||||
### maxh_Size
|
||||
```pascal
|
||||
function maxh_Size(Heap : PBinaryHeap) : uint32;
|
||||
```
|
||||
Returns the number of elements in the heap.
|
||||
|
||||
### maxh_IsEmpty
|
||||
```pascal
|
||||
function maxh_IsEmpty(Heap : PBinaryHeap) : boolean;
|
||||
```
|
||||
Returns `true` if the heap contains no elements.
|
||||
|
||||
### maxh_Free
|
||||
```pascal
|
||||
procedure maxh_Free(Heap : PBinaryHeap);
|
||||
```
|
||||
Frees the heap and all its internal buffers.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the max-heap test suite (inserts 5 elements out of order, verifies extraction in descending order) and logs a pass/fail summary to syslog under the `'MAXH'` channel.
|
||||
@@ -0,0 +1,67 @@
|
||||
# core.ds.minh
|
||||
|
||||
Min-heap: extracts the element with the lowest priority value first.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.minh` is a thin typed wrapper over `core.ds.bheap` that creates a min-heap. In a min-heap, `minh_ExtractMin` always yields the element whose `Priority` value is the smallest among all inserted elements. This is suitable for applications such as Dijkstra's algorithm or any scenario where the least-costly item should be processed first.
|
||||
|
||||
All heap mechanics (index-array indirection, free-slot recycling, automatic growth) are handled by the underlying `core.ds.bheap` engine.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.ds.types` — `TBinaryHeap`, `PBinaryHeap`
|
||||
- `core.ds.bheap` — heap engine
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
- `memory.heap` — `kfree` (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### minh_New
|
||||
```pascal
|
||||
function minh_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap;
|
||||
```
|
||||
Creates a new min-heap. `ElementSize` is the size in bytes of each data element. `InitialCapacity` is the starting number of slots (grows automatically).
|
||||
|
||||
### minh_Insert
|
||||
```pascal
|
||||
procedure minh_Insert(Heap : PBinaryHeap; Priority : uint32; Data : void);
|
||||
```
|
||||
Inserts an element with the given priority. Lower priority values are extracted first.
|
||||
|
||||
### minh_ExtractMin
|
||||
```pascal
|
||||
function minh_ExtractMin(Heap : PBinaryHeap; Data : void) : boolean;
|
||||
```
|
||||
Removes and copies the element with the lowest priority into `Data`. Returns `false` if the heap is empty.
|
||||
|
||||
### minh_PeekMin
|
||||
```pascal
|
||||
function minh_PeekMin(Heap : PBinaryHeap) : void;
|
||||
```
|
||||
Returns a direct pointer to the lowest-priority element's data without removing it. Returns `nil` if the heap is empty.
|
||||
|
||||
### minh_Size
|
||||
```pascal
|
||||
function minh_Size(Heap : PBinaryHeap) : uint32;
|
||||
```
|
||||
Returns the number of elements in the heap.
|
||||
|
||||
### minh_IsEmpty
|
||||
```pascal
|
||||
function minh_IsEmpty(Heap : PBinaryHeap) : boolean;
|
||||
```
|
||||
Returns `true` if the heap contains no elements.
|
||||
|
||||
### minh_Free
|
||||
```pascal
|
||||
procedure minh_Free(Heap : PBinaryHeap);
|
||||
```
|
||||
Frees the heap and all its internal buffers.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the min-heap test suite (basic operations plus a stress test of 50 elements inserted in reverse order and extracted in ascending order) and logs a pass/fail summary to syslog under the `'MINH'` channel.
|
||||
@@ -0,0 +1,71 @@
|
||||
# core.ds.prio
|
||||
|
||||
Min-heap ordered priority queue (lowest priority value dequeued first).
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.prio` is a thin typed wrapper over `core.ds.bheap` that presents a priority queue interface. Elements are dequeued in ascending priority order: the element with the lowest `Priority` value is always at the front. This convention (low number = high urgency) is used by the Asuro process scheduler and other subsystems that assign numeric priorities to tasks.
|
||||
|
||||
All heap mechanics are handled by the underlying `core.ds.bheap` engine.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `core.ds.bheap` — heap engine
|
||||
- `core.ds.types` — `TBinaryHeap`, `PBinaryHeap`
|
||||
- `io.syslog` — test output (implementation only)
|
||||
- `core.strings` — test output formatting (implementation only)
|
||||
- `memory.heap` — `kfree` (implementation only)
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### prio_New
|
||||
```pascal
|
||||
function prio_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap;
|
||||
```
|
||||
Creates a new priority queue. `ElementSize` is the size in bytes of each data element. `InitialCapacity` is the starting number of slots (grows automatically).
|
||||
|
||||
### prio_Enqueue
|
||||
```pascal
|
||||
procedure prio_Enqueue(Heap : PBinaryHeap; Priority : uint32; Data : void);
|
||||
```
|
||||
Enqueues an element with the given `Priority`. Elements with lower priority values will be dequeued before those with higher values.
|
||||
|
||||
### prio_Dequeue
|
||||
```pascal
|
||||
function prio_Dequeue(Heap : PBinaryHeap; Data : void) : boolean;
|
||||
```
|
||||
Removes and copies the highest-priority (lowest-valued) element into `Data`. Returns `false` if the queue is empty.
|
||||
|
||||
### prio_Peek
|
||||
```pascal
|
||||
function prio_Peek(Heap : PBinaryHeap) : void;
|
||||
```
|
||||
Returns a direct pointer to the highest-priority element's data without removing it. Returns `nil` if the queue is empty.
|
||||
|
||||
### prio_Size
|
||||
```pascal
|
||||
function prio_Size(Heap : PBinaryHeap) : uint32;
|
||||
```
|
||||
Returns the number of elements in the priority queue.
|
||||
|
||||
### prio_IsEmpty
|
||||
```pascal
|
||||
function prio_IsEmpty(Heap : PBinaryHeap) : boolean;
|
||||
```
|
||||
Returns `true` if the queue contains no elements.
|
||||
|
||||
### prio_Free
|
||||
```pascal
|
||||
procedure prio_Free(Heap : PBinaryHeap);
|
||||
```
|
||||
Frees the priority queue and all its internal buffers.
|
||||
|
||||
### UnitTest
|
||||
```pascal
|
||||
procedure UnitTest;
|
||||
```
|
||||
Runs the priority queue test suite (enqueues elements with priorities 1–5 in shuffled order, verifies dequeue in priority order) and logs a pass/fail summary to syslog under the `'PRIO'` channel.
|
||||
|
||||
## Notes
|
||||
|
||||
The priority convention is inverted from common intuition: a `Priority` value of `1` is dequeued before `5`. This matches the convention used by process schedulers where priority 0 or 1 represents the most urgent task.
|
||||
@@ -0,0 +1,106 @@
|
||||
# core.ds.types
|
||||
|
||||
Shared type definitions for all kernel data structures.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.ds.types` is a types-only unit that declares the record and pointer types used by the data structure units in the `core.ds` namespace. Centralising these definitions allows different data structure units to share types without circular dependencies. No functions or variables are defined here.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
## Types
|
||||
|
||||
### TQueueNode / PQueueNode
|
||||
```pascal
|
||||
TQueueNode = record
|
||||
Next : PQueueNode;
|
||||
Data : void;
|
||||
end;
|
||||
```
|
||||
Singly-linked node used by the linked-list FIFO (`core.ds.fifo`) and LIFO (`core.ds.lifo`) implementations. `Data` points to a heap-allocated copy of the stored element.
|
||||
|
||||
### TFIFOQueue / PFIFOQueue
|
||||
```pascal
|
||||
TFIFOQueue = record
|
||||
Head : PQueueNode;
|
||||
Tail : PQueueNode;
|
||||
Count : uint32;
|
||||
ElementSize : uint32;
|
||||
end;
|
||||
```
|
||||
First-In First-Out queue backed by a singly-linked list. `Head` is the dequeue end; `Tail` is the enqueue end.
|
||||
|
||||
### TCFIFOQueue / PCFIFOQueue
|
||||
```pascal
|
||||
TCFIFOQueue = record
|
||||
Data : void;
|
||||
Head : uint32;
|
||||
Count : uint32;
|
||||
Capacity : uint32;
|
||||
ElementSize : uint32;
|
||||
end;
|
||||
```
|
||||
Array-backed contiguous FIFO queue with lazy compaction and automatic growth. Elements are stored contiguously starting at `Data + (Head * ElementSize)`. When `Head` advances past half the capacity, elements are shifted back to index 0. The buffer doubles when full.
|
||||
|
||||
### TCFIFOList / PCFIFOList
|
||||
```pascal
|
||||
TCFIFOList = record
|
||||
Items : void;
|
||||
Count : uint32;
|
||||
Capacity : uint32;
|
||||
end;
|
||||
```
|
||||
Dynamic array of `PCFIFOQueue` pointers. Used to group related contiguous FIFO queues. `Items` is a flat buffer of pointer slots that grows automatically.
|
||||
|
||||
### TLIFOStack / PLIFOStack
|
||||
```pascal
|
||||
TLIFOStack = record
|
||||
Top : PQueueNode;
|
||||
Count : uint32;
|
||||
ElementSize : uint32;
|
||||
end;
|
||||
```
|
||||
Last-In First-Out stack backed by a singly-linked list. `Top` points to the most recently pushed node.
|
||||
|
||||
### TCircularQueue / PCircularQueue
|
||||
```pascal
|
||||
TCircularQueue = record
|
||||
Data : void;
|
||||
Head : uint32;
|
||||
Tail : uint32;
|
||||
Count : uint32;
|
||||
Capacity : uint32;
|
||||
ElementSize : uint32;
|
||||
end;
|
||||
```
|
||||
Fixed-capacity ring-buffer queue. `Head` is the index of the front element; `Tail` is the index of the next free slot. Wrap-around is handled with modulo arithmetic.
|
||||
|
||||
### TBinaryHeap / PBinaryHeap
|
||||
```pascal
|
||||
TBinaryHeap = record
|
||||
Data : void;
|
||||
Indices : void;
|
||||
FreeSlots : void;
|
||||
Count : uint32;
|
||||
Capacity : uint32;
|
||||
NextSlot : uint32;
|
||||
FreeCount : uint32;
|
||||
ElementSize : uint32;
|
||||
NodeStride : uint32;
|
||||
IsMinHeap : boolean;
|
||||
end;
|
||||
```
|
||||
Array-backed binary heap with index-array indirection. Element data is stored inline in `Data` as `[Priority (uint32)][Element (ElementSize bytes)]` per slot. `Indices` maps heap positions to data slot indices, allowing O(1) swaps by exchanging indices rather than copying data. Freed data slots are recycled through `FreeSlots`/`FreeCount`. `IsMinHeap` controls whether the root holds the minimum (`true`) or maximum (`false`) priority.
|
||||
|
||||
### TBloomFilter / PBloomFilter
|
||||
```pascal
|
||||
TBloomFilter = record
|
||||
Bits : void;
|
||||
BitCount : uint32;
|
||||
HashCount : uint32;
|
||||
Count : uint32;
|
||||
end;
|
||||
```
|
||||
Probabilistic set-membership filter. `Bits` is a flat byte buffer of `ceil(BitCount / 8)` bytes. Membership tests use `k = HashCount` independent bit positions derived from two base hashes (FNV-1a + DJB2) via double hashing: `h_i(x) = (h1(x) + i * h2(x)) mod BitCount`. False positives are possible; false negatives are not.
|
||||
@@ -0,0 +1,56 @@
|
||||
# core.enc.base64
|
||||
|
||||
Base64 encoding and decoding.
|
||||
|
||||
## Overview
|
||||
|
||||
`core.enc.base64` implements RFC 4648 Base64 encoding and decoding for the kernel. It operates on raw byte buffers or null-terminated strings and returns heap-allocated results. The encoder inserts a newline character every 72 output characters and appends `=` padding to complete the final group. The decoder ignores whitespace and newlines in the input.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `memory.heap` — `kalloc`, `kfree`
|
||||
- `core.strings` — `stringSize`
|
||||
- `debug.tracer` — call-stack tracing
|
||||
- `core.util` — `memset`
|
||||
- `arch.x86.util` — architecture utilities
|
||||
|
||||
## Constants
|
||||
|
||||
### base64_enc_map
|
||||
A 64-element character array containing the standard Base64 alphabet (`A`–`Z`, `a`–`z`, `0`–`9`, `+`, `/`). Used by the encoder to map 6-bit values to output characters.
|
||||
|
||||
## Functions and Procedures
|
||||
|
||||
### b64_encode
|
||||
```pascal
|
||||
function b64_encode(src : PuInt8; len : uInt32; out_len : PuInt32) : PuInt8;
|
||||
```
|
||||
Encodes `len` bytes from `src` into a heap-allocated Base64 string. If `out_len` is not `nil`, the output length (including the trailing null byte) is written there. Returns `nil` if the output length calculation overflows.
|
||||
|
||||
### b64_decode
|
||||
```pascal
|
||||
function b64_decode(src : PuInt8; len : uInt32; out_len : PuInt32) : PuInt8;
|
||||
```
|
||||
Decodes `len` bytes of Base64 data from `src` into a heap-allocated raw byte buffer. If `out_len` is not `nil`, the decoded byte count is written there. Returns `nil` if the input is invalid or allocation fails.
|
||||
|
||||
### b64_encode_str
|
||||
```pascal
|
||||
function b64_encode_str(src : PChar) : PChar;
|
||||
```
|
||||
Convenience wrapper: encodes the null-terminated string `src` and returns a heap-allocated Base64 string. Pushes tracer entries on entry and return.
|
||||
|
||||
### b64_decode_str
|
||||
```pascal
|
||||
function b64_decode_str(src : PChar) : PChar;
|
||||
```
|
||||
Convenience wrapper: decodes the null-terminated Base64 string `src` and returns a heap-allocated decoded string. Pushes tracer entries on entry and return.
|
||||
|
||||
## Notes
|
||||
|
||||
The encoder output includes newlines after every 72 characters. Consumers that do not expect line breaks should strip them or use `b64_encode` directly and handle the output buffer themselves.
|
||||
|
||||
The decoder builds a 256-entry decode table on the stack at each call. Unknown characters are mapped to `$80` (the sentinel for "skip"). Padding characters (`=`) are mapped to `0` and their count is tracked to trim the output length.
|
||||
|
||||
If the input to `b64_decode` is not a multiple of 4 valid Base64 characters, the function currently enters an unhandled branch (silent error). Callers should validate input length before decoding.
|
||||
|
||||
Both `b64_encode` and `b64_decode` return heap-allocated buffers that must be freed by the caller with `kfree`.
|
||||
Loaded 20 of 209 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user