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

Provide bounded miniz storage and the CBZ container writer. More...

#include <stdio.h>
#include <string.h>
#include "mdl_export.h"
#include "mdl_export_internal.h"
#include "mdl_urlname.h"
#include "miniz.h"
#include "ra8_attributes.h"
Include dependency graph for mdl_export_zip.c:

Go to the source code of this file.

Functions

static bool internal_zip_align_size (size_t bytes, size_t *out)
 Round a byte count up to maximum host alignment.
static mdl_zip_block_tinternal_zip_find_block (mdl_zip_allocator_t *alloc, const void *address)
 Find an allocator block by its payload address.
static void * internal_zip_workspace_alloc (void *opaque, size_t items, size_t size)
 Allocate reusable miniz storage from a bounded exporter arena.
static void internal_zip_workspace_free (void *opaque, void *address)
 Release a miniz block for reuse within the current writer.
static void * internal_zip_workspace_realloc (void *opaque, void *address, size_t items, size_t size)
 Resize a miniz block within the bounded reusable arena.
void priv_mdl_zip_workspace_bind (mz_zip_archive *zip, mdl_zip_allocator_t *alloc, mdl_export_workspace_t *ws)
 Bind one zeroed miniz archive to a bounded allocator.
void priv_mdl_zip_workspace_release (mdl_zip_allocator_t *alloc)
 Release all miniz allocations while preserving high-water.
ra8_err_t priv_mdl_zip_workspace_error (const mdl_zip_allocator_t *alloc)
 Map a miniz failure to bounded exhaustion when applicable.
ra8_err_t priv_mdl_export_prepare_cover (mdl_storage_t *storage, const mdl_export_meta_t *meta, const char names[][k_name_max], size_t count, mdl_external_cover_t *cover)
 Validate and canonicalize a cover not already present as a page.
static ra8_err_t internal_cbz_add_pages (mz_zip_archive *zip, mdl_storage_t *storage, const char *dir, char names[][k_name_max], size_t count)
 Add every discovered page to an initialized CBZ writer.
static ra8_err_t internal_cbz_add_metadata (mz_zip_archive *zip, const mdl_export_meta_t *meta, size_t count, const mdl_external_cover_t *cover, const mdl_zip_allocator_t *allocator)
 Build and append ComicInfo metadata to a CBZ writer.
ra8_err_t priv_mdl_export_cbz (mdl_storage_t *storage, const char *dir, char names[][k_name_max], size_t count, mdl_export_output_t *output, const mdl_export_meta_t *meta, mdl_export_workspace_t *ws)
 Write a CBZ with pages, canonical cover, and ComicInfo metadata.

Detailed Description

Provide bounded miniz storage and the CBZ container writer.

Adapts miniz allocation callbacks to caller-owned workspace, types external cover assets, and emits deterministic CBZ archives.

[Ring 4 / Domain] {World: NS}

Definition in file mdl_export_zip.c.

Function Documentation

◆ internal_cbz_add_metadata()

ra8_err_t internal_cbz_add_metadata ( mz_zip_archive * zip,
const mdl_export_meta_t * meta,
size_t count,
const mdl_external_cover_t * cover,
const mdl_zip_allocator_t * allocator )
static

Build and append ComicInfo metadata to a CBZ writer.

Rebases an external cover to logical page zero before rendering.

Parameters
[in,out]zipInitialized ZIP writer.
[in]metaMetadata to render, or NULL.
[in]countNumber of discovered pages.
[in]coverPrepared external-cover state.
[in]allocatorZIP workspace allocator for error translation.
Returns
Metadata/member-addition status.
Return values
k_ra8_okComicInfo.xml was added.
k_ra8_err_invalid_sizeMetadata did not fit.
k_ra8_failZIP member addition failed.
Precondition
zip, cover, and allocator are non-NULL.
An external cover implies non-NULL meta.
Postcondition
Success adds one ComicInfo.xml member.
Failure leaves writer cleanup to the caller.
Note
Not thread-safe for a shared writer.
Since
0.1.0

Definition at line 406 of file mdl_export_zip.c.

References mdl_export_meta_t::cover_index, mdl_external_cover_t::external, k_ra8_ok, mdl_export_build_comicinfo_pages(), priv_mdl_export_zip_add_memory(), priv_mdl_zip_workspace_error(), RA8_INTERNAL, and strlen().

Referenced by priv_mdl_export_cbz().

◆ internal_cbz_add_pages()

ra8_err_t internal_cbz_add_pages ( mz_zip_archive * zip,
mdl_storage_t * storage,
const char * dir,
char names[][k_name_max],
size_t count )
static

Add every discovered page to an initialized CBZ writer.

Builds each source path in bounded storage and stores the page without recompression.

Parameters
[in,out]zipInitialized ZIP writer.
[in,out]storageInjected portable page reader.
[in]dirChapter directory.
[in]namesSorted page-name rows.
[in]countNumber of page rows.
Returns
Whether all page members were added.
Return values
trueEvery page was accepted by the writer.
falseAt least one page could not be added.
Precondition
Paths and rows are valid, stable, and NUL-terminated.
zip is initialized.
Postcondition
Success adds exactly count page members.
Failure leaves writer cleanup to the caller.
Note
Not thread-safe for a shared writer.
Since
0.1.0

Definition at line 368 of file mdl_export_zip.c.

References k_fw_fs_path_cap, k_name_max, k_ra8_ok, priv_mdl_export_path_join(), priv_mdl_export_zip_add_file(), and RA8_INTERNAL.

Referenced by priv_mdl_export_cbz().

◆ internal_zip_align_size()

bool internal_zip_align_size ( size_t bytes,
size_t * out )
static

Round a byte count up to maximum host alignment.

Performs the power-of-two rounding only after overflow checks.

Parameters
[in]bytesRequested payload byte count.
[out]outRounded result.
Returns
Whether the aligned size is representable.
Return values
trueout contains the aligned size.
falseout is NULL or rounding would overflow.
Precondition
bytes is an untrusted bounded allocation request.
Maximum alignment is a nonzero power of two.
Postcondition
Success writes a value not smaller than bytes.
Failure does not write through out.
Note
Thread-safe and side-effect free.
Since
0.1.0

Definition at line 38 of file mdl_export_zip.c.

References RA8_INTERNAL.

Referenced by internal_zip_workspace_alloc().

◆ internal_zip_find_block()

mdl_zip_block_t * internal_zip_find_block ( mdl_zip_allocator_t * alloc,
const void * address )
static

Find an allocator block by its payload address.

Walks only aligned blocks created after the saved writer floor and never follows a pointer outside the current workspace high edge.

Parameters
[in]allocActive callback adapter.
[in]addressCandidate payload address.
Returns
Matching block header, or NULL.
Return values
non-NULLaddress names a block from this adapter.
NULLArguments are invalid or no block matches.
Precondition
alloc is NULL or owns a well-formed current block chain.
address is treated only as an opaque comparison value.
Postcondition
No allocator block or workspace counter is modified.
A returned header lies within the active workspace range.
Note
Not thread-safe with concurrent allocation from the same adapter.
Since
0.1.0

Definition at line 65 of file mdl_export_zip.c.

References mdl_export_workspace::data, mdl_zip_allocator_t::first, RA8_INTERNAL, mdl_export_workspace::used, and mdl_zip_allocator_t::ws.

Referenced by internal_zip_workspace_free(), and internal_zip_workspace_realloc().

◆ internal_zip_workspace_alloc()

void * internal_zip_workspace_alloc ( void * opaque,
size_t items,
size_t size )
static

Allocate reusable miniz storage from a bounded exporter arena.

Rejects multiplication overflow, reuses a released first-fit block, or appends one aligned block through mdl_export_workspace_take.

Parameters
[in,out]opaquePointer to the active mdl_zip_allocator_t.
[in]itemsElement count requested by miniz.
[in]sizeBytes per requested element.
Returns
Maximum-aligned payload storage, or NULL.
Return values
non-NULLThe complete bounded request was satisfied.
NULLArguments overflowed or caller capacity was exhausted.
Precondition
opaque points to an active exclusive writer adapter.
Its workspace data remains live and writable.
Postcondition
Success records exact requested bytes in one live block.
Failure sets the adapter exhaustion flag and performs no system allocation.
Note
Not thread-safe for a shared adapter.
Since
0.1.0

Definition at line 101 of file mdl_export_zip.c.

References mdl_zip_block_t::bytes, mdl_export_workspace::data, mdl_zip_allocator_t::exhausted, mdl_zip_allocator_t::first, mdl_zip_block_t::free, internal_zip_align_size(), mdl_export_workspace_take(), RA8_INTERNAL, mdl_zip_block_t::span, mdl_export_workspace::used, and mdl_zip_allocator_t::ws.

Referenced by internal_zip_workspace_realloc(), and priv_mdl_zip_workspace_bind().

◆ internal_zip_workspace_free()

void internal_zip_workspace_free ( void * opaque,
void * address )
static

Release a miniz block for reuse within the current writer.

Marks only blocks found in the current bounded adapter; no system deallocator or out-of-arena address is ever invoked.

Parameters
[in,out]opaquePointer to the active mdl_zip_allocator_t.
[in]addressPayload returned by this adapter, or NULL.
Precondition
opaque is NULL or identifies the active writer allocator.
address is NULL or was returned by the matching allocator.
Postcondition
A recognized block becomes available for first-fit reuse.
Workspace cursors and high-water accounting are unchanged.
Note
Not thread-safe for a shared writer allocator.
Since
0.1.0

Definition at line 159 of file mdl_export_zip.c.

References mdl_zip_block_t::free, internal_zip_find_block(), and RA8_INTERNAL.

Referenced by priv_mdl_zip_workspace_bind().

◆ internal_zip_workspace_realloc()

void * internal_zip_workspace_realloc ( void * opaque,
void * address,
size_t items,
size_t size )
static

Resize a miniz block within the bounded reusable arena.

Retains a sufficiently large block in place; otherwise obtains a replacement, copies the exact prior request, and releases the old block.

Parameters
[in,out]opaquePointer to the active mdl_zip_allocator_t.
[in]addressExisting payload, or NULL for allocation semantics.
[in]itemsNew element count.
[in]sizeBytes per new element.
Returns
Resized payload storage, or NULL.
Return values
non-NULLThe request was satisfied with preserved prior bytes.
NULLInput was invalid or bounded storage was exhausted.
Precondition
opaque points to an active exclusive writer adapter.
Non-NULL address came from the matching adapter and is still live.
Postcondition
Success preserves the previous requested payload prefix.
Failure never invokes a system allocator or frees caller storage.
Note
Not thread-safe for a shared adapter.
Since
0.1.0

Definition at line 187 of file mdl_export_zip.c.

References mdl_zip_block_t::bytes, mdl_zip_allocator_t::exhausted, mdl_zip_block_t::free, internal_zip_find_block(), internal_zip_workspace_alloc(), memcpy(), and mdl_zip_block_t::span.

Referenced by priv_mdl_zip_workspace_bind().

◆ priv_mdl_export_cbz()

ra8_err_t priv_mdl_export_cbz ( mdl_storage_t * storage,
const char * dir,
char names[][k_name_max],
size_t count,
mdl_export_output_t * output,
const mdl_export_meta_t * meta,
mdl_export_workspace_t * ws )

Write a CBZ with pages, canonical cover, and ComicInfo metadata.

Write a CBZ into a caller-owned staged output.

Stores each page without recompression, inserts an external cover first when present, and finalizes only after ComicInfo succeeds.

Parameters
[in,out]storageInjected portable file reader.
[in]dirNUL-terminated chapter directory.
[in]namesSorted page-name rows.
[in]countNumber of pages to archive.
[in,out]outputActive validated-publication output.
[in]metaMetadata to embed, or NULL.
[in,out]wsExclusive caller-owned workspace.
Returns
CBZ writer status.
Return values
k_ra8_okThe ZIP central directory finalized successfully.
k_ra8_err_validation_failedAn external cover is invalid.
k_ra8_err_invalid_sizeMetadata or a bounded name does not fit.
k_ra8_failZIP creation, member writing, or finalization failed.
Precondition
Paths and name rows are valid and stable.
output owns an active transaction.
Postcondition
Success leaves a finalized CBZ with ComicInfo.
External cover paths are represented only by canonical member names.
Note
Not thread-safe for the same output or changing source files.
Since
0.1.0

Definition at line 458 of file mdl_export_zip.c.

References mdl_external_cover_t::entry, mdl_export_output_t::error, mdl_zip_allocator_t::exhausted, mdl_external_cover_t::external, internal_cbz_add_metadata(), internal_cbz_add_pages(), k_name_max, k_ra8_err_invalid_size, k_ra8_fail, k_ra8_ok, priv_mdl_export_prepare_cover(), priv_mdl_export_zip_add_file(), priv_mdl_export_zip_write(), priv_mdl_zip_workspace_bind(), priv_mdl_zip_workspace_error(), priv_mdl_zip_workspace_release(), RA8_PRIV, and mdl_external_cover_t::source.

Referenced by internal_export_dispatch().

◆ priv_mdl_export_prepare_cover()

ra8_err_t priv_mdl_export_prepare_cover ( mdl_storage_t * storage,
const mdl_export_meta_t * meta,
const char names[][k_name_max],
size_t count,
mdl_external_cover_t * cover )

Validate and canonicalize a cover not already present as a page.

Validate and canonicalize an external cover.

Recognizes an in-chapter page by exact name; otherwise requires a stable regular image file, sniffs its bytes, and hides the trusted host path behind cover/cover.<actual-type>.

Parameters
[in,out]storageInjected portable file reader.
[in]metaMetadata carrying the trusted cover path, or NULL.
[in]namesSorted chapter page rows.
[in]countNumber of readable rows.
[out]coverCanonical external-cover descriptor.
Returns
Cover classification status.
Return values
k_ra8_okNo external cover is needed or one was validated.
k_ra8_err_invalid_argThe fixed path lacks a terminating NUL.
k_ra8_err_invalid_sizeThe canonical member path does not fit.
k_ra8_err_validation_failedThe source is absent, nonregular, or not an image.
Precondition
cover and names are valid for count rows.
meta is NULL or exclusively stable for the call.
Postcondition
Success fully initializes cover.
An external source path is never copied into an archive member name.
Note
Not thread-safe against concurrent replacement of the cover file.
Since
0.1.0

Definition at line 305 of file mdl_export_zip.c.

References mdl_export_meta_t::cover_path, mdl_external_cover_t::entry, fw_fs_stat_t::exists, mdl_external_cover_t::external, mdl_storage_t::fs, fw_fs_stat(), k_cover_ext_bytes, k_fw_fs_node_file, k_name_max, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_validation_failed, k_ra8_ok, mdl_urlname_sniff_file(), memset(), mdl_external_cover_t::mime, fw_fs_t::names, priv_mdl_export_snprintf_fit(), RA8_PRIV, fw_fs_stat_t::size_bytes, mdl_external_cover_t::source, strcmp(), strnlen(), and fw_fs_stat_t::type.

Referenced by priv_mdl_export_cbz(), and priv_mdl_export_epub().

◆ priv_mdl_zip_workspace_bind()

void priv_mdl_zip_workspace_bind ( mz_zip_archive * zip,
mdl_zip_allocator_t * alloc,
mdl_export_workspace_t * ws )

Bind one zeroed miniz archive to a bounded allocator.

Bind a miniz archive to caller-owned bounded storage.

Records the current workspace floor and installs allocation, release, and resize callbacks before miniz initialization.

Parameters
[out]zipArchive descriptor to initialize.
[out]allocCallback adapter with writer lifetime.
[in,out]wsExclusive initialized exporter workspace.
Precondition
All pointer arguments are non-NULL.
ws owns live writable storage through writer teardown.
Postcondition
zip has no default miniz allocator callback.
alloc records the cursor restored by priv_mdl_zip_workspace_release.
Note
Not thread-safe for a shared workspace.
Since
0.1.0

Definition at line 232 of file mdl_export_zip.c.

References internal_zip_workspace_alloc(), internal_zip_workspace_free(), internal_zip_workspace_realloc(), memset(), RA8_PRIV, and mdl_export_workspace::used.

Referenced by priv_mdl_export_cbz(), and priv_mdl_export_epub().

◆ priv_mdl_zip_workspace_error()

ra8_err_t priv_mdl_zip_workspace_error ( const mdl_zip_allocator_t * alloc)

Map a miniz failure to bounded exhaustion when applicable.

Classify a miniz writer failure.

Distinguishes an arena callback refusal from ordinary ZIP I/O or format failures so callers can size their explicit workspace.

Parameters
[in]allocActive callback adapter, or NULL.
Returns
Exporter error matching the recorded allocator state.
Return values
k_ra8_err_invalid_sizeBounded callback capacity was exhausted.
k_ra8_failNo allocator exhaustion was recorded.
Precondition
alloc is NULL or remains alive through result classification.
The writer has reported a failure before this helper is called.
Postcondition
No workspace counter or block is modified.
Identical allocator state produces an identical result.
Note
Thread-safe for immutable distinct adapters.
Since
0.1.0

Definition at line 278 of file mdl_export_zip.c.

References mdl_zip_allocator_t::exhausted, k_ra8_err_invalid_size, k_ra8_fail, and RA8_PRIV.

Referenced by internal_cbz_add_metadata(), priv_mdl_export_cbz(), and priv_mdl_export_epub().

◆ priv_mdl_zip_workspace_release()

void priv_mdl_zip_workspace_release ( mdl_zip_allocator_t * alloc)

Release all miniz allocations while preserving high-water.

Restore a workspace after a miniz writer ends.

Restores the bump cursor to its pre-writer floor after miniz has ended, making transient writer storage reusable by later phases.

Parameters
[in,out]allocActive callback adapter, or NULL.
Precondition
alloc is NULL or its writer has ended or failed initialization.
The associated workspace is not concurrently accessed.
Postcondition
A valid workspace cursor equals the saved floor.
high_water retains the largest observed allocation edge.
Note
Not thread-safe for a shared workspace.
Since
0.1.0

Definition at line 256 of file mdl_export_zip.c.

References mdl_zip_allocator_t::floor, RA8_PRIV, mdl_export_workspace::used, and mdl_zip_allocator_t::ws.

Referenced by internal_epub_finish_writer(), and priv_mdl_export_cbz().