19#ifndef DESCENT_XML_PARSE
20#define DESCENT_XML_PARSE
33#include <libadt/lptr.h>
34#include <libadt/vector.h>
69 struct libadt_const_lptr element_name,
70 struct libadt_const_lptr attributes,
90 struct libadt_const_lptr text,
144inline bool _descent_xml_is_attribute_value_type(
struct descent_xml_lex token)
146 return token.
type == descent_xml_classifier_attribute_value_single_quote
147 || token.
type == descent_xml_classifier_attribute_value_single_quote_entity_start
148 || token.
type == descent_xml_classifier_attribute_value_single_quote_entity
149 || token.
type == descent_xml_classifier_attribute_value_double_quote
150 || token.
type == descent_xml_classifier_attribute_value_double_quote_entity_start
151 || token.
type == descent_xml_classifier_attribute_value_double_quote_entity;
156 struct libadt_const_lptr
value;
158} _descent_xml_value_t;
160inline _descent_xml_value_t _descent_xml_attribute_value(
164 if (!_descent_xml_is_attribute_value_type(token))
165 return (_descent_xml_value_t) {
166 libadt_const_lptr_truncate(token.
value, 0),
170 struct libadt_const_lptr result = token.
value;
172 while (_descent_xml_is_attribute_value_type(next)) {
173 result.length += next.
value.length;
176 return (_descent_xml_value_t) { result, next };
185 const struct libadt_const_lptr name = token.
value;
191 LIBADT_VECTOR_WITH(attributes,
sizeof(
struct libadt_const_lptr), 0) {
192 while (token.
type == descent_xml_classifier_element_space) {
198 if (token.
type == descent_xml_classifier_attribute_name) {
199 attributes = libadt_vector_append(
206 if (token.
type == descent_xml_classifier_attribute_expect_assign)
208 if (token.
type == descent_xml_classifier_attribute_assign)
211 token.
type == descent_xml_classifier_attribute_value_single_quote_start
212 || token.
type == descent_xml_classifier_attribute_value_double_quote_start;
216 _descent_xml_value_t attr
217 = _descent_xml_attribute_value(token);
218 attributes = libadt_vector_append(
231 = token.
type == descent_xml_classifier_element_empty;
233 if (is_empty || token.
type == descent_xml_classifier_element_end) {
234 struct libadt_const_lptr attribsptr = {
235 .buffer = attributes.buffer,
236 .size =
sizeof(
struct libadt_const_lptr),
237 .length = (ssize_t)attributes.length,
240 token = element_handler(
254 return token.
type == descent_xml_classifier_text_space
255 || token.
type == descent_xml_classifier_text
256 || token.
type == descent_xml_classifier_text_entity_start
257 || token.
type == descent_xml_classifier_text_entity;
260inline _descent_xml_value_t _descent_xml_text_value(
264 struct libadt_const_lptr result = token.
value;
266 while (_descent_xml_is_text_type(next)) {
267 result.length += next.
value.length;
271 return (_descent_xml_value_t) { result, token };
280 _descent_xml_value_t result = _descent_xml_text_value(token);
281 text_handler(result.value,
false, context);
328 if (xml.type == descent_xml_classifier_element_name && element_handler) {
329 xml = _descent_xml_handle_element(
334 }
else if (_descent_xml_is_text_type(xml) && text_handler) {
335 xml = _descent_xml_handle_text(
340 }
else if (xml.type == descent_xml_lex_cdata && text_handler) {
342 struct libadt_const_lptr arg
343 = libadt_const_lptr_index(
345 sizeof(
"![CDATA[") - 1
347 arg = libadt_const_lptr_truncate(
351 text_handler(arg,
true, context);
362} _descent_xml_parse_cstr_context;
368 struct libadt_const_lptr element_name,
369 struct libadt_const_lptr attributes,
375 const _descent_xml_parse_cstr_context *
const cstr_context = context;
376 if (!cstr_context->element_handler)
379 char *
const cname = strndup(element_name.buffer, (
size_t)element_name.length);
381 goto error_return_xml;
383 char * *
const cattr = calloc((
size_t)(attributes.length + 1),
sizeof(
char*));
385 goto error_free_cname;
387 for (ssize_t i = 0; i < attributes.length; ++i) {
388 const struct libadt_const_lptr *
const attarr = attributes.buffer;
389 const struct libadt_const_lptr *
const attribute = &attarr[i];
390 cattr[i] = strndup(attribute->buffer, (
size_t)attribute->length);
392 goto error_free_cattr;
395 xml = cstr_context->element_handler(
400 cstr_context->context
403 for (
char **attr = cattr; *attr; attr++) {
412 for (
char **attr = cattr; *attr; attr++) {
419 xml.type = descent_xml_parse_error;
423inline void _cstr_text_handler(
424 struct libadt_const_lptr text,
429 _descent_xml_parse_cstr_context *
const cstr_context = context;
430 if (!cstr_context->text_handler)
433 char *
const ctext = strndup(text.buffer, (
size_t)text.length);
435 cstr_context->error = 1;
439 cstr_context->text_handler(
442 cstr_context->context
491 _descent_xml_parse_cstr_context cstr_context = {
492 .element_handler = element_handler,
493 .text_handler = text_handler,
498 _cstr_element_handler,
void descent_xml_classifier_void_fn(void)
Definition classifier.h:59
descent_xml_classifier_fn *const descent_xml_classifier_unexpected
descent_xml_classifier_fn *const descent_xml_classifier_eof
struct descent_xml_lex descent_xml_lex_next_raw(struct descent_xml_lex token)
Returns the next, raw token in the script referred to by previous.
Definition lex.h:608
void descent_xml_parse_text_cstr_fn(char *text, bool is_cdata, void *context)
Type signature for a user-passed text node parsing function. Used by descent_xml_parse_cstr().
Definition parse.h:132
struct descent_xml_lex descent_xml_parse_element_fn(struct descent_xml_lex token, struct libadt_const_lptr element_name, struct libadt_const_lptr attributes, bool empty, void *context)
Type signature for a user-passed element parsing function. Used by descent_xml_parse().
struct descent_xml_lex descent_xml_parse_element_cstr_fn(struct descent_xml_lex token, char *element_name, char **attributes, bool empty, void *context)
Type signature for a user-passed element parsing function. Used by descent_xml_parse_cstr().
struct descent_xml_lex descent_xml_parse_cstr(struct descent_xml_lex xml, descent_xml_parse_element_cstr_fn *element_handler, descent_xml_parse_text_cstr_fn *text_handler, void *context)
Function for parsing an XML document.
Definition parse.h:484
void descent_xml_parse_text_fn(struct libadt_const_lptr text, bool is_cdata, void *context)
Type signature for a user-passed text node parsing function. Used by descent_xml_parse().
Definition parse.h:89
struct descent_xml_lex descent_xml_parse(struct descent_xml_lex xml, descent_xml_parse_element_fn *element_handler, descent_xml_parse_text_fn *text_handler, void *context)
Function for parsing an XML document.
Definition parse.h:319
Represents a single token.
Definition lex.h:42
struct libadt_const_lptr value
A pointer to the classifiered value.
Definition lex.h:58
descent_xml_classifier_fn * type
Represents the type of token classifiered.
Definition lex.h:46