From 973aec43ea54bbf95b64fbcb636403401d1ca60e Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Fri, 28 Aug 2026 18:03:05 +0200 Subject: Import from e4b104792206ee7ea64bf39c6b7d2c0c230f9d14 --- server/src/xml.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 server/src/xml.cpp (limited to 'server/src/xml.cpp') diff --git a/server/src/xml.cpp b/server/src/xml.cpp new file mode 100644 index 0000000..cad42d1 --- /dev/null +++ b/server/src/xml.cpp @@ -0,0 +1,61 @@ +module; + +#include +#include + +module routemon:xml$impl; + +import :xml; + +namespace routemon::xml { + + auto qname_view::operator==(qname_view const& rhs) const -> bool { + return ns_uri == rhs.ns_uri && local == rhs.local; + } + + executor::executor() : + p_{XML_ParserCreateNS("UTF-8", detail::qname_sep)} + { + XML_SetUserData(p_, this); + XML_SetElementHandler(p_, handle_start_element, handle_end_element); + XML_SetCharacterDataHandler(p_, handle_character_data); + XML_SetProcessingInstructionHandler(p_, handle_processing_instructions); + XML_SetExternalEntityRefHandler(p_, handle_external_entity_ref); + XML_SetNamespaceDeclHandler(p_, handle_start_namespace_decl, handle_end_namespace_decl); + XML_SetXmlDeclHandler(p_, handle_xml_decl); + } + + executor::~executor() { + XML_ParserFree(p_); + } + + auto executor::start() -> void { + continuation_.resume(); + if (ex_) std::rethrow_exception(ex_); + } + + auto executor::read(std::string_view xml, bool is_final) -> void { + if (ex_) + throw std::runtime_error{"refusing to restart parser that was thrown in"}; + // TODO: narrow_cast + if (auto s = XML_Parse(p_, xml.data(), static_cast(xml.size()), is_final); s != XML_STATUS_OK) { + auto errc = XML_GetErrorCode(p_); + if (errc == XML_ERROR_ABORTED) { + assert(ex_); + std::rethrow_exception(ex_); + } else { + throw std::runtime_error{std::format("failed to parse XML: {}", XML_ErrorString(errc))}; + } + } + } + + auto executor::end() -> void { + if (ex_) + throw std::runtime_error{"refusing to restart parser that was thrown in"}; + ev_ = eof_event{}; + advance_ = false; + while (continuation_) continuation_.resume(); + if (ex_) std::rethrow_exception(ex_); + } + +} // namespace routemon::xml -- cgit v1.3