|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Import-time pagination cache serialiser / loader for reflow. More...
#include "reflow_cache.h"#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_err.h"#include "reflow.h"Go to the source code of this file.
Data Structures | |
| struct | priv_cache_key_t |
| Parsed header / invalidation key of a cache blob. More... | |
Enumerations | |
| enum | priv_cache_const_t : uint32_t { k_priv_fnv_offset = 0x811C9DC5U , k_priv_fnv_prime = 0x01000193U , k_priv_byte_mask = 0xFFU , k_priv_shift_8 = 8U , k_priv_shift_16 = 16U , k_priv_shift_24 = 24U } |
| FNV-1a parameters and byte-extraction shifts / mask. More... | |
| enum | priv_cache_off_t : size_t { k_priv_checksum_off = 48U } |
| Fixed byte offsets within the serialised header. More... | |
Functions | |
| static void | internal_put_u32 (uint8_t *buf, size_t *off, uint32_t word) |
| Append a little-endian uint32_t and advance the cursor. | |
| static void | internal_put_u16 (uint8_t *buf, size_t *off, uint16_t half) |
| Append a little-endian uint16_t and advance the cursor. | |
| static uint32_t | internal_get_u32 (const uint8_t *buf, size_t *off) |
| Read a little-endian uint32_t and advance the cursor. | |
| static uint16_t | internal_get_u16 (const uint8_t *buf, size_t *off) |
| Read a little-endian uint16_t and advance the cursor. | |
| static uint32_t | internal_fnv1a (const uint8_t *data, size_t len) |
| 32-bit FNV-1a hash over a byte range. | |
| static void | internal_put_glyph (uint8_t *buf, size_t *off, const reflow_glyph_t *glyph) |
| Serialise one glyph (20 bytes) and advance the cursor. | |
| static void | internal_get_glyph (const uint8_t *buf, size_t *off, reflow_glyph_t *glyph) |
| Deserialise one glyph (20 bytes) and advance the cursor. | |
| static void | internal_put_page (uint8_t *buf, size_t *off, const reflow_page_t *page) |
| Serialise one page record (8 bytes) and advance the cursor. | |
| static void | internal_get_page (const uint8_t *buf, size_t *off, reflow_page_t *page) |
| Deserialise one page record (8 bytes) and advance the cursor. | |
| static uint32_t | internal_font_hash (const reflow_t *engine) |
| Hash the engine's font blob (0 when no font is bound). | |
| static void | internal_put_header (uint8_t *buf, const reflow_t *engine, size_t content_len, uint32_t content_hash) |
| Write the fixed-size header (checksum left as a zero placeholder). | |
| static void | internal_get_header (const uint8_t *buf, priv_cache_key_t *key) |
| Parse the fixed-size header into a key struct. | |
| static size_t | internal_blob_size (uint32_t glyph_count, uint32_t page_count) |
| Total serialised size for the given record counts. | |
| static bool | internal_key_matches (const reflow_t *engine, const priv_cache_key_t *key, const uint8_t *content, size_t content_len) |
| True when the blob's key matches the engine + supplied content. | |
| static ra8_err_t | internal_parse_header (const uint8_t *buf, size_t len, priv_cache_key_t *key, size_t *need) |
| Validate a blob's header structure and report its total size. | |
| ra8_err_t | reflow_cache_size (const reflow_t *engine, size_t *out_bytes) |
| Report the exact serialised size of an engine's current layout. | |
| static ra8_err_t | internal_cache_precheck (const reflow_t *engine, const uint8_t *content, size_t content_len) |
| Shared serialize/load precheck: init state, content args, and the #109 multi-face cache-bypass invariant. | |
| ra8_err_t | reflow_cache_serialize (const reflow_t *engine, const uint8_t *content, size_t content_len, uint8_t *out_buf, size_t out_cap, size_t *out_len) |
| Serialise the laid-out pages of engine into a keyed byte blob. | |
| ra8_err_t | reflow_cache_load (reflow_t *engine, const uint8_t *content, size_t content_len, const uint8_t *buf, size_t len) |
| Validate a cache blob and, if it matches, restore the layout. | |
Import-time pagination cache serialiser / loader for reflow.
Implements reflow_cache.h: turn a laid-out engine's glyphs[] + pages[] into a keyed little-endian byte blob and back, so the expensive reflow_layout_chapter() pass can be skipped when the viewport / font / colours / font blob / chapter bytes are unchanged.
The serialisation is explicit per field (no memcpy of whole structs), which keeps the format compiler-independent and – crucially – keeps the body checksum deterministic because struct padding bytes are never hashed. Every loop is bounded by a count that the loader first checks against the engine's static pools (k_reflow_max_glyphs / k_reflow_max_pages) and the blob length, so a malformed blob can never overrun (NASA P10 Rules 2 and 7).
[Ring 4 / Reflow] {World: NS}
Definition in file reflow_cache.c.
| enum priv_cache_const_t : uint32_t |
FNV-1a parameters and byte-extraction shifts / mask.
Definition at line 46 of file reflow_cache.c.
| enum priv_cache_off_t : size_t |
Fixed byte offsets within the serialised header.
| Enumerator | |
|---|---|
| k_priv_checksum_off | Body-checksum field offset. |
Definition at line 59 of file reflow_cache.c.
|
static |
Total serialised size for the given record counts.
header + glyph_count * glyph_bytes + page_count * page_bytes. Shared by the size query, the serialiser and the loader so all three agree on the layout.
| [in] | glyph_count | Number of glyph records. |
| [in] | page_count | Number of page records. |
| value | >= k_reflow_cache_header_bytes. |
Definition at line 489 of file reflow_cache.c.
References k_reflow_cache_glyph_bytes, k_reflow_cache_header_bytes, and k_reflow_cache_page_bytes.
Referenced by internal_parse_header(), reflow_cache_serialize(), and reflow_cache_size().
|
static |
Shared serialize/load precheck: init state, content args, and the #109 multi-face cache-bypass invariant.
Per-glyph embedded face indices (#109) are not part of the cache key/format, so a book with any registered @font-face is never cached: it live-layouts instead, and a persisted page can never be mis-served under a different face set. The caller checks its own NULL pointers first.
| [in] | engine | Engine (already NULL-checked by the caller). |
| [in] | content | Chapter bytes, or NULL iff content_len is 0. |
| [in] | content_len | Length of content, bytes. |
| k_ra8_ok | Engine is initialised, content args are valid, and no @font-face faces are registered. |
| k_ra8_err_not_initialized | Engine in_use flag is clear. |
| k_ra8_err_invalid_arg | content is NULL but content_len is non-zero. |
| k_ra8_err_invalid_state | At least one @font-face face is registered; the cache must be bypassed for this chapter. |
Definition at line 665 of file reflow_cache.c.
References reflow_t::face_count, reflow_t::in_use, k_ra8_err_invalid_arg, k_ra8_err_invalid_state, k_ra8_err_not_initialized, and k_ra8_ok.
Referenced by reflow_cache_load(), and reflow_cache_serialize().
|
static |
32-bit FNV-1a hash over a byte range.
Standard FNV-1a: seed with the offset basis, then for each byte XOR-in and multiply by the FNV prime. Used for both the font and content key hashes and the body checksum.
| [in] | data | Bytes to hash (may be NULL only when len == 0). |
| [in] | len | Number of bytes. |
| value | The 32-bit hash of data[0 .. len). |
Definition at line 233 of file reflow_cache.c.
References k_priv_fnv_offset, and k_priv_fnv_prime.
Referenced by internal_font_hash(), reflow_cache_load(), and reflow_cache_serialize().
|
static |
Hash the engine's font blob (0 when no font is bound).
Computes the FNV-1a digest over engine->font_data so a different font face / subset invalidates a cached layout.
| [in] | engine | Engine whose font blob is hashed. |
| 0 | engine->font_data is NULL. |
| value | FNV-1a of font_data[0 .. font_len). |
Definition at line 379 of file reflow_cache.c.
References reflow_t::font_data, reflow_t::font_len, and internal_fnv1a().
Referenced by internal_key_matches(), and internal_put_header().
|
static |
Deserialise one glyph (20 bytes) and advance the cursor.
Reads the seven serialised fields, including the reserved link id, so the restored struct is byte-identical to the original (no field is silently zeroed).
| [in] | buf | Source buffer (>= 20 bytes readable at *off). |
| [in,out] | off | Read cursor (advanced by 20). |
| [out] | glyph | Receives the decoded glyph. |
Definition at line 295 of file reflow_cache.c.
References reflow_glyph_t::color, reflow_glyph_t::cp, reflow_glyph_t::font_px, internal_get_u16(), internal_get_u32(), reflow_glyph_t::reserved, reflow_glyph_t::style, reflow_glyph_t::x, and reflow_glyph_t::y.
Referenced by reflow_cache_load().
|
static |
Parse the fixed-size header into a key struct.
Decodes every header field in the same order internal_put_header() wrote them, skipping the two reserved half-words.
| [in] | buf | Source buffer (>= header bytes readable). |
| [out] | key | Receives the parsed header fields. |
Definition at line 447 of file reflow_cache.c.
References priv_cache_key_t::body_checksum, priv_cache_key_t::body_color, priv_cache_key_t::content_hash, priv_cache_key_t::content_len, priv_cache_key_t::font_hash, priv_cache_key_t::font_len, priv_cache_key_t::font_px, priv_cache_key_t::glyph_count, internal_get_u16(), internal_get_u32(), priv_cache_key_t::link_color, priv_cache_key_t::magic, priv_cache_key_t::page_count, priv_cache_key_t::version, priv_cache_key_t::viewport_h, and priv_cache_key_t::viewport_w.
Referenced by internal_parse_header().
|
static |
Deserialise one page record (8 bytes) and advance the cursor.
Reads the two uint32_t glyph-range fields little-endian.
| [in] | buf | Source buffer (>= 8 bytes readable at *off). |
| [in,out] | off | Read cursor (advanced by 8). |
| [out] | page | Receives the decoded page record. |
Definition at line 348 of file reflow_cache.c.
References reflow_page_t::glyph_count, reflow_page_t::glyph_first, and internal_get_u32().
Referenced by reflow_cache_load().
|
static |
Read a little-endian uint16_t and advance the cursor.
Reads two bytes least-significant-first from *off and advances *off by 2.
| [in] | buf | Source buffer (>= 2 bytes readable at *off). |
| [in,out] | off | Read cursor (advanced by 2). |
| value | The little-endian half-word assembled from two bytes. |
Definition at line 198 of file reflow_cache.c.
References k_priv_shift_8.
Referenced by internal_get_glyph(), and internal_get_header().
|
static |
Read a little-endian uint32_t and advance the cursor.
Reads four bytes least-significant-first from *off and advances *off by 4.
| [in] | buf | Source buffer (>= 4 bytes readable at *off). |
| [in,out] | off | Read cursor (advanced by 4). |
| value | The little-endian word assembled from four bytes. |
Definition at line 165 of file reflow_cache.c.
References k_priv_shift_16, k_priv_shift_24, and k_priv_shift_8.
Referenced by internal_get_glyph(), internal_get_header(), and internal_get_page().
|
static |
True when the blob's key matches the engine + supplied content.
Compares every keyed attribute – viewport, font size, body / link colours, font length + hash, and content length + hash – so any change that would alter the layout is detected.
| [in] | engine | Engine holding the current viewport / font / colours. |
| [in] | key | Parsed blob header. |
| [in] | content | Chapter bytes to hash and compare. |
| [in] | content_len | Length of content, bytes. |
| true | Every keyed attribute matches. |
| false | At least one attribute differs (layout is stale). |
Definition at line 520 of file reflow_cache.c.
References priv_cache_key_t::body_color, reflow_t::body_color, priv_cache_key_t::content_hash, priv_cache_key_t::content_len, priv_cache_key_t::font_hash, priv_cache_key_t::font_len, reflow_t::font_len, priv_cache_key_t::font_px, reflow_t::font_px, internal_fnv1a(), internal_font_hash(), priv_cache_key_t::link_color, reflow_t::link_color, priv_cache_key_t::viewport_h, reflow_t::viewport_h, priv_cache_key_t::viewport_w, and reflow_t::viewport_w.
Referenced by reflow_cache_load().
|
static |
Validate a blob's header structure and report its total size.
Checks, in order, that len covers the fixed header, that the magic and format version match, and that the record counts do not exceed the engine's static pools (k_reflow_max_glyphs / k_reflow_max_pages), then computes the expected total blob size and confirms len covers it. Pure structural validation – the invalidation key and the body checksum are verified by the caller.
| [in] | buf | Serialised blob (at least len readable bytes). |
| [in] | len | Length of buf, bytes. |
| [out] | key | Receives the parsed header fields. |
| [out] | need | Receives the expected total blob size, bytes. |
| k_ra8_ok | Header valid; *need set. |
| k_ra8_err_not_found | Magic mismatch (not a cache blob). |
| k_ra8_err_invalid_state | Format version mismatch. |
| k_ra8_err_invalid_size | Short header, record counts beyond the engine pools, or len below the size. |
Definition at line 592 of file reflow_cache.c.
References priv_cache_key_t::glyph_count, internal_blob_size(), internal_get_header(), k_ra8_err_invalid_size, k_ra8_err_invalid_state, k_ra8_err_not_found, k_ra8_ok, k_reflow_cache_header_bytes, k_reflow_cache_magic, k_reflow_cache_version, k_reflow_max_glyphs, k_reflow_max_pages, priv_cache_key_t::magic, priv_cache_key_t::page_count, and priv_cache_key_t::version.
Referenced by reflow_cache_load().
|
static |
Serialise one glyph (20 bytes) and advance the cursor.
Writes the seven meaningful fields (x, y, cp, colour, font_px, style, reserved). reserved holds the 1-based <a> link id (0 = not a link), which is layout state the renderer needs for hyperlink hit-testing – it is not padding, so it is stored.
| [out] | buf | Destination buffer (>= 20 bytes free at *off). |
| [in,out] | off | Write cursor (advanced by 20). |
| [in] | glyph | Glyph to serialise. |
Definition at line 263 of file reflow_cache.c.
References reflow_glyph_t::color, reflow_glyph_t::cp, reflow_glyph_t::font_px, internal_put_u16(), internal_put_u32(), reflow_glyph_t::reserved, reflow_glyph_t::style, reflow_glyph_t::x, and reflow_glyph_t::y.
Referenced by reflow_cache_serialize().
|
static |
Write the fixed-size header (checksum left as a zero placeholder).
Encodes the magic, version, the invalidation key (viewport / font / colours / font hash / content hash) and the record counts. The body-checksum field is written as zero and back-patched by the caller once the payload exists.
| [out] | buf | Destination buffer (>= header bytes). |
| [in] | engine | Engine providing viewport / font / colours. |
| [in] | content_len | Chapter byte length for the key. |
| [in] | content_hash | FNV-1a of the chapter bytes for the key. |
Definition at line 409 of file reflow_cache.c.
References reflow_t::body_color, reflow_t::font_len, reflow_t::font_px, reflow_t::glyph_count, internal_font_hash(), internal_put_u16(), internal_put_u32(), k_reflow_cache_magic, k_reflow_cache_version, reflow_t::link_color, reflow_t::page_count, reflow_t::viewport_h, and reflow_t::viewport_w.
Referenced by reflow_cache_serialize().
|
static |
Serialise one page record (8 bytes) and advance the cursor.
Writes the two uint32_t glyph-range fields little-endian.
| [out] | buf | Destination buffer (>= 8 bytes free at *off). |
| [in,out] | off | Write cursor (advanced by 8). |
| [in] | page | Page record to serialise. |
Definition at line 325 of file reflow_cache.c.
References reflow_page_t::glyph_count, reflow_page_t::glyph_first, and internal_put_u32().
Referenced by reflow_cache_serialize().
|
static |
Append a little-endian uint16_t and advance the cursor.
Writes the two bytes least-significant-first at *off and advances *off by 2.
| [out] | buf | Destination buffer (>= 2 bytes free at *off). |
| [in,out] | off | Write cursor (advanced by 2). |
| [in] | half | Value to store. |
Definition at line 137 of file reflow_cache.c.
References k_priv_byte_mask, and k_priv_shift_8.
Referenced by internal_put_glyph(), and internal_put_header().
|
static |
Append a little-endian uint32_t and advance the cursor.
Writes the four bytes least-significant-first at *off and advances *off by 4.
| [out] | buf | Destination buffer (>= 4 bytes free at *off). |
| [in,out] | off | Write cursor (advanced by 4). |
| [in] | word | Value to store. |
Definition at line 107 of file reflow_cache.c.
References k_priv_byte_mask, k_priv_shift_16, k_priv_shift_24, and k_priv_shift_8.
Referenced by internal_put_glyph(), internal_put_header(), internal_put_page(), and reflow_cache_serialize().
|
nodiscard |
Validate a cache blob and, if it matches, restore the layout.
Parses the blob header, then validates – in order – the magic, the format version, the record counts (against the engine's static pools and the blob length), the invalidation key (viewport / font / colours / font hash / content hash) and the body checksum. Only when all pass are the glyphs[] and pages[] arrays copied back into engine and engine->xhtml_buf / xhtml_len repointed at content (so a later reflow_set_font_size() can still re-flow). On any mismatch the engine is left untouched and the caller should re-lay-out.
| [in,out] | engine | Engine initialised with the same viewport / font / colours the blob was made with (the load validates this). |
| [in] | content | Chapter bytes (hashed and compared to the blob's content hash). May be NULL only when content_len == 0. |
| [in] | content_len | Length of content, bytes. |
| [in] | buf | Serialised blob. |
| [in] | len | Length of buf, bytes. |
| k_ra8_ok | Loaded; glyphs / pages restored. |
| k_ra8_err_null_ptr | engine or buf is NULL. |
| k_ra8_err_not_initialized | engine->in_use == 0. |
| k_ra8_err_invalid_arg | content NULL with content_len>0. |
| k_ra8_err_not_found | Magic mismatch (not a cache blob). |
| k_ra8_err_invalid_state | Version or key mismatch – the layout is stale; re-lay-out and re-serialise. |
| k_ra8_err_invalid_size | Truncated blob or counts exceed pools. |
| k_ra8_err_checksum_mismatch | Body checksum failed (corrupt blob). |
Definition at line 716 of file reflow_cache.c.
References priv_cache_key_t::body_checksum, priv_cache_key_t::glyph_count, reflow_t::glyph_count, reflow_t::glyphs, internal_cache_precheck(), internal_fnv1a(), internal_get_glyph(), internal_get_page(), internal_key_matches(), internal_parse_header(), k_ra8_err_checksum_mismatch, k_ra8_err_invalid_state, k_ra8_err_null_ptr, k_ra8_ok, k_reflow_cache_header_bytes, priv_cache_key_t::page_count, reflow_t::page_count, reflow_t::pages, reflow_t::xhtml_buf, and reflow_t::xhtml_len.
Referenced by internal_pc_invalidate_check_or_halt(), and internal_pc_reload_check_or_halt().
|
nodiscard |
Serialise the laid-out pages of engine into a keyed byte blob.
Writes the header (magic, version, the invalidation key, glyph / page counts and a body checksum) followed by the flat glyphs[] array and the pages[] index ranges, each field little-endian. The key captures the engine's viewport, font size, colours, the font blob (length + FNV-1a hash) and the supplied content (length + FNV-1a hash) so a later reflow_cache_load() can detect any change that would invalidate the layout.
| [in] | engine | Laid-out engine handle. |
| [in] | content | Chapter bytes the layout was produced from (hashed into the key). May be NULL only when content_len == 0. |
| [in] | content_len | Length of content, bytes. |
| [out] | out_buf | Destination buffer. |
| [in] | out_cap | Capacity of out_buf, bytes. |
| [out] | out_len | Receives the number of bytes written. |
| k_ra8_ok | Serialised; *out_len bytes written. |
| k_ra8_err_null_ptr | engine, out_buf or out_len NULL. |
| k_ra8_err_not_initialized | engine->in_use == 0. |
| k_ra8_err_invalid_arg | content NULL with content_len > 0. |
| k_ra8_err_invalid_size | out_cap smaller than the blob size. |
Definition at line 679 of file reflow_cache.c.
References reflow_t::glyph_count, reflow_t::glyphs, internal_blob_size(), internal_cache_precheck(), internal_fnv1a(), internal_put_glyph(), internal_put_header(), internal_put_page(), internal_put_u32(), k_priv_checksum_off, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, k_reflow_cache_header_bytes, reflow_t::page_count, and reflow_t::pages.
Referenced by internal_pc_live_layout_or_halt(), and internal_pc_reload_check_or_halt().
Report the exact serialised size of an engine's current layout.
Lets the caller size (or bounds-check) the destination buffer before calling reflow_cache_serialize(). The value is k_reflow_cache_header_bytes + engine->glyph_count * k_reflow_cache_glyph_bytes + engine->page_count * k_reflow_cache_page_bytes.
| [in] | engine | Initialised engine (a chapter need not be laid out yet; an empty layout serialises to just the header). |
| [out] | out_bytes | Receives the required buffer size in bytes. |
| k_ra8_ok | Size reported. |
| k_ra8_err_null_ptr | engine or out_bytes is NULL. |
| k_ra8_err_not_initialized | engine->in_use == 0. |
Definition at line 622 of file reflow_cache.c.
References reflow_t::glyph_count, reflow_t::in_use, internal_blob_size(), k_ra8_err_not_initialized, k_ra8_err_null_ptr, k_ra8_ok, and reflow_t::page_count.