|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Bounded-RAM streaming + windowed extraction of a single ZIP entry (#231). More...
#include "epub_entry.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "epub.h"#include "epub_internal.h"#include "miniz.h"#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"Go to the source code of this file.
Enumerations | |
| enum | epub_ldh_t : uint8_t { k_epub_ldh_size = 30U , k_epub_ldh_fname_len_ofs = 26U , k_epub_ldh_extra_len_ofs = 28U } |
| Local-file-header size + the two variable-length field-length offsets. More... | |
| enum | epub_ldh_sig_t : uint8_t { k_epub_ldh_sig_0 = 0x50U , k_epub_ldh_sig_1 = 0x4BU , k_epub_ldh_sig_2 = 0x03U , k_epub_ldh_sig_3 = 0x04U } |
| Local-file-header signature bytes (little-endian 0x04034b50). More... | |
| enum | epub_le_t : uint8_t { k_epub_le_lo = 0U , k_epub_le_hi = 1U , k_epub_le_shift = 8U } |
| Little-endian byte shift + index constants for the header fields. More... | |
Functions | |
| static mz_zip_archive * | internal_zip (epub_book_t *book) |
| Borrow the book's inline mz_zip_archive. | |
| static ra8_err_t | internal_locate (mz_zip_archive *zip, epub_book_t *book, const char *path, int32_t *out_idx) |
| Locate an entry by OPF-prefixed path, falling back to the bare path. | |
| static bool | internal_backing_read (epub_book_t *book, uint64_t archive_ofs, uint8_t *buf, size_t n) |
Read n absolute archive bytes off the book's backing (resident or streamed). | |
| static bool | internal_data_offset (const uint8_t *hdr, uint64_t local_header_ofs, uint64_t *out_data_ofs) |
| Verify a 30-byte local header and return the entry's data offset. | |
| static ra8_err_t | internal_open_iter (epub_book_t *book, const char *path, mz_zip_reader_extract_iter_state **out_iter, uint64_t *out_uncomp) |
| Locate + stat an entry and start a miniz extract-iterator over it. | |
| static ra8_err_t | internal_stored_data_offset (epub_book_t *book, const char *path, uint64_t *out_data_ofs, uint64_t *out_uncomp) |
| Resolve a stored entry's archive data offset + uncompressed size. | |
| ra8_err_t | epub_entry_open (epub_book_t *book, const char *path, epub_entry_reader_t *out_reader, uint64_t *out_size) |
| Begin a bounded-RAM streaming extraction of one archive entry (#231). | |
| ra8_err_t | epub_entry_read (epub_entry_reader_t *reader, uint8_t *buf, size_t cap, size_t *got) |
| Pull the next chunk of a streaming entry into a bounded caller buffer (#231). | |
| ra8_err_t | epub_entry_close (epub_entry_reader_t *reader) |
| Tear down a streaming-entry cursor and release its inflate state (#231). | |
| static ra8_err_t | internal_pread_null_ok (const epub_book_t *book, const char *path, const uint8_t *buf, const size_t *got) |
| Reject any NULL epub_entry_pread pointer argument. | |
| ra8_err_t | epub_entry_pread (epub_book_t *book, const char *path, uint64_t offset, uint8_t *buf, size_t len, size_t *got) |
| Positioned read of a stored (uncompressed) archive entry – windowed random access in bounded RAM (#231). | |
Variables | |
| static const char *const | s_tag = "epub_entry" |
| Module log tag. | |
Bounded-RAM streaming + windowed extraction of a single ZIP entry (#231).
The whole-entry accessors (epub_load_chapter, epub_get_resource, ...) inflate an entry via mz_zip_reader_extract_to_mem into a caller buffer sized to the entry's uncompressed size – fine for small text/CSS/font entries, but a full-page manga scan in an all-image EPUB inflates to tens of megabytes and cannot be held whole on a ~10 MB working-set device.
This TU adds two ways to read an entry without materialising it:
Both work for a resident book (epub_open) and a streamed book (epub_open_streamed); in the streamed case every compressed / stored byte is fetched on demand through the book's seek+read backing.
[Ring 4 / EPUB] {World: NS}
Definition in file epub_entry.c.
| enum epub_ldh_sig_t : uint8_t |
Local-file-header signature bytes (little-endian 0x04034b50).
| Enumerator | |
|---|---|
| k_epub_ldh_sig_0 | Signature byte 0 ('P'). |
| k_epub_ldh_sig_1 | Signature byte 1 ('K'). |
| k_epub_ldh_sig_2 | Signature byte 2. |
| k_epub_ldh_sig_3 | Signature byte 3. |
Definition at line 76 of file epub_entry.c.
| enum epub_ldh_t : uint8_t |
Local-file-header size + the two variable-length field-length offsets.
A ZIP local file header is a fixed 30-byte record followed by the file name and an extra field; the entry's stored/compressed data begins right after them. epub_entry_pread() reads the 30-byte header to learn those two lengths and thereby the data offset.
| Enumerator | |
|---|---|
| k_epub_ldh_size | Fixed local-header length, bytes. |
| k_epub_ldh_fname_len_ofs | uint16 file-name length field offset. |
| k_epub_ldh_extra_len_ofs | uint16 extra-field length field offset. |
Definition at line 66 of file epub_entry.c.
| enum epub_le_t : uint8_t |
Little-endian byte shift + index constants for the header fields.
| Enumerator | |
|---|---|
| k_epub_le_lo | Low-order byte index. |
| k_epub_le_hi | High-order byte index. |
| k_epub_le_shift | High-byte left shift. |
Definition at line 87 of file epub_entry.c.
|
nodiscard |
Tear down a streaming-entry cursor and release its inflate state (#231).
Frees the miniz iterator (returning its LZ dictionary + read buffer to the allocator). If the entire entry had been read, the entry's CRC/size are verified as a corruption check; an early close (before EOF) is legal and simply releases resources. Idempotent on an already-closed cursor.
| [in,out] | reader | Cursor from epub_entry_open(). |
| k_ra8_ok | Cursor closed and state released. |
| k_ra8_err_null_ptr | reader is NULL. |
| k_ra8_err_validation_failed | The fully-read entry failed CRC/size verification. |
reader is a cursor (open or already closed). Definition at line 392 of file epub_entry.c.
References epub_entry_reader_t::consumed, epub_entry_reader_t::iter, k_ra8_err_validation_failed, k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and epub_entry_reader_t::total.
|
nodiscard |
Begin a bounded-RAM streaming extraction of one archive entry (#231).
Resolves path the same way epub_get_resource() does – first joined onto the OPF directory (book->opf_dir), then as a bare archive-rooted path – then starts a miniz extract-iterator over the located entry. No entry bytes are inflated yet; the caller pulls them with epub_entry_read(). The entry's uncompressed size is reported so the caller can size a progress bar or a tile grid without materialising the entry.
| [in] | book | Open book (in_use == 1, archive active). |
| [in] | path | Entry path, OPF-dir-relative or archive-rooted, NUL-terminated. |
| [out] | out_reader | Cursor to populate (zero-initialised by the caller). |
| [out] | out_size | Receives the entry's uncompressed size in bytes (may be NULL). |
| k_ra8_ok | Cursor open; read with epub_entry_read(). |
| k_ra8_err_null_ptr | book, path, or out_reader is NULL. |
| k_ra8_err_not_initialized | Book not open / archive inactive. |
| k_ra8_err_not_found | No entry at path (prefixed or bare). |
| k_ra8_err_validation_failed | The iterator could not be started (corrupt entry). |
out_reader points at writable, zero-initialised storage. Definition at line 331 of file epub_entry.c.
References epub_entry_reader_t::book, epub_entry_reader_t::done, epub_book_t::in_use, internal_open_iter(), epub_entry_reader_t::iter, k_ra8_err_not_initialized, k_ra8_ok, memset(), priv_epub_book_not_ready(), RA8_CHECK_NULL_PTR, s_tag, epub_entry_reader_t::total, and epub_book_t::zip_archive_active.
|
nodiscard |
Positioned read of a stored (uncompressed) archive entry – windowed random access in bounded RAM (#231).
For an entry stored with no compression (ZIP method 0 – the natural choice for already-compressed pixel data or a display-native tile atlas), the uncompressed bytes lie contiguously in the archive, so any window [offset, offset+len) can be read directly off the backing without inflating from the start. This is the random-access primitive the tile source (epub_img_tiles) uses to page a single tile without holding the whole image. A short read at the entry's tail is reported via *got.
Deflated entries are rejected (k_ra8_err_not_supported): random access into a DEFLATE stream requires inflating from the start, which the forward cursor (epub_entry_read()) already provides.
| [in] | book | Open book (in_use == 1, archive active). |
| [in] | path | Entry path, OPF-dir-relative or archive-rooted, NUL-terminated. |
| [in] | offset | Byte offset into the entry's uncompressed data. |
| [out] | buf | Destination buffer (len writable bytes). |
| [in] | len | Bytes requested. |
| [out] | got | Bytes actually read (0 at/after the entry's end). |
| k_ra8_ok | Window read (possibly short at EOF; see *got). |
| k_ra8_err_null_ptr | book, path, buf, or got is NULL. |
| k_ra8_err_not_initialized | Book not open / archive inactive. |
| k_ra8_err_not_found | No entry at path (prefixed or bare). |
| k_ra8_err_not_supported | The entry is DEFLATE-compressed (use the cursor). |
| k_ra8_err_validation_failed | The local header could not be read / is corrupt. |
buf holds len writable bytes. buf. Definition at line 446 of file epub_entry.c.
References epub_book_t::in_use, internal_backing_read(), internal_pread_null_ok(), internal_stored_data_offset(), k_ra8_err_not_initialized, k_ra8_err_validation_failed, k_ra8_ok, priv_epub_book_not_ready(), and epub_book_t::zip_archive_active.
|
nodiscard |
Pull the next chunk of a streaming entry into a bounded caller buffer (#231).
Inflates up to cap more bytes of the entry into buf. A short read (*got < cap) means end-of-entry has been reached; a subsequent call reports *got == 0. The caller reuses the same fixed buf across calls, so the high-water resident footprint is cap – constant regardless of how large the entry inflates to.
| [in] | reader | Cursor from epub_entry_open(). |
| [out] | buf | Destination chunk buffer (cap writable bytes). |
| [in] | cap | Capacity of buf, bytes (> 0). |
| [out] | got | Bytes written this call (0 at end-of-entry). |
| k_ra8_ok | Chunk delivered (or clean EOF with *got == 0). |
| k_ra8_err_null_ptr | reader, buf, or got is NULL. |
| k_ra8_err_not_initialized | reader is closed / never opened. |
| k_ra8_err_invalid_size | cap == 0. |
| k_ra8_err_validation_failed | The compressed stream is corrupt (bad CRC / LZ). |
reader came from a successful epub_entry_open(). buf holds cap writable bytes. Definition at line 360 of file epub_entry.c.
References epub_entry_reader_t::consumed, epub_entry_reader_t::done, epub_entry_reader_t::iter, k_ra8_err_invalid_size, k_ra8_err_not_initialized, k_ra8_err_validation_failed, k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and epub_entry_reader_t::total.
|
static |
Read n absolute archive bytes off the book's backing (resident or streamed).
See implementation. Resident books memcpy from the resident blob; a streamed book pulls the window through its seek+read callback.
| [in] | book | Open book. |
| [in] | archive_ofs | Absolute byte offset within the archive. |
| [out] | buf | Destination (n writable bytes). |
| [in] | n | Bytes to read. |
n bytes were read. | true | Exactly n bytes were copied into buf. |
| false | Short read, out-of-range offset, or no read backend. |
book, buf are non-NULL. n > 0. buf holds the requested window. buf contents are unspecified. Definition at line 170 of file epub_entry.c.
References epub_stream_media_t::ctx, memcpy(), epub_stream_media_t::read, epub_book_t::stream_media, epub_book_t::zip_bytes, and epub_book_t::zip_size.
Referenced by epub_entry_pread(), and internal_stored_data_offset().
|
static |
Verify a 30-byte local header and return the entry's data offset.
See implementation. Checks the local-header signature, then adds the fixed header size plus the file-name and extra-field lengths.
| [in] | hdr | 30-byte local file header. |
| [in] | local_header_ofs | Archive offset the header was read from. |
| [out] | out_data_ofs | Receives the entry's stored-data archive offset. |
| true | Local-header signature matched; *out_data_ofs is set. |
| false | Signature mismatch; *out_data_ofs is left unmodified. |
hdr holds k_epub_ldh_size readable bytes. out_data_ofs is non-NULL. Definition at line 205 of file epub_entry.c.
References k_epub_ldh_extra_len_ofs, k_epub_ldh_fname_len_ofs, k_epub_ldh_sig_0, k_epub_ldh_sig_1, k_epub_ldh_sig_2, k_epub_ldh_sig_3, k_epub_ldh_size, k_epub_le_hi, k_epub_le_lo, k_epub_le_shift, and memcmp().
Referenced by internal_stored_data_offset().
|
static |
Locate an entry by OPF-prefixed path, falling back to the bare path.
See implementation. Mirrors internal_locate_extract() in the chapter TU.
| [in] | zip | Open archive. |
| [in] | book | Book supplying opf_dir for the prefixed attempt. |
| [in] | path | Entry path, OPF-relative or archive-rooted. |
| [out] | out_idx | Receives the located file index on success. |
| k_ra8_ok | Entry located; *out_idx set. |
| k_ra8_err_not_found | Neither the prefixed nor the bare path exists. |
zip, book, path, out_idx are non-NULL. Definition at line 136 of file epub_entry.c.
References k_epub_max_path_len, k_ra8_err_not_found, k_ra8_ok, epub_book_t::opf_dir, and priv_epub_join_path().
Referenced by internal_open_iter(), and internal_stored_data_offset().
|
static |
Locate + stat an entry and start a miniz extract-iterator over it.
See implementation. Split out so epub_entry_open stays under the NASA-Rule-4 statement budget.
| [in] | book | Open book. |
| [in] | path | Entry path (OPF-relative or archive-rooted). |
| [out] | out_iter | Receives the started iterator on success. |
| [out] | out_uncomp | Receives the entry's uncompressed size. |
| k_ra8_ok | Iterator started; outputs set. |
| k_ra8_err_not_found | No entry at path. |
| k_ra8_err_validation_failed | Stat / iterator start failed. |
book is open; out_iter and out_uncomp are non-NULL. Definition at line 244 of file epub_entry.c.
References internal_locate(), internal_zip(), k_ra8_err_validation_failed, k_ra8_ok, and priv_epub_zip_guard_entry().
Referenced by epub_entry_open().
|
static |
Reject any NULL epub_entry_pread pointer argument.
See implementation. Split out so epub_entry_pread stays under the NASA-Rule-4 statement budget.
| [in] | book | Book handle. |
| [in] | path | Entry path. |
| [in] | buf | Destination buffer. |
| [in] | got | Output count. |
| k_ra8_ok | All four pointers are non-NULL. |
| k_ra8_err_null_ptr | Some pointer is NULL. |
Definition at line 434 of file epub_entry.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by epub_entry_pread().
|
static |
Resolve a stored entry's archive data offset + uncompressed size.
See implementation. Split out so epub_entry_pread stays under the NASA-Rule-4 statement budget. Rejects DEFLATE entries.
| [in] | book | Open book. |
| [in] | path | Entry path (OPF-relative or archive-rooted). |
| [out] | out_data_ofs | Receives the entry's stored-data archive offset. |
| [out] | out_uncomp | Receives the entry's uncompressed size. |
| k_ra8_ok | Offset + size resolved. |
| k_ra8_err_not_found | No entry at path. |
| k_ra8_err_not_supported | The entry is DEFLATE-compressed. |
| k_ra8_err_validation_failed | Stat / local-header read failed. |
book is open; out_data_ofs and out_uncomp are non-NULL. Definition at line 293 of file epub_entry.c.
References internal_backing_read(), internal_data_offset(), internal_locate(), internal_zip(), k_epub_ldh_size, k_ra8_err_not_supported, k_ra8_err_validation_failed, k_ra8_ok, and priv_epub_zip_guard_entry().
Referenced by epub_entry_pread().
|
static |
Borrow the book's inline mz_zip_archive.
See implementation.
| [in] | book | Open book owning the inline archive storage. |
book). book is non-NULL. book was opened (archive storage initialised). book storage. Definition at line 111 of file epub_entry.c.
References epub_book_t::zip_archive_storage.
Referenced by internal_open_iter(), and internal_stored_data_offset().
|
static |
Module log tag.
Definition at line 48 of file epub_entry.c.