ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
xml_doctype.c
Go to the documentation of this file.
1
15#include <stddef.h>
16#include <stdint.h>
17#include <string.h>
18
19#include "xml_internal.h"
20
35RA8_INTERNAL static bool internal_space(uint8_t byte)
36{
37 return (byte == (uint8_t)' ') || (byte == (uint8_t)'\t') || (byte == (uint8_t)'\n') ||
38 (byte == (uint8_t)'\r');
39}
40
57RA8_INTERNAL static bool internal_skip_space(const uint8_t* source, size_t end, size_t* position)
58{
59 const size_t initial = *position;
60 while ((*position < end) && internal_space(source[*position])) {
61 ++*position;
62 }
63 return *position != initial;
64}
65
80RA8_INTERNAL static bool internal_pubid_byte(uint8_t byte)
81{
82 static const char punctuation[] = "-'()+,./:=?;!*#@$_%";
83 return (byte == (uint8_t)' ') || (byte == (uint8_t)'\r') || (byte == (uint8_t)'\n') ||
84 ((byte >= (uint8_t)'A') && (byte <= (uint8_t)'Z')) ||
85 ((byte >= (uint8_t)'a') && (byte <= (uint8_t)'z')) ||
86 ((byte >= (uint8_t)'0') && (byte <= (uint8_t)'9')) ||
87 ((byte != 0U) && (strchr(punctuation, (int)byte) != nullptr));
88}
89
108internal_literal(const uint8_t* source, size_t end, size_t* position, bool public_id)
109{
110 if ((*position >= end) ||
111 ((source[*position] != (uint8_t)'\'') && (source[*position] != (uint8_t)'"'))) {
113 }
114 const uint8_t quote = source[*position];
115 *position += 1U;
116 const size_t start = *position;
117 while ((*position < end) && (source[*position] != quote)) {
118 if (public_id && !internal_pubid_byte(source[*position])) {
120 }
121 ++*position;
122 }
123 if (*position >= end) {
125 }
126 const ra8_err_t err = public_id ? k_ra8_ok : priv_xml_raw(source, start, *position);
127 ++*position;
128 return err;
129}
130
149internal_keyword(const uint8_t* source, size_t end, size_t* position, const char* keyword)
150{
151 const size_t length = strlen(keyword);
152 // mcdc-deactivated: internal_keyword prefix recheck; the only caller, internal_external_id, has already proved `(*position + 6U) <= end` and matched the same six bytes before selecting the keyword, and both keywords are exactly six bytes long, so both conditions are constant-false on every reachable path.
153 if (((*position + length) > end) || !priv_xml_bytes_equal(source, *position, keyword, length)) {
155 }
156 *position += length;
157 return internal_skip_space(source, end, position) ? k_ra8_ok : k_ra8_err_validation_failed;
158}
159
177internal_external_id(const uint8_t* source, size_t end, size_t* position)
178{
179 if (((*position + 6U) <= end) && priv_xml_bytes_equal(source, *position, "SYSTEM", 6U)) {
180 ra8_err_t err = internal_keyword(source, end, position, "SYSTEM");
181 return (err == k_ra8_ok) ? internal_literal(source, end, position, false) : err;
182 }
183 if (((*position + 6U) <= end) && priv_xml_bytes_equal(source, *position, "PUBLIC", 6U)) {
184 ra8_err_t err = internal_keyword(source, end, position, "PUBLIC");
185 if (err == k_ra8_ok) {
186 err = internal_literal(source, end, position, true);
187 }
188 if ((err == k_ra8_ok) && !internal_skip_space(source, end, position)) {
190 }
191 return (err == k_ra8_ok) ? internal_literal(source, end, position, false) : err;
192 }
194}
195
197{
198 static const char prefix[] = "<!DOCTYPE";
199 const size_t end = reader->source_len;
200 size_t position = reader->position;
201 if ((reader->root_count != 0U) || (reader->doctype_seen != 0U) ||
202 ((position + sizeof(prefix) - 1U) > end) ||
203 !priv_xml_bytes_equal(reader->source, position, prefix, sizeof(prefix) - 1U)) {
205 }
206 position += sizeof(prefix) - 1U;
207 if (!internal_skip_space(reader->source, end, &position)) {
209 }
210 size_t name_end = 0U;
211 if (priv_xml_qname(reader->source, end, position, &name_end) != k_ra8_ok) {
213 }
214 position = name_end;
215 const bool separated = internal_skip_space(reader->source, end, &position);
216 if ((position < end) && (reader->source[position] != (uint8_t)'>')) {
217 if (!separated || (internal_external_id(reader->source, end, &position) != k_ra8_ok)) {
219 }
220 (void)internal_skip_space(reader->source, end, &position);
221 }
222 if ((position >= end) || (reader->source[position] != (uint8_t)'>')) {
224 }
225 reader->doctype_seen = 1U;
226 reader->position = position + 1U;
227 return k_ra8_ok;
228}
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
size_t strlen(const char *s)
Calculate string length.
char * strchr(const char *s, int c)
Locate first occurrence of character in string.
Pull-reader state; initialise before each pass.
Definition xml.h:93
uint8_t root_count
Completed/started roots.
Definition xml.h:99
const uint8_t * source
Immutable source bytes.
Definition xml.h:94
uint8_t doctype_seen
One after a supported DOCTYPE.
Definition xml.h:102
size_t source_len
Source byte count.
Definition xml.h:95
size_t position
Next scan position.
Definition xml.h:96
ra8_err_t priv_xml_qname(const uint8_t *source, size_t end, size_t start, size_t *out_end)
Scan the supported QName subset over a bounded byte range.
Definition xml.c:47
bool priv_xml_bytes_equal(const uint8_t *source, size_t offset, const char *literal, size_t length)
Compare bounded source bytes against a literal of known length.
Definition xml_decode.c:260
ra8_err_t priv_xml_raw(const uint8_t *source, size_t start, size_t end)
Validate canonical UTF-8 XML 1.0 characters over a byte range.
Definition xml_decode.c:610
static ra8_err_t internal_literal(const uint8_t *source, size_t end, size_t *position, bool public_id)
Parse one quoted system or public identifier literal.
static bool internal_space(uint8_t byte)
Test whether one byte is XML spacing inside a DOCTYPE.
Definition xml_doctype.c:35
static ra8_err_t internal_keyword(const uint8_t *source, size_t end, size_t *position, const char *keyword)
Consume an exact ASCII keyword followed by required spacing.
ra8_err_t priv_xml_doctype(xml_reader_t *reader)
Validate and skip one supported pre-root external DOCTYPE.
static bool internal_skip_space(const uint8_t *source, size_t end, size_t *position)
Skip XML spacing and report whether at least one byte was consumed.
Definition xml_doctype.c:57
static bool internal_pubid_byte(uint8_t byte)
Test the XML PubidChar subset accepted in public identifiers.
Definition xml_doctype.c:80
static ra8_err_t internal_external_id(const uint8_t *source, size_t end, size_t *position)
Parse a SYSTEM or PUBLIC external identifier.
Private lexical seams shared by the bounded XML reader.