ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
reflow_css_rules.c File Reference

Content-CSS selector + @font-face rule parsing (#111). More...

#include <stddef.h>
#include <string.h>
#include "ra8_attributes.h"
#include "reflow.h"
#include "reflow_css.h"
#include "reflow_css_internal.h"
#include "reflow_tokenize_internal.h"
Include dependency graph for reflow_css_rules.c:

Go to the source code of this file.

Data Structures

struct  priv_face_ctx_t
 Context threading a sheet + the face being built through the loop. More...
struct  priv_family_ctx_t
 Context threading a sheet + the rule declaration through the loop. More...

Typedefs

typedef void(* priv_decl_fn) (void *ctx, const char *prop, size_t plen, const char *val, size_t vlen)
 Callback invoked by internal_for_each_decl on each prop:value pair.

Enumerations

enum  priv_css_face_t : uint8_t { k_priv_url_len = 4U }
 @font-face parsing constants. More...

Functions

static bool internal_is_name_char (char c)
 True if c can appear inside a bare type / class / id name.
static bool internal_intern_name (ra8_css_sheet_t *sheet, const char *s, size_t len, uint16_t *off)
 Intern a class/id name into the sheet pool; false if it does not fit.
static bool internal_parse_sel_type (const char *s, size_t len, size_t *i, ra8_css_rule_t *rule)
 Parse the optional leading type / * of a compound selector.
static bool internal_parse_sel_part (ra8_css_sheet_t *sheet, const char *s, size_t len, size_t *i, ra8_css_rule_t *rule)
 Parse one .class / #id part at s[*i] into rule; advance i.
static bool internal_parse_selector (ra8_css_sheet_t *sheet, const char *s, size_t len, ra8_css_rule_t *rule)
 Parse ONE trimmed compound selector into rule; false if unsupported.
static int32_t internal_split_compounds (const char *s, size_t len, const char **part_p, size_t *part_n)
 Split s into whitespace-separated compound spans.
static bool internal_parse_complex_selector (ra8_css_sheet_t *sheet, const char *s, size_t len, ra8_css_rule_t *rule)
 Parse a (possibly descendant) selector string into rule.
static void internal_push_rule (ra8_css_sheet_t *sheet, const ra8_css_rule_t *rule)
 Append one fully-built rule to the sheet; drop silently if full.
static void internal_parse_selector_list (ra8_css_sheet_t *sheet, const char *sel, size_t sel_len, ra8_css_style_t decl)
 Parse a comma-grouped selector list sharing declaration decl.
static const char * internal_strip_quotes (const char *s, size_t *len)
 Strip one layer of matching '/" quotes from span s[0..*len).
static bool internal_extract_url (const char *val, size_t vlen, const char **url, size_t *ulen)
 Extract the path inside the first url(...) of a src value.
static bool internal_is_bold_kw (const char *val, size_t vlen)
 True for a font-weight keyword that selects the bold face.
static bool internal_is_italic_kw (const char *val, size_t vlen)
 True for a font-style keyword that selects the italic face.
static void internal_face_apply (ra8_css_sheet_t *sheet, const char *prop, size_t plen, const char *val, size_t vlen, ra8_css_fontface_t *face)
 Apply one @font-face declaration to the face being built.
static void internal_for_each_decl (const char *s, size_t len, priv_decl_fn cb, void *ctx)
 Iterate prop:value; pairs in a declaration block (no braces).
static void internal_face_cb (void *ctx, const char *prop, size_t plen, const char *val, size_t vlen)
 priv_decl_fn adapter that routes one descriptor to internal_face_apply().
static void internal_parse_fontface (ra8_css_sheet_t *sheet, const char *block, size_t len)
 Parse one @font-face { ... } block; append it if family + src set.
static void internal_family_cb (void *ctx, const char *prop, size_t plen, const char *val, size_t vlen)
 priv_decl_fn adapter that interns a rule's font-family value.
static void internal_extract_family (ra8_css_sheet_t *sheet, const char *block, size_t len, ra8_css_style_t *decl)
 Scan a rule's declaration block for font-family, interning it.
static void internal_parse_at_rule (ra8_css_sheet_t *sheet, const char *sel, size_t sel_len, const char *block, size_t block_len)
 Route an at-rule: parse @font-face; skip every other @-rule.
void priv_reflow_css_parse_one_block (ra8_css_sheet_t *sheet, const char *sel, size_t sel_len, const char *block, size_t block_len)
 Dispatch one selector|@rule { block }: at-rule vs.

Detailed Description

Content-CSS selector + @font-face rule parsing (#111).

The selector grammar (type / class / id / descendant compounds) and the @font-face descriptor parser for the v1 CSS subset documented in reflow_css.h. Parsed selectors and faces are interned into the caller-owned ra8_css_sheet_t name pool and rule / face tables. The top-level block dispatcher priv_reflow_css_parse_one_block lives here because it drives the selector and @font-face parsers; it is invoked by the stylesheet scanner ra8_css_parse in a sibling translation unit. No MMIO, no heap.

[Ring 4 / Reflow] {World: NS}

Since
0.1.0

Definition in file reflow_css_rules.c.

Typedef Documentation

◆ priv_decl_fn

typedef void( * priv_decl_fn) (void *ctx, const char *prop, size_t plen, const char *val, size_t vlen)

Callback invoked by internal_for_each_decl on each prop:value pair.

Definition at line 680 of file reflow_css_rules.c.

Enumeration Type Documentation

◆ priv_css_face_t

enum priv_css_face_t : uint8_t

@font-face parsing constants.

Enumerator
k_priv_url_len 

Length of the url( token prefix.

Definition at line 41 of file reflow_css_rules.c.

Function Documentation

◆ internal_extract_family()

void internal_extract_family ( ra8_css_sheet_t * sheet,
const char * block,
size_t len,
ra8_css_style_t * decl )
static

Scan a rule's declaration block for font-family, interning it.

Calls internal_for_each_decl() with internal_family_cb() to find and intern the "font-family" property from block into sheet->names and record it in decl. This is a thin convenience wrapper that sets up a priv_family_ctx_t and delegates all logic to the callback.

Parameters
[in,out]sheetSheet whose name pool may receive the interned family name.
[in]blockDeclaration block text (no surrounding braces).
[in]lenNumber of bytes in block.
[in,out]declDeclaration to update with the font-family slice.
Returns
Nothing.
Precondition
sheet and decl are non-NULL.
block points to at least len readable bytes (may be NULL when len == 0).
Postcondition
If "font-family" is present in block and intern succeeds, decl has k_ra8_css_set_family set and family_off/family_len populated.
block is not modified.
Note
Thread-safe with respect to distinct sheet and decl instances.
Since
0.1.0

Definition at line 887 of file reflow_css_rules.c.

References internal_family_cb(), and internal_for_each_decl().

Referenced by priv_reflow_css_parse_one_block().

◆ internal_extract_url()

bool internal_extract_url ( const char * val,
size_t vlen,
const char ** url,
size_t * ulen )
static

Extract the path inside the first url(...) of a src value.

Scans val[0..vlen) for the first case-insensitive "url(" prefix, then locates the matching closing ')' and trims whitespace and one layer of matching single or double quotes from the content via internal_strip_quotes(). On success, *url and *ulen receive the path span (pointing into val) and the function returns true. Returns false when no "url(" is found or the extracted path is empty after trimming.

Parameters
[in]valCSS src value span (e.g. url('foo.ttf') format('truetype')).
[in]vlenNumber of bytes in val.
[out]urlReceives a pointer into val at the start of the path (valid only on true).
[out]ulenReceives the length of the path in bytes (valid only on true).
Returns
bool Whether a non-empty URL path was extracted.
Return values
true*url and *ulen point to the unquoted path inside "url(...)".
falseNo "url(" was found, or the extracted path was empty.
Precondition
val points to at least vlen readable bytes.
url and ulen are non-NULL.
Postcondition
On true, *url points into val and *ulen > 0.
val is not modified.
Note
Thread-safe; operates only on caller-owned memory.
Since
0.1.0

Definition at line 533 of file reflow_css_rules.c.

References internal_strip_quotes(), k_priv_url_len, priv_reflow_css_ci_eq(), and priv_reflow_css_trim().

Referenced by internal_face_apply().

◆ internal_face_apply()

void internal_face_apply ( ra8_css_sheet_t * sheet,
const char * prop,
size_t plen,
const char * val,
size_t vlen,
ra8_css_fontface_t * face )
static

Apply one @font-face declaration to the face being built.

Handles the four recognised @font-face descriptors:

  • "font-family": strips quotes and interns the family name into sheet; stores (off, len) in face->family_off / family_len.
  • "font-weight": sets face->weight_bold via internal_is_bold_kw().
  • "font-style": sets face->style_italic via internal_is_italic_kw().
  • "src": extracts the first url() path via internal_extract_url() and interns it; stores (off, len) in face->src_off / src_len. All other descriptors (e.g., unicode-range) are silently ignored.
Parameters
[in,out]sheetSheet whose name pool receives interned strings.
[in]propDescriptor property name span (not NUL-terminated).
[in]plenLength of prop in bytes.
[in]valDescriptor value span (not NUL-terminated).
[in]vlenLength of val in bytes.
[in,out]faceFont-face record being accumulated.
Returns
Nothing.
Precondition
sheet and face are non-NULL.
prop points to at least plen readable bytes.
Postcondition
On a recognised descriptor, the matching field of face is updated.
prop and val are not modified.
Note
Thread-safe with respect to distinct sheet and face instances.
Since
0.1.0

Definition at line 646 of file reflow_css_rules.c.

References ra8_css_fontface_t::family_len, ra8_css_fontface_t::family_off, internal_extract_url(), internal_intern_name(), internal_is_bold_kw(), internal_is_italic_kw(), internal_strip_quotes(), priv_reflow_css_ci_eq(), ra8_css_fontface_t::src_len, ra8_css_fontface_t::src_off, ra8_css_fontface_t::style_italic, and ra8_css_fontface_t::weight_bold.

Referenced by internal_face_cb().

◆ internal_face_cb()

void internal_face_cb ( void * ctx,
const char * prop,
size_t plen,
const char * val,
size_t vlen )
static

priv_decl_fn adapter that routes one descriptor to internal_face_apply().

Casts ctx to a priv_face_ctx_t pointer and forwards the property and value spans to internal_face_apply() with the sheet and face from the context. This function is designed to be passed as the cb argument of internal_for_each_decl() when parsing an @font-face block.

Parameters
[in]ctxPointer to a priv_face_ctx_t (sheet + face); must not be NULL.
[in]propProperty name span (not NUL-terminated).
[in]plenLength of prop in bytes.
[in]valProperty value span (not NUL-terminated).
[in]vlenLength of val in bytes.
Returns
Nothing.
Precondition
ctx is a non-NULL priv_face_ctx_t pointer with valid sheet and face fields.
prop points to at least plen readable bytes.
Postcondition
internal_face_apply() has been called with the unwrapped context fields.
prop and val are not modified.
Note
Thread-safety matches that of internal_face_apply().
Since
0.1.0

Definition at line 765 of file reflow_css_rules.c.

References priv_face_ctx_t::face, internal_face_apply(), and priv_face_ctx_t::sheet.

Referenced by internal_parse_fontface().

◆ internal_family_cb()

void internal_family_cb ( void * ctx,
const char * prop,
size_t plen,
const char * val,
size_t vlen )
static

priv_decl_fn adapter that interns a rule's font-family value.

Casts ctx to a priv_family_ctx_t pointer. Ignores the callback unless prop matches "font-family". When it does, strips quotes from val via internal_strip_quotes() and interns the result into the sheet's name pool. On success, sets the k_ra8_css_set_family bit in decl->set and stores (off, len) in decl->family_off / family_len. This function is designed to be used as the cb argument of internal_for_each_decl().

Parameters
[in]ctxPointer to a priv_family_ctx_t (sheet + decl); must not be NULL.
[in]propProperty name span (not NUL-terminated).
[in]plenLength of prop in bytes.
[in]valProperty value span (not NUL-terminated).
[in]vlenLength of val in bytes.
Returns
Nothing.
Precondition
ctx is a non-NULL priv_family_ctx_t with valid sheet and decl fields.
prop points to at least plen readable bytes.
Postcondition
When prop is "font-family" and intern succeeds, ctx->decl has the family fields set and k_ra8_css_set_family OR'd into ctx->decl->set.
prop and val are not modified.
Note
Thread-safety matches that of internal_intern_name().
Since
0.1.0

Definition at line 846 of file reflow_css_rules.c.

References priv_family_ctx_t::decl, ra8_css_style_t::family_len, ra8_css_style_t::family_off, internal_intern_name(), internal_strip_quotes(), k_ra8_css_set_family, priv_reflow_css_ci_eq(), ra8_css_style_t::set, and priv_family_ctx_t::sheet.

Referenced by internal_extract_family().

◆ internal_for_each_decl()

void internal_for_each_decl ( const char * s,
size_t len,
priv_decl_fn cb,
void * ctx )
static

Iterate prop:value; pairs in a declaration block (no braces).

Scans s[0..len) for semicolon-delimited declarations and invokes cb(ctx, prop, plen, val, vlen) for each pair that has a non-empty property and value after whitespace trimming. The outer loop advances past each semicolon and is bounded by len; the inner colon search is bounded by the semicolon position. Pairs missing a colon are skipped silently.

Parameters
[in]sDeclaration block text (no surrounding braces).
[in]lenNumber of bytes in s.
[in]cbCallback invoked once per valid prop:value pair; must not be NULL.
[in]ctxOpaque context pointer forwarded to cb unchanged.
Returns
Nothing.
Precondition
s points to at least len readable bytes (may be NULL when len == 0).
cb is non-NULL.
Postcondition
cb has been called for each valid declaration found in s.
s is not modified.
Note
Thread-safety depends on cb and ctx; the scanner itself is stateless.
Since
0.1.0

Definition at line 708 of file reflow_css_rules.c.

References priv_reflow_css_trim().

Referenced by internal_extract_family(), and internal_parse_fontface().

◆ internal_intern_name()

bool internal_intern_name ( ra8_css_sheet_t * sheet,
const char * s,
size_t len,
uint16_t * off )
static

Intern a class/id name into the sheet pool; false if it does not fit.

Copies len bytes of s into sheet->names at offset sheet->names_used, then advances names_used by len. On success, *off receives the offset at which the name was stored so that a rule or face can reference it by (off, len) rather than by pointer. Returns false without mutation when len is 0, exceeds k_ra8_css_name_max, or would cause names_used to overflow k_ra8_css_name_pool.

Parameters
[in,out]sheetSheet whose name pool receives the interned bytes.
[in]sByte span to intern (need not be NUL-terminated).
[in]lenNumber of bytes to copy.
[out]offReceives the pool offset of the interned name on success.
Returns
bool Whether the name was successfully interned.
Return values
true*off holds the start offset; sheet->names_used increased by len.
falselen is 0 or too large, or the pool has insufficient space.
Precondition
sheet and off are non-NULL.
s points to at least len readable bytes.
Postcondition
On true, sheet->names[*off .. *off + len) contains the copied name.
On false, sheet is not modified.
Note
Thread-safe with respect to distinct sheet instances.
Since
0.1.0

Definition at line 107 of file reflow_css_rules.c.

References k_ra8_css_name_max, k_ra8_css_name_pool, memcpy(), ra8_css_sheet_t::names, and ra8_css_sheet_t::names_used.

Referenced by internal_face_apply(), internal_family_cb(), and internal_parse_sel_part().

◆ internal_is_bold_kw()

bool internal_is_bold_kw ( const char * val,
size_t vlen )
static

True for a font-weight keyword that selects the bold face.

Returns true when val[0..vlen) matches (case-insensitively) any of the CSS bold-weight keywords: "bold", "bolder", "600", "700", "800", or "900". All comparisons are delegated to priv_reflow_css_ci_eq().

Parameters
[in]valCSS font-weight value span (not NUL-terminated).
[in]vlenNumber of bytes in val.
Returns
bool Whether the value selects the bold face.
Return values
trueval is a bold-selecting keyword or numeric weight.
falseval is a non-bold weight (e.g., "normal", "400").
Precondition
val points to at least vlen readable bytes.
vlen accurately reflects the span length.
Postcondition
No state is mutated; the function is pure.
val is not modified.
Note
Thread-safe; pure function with no shared state.
Since
0.1.0

Definition at line 581 of file reflow_css_rules.c.

References priv_reflow_css_ci_eq().

Referenced by internal_face_apply().

◆ internal_is_italic_kw()

bool internal_is_italic_kw ( const char * val,
size_t vlen )
static

True for a font-style keyword that selects the italic face.

Returns true when val[0..vlen) matches (case-insensitively) either "italic" or "oblique" via priv_reflow_css_ci_eq(). All other values (e.g., "normal") return false.

Parameters
[in]valCSS font-style value span (not NUL-terminated).
[in]vlenNumber of bytes in val.
Returns
bool Whether the value selects the italic face.
Return values
trueval is "italic" or "oblique".
falseval is any other font-style value.
Precondition
val points to at least vlen readable bytes.
vlen accurately reflects the span length.
Postcondition
No state is mutated; the function is pure.
val is not modified.
Note
Thread-safe; pure function with no shared state.
Since
0.1.0

Definition at line 611 of file reflow_css_rules.c.

References priv_reflow_css_ci_eq().

Referenced by internal_face_apply().

◆ internal_is_name_char()

bool internal_is_name_char ( char c)
static

True if c can appear inside a bare type / class / id name.

Accepts ASCII letters ('a'-'z', 'A'-'Z'), decimal digits ('0'-'9'), the hyphen ('-'), and the underscore ('_'), which are the characters allowed in CSS identifiers per the CSS specification. Used by internal_parse_sel_type() and internal_parse_sel_part() to delimit token boundaries in selector text.

Parameters
[in]cByte to classify.
Returns
bool Classification result.
Return values
truec is a valid CSS identifier character.
falsec is not a valid CSS identifier character.
Precondition
No precondition on c; all byte values are valid inputs.
Caller uses the return value to decide whether to advance a cursor.
Postcondition
No state is mutated; the function is pure.
c is not modified.
Note
Thread-safe; pure function with no shared state.
Since
0.1.0

Definition at line 73 of file reflow_css_rules.c.

Referenced by internal_parse_sel_part(), internal_parse_sel_type(), and internal_parse_selector().

◆ internal_parse_at_rule()

void internal_parse_at_rule ( ra8_css_sheet_t * sheet,
const char * sel,
size_t sel_len,
const char * block,
size_t block_len )
static

Route an at-rule: parse @font-face; skip every other @-rule.

Compares the trimmed at-keyword sel against "@font-face" (case-insensitive). When it matches, delegates parsing of the block to internal_parse_fontface(). All other at-rules (@media, @import, @page, etc.) are out of the v1 scope and are silently discarded.

Parameters
[in,out]sheetSheet that may receive the parsed font face.
[in]selAt-keyword span (e.g. "@font-face"), trimmed.
[in]sel_lenLength of sel in bytes.
[in]blockBlock body text (no surrounding braces).
[in]block_lenNumber of bytes in block.
Returns
Nothing.
Precondition
sheet is non-NULL.
sel points to at least sel_len readable bytes.
Postcondition
When sel is "@font-face", internal_parse_fontface() has been called.
sel and block are not modified.
Note
Thread-safe with respect to distinct sheet instances.
Since
0.1.0

Definition at line 921 of file reflow_css_rules.c.

References internal_parse_fontface(), and priv_reflow_css_ci_eq().

Referenced by priv_reflow_css_parse_one_block().

◆ internal_parse_complex_selector()

bool internal_parse_complex_selector ( ra8_css_sheet_t * sheet,
const char * s,
size_t len,
ra8_css_rule_t * rule )
static

Parse a (possibly descendant) selector string into rule.

Splits s on whitespace via internal_split_compounds() to isolate the subject compound (last token) and ancestor compounds (preceding tokens). The subject is parsed into rule's sel_tag, class, and id fields via internal_parse_selector(). Each ancestor is parsed into a temporary rule and its constraints are stored in rule->anc[] in selector order (outermost first), with rule->anc_count set to the number of ancestor parts. Returns false when internal_split_compounds() returns <= 0, or any compound fails to parse.

Parameters
[in,out]sheetSheet whose name pool receives interned class/id names.
[in]sSelector text (may include whitespace for descendants).
[in]lenNumber of bytes in s.
[in,out]ruleRule record to populate; must be zero-initialised on entry.
Returns
bool Whether the full selector was parsed.
Return values
trueAll compounds parsed; rule holds the complete selector.
falses is empty, has too many parts, or any compound is unsupported.
Precondition
sheet and rule are non-NULL.
s points to at least len readable bytes.
Postcondition
On true, rule->anc_count and rule->anc[] reflect the ancestor chain.
On false, rule is in a partial state and must be discarded.
Note
Thread-safe with respect to distinct sheet and rule instances.
Since
0.1.0

Definition at line 373 of file reflow_css_rules.c.

References ra8_css_rule_t::anc, ra8_css_rule_t::anc_count, ra8_css_anc_t::class_len, ra8_css_rule_t::class_len, ra8_css_anc_t::class_off, ra8_css_rule_t::class_off, ra8_css_anc_t::id_len, ra8_css_rule_t::id_len, ra8_css_anc_t::id_off, ra8_css_rule_t::id_off, internal_parse_selector(), internal_split_compounds(), k_ra8_css_max_anc, ra8_css_rule_t::sel_tag, and ra8_css_anc_t::tag.

Referenced by internal_parse_selector_list().

◆ internal_parse_fontface()

void internal_parse_fontface ( ra8_css_sheet_t * sheet,
const char * block,
size_t len )
static

Parse one @font-face { ... } block; append it if family + src set.

Iterates over the declaration block via internal_for_each_decl() with internal_face_cb() as the callback to accumulate font-family, font-weight, font-style, and src into a local ra8_css_fontface_t. The face is appended to sheet->faces[] only when both family_len and src_len are non-zero. If the sheet is already at k_ra8_css_max_faces capacity, the function returns without parsing.

Parameters
[in,out]sheetSheet that may receive the parsed font face.
[in]blockDeclaration block text (no surrounding braces).
[in]lenNumber of bytes in block.
Returns
Nothing.
Precondition
sheet is non-NULL.
block points to at least len readable bytes (may be NULL when len == 0).
Postcondition
When family and src were set, sheet->face_count is incremented by 1 and the face is stored in sheet->faces[].
block is not modified.
Note
Thread-safe with respect to distinct sheet instances.
Since
0.1.0

Definition at line 797 of file reflow_css_rules.c.

References ra8_css_sheet_t::face_count, ra8_css_sheet_t::faces, ra8_css_fontface_t::family_len, internal_face_cb(), internal_for_each_decl(), k_ra8_css_max_faces, and ra8_css_fontface_t::src_len.

Referenced by internal_parse_at_rule().

◆ internal_parse_sel_part()

bool internal_parse_sel_part ( ra8_css_sheet_t * sheet,
const char * s,
size_t len,
size_t * i,
ra8_css_rule_t * rule )
static

Parse one .class / #id part at s[*i] into rule; advance i.

Reads the '.' or '#' prefix at s[*i], then consumes a run of internal_is_name_char() bytes as the name. Interns the name via internal_intern_name() and stores the resulting (off, len) pair in the appropriate field of rule:

  • '.' -> rule->class_off / rule->class_len (only one class supported in v1)
  • '#' -> rule->id_off / rule->id_len (only one id supported in v1) Returns false when the name is empty, fails to intern, or is a duplicate of an already-stored class/id on the same rule.
Parameters
[in,out]sheetSheet whose name pool may receive the interned name.
[in]sSelector text span.
[in]lenLength of s in bytes.
[in,out]iCursor into s; advanced past '.' or '#' and the name.
[in,out]ruleRule record to update with the class or id constraint.
Returns
bool Whether the part was parsed and stored successfully.
Return values
trueA class or id constraint was interned and stored in rule.
falseThe name was empty, overflowed the pool, or was a duplicate.
Precondition
sheet, i, and rule are non-NULL.
s[*i] is '.' or '#' on entry.
Postcondition
On true, *i is advanced past the name; the matching rule field is set.
On false, rule and sheet state are left in an undefined partial state (the rule is discarded by the caller).
Note
Thread-safe with respect to distinct sheet and rule instances.
Since
0.1.0

Definition at line 201 of file reflow_css_rules.c.

References ra8_css_rule_t::class_len, ra8_css_rule_t::class_off, ra8_css_rule_t::id_len, ra8_css_rule_t::id_off, internal_intern_name(), and internal_is_name_char().

Referenced by internal_parse_selector().

◆ internal_parse_sel_type()

bool internal_parse_sel_type ( const char * s,
size_t len,
size_t * i,
ra8_css_rule_t * rule )
static

Parse the optional leading type / * of a compound selector.

Reads the element type or universal selector at s[*i]:

  • If the current byte is '*', advances *i by 1 and returns true without recording a type constraint (universal selector).
  • Otherwise, consumes a run of internal_is_name_char() bytes and classifies the span via priv_reflow_tok_classify(). On success, stores the tag in rule->sel_tag and returns true. Returns false if the name is not a recognised HTML tag (caller drops the rule).
Parameters
[in]sSelector text span.
[in]lenLength of s in bytes.
[in,out]iCursor into s; advanced past the consumed type token.
[in,out]ruleRule record to update with the parsed tag.
Returns
bool Whether the type token was parsed successfully.
Return values
trueA recognised type or universal selector was consumed.
falseThe name at s[*i] is not a recognised HTML element tag.
Precondition
s points to at least len readable bytes.
i and rule are non-NULL; *i < len on entry.
Postcondition
On true, *i is advanced past the consumed token.
On true, rule->sel_tag holds the classified tag (or remains unknown for '*').
Note
Thread-safe with respect to distinct rule instances.
Since
0.1.0

Definition at line 151 of file reflow_css_rules.c.

References internal_is_name_char(), k_reflow_tag_unknown, priv_reflow_tok_classify(), and ra8_css_rule_t::sel_tag.

Referenced by internal_parse_selector().

◆ internal_parse_selector()

bool internal_parse_selector ( ra8_css_sheet_t * sheet,
const char * s,
size_t len,
ra8_css_rule_t * rule )
static

Parse ONE trimmed compound selector into rule; false if unsupported.

Accepts one type + one class + one id in CSS order, e.g. *, p, .note, #x, p.note, p#x, .note#x. Two classes (.a.b), descendant combinators (div p) and pseudo selectors fail (the caller drops the rule). Delegates to internal_parse_sel_type() and internal_parse_sel_part() for each token.

Parameters
[in,out]sheetSheet whose name pool may receive interned names.
[in]sTrimmed compound selector span (no surrounding whitespace).
[in]lenLength of s in bytes.
[in,out]ruleRule record to populate with selector constraints.
Returns
bool Whether the selector was fully parsed.
Return values
trueThe entire span was consumed as a supported compound selector.
falselen is 0, an unsupported combinator or pseudo was encountered, or an inner parse helper returned false.
Precondition
sheet and rule are non-NULL.
s points to at least len readable bytes (may be NULL when len == 0).
Postcondition
On true, rule contains all parsed constraints; sheet->names_used may have grown.
On false, rule is left in a partial state and must be discarded.
Note
Thread-safe with respect to distinct sheet and rule instances.
Since
0.1.0

Definition at line 263 of file reflow_css_rules.c.

References internal_is_name_char(), internal_parse_sel_part(), and internal_parse_sel_type().

Referenced by internal_parse_complex_selector().

◆ internal_parse_selector_list()

void internal_parse_selector_list ( ra8_css_sheet_t * sheet,
const char * sel,
size_t sel_len,
ra8_css_style_t decl )
static

Parse a comma-grouped selector list sharing declaration decl.

Iterates over comma-delimited selectors in sel[0..sel_len), trims each individual selector, constructs a fresh ra8_css_rule_t carrying decl, and attempts to parse the selector via internal_parse_complex_selector(). Rules that parse successfully are appended to sheet via internal_push_rule(); those that fail to parse are silently discarded. The loop is bounded by sel_len; each iteration advances past the next comma.

Parameters
[in,out]sheetSheet that receives the generated rules.
[in]selComma-separated selector list span.
[in]sel_lenNumber of bytes in sel.
[in]declShared declaration applied to every generated rule.
Returns
Nothing.
Precondition
sheet is non-NULL.
sel points to at least sel_len readable bytes (may be NULL when 0).
Postcondition
Zero or more rules derived from sel and decl have been appended to sheet (subject to k_ra8_css_max_rules capacity).
sel is not modified.
Note
Thread-safe with respect to distinct sheet instances.
Since
0.1.0

Definition at line 467 of file reflow_css_rules.c.

References ra8_css_rule_t::decl, internal_parse_complex_selector(), internal_push_rule(), and priv_reflow_css_trim().

Referenced by priv_reflow_css_parse_one_block().

◆ internal_push_rule()

void internal_push_rule ( ra8_css_sheet_t * sheet,
const ra8_css_rule_t * rule )
static

Append one fully-built rule to the sheet; drop silently if full.

Copies *rule into sheet->rules[sheet->rule_count], stamps the stored rule's order field with sheet->next_order, then increments both sheet->rule_count and sheet->next_order. When the sheet has already reached k_ra8_css_max_rules, the function returns immediately without modifying any field, silently discarding the rule.

Parameters
[in,out]sheetSheet that receives the appended rule.
[in]ruleFully-parsed rule to append; must not be NULL.
Returns
Nothing.
Precondition
sheet and rule are non-NULL.
rule is fully populated (selector and declaration fields valid).
Postcondition
When sheet->rule_count < k_ra8_css_max_rules, rule_count and next_order are each incremented by 1 and the rule is stored.
When sheet->rule_count == k_ra8_css_max_rules, no field is modified.
Note
Thread-safe with respect to distinct sheet instances.
Since
0.1.0

Definition at line 429 of file reflow_css_rules.c.

References k_ra8_css_max_rules, ra8_css_sheet_t::next_order, ra8_css_rule_t::order, ra8_css_sheet_t::rule_count, and ra8_css_sheet_t::rules.

Referenced by internal_parse_selector_list().

◆ internal_split_compounds()

int32_t internal_split_compounds ( const char * s,
size_t len,
const char ** part_p,
size_t * part_n )
static

Split s into whitespace-separated compound spans.

Iterates over s[0..len), skipping runs of priv_reflow_css_is_ws() characters and recording the start and length of each non-whitespace token in the parallel part_p / part_n arrays. Returns -1 early when the part count would exceed (k_ra8_css_max_anc + 1), enforcing the maximum ancestor depth. Both output arrays must have capacity for at least (k_ra8_css_max_anc + 1) entries.

Parameters
[in]sSelector text span (need not be NUL-terminated).
[in]lenNumber of bytes in s.
[out]part_pArray of pointers; each entry points into s at the start of the corresponding compound token.
[out]part_nArray of sizes; each entry is the byte length of the corresponding compound token.
Returns
int32_t Number of parts found, or -1 on overflow.
Return values
0The span is empty or contains only whitespace.
>0The number of whitespace-separated compound tokens found.
-1More than (k_ra8_css_max_anc + 1) tokens were encountered.
Precondition
s points to at least len readable bytes.
part_p and part_n are non-NULL with capacity >= (k_ra8_css_max_anc + 1).
Postcondition
On a non-negative return, part_p[0..ret) and part_n[0..ret) are set.
s is not modified; entries beyond the return count are unspecified.
Note
Thread-safe; operates only on caller-owned arrays.
Since
0.1.0

Definition at line 317 of file reflow_css_rules.c.

References k_ra8_css_max_anc, and priv_reflow_css_is_ws().

Referenced by internal_parse_complex_selector().

◆ internal_strip_quotes()

const char * internal_strip_quotes ( const char * s,
size_t * len )
static

Strip one layer of matching '/" quotes from span s[0..*len).

Definition at line 496 of file reflow_css_rules.c.

Referenced by internal_extract_url(), internal_face_apply(), and internal_family_cb().

◆ priv_reflow_css_parse_one_block()

void priv_reflow_css_parse_one_block ( ra8_css_sheet_t * sheet,
const char * sel,
size_t sel_len,
const char * block,
size_t block_len )

Dispatch one selector|@rule { block }: at-rule vs.

style rule.

Trims sel to obtain the effective keyword. When the first byte is '@', routes to internal_parse_at_rule(). Otherwise, parses the declaration block via priv_reflow_css_parse_decls() and internal_extract_family(), then distributes the resulting style to every comma-separated selector in sel via internal_parse_selector_list().

Parameters
[in,out]sheetSheet receiving parsed rules or font faces.
[in]selSelector or at-keyword text.
[in]sel_lenNumber of bytes in sel.
[in]blockDeclaration block body (no surrounding braces).
[in]block_lenNumber of bytes in block.
Returns
Nothing.
Precondition
sheet is non-NULL.
sel points to at least sel_len readable bytes.
Postcondition
sheet has been updated with all rules or faces derived from this block.
sel and block are not modified.
Note
Thread-safe with respect to distinct sheet instances.
Since
0.1.0

Definition at line 958 of file reflow_css_rules.c.

References internal_extract_family(), internal_parse_at_rule(), internal_parse_selector_list(), priv_reflow_css_parse_decls(), and priv_reflow_css_trim().

Referenced by ra8_css_parse().