49 const uint8_t* source,
77 while (scan < ctx->string_size) {
79 const size_t length =
strlen(candidate);
80 if (length == written) {
81 size_t equal_bytes = 0U;
82 while ((equal_bytes < written) && (candidate[equal_bytes] == scratch[equal_bytes])) {
85 if (equal_bytes == written) {
89 scan += (uint32_t)length + 1U;
127 for (uint16_t i = 0U; i <
event->attribute_count; ++i) {
129 bool has_value =
false;
131 xml_attr_next(source, source_len, event, &cursor, &attribute, &has_value);
168 uint16_t parent_level,
169 uint32_t next_sibling)
171 const uint32_t previous_node = workspace->
last_children[parent_level];
206 uint16_t selected_depth,
216 const uint32_t node =
221 const uint16_t level = (uint16_t)(event->
depth - selected_depth);
256 uint16_t selected_depth,
272 const uint16_t parent_level = (uint16_t)(event->
depth - selected_depth - 1U);
303 uint16_t* root_depth,
305 uint16_t* direct_children,
312 *root_depth =
event->depth;
320 if (event->
depth != (uint16_t)(*root_depth + 1U)) {
359 uint16_t root_depth = 0U;
360 uint16_t direct_children = 0U;
361 bool saw_root =
false;
363 while ((err ==
k_ra8_ok) && !done) {
478 return internal_emit_start(source, length, selection, event, ctx, workspace, active, out_root);
554 return internal_emit(source, source_len, &selection, ctx, workspace, &root);
583 const char* chapter_href,
584 const char* chapter_title,
587 if (xhtml_bytes ==
nullptr) {
590 if (ctx ==
nullptr) {
593 if (chapter_href ==
nullptr) {
596 if (chapter_title ==
nullptr) {
599 if (workspace ==
nullptr) {
602 if (xhtml_len == 0U) {
611 const char* chapter_href,
612 const char* chapter_title,
632 err =
internal_emit(xhtml_bytes, xhtml_len, &selection, ctx, workspace, &root);
@ k_book_nil
Absent index / "applies to all chapters".
Annotation-attribute framework macros for ra8-firmware.
#define RA8_TEST_HELPER
Mark a symbol as externally-linked but only callable from tests.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
size_t strlen(const char *s)
Calculate string length.
static uint32_t internal_intern_span(ra8_rabook_ctx_t *ctx, const uint8_t *source, size_t source_len, xml_span_t span)
Intern one decoded immutable span through the existing string pool.
static ra8_err_t internal_select_event(const uint8_t *source, size_t length, const xml_event_t *event, uint16_t *root_depth, bool *saw_root, uint16_t *direct_children, priv_selection_t *out, bool *out_done)
Apply one reader event to the direct-body selection search.
ra8_err_t ra8_rabook_xml_parse_chapter(const uint8_t *xhtml_bytes, size_t xhtml_len, ra8_rabook_ctx_t *ctx, const char *chapter_href, const char *chapter_title, ra8_rabook_xml_workspace_t *workspace)
Parse one XHTML chapter and append it to ctx.
static ra8_err_t internal_emit_event(const uint8_t *source, size_t length, const priv_selection_t *selection, const xml_event_t *event, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace, bool *active, uint32_t *out_root)
Apply one reader event to the in-progress subtree emission.
static ra8_err_t internal_select(const uint8_t *source, size_t length, xml_workspace_t *xml, priv_selection_t *out)
Find a direct body or fall back to the document root.
static ra8_err_t internal_text(const uint8_t *source, size_t source_len, const xml_event_t *event, uint16_t selected_depth, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace)
Emit one decoded text run beneath the current element.
static ra8_err_t internal_parse_chapter_validate_args(const uint8_t *xhtml_bytes, size_t xhtml_len, const ra8_rabook_ctx_t *ctx, const char *chapter_href, const char *chapter_title, const ra8_rabook_xml_workspace_t *workspace)
Validate the public chapter-parse entry point's arguments.
static ra8_err_t internal_link(ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace, uint16_t parent_level, uint32_t next_sibling)
Link a new node beneath its selected-subtree parent.
static ra8_err_t internal_emit_start(const uint8_t *source, size_t length, const priv_selection_t *selection, const xml_event_t *event, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace, bool *active, uint32_t *out_root)
Handle one start event for the in-progress subtree emission.
static ra8_err_t internal_element(const uint8_t *source, size_t source_len, const xml_event_t *event, uint16_t selected_depth, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace, uint32_t *out_node)
Emit one element event and link it into preorder.
static ra8_err_t internal_attributes(const uint8_t *source, size_t source_len, const xml_event_t *event, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace)
Collect and intern one event's attributes.
static ra8_err_t internal_emit(const uint8_t *source, size_t length, const priv_selection_t *selection, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace, uint32_t *out_root)
Stream the selected subtree into the builder.
Bounded XHTML-to-RABOOK streaming builder.
@ k_ra8_rabook_xml_max_attributes
Attributes accepted per element.
@ k_ra8_rabook_xml_body_siblings
Direct children searched for body.
Test-only seams for post-validation XML reader faults.
ra8_err_t priv_ra8_rabook_xml_select_unvalidated_test(const uint8_t *source, size_t source_len, ra8_rabook_xml_workspace_t *workspace)
Run the XML subtree-selection pass without public validation.
ra8_err_t priv_ra8_rabook_xml_emit_unvalidated_test(const uint8_t *source, size_t source_len, ra8_rabook_ctx_t *ctx, ra8_rabook_xml_workspace_t *workspace)
Run XML subtree emission without public validation or rollback.
uint32_t ra8_rabook_add_element(ra8_rabook_ctx_t *ctx, uint32_t name_off, const book_attr_t *attrs, uint16_t attr_count)
Append an element node with its attributes; return its node index.
ra8_err_t ra8_rabook_link_sibling(ra8_rabook_ctx_t *ctx, uint32_t previous_node, uint32_t next_sibling)
Set previous_node's next sibling to next_sibling.
uint32_t ra8_rabook_add_text(ra8_rabook_ctx_t *ctx, uint32_t text_off)
Append a text node carrying text_off; return its node index.
ra8_err_t ra8_rabook_link_child(ra8_rabook_ctx_t *ctx, uint32_t parent, uint32_t child)
Set parent's first child to child.
uint32_t ra8_rabook_intern(ra8_rabook_ctx_t *ctx, const char *str)
Intern a NUL-terminated UTF-8 string into the pool, de-duplicated.
uint32_t ra8_rabook_add_chapter(ra8_rabook_ctx_t *ctx, uint32_t title_off, uint32_t href_off, uint32_t root_node)
Append a spine chapter; return its chapter index.
uint32_t value_off
String-pool offset of the attribute value.
uint32_t name_off
String-pool offset of the attribute name.
Selected subtree root coordinates.
uint16_t depth
Absolute XML depth.
uint32_t offset
Start-markup offset.
char * string_pool
String-pool byte arena.
uint32_t string_cap
String-pool capacity in bytes.
Builder state: the arenas plus running counts and a sticky-fail flag.
bool failed
Sticky: an arena overflowed.
uint32_t string_size
String-pool bytes used.
ra8_rabook_buffers_t buf
Caller-provided arenas.
Caller-owned storage for one parser invocation.
uint32_t element_nodes[k_xml_workspace_frames]
Element node at each selected-subtree depth.
uint32_t last_children[k_xml_workspace_frames]
Last emitted child at each selected-subtree depth.
xml_workspace_t xml
Strict reader nesting stack (4096 bytes).
book_attr_t attributes[k_ra8_rabook_xml_max_attributes]
Source-order attributes for the element currently emitted.
Mutable cursor for one start event's attributes.
Source-order attribute view.
xml_span_t value
Quoted value excluding delimiters.
xml_span_t name
Attribute name.
uint16_t attribute_count
Source-order attributes on start.
xml_span_t markup
Complete markup span, or text payload.
uint8_t self_closing
One for an empty-element start.
xml_span_t name
Element name for start/end.
uint16_t depth
Root is depth zero.
uint8_t kind
xml_event_kind_t.
Pull-reader state; initialise before each pass.
Immutable byte span expressed relative to the source.
uint32_t offset
First byte offset.
Exactly bounded caller-owned nesting storage.
ra8_err_t xml_decoded_size(const uint8_t *source, size_t source_len, xml_span_t span, size_t *out_length)
Measure the entity-decoded byte count of a bounded span.
void xml_attr_begin(const xml_event_t *event, xml_attr_cursor_t *cursor)
Initialise source-order attribute iteration for a start event.
ra8_err_t xml_attr_next(const uint8_t *source, size_t source_len, const xml_event_t *event, xml_attr_cursor_t *cursor, xml_attribute_t *out_attribute, bool *out_has_value)
Return the next source-order attribute.
@ k_xml_event_start
Element start.
@ k_xml_event_none
No event / end of source.
@ k_xml_event_text
Character-data run.
@ k_xml_event_end
Element end.
ra8_err_t xml_validate(const uint8_t *source, size_t source_len, xml_workspace_t *workspace)
Validate a complete document before any consumer mutation.
bool xml_span_equal(const uint8_t *source, size_t source_len, xml_span_t span, const char *literal)
Compare a bounded span with an exact ASCII literal.
ra8_err_t xml_decode(const uint8_t *source, size_t source_len, xml_span_t span, char *destination, size_t capacity, size_t *out_length)
Entity-decode a source span into a bounded NUL-terminated buffer.
ra8_err_t xml_reader_init(xml_reader_t *reader, const uint8_t *source, size_t source_len, xml_workspace_t *workspace)
Initialise a pull pass over immutable bytes.
ra8_err_t xml_reader_next(xml_reader_t *reader, xml_event_t *out_event)
Return the next semantic event and validate syntax incrementally.