ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
reflow_tokenize_attr.c
Go to the documentation of this file.
1
29
30#include <stddef.h>
31#include <stdint.h>
32#include <string.h>
33
34#include "ra8_attributes.h"
35#include "ra8_err.h"
36#include "reflow.h"
38
39/* ===========================================================================
40 * Quoted-attribute scanning + value capture
41 * ===========================================================================
42 */
43
66static bool internal_attr_name_at(const uint8_t* tag, size_t i, const char* name, size_t name_len)
67{
68 for (size_t k = 0U; k < name_len; ++k) {
69 if ((tag[i + k] | 0x20U) != (uint8_t)name[k]) {
70 return false;
71 }
72 }
73 const uint8_t prev = (i == 0U) ? (uint8_t)'<' : tag[i - 1U];
74 return !(((prev >= (uint8_t)'a') && (prev <= (uint8_t)'z')) ||
75 ((prev >= (uint8_t)'A') && (prev <= (uint8_t)'Z')));
76}
77
100static bool internal_attr_quoted_value(const uint8_t* tag,
101 size_t tag_len,
102 size_t pos,
103 size_t* vstart,
104 size_t* vlen)
105{
106 size_t j = pos;
107 while ((j < tag_len) && priv_reflow_tok_is_xml_whitespace((char)tag[j])) {
108 ++j;
109 }
110 if ((j >= tag_len) || (tag[j] != (uint8_t)'=')) {
111 return false;
112 }
113 ++j;
114 while ((j < tag_len) && priv_reflow_tok_is_xml_whitespace((char)tag[j])) {
115 ++j;
116 }
117 if ((j >= tag_len) || ((tag[j] != (uint8_t)'"') && (tag[j] != (uint8_t)'\''))) {
118 return false;
119 }
120 const uint8_t quote = tag[j];
121 ++j;
122 *vstart = j;
123 while ((j < tag_len) && (tag[j] != quote)) {
124 ++j;
125 }
126 *vlen = j - *vstart;
127 return true;
128}
129
153bool priv_reflow_tok_find_attr(const uint8_t* tag,
154 size_t tag_len,
155 const char* name,
156 size_t name_len,
157 size_t* out_voff,
158 size_t* out_vlen)
159{
160 if (tag_len < name_len) {
161 return false;
162 }
163 for (size_t i = 0U; (i + name_len) <= tag_len; ++i) {
164 if (internal_attr_name_at(tag, i, name, name_len) &&
165 internal_attr_quoted_value(tag, tag_len, i + name_len, out_voff, out_vlen)) {
166 return true;
167 }
168 }
169 return false;
170}
171
197 const uint8_t* tag,
198 size_t tag_len,
199 const char* name,
200 size_t name_len,
201 uint32_t* out_off,
202 uint32_t* out_len)
203{
204 *out_off = 0U;
205 *out_len = 0U;
206 size_t vstart = 0U;
207 size_t vlen = 0U;
208 if (!priv_reflow_tok_find_attr(tag, tag_len, name, name_len, &vstart, &vlen)) {
209 return;
210 }
211 if ((vlen == 0U) ||
212 (((size_t)engine->text_pool_used + vlen) > (size_t)k_reflow_text_pool_bytes)) {
213 return;
214 }
215 const uint32_t off = engine->text_pool_used;
216 (void)memcpy(&engine->text_pool[off], &tag[vstart], vlen);
217 engine->text_pool_used += (uint32_t)vlen;
218 *out_off = off;
219 *out_len = (uint32_t)vlen;
220}
221
243priv_reflow_tok_css_element(reflow_html_tag_t kind, const uint8_t* tag, size_t span)
244{
245 ra8_css_element_t el = {};
246 el.tag = (uint8_t)kind;
247 size_t off = 0U;
248 size_t len = 0U;
249 if (priv_reflow_tok_find_attr(tag, span, "id", sizeof("id") - 1U, &off, &len)) {
250 el.id = (const char*)&tag[off];
251 el.id_len = (uint16_t)len;
252 }
253 if (priv_reflow_tok_find_attr(tag, span, "class", sizeof("class") - 1U, &off, &len)) {
254 el.class_str = (const char*)&tag[off];
255 el.class_len = (uint16_t)len;
256 }
257 return el;
258}
259
279ra8_css_style_t priv_reflow_tok_css_inline(const uint8_t* tag, size_t span)
280{
281 ra8_css_style_t inl = {};
282 size_t off = 0U;
283 size_t len = 0U;
284 if (priv_reflow_tok_find_attr(tag, span, "style", sizeof("style") - 1U, &off, &len)) {
285 (void)ra8_css_parse_inline((const char*)&tag[off], (uint32_t)len, &inl);
286 }
287 return inl;
288}
289
290/* ===========================================================================
291 * Link interning + stylesheet-rel detection + face resolution
292 * ===========================================================================
293 */
294
315uint8_t priv_reflow_tok_intern_link(reflow_t* engine, uint32_t href_off, uint32_t href_len)
316{
317 if ((href_len == 0U) || (engine->link_target_count >= (uint32_t)k_reflow_max_links)) {
318 return 0U;
319 }
320 const uint32_t idx = engine->link_target_count;
321 engine->link_targets[idx].href_off = href_off;
322 engine->link_targets[idx].href_len = href_len;
323 engine->link_target_count = idx + 1U;
324 return (uint8_t)(idx + 1U); /* 1-based: 0 means "no link" */
325}
326
347bool priv_reflow_tok_rel_is_stylesheet(const uint8_t* rel, size_t len)
348{
349 static const char k_kw[] = "stylesheet";
350 const size_t k_klen = sizeof(k_kw) - 1U;
351 for (size_t i = 0U; (i + k_klen) <= len; i++) {
352 size_t j = 0U;
353 for (; (j < k_klen) && (rel[i + j] == (uint8_t)k_kw[j]); j++) {
354 }
355 if (j == k_klen) {
356 return true;
357 }
358 }
359 return false;
360}
361
383{
384 if ((engine->face_count == 0U) || ((comp->set & (uint8_t)k_ra8_css_set_family) == 0U) ||
385 (comp->family_len == 0U)) {
386 return 0U;
387 }
388 const char* family = (const char*)&engine->css.names[comp->family_off];
389 const bool bold = (comp->style & (uint8_t)k_reflow_style_bold) != 0U;
390 const bool italic = (comp->style & (uint8_t)k_reflow_style_italic) != 0U;
391 const int16_t ci = ra8_css_match_face(&engine->css, family, comp->family_len, bold, italic);
392 if (ci < 0) {
393 return 0U;
394 }
395 for (uint8_t k = 0U; k < engine->face_count; ++k) {
396 if (engine->faces[k].css_face_idx == (uint8_t)ci) {
397 return (uint8_t)(k + 1U);
398 }
399 }
400 return 0U;
401}
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
HTML / CSS reflow + paginate engine for the ra8d2 ereader.
ra8_err_t ra8_css_parse_inline(const char *decls, uint32_t len, ra8_css_style_t *out)
Parse an inline style="..." declaration body into one style.
Definition reflow_css.c:805
@ k_ra8_css_set_family
font-family was declared.
Definition reflow_css.h:98
int16_t ra8_css_match_face(const ra8_css_sheet_t *sheet, const char *family, uint16_t family_len, bool want_bold, bool want_italic)
Pick the @font-face whose family + emphasis best fits a run.
ra8_css_style_t priv_reflow_tok_css_inline(const uint8_t *tag, size_t span)
Parse a just-opened tag's inline style="..." into a CSS declaration.
ra8_css_element_t priv_reflow_tok_css_element(reflow_html_tag_t kind, const uint8_t *tag, size_t span)
Build a CSS element identity from a just-opened tag's attributes.
bool priv_reflow_tok_find_attr(const uint8_t *tag, size_t tag_len, const char *name, size_t name_len, size_t *out_voff, size_t *out_vlen)
Locate a named attribute's quoted value span within a tag (no copy).
static bool internal_attr_quoted_value(const uint8_t *tag, size_t tag_len, size_t pos, size_t *vstart, size_t *vlen)
Parse = "value" after an attribute name; return the value span.
void priv_reflow_tok_capture_attr(reflow_t *engine, const uint8_t *tag, size_t tag_len, const char *name, size_t name_len, uint32_t *out_off, uint32_t *out_len)
Copy a named attribute's quoted value from a tag span into the text pool.
bool priv_reflow_tok_rel_is_stylesheet(const uint8_t *rel, size_t len)
True if a rel attribute value contains the stylesheet token.
static bool internal_attr_name_at(const uint8_t *tag, size_t i, const char *name, size_t name_len)
True iff attribute name (case-insensitive) begins at tag[i].
uint8_t priv_reflow_tok_resolve_face_slot(const reflow_t *engine, const ra8_css_style_t *comp)
Map a cascaded run's (font-family + emphasis) to an embedded face slot.
uint8_t priv_reflow_tok_intern_link(reflow_t *engine, uint32_t href_off, uint32_t href_len)
Intern an <a> href slice into the link-target table.
Test-access surface for reflow_tokenize.c internal helpers.
bool priv_reflow_tok_is_xml_whitespace(char c)
True for the ASCII characters XHTML treats as whitespace.
reflow_html_tag_t
Recognised HTML element kinds.
@ k_reflow_max_links
Max distinct <a href> per chapter.
@ k_reflow_text_pool_bytes
Bytes of text pool.
@ k_reflow_style_italic
Italic face.
@ k_reflow_style_bold
Bold face.
The identity of one element, used to match selectors.
Definition reflow_css.h:230
uint16_t class_len
Length of class_str, bytes.
Definition reflow_css.h:235
const char * id
id attribute bytes (NULL = none).
Definition reflow_css.h:232
const char * class_str
class attribute bytes (NULL = none).
Definition reflow_css.h:234
uint16_t id_len
Length of id, bytes.
Definition reflow_css.h:233
uint8_t tag
reflow_html_tag_t of the element.
Definition reflow_css.h:231
uint8_t names[k_ra8_css_name_pool]
class/id/font name bytes.
Definition reflow_css.h:219
A declared or computed style: a presence mask plus property values.
Definition reflow_css.h:122
uint16_t family_len
font-family name slice length (0 = none).
Definition reflow_css.h:132
uint8_t style
reflow_font_style_t bit VALUES (bold/italic/ul).
Definition reflow_css.h:124
uint8_t set
ra8_css_set_t bitmask: which properties are present.
Definition reflow_css.h:123
uint16_t family_off
font-family name slice offset (valid iff set&family).
Definition reflow_css.h:131
uint8_t css_face_idx
@font-face table index this blob satisfies.
Reflow / pagination engine state.
uint8_t text_pool[k_reflow_text_pool_bytes]
Text bytes.
ra8_css_sheet_t css
Parsed <style> rules for the chapter.
uint32_t text_pool_used
Bytes consumed in text_pool.
uint32_t link_target_count
Interned link targets.
reflow_face_t faces[k_reflow_max_faces]
Embedded @font-face set.
reflow_link_target_t link_targets[k_reflow_max_links]
Distinct hrefs.
uint8_t face_count
Embedded face count (0 = single-face).