|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Serialize a compiled-book chapter DOM back to XHTML for the renderer. More...
#include <string.h>#include "book.h"#include "book_internal.h"#include "book_paged.h"#include "ra8_attributes.h"#include "ra8_check.h"Go to the source code of this file.
Data Structures | |
| struct | book_walk_entry_t |
| One deferred unit of work on the serializer stack. More... | |
Functions | |
| static bool | internal_emit (char *out, size_t cap, size_t *pos, const char *src, size_t len) |
| Append a raw byte span to the output buffer. | |
| static bool | internal_emit_cstr (char *out, size_t cap, size_t *pos, const char *str) |
| Append a NUL-terminated string to the output buffer. | |
| static bool | internal_emit_escaped (char *out, size_t cap, size_t *pos, const char *str, bool in_attr) |
| Append entity-escaped text to the output buffer. | |
| static bool | internal_is_void (const char *name) |
| Test whether an element name is an HTML void element. | |
| static bool | internal_emit_attrs (const void *base, const book_node_t *node, char *out, size_t cap, size_t *pos) |
| Append all attributes of a DOM node to the output buffer. | |
| static bool | internal_open_element (const void *base, const book_node_t *node, char *out, size_t cap, size_t *pos, book_walk_entry_t *stack, uint32_t *sp) |
| Emit an element open tag and schedule its close and children on the walk stack. | |
| static bool | internal_walk_to_xhtml (const void *base, uint32_t root, uint32_t node_count, char *out, size_t cap, size_t *pos) |
| Iterative, bounded DOM walk that serialises a subtree to XHTML. | |
| bool | priv_book_is_block (const char *name) |
| Test whether an element name is a block-level HTML element. | |
| bool | priv_book_emit_text (char *out, size_t cap, size_t *pos, const char *str, bool *at_break) |
| Append a whitespace-collapsed text run to the output buffer. | |
| bool | priv_book_emit_break (char *out, size_t cap, size_t *pos, bool *at_break) |
| Append a paragraph break, collapsing consecutive block-level breaks. | |
| static bool | internal_walk_text (const void *base, uint32_t root, uint32_t node_count, char *out, size_t cap, size_t *pos) |
| Bounded pre-order walk that extracts plain text from a DOM subtree. | |
| ra8_err_t | book_chapter_text (const void *base, uint32_t chapter_idx, char *out, size_t cap, size_t *out_len) |
| Extract one chapter's readable plain text from the DOM. | |
| ra8_err_t | book_chapter_to_xhtml (const void *base, uint32_t chapter_idx, char *out, size_t cap, size_t *out_len) |
| Serialize one chapter's DOM subtree back to XHTML for the renderer. | |
Variables | |
| static const char *const | s_tag_xhtml = "book_xhtml" |
| Log tag for serializer diagnostics. | |
Serialize a compiled-book chapter DOM back to XHTML for the renderer.
reflow_layout_chapter() consumes XHTML. This bridge walks a chapter's pre-parsed book DOM and re-emits well-formed XHTML so a compiled book renders through the existing, MC/DC-tested reflow engine without modifying it. The walk is iterative (an explicit open/close stack, NASA Rule 1) and bounded (NASA Rule 2): nothing recurses, the stack and iteration count are capped. Serialization is lossless – every element tag, attribute and text run is preserved; void elements self-close and text/attribute values are entity-escaped.
A future optimization can feed the DOM straight into the tokenizer and skip this XHTML round-trip; until then the bridge keeps the renderer untouched.
Definition in file book_xhtml.c.
| ra8_err_t book_chapter_text | ( | const void * | base, |
| uint32_t | chapter_idx, | ||
| char * | out, | ||
| size_t | cap, | ||
| size_t * | out_len ) |
Extract one chapter's readable plain text from the DOM.
Walks the chapter's element/text tree iteratively (no recursion, bounded stack) and writes its text runs into out, inserting a newline at each block-level element so paragraphs stay separated. Markup, attributes and inline structure are dropped – this is for a simple word-wrap reader, not rich layout. The output is NOT NUL-terminated.
| [in] | base | Validated book blob base (non-NULL). |
| [in] | chapter_idx | Spine chapter index (< header chapter_count). |
| [out] | out | Destination text buffer (non-NULL). |
| [in] | cap | Capacity of out in bytes. |
| [out] | out_len | Receives the text byte length written. |
| k_ra8_ok | Chapter text extracted. |
| k_ra8_err_null_ptr | A required pointer argument is NULL. |
| k_ra8_err_invalid_arg | chapter_idx is out of range. |
| k_ra8_err_invalid_size | Output did not fit cap, or DOM nesting exceeded the bounded walk stack. |
base was accepted by book_validate() / book_open(). chapter_idx is less than book_header(base)->chapter_count. out contents are unspecified.out. Definition at line 683 of file book_xhtml.c.
References book_chapters(), book_header(), book_header_t::chapter_count, internal_walk_text(), k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_ok, book_header_t::node_count, RA8_CHECK_NULL_PTR, book_chapter_t::root_node, and s_tag_xhtml.
Referenced by book_chapter_text_src(), and imp_walk_book().
| ra8_err_t book_chapter_to_xhtml | ( | const void * | base, |
| uint32_t | chapter_idx, | ||
| char * | out, | ||
| size_t | cap, | ||
| size_t * | out_len ) |
Serialize one chapter's DOM subtree back to XHTML for the renderer.
A bridge for feeding a compiled book into reflow_layout_chapter(), which consumes XHTML. Walks the chapter's element/text tree iteratively (no recursion, bounded stack) and writes well-formed XHTML – every tag, attribute and text run, faithfully – into out. Void elements self-close; text and attribute values are entity-escaped. The output is NOT NUL-terminated.
| [in] | base | Validated book blob base (non-NULL). |
| [in] | chapter_idx | Spine chapter index (< header chapter_count). |
| [out] | out | Destination XHTML buffer (non-NULL). |
| [in] | cap | Capacity of out in bytes. |
| [out] | out_len | Receives the XHTML byte length written. |
| k_ra8_ok | Chapter serialized; out_len bytes written. |
| k_ra8_err_null_ptr | A required pointer argument is NULL. |
| k_ra8_err_invalid_arg | chapter_idx is out of range. |
| k_ra8_err_invalid_size | Output did not fit cap, or DOM nesting exceeded the bounded walk stack. |
base was accepted by book_validate() / book_open(). cap is large enough for the chapter's serialized XHTML. out contents are unspecified.out. Definition at line 702 of file book_xhtml.c.
References book_chapters(), book_header(), book_header_t::chapter_count, internal_walk_to_xhtml(), k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_ok, book_header_t::node_count, RA8_CHECK_NULL_PTR, book_chapter_t::root_node, and s_tag_xhtml.
Referenced by erb_render_chapter().
|
static |
Append a raw byte span to the output buffer.
Copies exactly len bytes from src into out starting at *pos, advancing *pos by len on success. If the copy would exceed cap the buffer is left unchanged and the function returns false so callers can chain with && and abort the entire serialisation on first overflow.
| [out] | out | Destination character buffer receiving the bytes. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset into out; advanced by len when the append succeeds. |
| [in] | src | Source byte span to copy (need not be NUL-terminated). |
| [in] | len | Number of bytes to copy from src. |
| true | Bytes copied successfully; *pos advanced by len. |
| false | Output buffer would overflow; buffer and *pos unchanged. |
out is a valid, writable buffer of at least cap bytes. pos is non-null and *pos <= cap on entry. *pos equals the previous value plus len. *pos and out contents are unchanged.Definition at line 75 of file book_xhtml.c.
References memcpy().
Referenced by internal_emit_attrs(), internal_emit_cstr(), internal_emit_escaped(), internal_open_element(), internal_walk_to_xhtml(), priv_book_emit_break(), and priv_book_emit_text().
|
static |
Append all attributes of a DOM node to the output buffer.
Iterates over the attr_count attribute slots starting at node->first_attr in the flat attribute array returned by book_attrs. For each attribute it emits a single space, the attribute name, =" (with entity-escaped value),
and a closing @c " using internal_emit and internal_emit_escaped. The function is called while the opening tag is still open (before the > or />) so the caller must emit the tag terminator after this returns.
| [in] | base | Pointer to the start of the compiled book blob; used to resolve attribute name and value string offsets via book_string and book_attrs. |
| [in] | node | DOM node whose attributes are to be serialised. |
| [out] | out | Destination character buffer. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced for each byte emitted. |
| true | All attributes emitted successfully. |
| false | Output buffer overflowed; partial output may have been written. |
base points to a valid, fully initialised compiled book blob. node is a non-null pointer to an element node within the blob. *pos reflects all attribute bytes written. *pos reflects the bytes written before the overflow.Definition at line 274 of file book_xhtml.c.
References book_node_t::attr_count, book_attrs(), book_string(), book_node_t::first_attr, internal_emit(), internal_emit_cstr(), internal_emit_escaped(), book_attr_t::name_off, and book_attr_t::value_off.
Referenced by internal_open_element().
|
static |
Append a NUL-terminated string to the output buffer.
Determines the length of str with strlen and delegates to internal_emit. Provides a convenient wrapper so callers do not need to compute string lengths manually when emitting tag names, attribute names, or literal XML punctuation.
| [out] | out | Destination character buffer. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced by the string length on success. |
| [in] | str | NUL-terminated source string to append. |
| true | String appended; *pos advanced by strlen(str). |
| false | Output buffer would overflow; buffer and *pos unchanged. |
out is a valid, writable buffer of at least cap bytes. str is a valid, NUL-terminated C string. *pos equals the previous value plus strlen(str). *pos and out contents are unchanged.Definition at line 113 of file book_xhtml.c.
References internal_emit(), RA8_INTERNAL, and strlen().
Referenced by internal_emit_attrs(), internal_emit_escaped(), internal_open_element(), and internal_walk_to_xhtml().
|
static |
Append entity-escaped text to the output buffer.
Iterates over every character in str and replaces XML-special characters with their entity references before writing them to the output buffer via internal_emit or internal_emit_cstr. The substitution table is:
& becomes & < becomes < > becomes > " becomes @c " only when @p in_attr is @c true; otherwise
the literal @c " is emitted unchanged. All other characters are forwarded as-is. The function stops on the first overflow, leaving *pos at the last successfully written position.| [out] | out | Destination character buffer. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced for each character (or its entity expansion) successfully appended. |
| [in] | str | NUL-terminated source text to escape and append. |
| [in] | in_attr | When true the context is an XML attribute value and double-quotes are entity-escaped; when false the context is element content and " is literal. |
| true | All characters written successfully. |
| false | Output buffer overflowed; partial output may have been written. |
out is a valid, writable buffer of at least cap bytes. str is a valid, NUL-terminated C string. str has been entity-escaped and appended; *pos reflects the total bytes written. *pos reflects the number of bytes written before the overflow.Definition at line 158 of file book_xhtml.c.
References internal_emit(), and internal_emit_cstr().
Referenced by internal_emit_attrs(), and internal_walk_to_xhtml().
|
static |
Test whether an element name is an HTML void element.
Performs a linear search through a fixed table of HTML void element names (elements that must self-close and may not have child nodes in XHTML): br, hr, img, meta, link, input, area, base, col, embed, param, source, track, and wbr. The comparison is case-sensitive because compiled book DOM names are already lower-cased during parsing.
| [in] | name | NUL-terminated element name to test (e.g. "br"). |
| true | name matches a known void element; the serialiser must emit /> instead of a separate close tag. |
| false | name is not a void element; a close tag is required. |
name is a valid, NUL-terminated C string. name contains only lower-case ASCII letters (DOM invariant). name with no side effects.Definition at line 214 of file book_xhtml.c.
References RA8_INTERNAL, and strcmp().
Referenced by internal_open_element().
|
static |
Emit an element open tag and schedule its close and children on the walk stack.
Serialises the opening half of a DOM element node into out: emits <, the tag name, all attributes via internal_emit_attrs, then either /> for void elements (using internal_is_void) or > for non-void elements. For non-void elements two entries are pushed onto the caller-supplied stack before returning: first a close entry (so the closing tag is emitted after all descendants), then a child-list entry (so the first child is processed next by the outer loop in internal_walk_to_xhtml). Stack indices grow upward; the current depth is held in *sp.
| [in] | base | Pointer to the compiled book blob; used to resolve string offsets via book_string. |
| [in] | node | Element node to open; must have kind == element. |
| [out] | out | Destination character buffer. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced for each byte emitted. |
| [in,out] | stack | Caller-managed walk stack array of length k_book_xhtml_stack. |
| [in,out] | sp | Stack pointer (count of live entries); incremented by up to 2 for non-void elements. |
| true | Open tag emitted; child and close entries pushed for non-void. |
| false | Output buffer overflowed or stack is full. |
base points to a valid, fully initialised compiled book blob. node is a non-null pointer to an element node; *sp < k_book_xhtml_stack. out and *sp is incremented by 2 for non-void elements (0 for void elements). *pos and *sp may reflect partially completed writes; the caller must abort the walk.Definition at line 331 of file book_xhtml.c.
References book_string(), book_node_t::first_child, internal_emit(), internal_emit_attrs(), internal_emit_cstr(), internal_is_void(), k_book_xhtml_stack, book_node_t::name_off, and RA8_INTERNAL.
Referenced by internal_walk_to_xhtml().
|
static |
Bounded pre-order walk that extracts plain text from a DOM subtree.
Traverses the subtree rooted at root in pre-order using an iterative stack (maximum depth k_book_xhtml_stack) without recursion. An iteration guard capped at node_count * k_book_xhtml_iter_x + k_book_xhtml_stack prevents unbounded execution. For each node:
priv_book_emit_text for whitespace collapsing.priv_book_is_block) trigger priv_book_emit_break to insert a paragraph separator before descending into the element's children.at_break flag threads through all text and break calls so that leading whitespace at the start of each block is suppressed.| [in] | base | Pointer to the compiled book blob. |
| [in] | root | Node index of the subtree root to extract text from. |
| [in] | node_count | Total number of nodes in the blob; used to compute the iteration guard bound. |
| [out] | out | Destination character buffer for the plain text. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced as bytes are emitted. |
| true | Entire subtree processed; plain text in out at *pos bytes. |
| false | Output buffer overflowed, stack exhausted, or iteration guard triggered (possible cycle in DOM). |
base points to a valid, fully initialised compiled book blob. root is a valid node index within the blob (less than node_count). *pos equals the number of plain-text bytes written. *pos reflects bytes written before the error condition.Definition at line 633 of file book_xhtml.c.
References book_nodes(), book_string(), book_node_t::first_child, k_book_nil, k_book_node_text, k_book_xhtml_iter_x, k_book_xhtml_stack, book_node_t::kind, book_node_t::name_off, book_node_t::next_sibling, priv_book_emit_break(), priv_book_emit_text(), priv_book_is_block(), RA8_INTERNAL, and book_node_t::text_off.
Referenced by book_chapter_text().
|
static |
Iterative, bounded DOM walk that serialises a subtree to XHTML.
Performs a depth-first serialisation of the subtree rooted at root without recursion. A book_walk_entry_t stack (maximum depth k_book_xhtml_stack) holds deferred work: each entry is either a node-to-open or a pending close tag. The main loop pops one entry per iteration, emitting the appropriate text. An iteration guard capped at node_count * k_book_xhtml_iter_x + k_book_xhtml_stack prevents any unbounded execution even if the DOM contains cycles. Element nodes delegate opening (and child/close scheduling) to internal_open_element; text nodes are emitted via internal_emit_escaped.
| [in] | base | Pointer to the compiled book blob. |
| [in] | root | Node index of the subtree root to serialise. |
| [in] | node_count | Total number of nodes in the blob; used to compute the iteration guard bound. |
| [out] | out | Destination character buffer for the XHTML output. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced as bytes are emitted. |
| true | Entire subtree serialised without overflow or guard expiry. |
| false | Output buffer overflowed, stack exhausted, or iteration guard triggered (possible cycle in DOM). |
base points to a valid, fully initialised compiled book blob. root is a valid node index within the blob (less than node_count). *pos reflects all XHTML bytes written for the subtree. *pos reflects bytes written before the error condition.Definition at line 393 of file book_xhtml.c.
References book_nodes(), book_string(), internal_emit(), internal_emit_cstr(), internal_emit_escaped(), internal_open_element(), book_walk_entry_t::is_close, k_book_nil, k_book_node_text, k_book_xhtml_iter_x, k_book_xhtml_stack, book_node_t::kind, book_node_t::next_sibling, RA8_INTERNAL, book_node_t::text_off, and book_walk_entry_t::value.
Referenced by book_chapter_to_xhtml().
| bool priv_book_emit_break | ( | char * | out, |
| size_t | cap, | ||
| size_t * | pos, | ||
| bool * | at_break ) |
Append a paragraph break, collapsing consecutive block-level breaks.
Trims any trailing space characters already written to out (by decrementing *pos while the last byte is ' '), then sets *at_break to true to suppress leading whitespace in the next text fragment. If the last byte already in out is '\n' no additional newline is written, which collapses runs of breaks produced by consecutive or nested block-level elements (e.g. a p inside a div) into a single blank line. Otherwise a single '\n' is appended via internal_emit.
| [out] | out | Destination character buffer. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; may be decremented to trim trailing spaces, then advanced by 1 if a newline is emitted. |
| [in,out] | at_break | Set to true on entry to suppress subsequent leading whitespace; value on entry is ignored. |
| true | Break emitted (or collapsed into an existing newline). |
| false | Output buffer overflowed while writing the newline byte. |
out is a valid, writable buffer of at least cap bytes. pos is non-null and *pos <= cap on entry. *at_break is true on return. out before the current *pos have been removed; at most one '\n' is appended.Definition at line 583 of file book_xhtml.c.
References internal_emit(), and RA8_PRIV.
Referenced by internal_paged_visit_node(), and internal_walk_text().
| bool priv_book_emit_text | ( | char * | out, |
| size_t | cap, | ||
| size_t * | pos, | ||
| const char * | str, | ||
| bool * | at_break ) |
Append a whitespace-collapsed text run to the output buffer.
Iterates over str character by character applying the HTML whitespace-collapsing rule: any run of space (' '), tab ('\t'), carriage return ('\r'), or newline ('\n') characters is folded into at most a single ASCII space. Non-whitespace characters are passed through unchanged via internal_emit. The at_break flag carries inter-call state: when true any leading whitespace in the current fragment is silently dropped, preventing pretty-print indentation between inline elements from leaking into the rendered prose. at_break is set to true after a whitespace run is emitted and set to false after any non-whitespace character is emitted.
| [out] | out | Destination character buffer. |
| [in] | cap | Total capacity of out in bytes. |
| [in,out] | pos | Current write offset; advanced for each byte written. |
| [in] | str | NUL-terminated text fragment to collapse and append. |
| [in,out] | at_break | On entry: true if the previous output ended with a break or collapsed space that suppresses leading whitespace. On exit: updated to reflect the trailing state of this fragment. |
| true | Text run appended successfully (or was entirely suppressed whitespace). |
| false | Output buffer overflowed; partial output may have been written. |
out is a valid, writable buffer of at least cap bytes. str is a valid, NUL-terminated C string. str has been processed and *pos reflects the bytes appended to out. *at_break accurately reflects the trailing whitespace state after the call, regardless of success or failure.Definition at line 526 of file book_xhtml.c.
References internal_emit().
Referenced by internal_paged_emit_run(), and internal_walk_text().
| bool priv_book_is_block | ( | const char * | name | ) |
Test whether an element name is a block-level HTML element.
Performs a linear search through a fixed table of block-level element names used to decide where to insert paragraph-break newlines during plain-text extraction. The checked names are: p, h1, h2, h3, h4, h5, h6, li, ul, ol, div, br, hr, section, tr, pre, header, blockquote, article, aside, footer, figure, and figcaption. The comparison is case-sensitive because compiled book DOM names are lower-cased during parsing.
| [in] | name | NUL-terminated element name to test (e.g. "p"). |
| true | name is a block-level element; the text walker should emit a line break before descending into this element. |
| false | name is an inline element; no break is inserted. |
name is a valid, NUL-terminated C string. name contains only lower-case ASCII letters (DOM invariant). name with no side effects.Definition at line 470 of file book_xhtml.c.
References RA8_PRIV, and strcmp().
Referenced by internal_paged_visit_node(), and internal_walk_text().
|
static |
Log tag for serializer diagnostics.
Definition at line 32 of file book_xhtml.c.
Referenced by book_chapter_text(), and book_chapter_to_xhtml().