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