38 return (c ==
' ') || (c ==
'\t') || (c ==
'\n') || (c ==
'\r') || (c ==
'\f') || (c ==
'\v');
74 const size_t start = *i + 1U;
75 for (
size_t e = 0U; e < (
sizeof(table) /
sizeof(table[0])); ++e) {
76 const size_t nlen =
strlen(table[e].name);
77 if (((start + nlen) <= len) && (
memcmp(s + start, table[e].name, nlen) == 0)) {
78 *i = start + nlen - 1U;
79 *space = (table[e].
ch ==
'\0');
80 *out_ch = table[e].
ch;
108 if ((*n + 1U) < cap) {
139 bool pending =
false;
141 for (
size_t i = 0U; i < len; ++i) {
142 const char c = text[i];
144 while ((i < len) && (text[i] !=
'>')) {
187 const char* q = strpbrk(url,
"?#");
188 const size_t end = (q ==
nullptr) ?
strlen(url) : (size_t)(q - url);
191 while ((fin > 0U) && (url[fin - 1U] ==
'/')) {
195 while ((beg > 0U) && (url[beg - 1U] !=
'/')) {
199 for (
size_t i = beg; (i < fin) && ((n + 1U) < cap); ++i) {
240 if (gt_off >= html_len) {
243 const size_t text_off = gt_off + 1U;
244 const char* close =
internal_find_ci(html + text_off, html_len - text_off,
"</a");
245 const size_t text_len =
246 (close ==
nullptr) ? (html_len - text_off) : (size_t)(close - (html + text_off));
267 for (
size_t i = 0U; i < out->
count; ++i) {
301 if (at < out->count) {
302 if (title_real && !real[at]) {
313 real[out->
count] = title_real;
342 const char* base_url,
364 const bool title_real =
374 const char* base_url,
375 const char* url_contains,
378 if ((html ==
nullptr) || (base_url ==
nullptr) || (out ==
nullptr)) {
384 memset(real, 0,
sizeof(real));
387 while (pos < html_len) {
389 if (tag ==
nullptr) {
392 const size_t tag_off = (size_t)(tag - html);
393 const size_t after = tag_off + (
sizeof(
"<a") - 1U);
398 const char* gt =
memchr(tag,
'>', html_len - tag_off);
399 const size_t gt_off = (gt ==
nullptr) ? html_len : (size_t)(gt - html);
400 const size_t tag_len = (gt ==
nullptr) ? (html_len - tag_off) : (size_t)(gt - tag);
412 pos = tag_off + ((gt ==
nullptr) ? tag_len : (tag_len + 1U));
435 const size_t value_len =
strlen(value);
436 const char* at = classes;
437 while ((at =
strstr(at, value)) !=
nullptr) {
439 const char after = at[value_len];
441 if (left_ok && right_ok) {
468 if (value[0] ==
'\0') {
503 if (tag ==
nullptr) {
506 const size_t off = (size_t)(tag - html);
507 const char* gt =
memchr(tag,
'>', len - off);
511 const size_t tag_len = (size_t)(gt - tag);
516 if (named && (
strcmp(name, key) == 0) &&
523 pos = off + tag_len + 1U;
553 const char* tag =
memchr(html + pos,
'<', len - pos);
554 if (tag ==
nullptr) {
557 const size_t off = (size_t)(tag - html);
558 const char* gt =
memchr(tag,
'>', len - off);
562 const size_t tag_len = (size_t)(gt - tag);
566 const size_t inner_off = (size_t)(gt - html) + 1U;
567 const char* close =
internal_find_ci(html + inner_off, len - inner_off,
"</");
568 const size_t inner_len =
569 (close ==
nullptr) ? (len - inner_off) : (size_t)(close - (html + inner_off));
575 pos = off + tag_len + 1U;
604 if (hit ==
nullptr) {
607 const size_t after_label = (size_t)(hit - html) +
strlen(label);
608 const char* anchor =
internal_find_ci(html + after_label, len - after_label,
"<a");
609 if (anchor ==
nullptr) {
612 const size_t anchor_off = (size_t)(anchor - html);
613 const char* gt =
memchr(anchor,
'>', len - anchor_off);
617 const size_t inner_off = (size_t)(gt - html) + 1U;
618 const char* close =
internal_find_ci(html + inner_off, len - inner_off,
"</a");
619 const size_t inner_len =
620 (close ==
nullptr) ? (len - inner_off) : (size_t)(close - (html + inner_off));
629 const char* selector,
633 if ((html ==
nullptr) || (selector ==
nullptr) || (out ==
nullptr) || (out_cap == 0U)) {
637 const char* value =
strchr(selector,
':');
638 if ((value ==
nullptr) || (value[1] ==
'\0')) {
642 if (
strncmp(selector,
"meta:",
sizeof(
"meta:") - 1U) == 0) {
645 if (
strncmp(selector,
"class:",
sizeof(
"class:") - 1U) == 0) {
648 if (
strncmp(selector,
"label:",
sizeof(
"label:") - 1U) == 0) {
651 if (
strncmp(selector,
"literal:",
sizeof(
"literal:") - 1U) == 0) {
#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_invalid_arg
Invalid function argument.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
@ 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.
int strncmp(const char *s1, const char *s2, size_t n)
Compare two strings up to a specified length.
void * memchr(const void *s, int c, size_t n)
Locate a byte in a memory area.
int strcmp(const char *s1, const char *s2)
Compare two null-terminated strings.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
size_t strlen(const char *s)
Calculate string length.
char * strstr(const char *haystack, const char *needle)
Locate substring in string.
char * strchr(const char *s, int c)
Locate first occurrence of character in string.
int abs(int j)
Compute absolute value of integer.
One recognised HTML entity mapped to its single replacement byte.
const char * name
Entity body after '&', including the ';'.
char ch
Decoded byte ('\0' means "emit a space").
Bounded list of titled hits plus the raw anchor tally.
mdl_hit_t hits[k_mdl_max_hits]
Deduplicated titled hits.
size_t count
Number of valid hits.
size_t anchors_seen
Total resolvable <a href> anchors.
char title[k_mdl_hit_title_max]
Display title, NUL-terminated.
char url[k_mdl_url_max]
Absolute series URL, NUL-terminated.