ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
epub_miniz_alloc.c File Reference

First-fit allocator over one caller-owned miniz workspace. More...

#include "epub_miniz_alloc.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
Include dependency graph for epub_miniz_alloc.c:

Go to the source code of this file.

Data Structures

struct  priv_blk_t
 Header prefixing every arena block. More...

Enumerations

enum  priv_alloc_const_t : size_t {
  k_priv_hdr_bytes ,
  k_priv_align = alignof(max_align_t) ,
  k_priv_walk_max ,
  k_priv_blk_free = 1U ,
  k_priv_blk_used = 0U
}
 Private allocator geometry and sentinel values. More...

Functions

static uintptr_t internal_pointer_address (const void *pointer)
 Copy a pointer representation into an integer address.
static bool internal_ready (const epub_miniz_arena_t *arena)
 Validate an arena descriptor before using caller-owned storage.
static priv_blk_tinternal_cell_at (const epub_miniz_arena_t *arena, size_t off)
 Cast byte offset off to an aligned block header.
static uint8_t * internal_end (const epub_miniz_arena_t *arena)
 Return the arena's one-past byte sentinel.
static uint8_t * internal_payload (priv_blk_t *block)
 Return the payload immediately following block.
static priv_blk_tinternal_header (const epub_miniz_arena_t *arena, void *address)
 Return the header for an allocation payload.
static priv_blk_tinternal_next (const epub_miniz_arena_t *arena, priv_blk_t *block)
 Return the block immediately following block.
static bool internal_in_pool (const epub_miniz_arena_t *arena, const void *address)
 Test whether an address lies in the payload-bearing arena range.
static size_t internal_align_up (size_t bytes)
 Align a pool-bounded request upward to a complete arena cell.
static bool internal_request_bytes (size_t items, size_t size, size_t *out_bytes)
 Validate and multiply a miniz count/size request exactly once.
static void internal_split (const epub_miniz_arena_t *arena, priv_blk_t *block, size_t need)
 Split a block if its remainder can hold another allocation.
static void internal_coalesce (const epub_miniz_arena_t *arena)
 Merge all adjacent free blocks in an arena.
ra8_err_t epub_miniz_arena_init (epub_miniz_arena_t *arena, void *workspace, size_t workspace_bytes)
 Initialise or reset a miniz arena over caller-owned storage.
void epub_miniz_arena_deinit (epub_miniz_arena_t *arena)
 Invalidate an arena descriptor after miniz has released its blocks.
void * epub_miniz_alloc (void *opaque, size_t items, size_t size)
 miniz-compatible allocator (mz_alloc_func).
void epub_miniz_free (void *opaque, void *address)
 miniz-compatible free (mz_free_func).
void * epub_miniz_realloc (void *opaque, void *address, size_t items, size_t size)
 miniz-compatible realloc (mz_realloc_func).

Detailed Description

First-fit allocator over one caller-owned miniz workspace.

Each EPUB or CBZ object embeds its own aligned workspace and arena descriptor. Miniz receives that descriptor through m_pAlloc_opaque. Blocks form an implicit list with in-band headers; allocation is first-fit, free coalesces adjacent blocks, and realloc preserves the original block when a grow cannot be satisfied. No global arena and no host heap fallback exist.

Definition in file epub_miniz_alloc.c.

Enumeration Type Documentation

◆ priv_alloc_const_t

enum priv_alloc_const_t : size_t

Private allocator geometry and sentinel values.

Enumerator
k_priv_hdr_bytes 

Aligned in-band header bytes.

k_priv_align 

Maximum-alignment cell size.

k_priv_walk_max 

Block-walk guard.

k_priv_blk_free 

Free-block marker.

k_priv_blk_used 

Live-block marker.

Definition at line 30 of file epub_miniz_alloc.c.

Function Documentation

◆ epub_miniz_alloc()

void * epub_miniz_alloc ( void * opaque,
size_t items,
size_t size )

miniz-compatible allocator (mz_alloc_func).

Returns a block of at least items * size bytes from opaque's arena, aligned to max_align_t. First-fit over the free list; splits an oversized free block when the remainder can hold a header plus a minimum payload. Returns NULL on overflow of items * size or pool exhaustion.

Parameters
[in]opaquePointer to an initialised epub_miniz_arena_t.
[in]itemsElement count.
[in]sizeElement size, bytes.
Returns
Pointer to an aligned block, or NULL on overflow / exhaustion.
Precondition
items * size does not overflow size_t (checked; NULL if it does).
opaque names a live arena (NULL is rejected).
The arena has a free block large enough (else NULL).
Postcondition
On success the returned block is marked in-use and is >= requested.
On failure the pool is unchanged.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 318 of file epub_miniz_alloc.c.

References internal_align_up(), internal_cell_at(), internal_end(), internal_next(), internal_payload(), internal_ready(), internal_request_bytes(), internal_split(), priv_blk_t::is_free, k_priv_align, k_priv_blk_free, k_priv_blk_used, k_priv_walk_max, and priv_blk_t::size.

Referenced by epub_miniz_realloc(), internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ epub_miniz_arena_deinit()

void epub_miniz_arena_deinit ( epub_miniz_arena_t * arena)

Invalidate an arena descriptor after miniz has released its blocks.

Clears only the descriptor; caller-owned workspace bytes remain available for a later explicit reinitialization.

Parameters
[in,out]arenaArena to invalidate; NULL is accepted.
Precondition
All allocations from arena have been released.
No miniz archive retains arena as its allocation context.
Postcondition
A non-NULL descriptor is zeroed; workspace bytes are unchanged.
A NULL argument performs no operation.
Note
Reinitialise with epub_miniz_arena_init before reuse.
Since
0.1.0

Definition at line 311 of file epub_miniz_alloc.c.

Referenced by epub_close(), epub_open(), epub_open_streamed(), priv_comic_cbz_close(), and priv_comic_cbz_open().

◆ epub_miniz_arena_init()

ra8_err_t epub_miniz_arena_init ( epub_miniz_arena_t * arena,
void * workspace,
size_t workspace_bytes )
nodiscard

Initialise or reset a miniz arena over caller-owned storage.

Parameters
[out]arenaDescriptor to initialise.
[in,out]workspaceMaximally-aligned backing storage.
[in]workspace_bytesWritable bytes at workspace.
Return values
k_ra8_okWorkspace accepted and reset to one free block.
k_ra8_err_null_ptrarena or workspace is NULL.
k_ra8_err_invalid_sizeFewer than k_epub_miniz_pool_bytes bytes were supplied.
k_ra8_err_invalid_argworkspace is not aligned for max_align_t.
Precondition
No allocation from arena is live when reinitialising it.
Postcondition
On success exactly k_epub_miniz_pool_bytes are bound.
On failure arena and workspace are unchanged.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 288 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::capacity, internal_cell_at(), internal_pointer_address(), priv_blk_t::is_free, k_epub_miniz_pool_bytes, k_priv_blk_free, k_priv_hdr_bytes, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, and priv_blk_t::size.

Referenced by internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ epub_miniz_free()

void epub_miniz_free ( void * opaque,
void * address )

miniz-compatible free (mz_free_func).

Marks address's block free and coalesces it with adjacent free blocks. A NULL address, invalid arena, or pointer outside that arena is ignored.

Parameters
[in]opaquePointer to the owning epub_miniz_arena_t.
[in]addressBlock previously returned by epub_miniz_alloc / epub_miniz_realloc, or NULL.
Precondition
address is NULL or a live block from this allocator.
opaque is the same live arena that allocated address.
Postcondition
address's block is free and merged with any free neighbours.
A NULL / out-of-pool address leaves the pool unchanged.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 347 of file epub_miniz_alloc.c.

References internal_coalesce(), internal_header(), internal_in_pool(), priv_blk_t::is_free, and k_priv_blk_free.

Referenced by epub_miniz_realloc(), internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ epub_miniz_realloc()

void * epub_miniz_realloc ( void * opaque,
void * address,
size_t items,
size_t size )

miniz-compatible realloc (mz_realloc_func).

Grows or shrinks address to at least items * size bytes. Keeps the block in place when it already fits; otherwise allocates a new block, copies the old payload, and frees the old block. realloc(NULL, n) allocates; realloc(p, 0) frees and returns NULL.

Parameters
[in]opaquePointer to the owning epub_miniz_arena_t.
[in]addressExisting block, or NULL.
[in]itemsNew element count.
[in]sizeNew element size, bytes.
Returns
Pointer to a block of at least the requested size, or NULL on overflow / exhaustion (in which case address remains valid).
Precondition
opaque names a live arena.
address is NULL or a live block from that arena.
items * size does not overflow (checked).
Postcondition
On a moved grow, the old payload bytes are preserved in the new block.
On NULL-return for a non-NULL address, that block is still valid.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 358 of file epub_miniz_alloc.c.

References epub_miniz_alloc(), epub_miniz_free(), internal_align_up(), internal_header(), internal_in_pool(), internal_request_bytes(), memcpy(), and priv_blk_t::size.

Referenced by internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ internal_align_up()

size_t internal_align_up ( size_t bytes)
static

Align a pool-bounded request upward to a complete arena cell.

Applies the power-of-two maximum-alignment mask after request bounds have already excluded arithmetic overflow.

Parameters
[in]bytesUnaligned request no larger than the arena capacity.
Returns
Smallest aligned cell count covering bytes.
Return values
0Returned when bytes is zero.
alignedA multiple of k_priv_align not smaller than bytes.
Precondition
bytes passed internal_request_bytes.
k_priv_align is a non-zero power of two.
Postcondition
Return value is arena-bounded and aligned.
No state is modified.
Note
Pure and thread-safe.
Since
0.1.0

Definition at line 190 of file epub_miniz_alloc.c.

References k_priv_align.

Referenced by epub_miniz_alloc(), and epub_miniz_realloc().

◆ internal_cell_at()

priv_blk_t * internal_cell_at ( const epub_miniz_arena_t * arena,
size_t off )
static

Cast byte offset off to an aligned block header.

Parameters
[in]arenaLive arena.
[in]offAligned byte offset, at most the arena capacity.
Returns
Header pointer or the one-past sentinel.

Definition at line 107 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base.

Referenced by epub_miniz_alloc(), epub_miniz_arena_init(), internal_coalesce(), internal_header(), internal_next(), and internal_split().

◆ internal_coalesce()

void internal_coalesce ( const epub_miniz_arena_t * arena)
static

Merge all adjacent free blocks in an arena.

Walks the implicit bounded block list and folds each contiguous free run into its first header without moving live payload bytes.

Parameters
[in,out]arenaLive arena whose in-band headers may be updated.
Precondition
arena is ready and its block chain is geometrically valid.
No concurrent allocation operation uses the same arena.
Postcondition
No two adjacent blocks are both marked free.
Live block addresses and payload bytes are unchanged.
Note
The fixed walk guard bounds behavior if metadata is corrupted.
Since
0.1.0

Definition at line 270 of file epub_miniz_alloc.c.

References internal_cell_at(), internal_end(), internal_next(), priv_blk_t::is_free, k_priv_blk_free, k_priv_hdr_bytes, k_priv_walk_max, and priv_blk_t::size.

Referenced by epub_miniz_free().

◆ internal_end()

uint8_t * internal_end ( const epub_miniz_arena_t * arena)
static

Return the arena's one-past byte sentinel.

Definition at line 115 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base, and epub_miniz_arena_t::capacity.

Referenced by epub_miniz_alloc(), and internal_coalesce().

◆ internal_header()

priv_blk_t * internal_header ( const epub_miniz_arena_t * arena,
void * address )
static

Return the header for an allocation payload.

Definition at line 129 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base, internal_cell_at(), internal_pointer_address(), and k_priv_hdr_bytes.

Referenced by epub_miniz_free(), and epub_miniz_realloc().

◆ internal_in_pool()

bool internal_in_pool ( const epub_miniz_arena_t * arena,
const void * address )
static

Test whether an address lies in the payload-bearing arena range.

Rejects inactive arenas and excludes the header-only prefix and one-past byte without dereferencing the candidate address.

Parameters
[in]arenaArena descriptor to validate and bound the comparison.
[in]addressCandidate allocation payload address.
Returns
Whether the numeric address is inside the payload-bearing range.
Return values
trueAddress is at or after the first payload byte and before end.
falseArena is invalid or address lies outside the numeric range.
Precondition
arena is null or points to a readable descriptor.
address may be null or any non-dereferenced pointer value.
Postcondition
No arena or candidate memory is changed.
The candidate address is never dereferenced.
Note
Range membership alone does not prove the address starts a live block.
Since
0.1.0

Definition at line 162 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base, epub_miniz_arena_t::capacity, internal_pointer_address(), internal_ready(), and k_priv_hdr_bytes.

Referenced by epub_miniz_free(), and epub_miniz_realloc().

◆ internal_next()

priv_blk_t * internal_next ( const epub_miniz_arena_t * arena,
priv_blk_t * block )
static

Return the block immediately following block.

Definition at line 138 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base, internal_cell_at(), internal_payload(), internal_pointer_address(), and priv_blk_t::size.

Referenced by epub_miniz_alloc(), and internal_coalesce().

◆ internal_payload()

uint8_t * internal_payload ( priv_blk_t * block)
static

Return the payload immediately following block.

Definition at line 122 of file epub_miniz_alloc.c.

References k_priv_hdr_bytes.

Referenced by epub_miniz_alloc(), internal_next(), and internal_split().

◆ internal_pointer_address()

uintptr_t internal_pointer_address ( const void * pointer)
static

Copy a pointer representation into an integer address.

Uses a bytewise copy so the conversion does not violate pointer aliasing rules checked by the static analyzer.

Parameters
[in]pointerObject pointer whose representation is copied.
Returns
Integer address carrying the same representation.
Return values
0The null pointer representation when it is all-zero on this target.
Precondition
pointer may carry any object-pointer representation.
uintptr_t and object pointers have identical representation widths.
Postcondition
No pointed-to byte is read or modified.
The returned bytes equal the pointer representation on entry.
Note
Pure and thread-safe.
Since
Version 0.1.0

Definition at line 60 of file epub_miniz_alloc.c.

References memcpy().

Referenced by epub_miniz_arena_init(), internal_header(), internal_in_pool(), internal_next(), internal_ready(), and internal_split().

◆ internal_ready()

bool internal_ready ( const epub_miniz_arena_t * arena)
static

Validate an arena descriptor before using caller-owned storage.

Checks lifecycle, exact capacity, backing pointer, and alignment.

Parameters
[in]arenaDescriptor to inspect.
Returns
Whether the descriptor is live and geometrically valid.
Return values
trueArena is initialized with exact aligned backing storage.
falseArena is null, inactive, malformed, or misaligned.
Precondition
arena is null or points to a readable descriptor.
Descriptor fields may contain any representable values.
Postcondition
No state is modified.
No backing byte is inspected.
Note
Pure and thread-safe for immutable input.
Since
0.1.0

Definition at line 83 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base, epub_miniz_arena_t::capacity, epub_miniz_arena_t::initialized, internal_pointer_address(), and k_epub_miniz_pool_bytes.

Referenced by epub_miniz_alloc(), and internal_in_pool().

◆ internal_request_bytes()

bool internal_request_bytes ( size_t items,
size_t size,
size_t * out_bytes )
static

Validate and multiply a miniz count/size request exactly once.

Parameters
[in]itemsElement count.
[in]sizeElement size.
[out]out_bytesProduct on success; unchanged on failure.
Returns
Whether the product is representable and arena-bounded.

Performs multiplication only after its overflow guard and rejects requests larger than the complete caller-owned pool.

Return values
trueProduct is representable, bounded, and stored in out_bytes.
falseMultiplication overflows or the product exceeds pool capacity.
Precondition
out_bytes is non-null and writable.
items and size may be any representable size_t values.
Postcondition
Success initializes out_bytes exactly once.
Failure leaves out_bytes unchanged.
Note
Pure and thread-safe.
Since
0.1.0

Definition at line 214 of file epub_miniz_alloc.c.

References k_epub_miniz_pool_bytes.

Referenced by epub_miniz_alloc(), and epub_miniz_realloc().

◆ internal_split()

void internal_split ( const epub_miniz_arena_t * arena,
priv_blk_t * block,
size_t need )
static

Split a block if its remainder can hold another allocation.

Leaves unusably small tails inside the live block; otherwise emits one aligned free block with its own in-band header.

Parameters
[in]arenaLive arena owning block.
[in,out]blockFree block selected for allocation.
[in]needAligned payload bytes required by the allocation.
Precondition
arena is ready and block is a valid free arena block.
need is aligned, non-zero, and no greater than block->size.
Postcondition
The original block retains at least need payload bytes.
Any emitted remainder is aligned, free, and wholly inside the arena.
Note
Not thread-safe through one arena.
Since
0.1.0

Definition at line 242 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::base, internal_cell_at(), internal_payload(), internal_pointer_address(), priv_blk_t::is_free, k_priv_align, k_priv_blk_free, k_priv_hdr_bytes, and priv_blk_t::size.

Referenced by epub_miniz_alloc().