diff options
Diffstat (limited to 'server/src/xml.cppm')
| -rw-r--r-- | server/src/xml.cppm | 140 |
1 files changed, 70 insertions, 70 deletions
diff --git a/server/src/xml.cppm b/server/src/xml.cppm index 0c319e6..4648047 100644 --- a/server/src/xml.cppm +++ b/server/src/xml.cppm | |||
| @@ -66,7 +66,7 @@ public: | |||
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | inline explicit attribute_view_iterator( | 68 | inline explicit attribute_view_iterator( |
| 69 | std::string_view default_ns_uri, char const* const* attrs) | 69 | std::string_view default_ns_uri, char const* const* attrs) |
| 70 | : default_ns_uri_{default_ns_uri}, attrs_{attrs} | 70 | : default_ns_uri_{default_ns_uri}, attrs_{attrs} |
| 71 | { | 71 | { |
| 72 | } | 72 | } |
| @@ -105,7 +105,7 @@ class attribute_view : std::ranges::view_base | |||
| 105 | 105 | ||
| 106 | public: | 106 | public: |
| 107 | inline explicit attribute_view( | 107 | inline explicit attribute_view( |
| 108 | std::string_view default_ns_uri, char const** attrs) | 108 | std::string_view default_ns_uri, char const** attrs) |
| 109 | : default_ns_uri_{default_ns_uri}, | 109 | : default_ns_uri_{default_ns_uri}, |
| 110 | attrs_{const_cast<char const* const*>(attrs)} | 110 | attrs_{const_cast<char const* const*>(attrs)} |
| 111 | { | 111 | { |
| @@ -122,7 +122,7 @@ public: | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | inline auto lookup(qname_view want) | 124 | inline auto lookup(qname_view want) |
| 125 | -> std::optional<util::not_null<util::lazy_zstring_view>> | 125 | -> std::optional<util::not_null<util::lazy_zstring_view>> |
| 126 | { | 126 | { |
| 127 | for (auto const& [name, v] : *this) | 127 | for (auto const& [name, v] : *this) |
| 128 | { | 128 | { |
| @@ -200,8 +200,8 @@ struct eof_event | |||
| 200 | }; | 200 | }; |
| 201 | 201 | ||
| 202 | using event = std::variant< | 202 | using event = std::variant< |
| 203 | start_element_event, end_element_event, character_data_event, | 203 | start_element_event, end_element_event, character_data_event, |
| 204 | processing_instructions_event, xml_decl_event, eof_event>; | 204 | processing_instructions_event, xml_decl_event, eof_event>; |
| 205 | 205 | ||
| 206 | template <class T> | 206 | template <class T> |
| 207 | concept event_type = requires(event ev) { std::get<T>(ev); }; | 207 | concept event_type = requires(event ev) { std::get<T>(ev); }; |
| @@ -237,7 +237,7 @@ public: | |||
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | [[nodiscard]] inline auto continuation() const | 239 | [[nodiscard]] inline auto continuation() const |
| 240 | -> std::coroutine_handle<promise_base> | 240 | -> std::coroutine_handle<promise_base> |
| 241 | { | 241 | { |
| 242 | return continuation_; | 242 | return continuation_; |
| 243 | } | 243 | } |
| @@ -285,11 +285,11 @@ class executor | |||
| 285 | s != XML_STATUS_OK) | 285 | s != XML_STATUS_OK) |
| 286 | { | 286 | { |
| 287 | ex_ = std::make_exception_ptr( | 287 | ex_ = std::make_exception_ptr( |
| 288 | std::runtime_error{"unexpected error when stopping XML parser"}); | 288 | std::runtime_error{"unexpected error when stopping XML parser"}); |
| 289 | return; | 289 | return; |
| 290 | } | 290 | } |
| 291 | ex_ = std::make_exception_ptr( | 291 | ex_ = std::make_exception_ptr( |
| 292 | std::runtime_error{"parser did not consume entire XML document"}); | 292 | std::runtime_error{"parser did not consume entire XML document"}); |
| 293 | return; | 293 | return; |
| 294 | } | 294 | } |
| 295 | continuation_.resume(); | 295 | continuation_.resume(); |
| @@ -302,74 +302,74 @@ class executor | |||
| 302 | 302 | ||
| 303 | static auto | 303 | static auto |
| 304 | handle_start_element(void* ctx, char const* name, char const** attrs) noexcept | 304 | handle_start_element(void* ctx, char const* name, char const** attrs) noexcept |
| 305 | -> void | 305 | -> void |
| 306 | { | 306 | { |
| 307 | auto qname = detail::split_name(name); | 307 | auto qname = detail::split_name(name); |
| 308 | static_cast<executor*>(ctx)->try_handle_event( | 308 | static_cast<executor*>(ctx)->try_handle_event( |
| 309 | start_element_event{ | 309 | start_element_event{ |
| 310 | .name = qname, | 310 | .name = qname, |
| 311 | .attrs = attribute_view{qname.ns_uri, attrs}, | 311 | .attrs = attribute_view{qname.ns_uri, attrs}, |
| 312 | }); | 312 | }); |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | static auto handle_end_element(void* ctx, char const* name) noexcept -> void | 315 | static auto handle_end_element(void* ctx, char const* name) noexcept -> void |
| 316 | { | 316 | { |
| 317 | static_cast<executor*>(ctx)->try_handle_event( | 317 | static_cast<executor*>(ctx)->try_handle_event( |
| 318 | end_element_event{ | 318 | end_element_event{ |
| 319 | .name = detail::split_name(name), | 319 | .name = detail::split_name(name), |
| 320 | }); | 320 | }); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | static auto handle_character_data(void* ctx, char const* s, int len) noexcept | 323 | static auto handle_character_data(void* ctx, char const* s, int len) noexcept |
| 324 | -> void | 324 | -> void |
| 325 | { | 325 | { |
| 326 | static_cast<executor*>(ctx)->try_handle_event( | 326 | static_cast<executor*>(ctx)->try_handle_event( |
| 327 | character_data_event{ | 327 | character_data_event{ |
| 328 | .data = std::string_view{s, static_cast<std::size_t>(len)}, | 328 | .data = std::string_view{s, static_cast<std::size_t>(len)}, |
| 329 | }); | 329 | }); |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | static auto handle_processing_instructions( | 332 | static auto handle_processing_instructions( |
| 333 | void* ctx, char const* target, char const* data) noexcept -> void | 333 | void* ctx, char const* target, char const* data) noexcept -> void |
| 334 | { | 334 | { |
| 335 | static_cast<executor*>(ctx)->try_handle_event( | 335 | static_cast<executor*>(ctx)->try_handle_event( |
| 336 | processing_instructions_event{ | 336 | processing_instructions_event{ |
| 337 | .target = util::lazy_zstring_view{target}, | 337 | .target = util::lazy_zstring_view{target}, |
| 338 | .data = util::lazy_zstring_view{data}, | 338 | .data = util::lazy_zstring_view{data}, |
| 339 | }); | 339 | }); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | static auto handle_external_entity_ref( | 342 | static auto handle_external_entity_ref( |
| 343 | XML_Parser, char const* /* context */, char const* /* base */, | 343 | XML_Parser, char const* /* context */, char const* /* base */, |
| 344 | char const* /* system_id */, char const* /* public_id */) noexcept -> int | 344 | char const* /* system_id */, char const* /* public_id */) noexcept -> int |
| 345 | { | 345 | { |
| 346 | return XML_STATUS_ERROR; | 346 | return XML_STATUS_ERROR; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static auto handle_start_namespace_decl( | 349 | static auto handle_start_namespace_decl( |
| 350 | void* ctx, char const* prefix, char const* uri) noexcept -> void | 350 | void* ctx, char const* prefix, char const* uri) noexcept -> void |
| 351 | { | 351 | { |
| 352 | if (prefix) | 352 | if (prefix) |
| 353 | { | 353 | { |
| 354 | static_cast<executor*>(ctx) | 354 | static_cast<executor*>(ctx) |
| 355 | ->namespaces_[std::string_view{prefix}] | 355 | ->namespaces_[std::string_view{prefix}] |
| 356 | .emplace_back(uri); | 356 | .emplace_back(uri); |
| 357 | } | 357 | } |
| 358 | else | 358 | else |
| 359 | { | 359 | { |
| 360 | static_cast<executor*>(ctx)->default_namespace_.push_back( | 360 | static_cast<executor*>(ctx)->default_namespace_.push_back( |
| 361 | uri ? std::make_optional<std::string>(uri) : std::nullopt); | 361 | uri ? std::make_optional<std::string>(uri) : std::nullopt); |
| 362 | } | 362 | } |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | static auto handle_end_namespace_decl(void* ctx, char const* prefix) noexcept | 365 | static auto handle_end_namespace_decl(void* ctx, char const* prefix) noexcept |
| 366 | -> void | 366 | -> void |
| 367 | { | 367 | { |
| 368 | if (prefix) | 368 | if (prefix) |
| 369 | { | 369 | { |
| 370 | static_cast<executor*>(ctx) | 370 | static_cast<executor*>(ctx) |
| 371 | ->namespaces_[std::string_view{prefix}] | 371 | ->namespaces_[std::string_view{prefix}] |
| 372 | .pop_back(); | 372 | .pop_back(); |
| 373 | } | 373 | } |
| 374 | else | 374 | else |
| 375 | { | 375 | { |
| @@ -378,16 +378,16 @@ class executor | |||
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | static auto handle_xml_decl( | 380 | static auto handle_xml_decl( |
| 381 | void* ctx, char const* version, char const* encoding, | 381 | void* ctx, char const* version, char const* encoding, |
| 382 | int standalone) noexcept -> void | 382 | int standalone) noexcept -> void |
| 383 | { | 383 | { |
| 384 | static_cast<executor*>(ctx)->try_handle_event( | 384 | static_cast<executor*>(ctx)->try_handle_event( |
| 385 | xml_decl_event{ | 385 | xml_decl_event{ |
| 386 | .version = util::lazy_zstring_view{version}, | 386 | .version = util::lazy_zstring_view{version}, |
| 387 | .encoding = util::lazy_zstring_view{encoding}, | 387 | .encoding = util::lazy_zstring_view{encoding}, |
| 388 | .standalone = | 388 | .standalone = standalone < 0 ? std::nullopt |
| 389 | standalone < 0 ? std::nullopt : std::make_optional(standalone > 0), | 389 | : std::make_optional(standalone > 0), |
| 390 | }); | 390 | }); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | inline auto advance_flag() -> bool { return advance_; } | 393 | inline auto advance_flag() -> bool { return advance_; } |
| @@ -431,7 +431,7 @@ public: | |||
| 431 | inline auto event() const -> std::optional<event> const& { return ev_; } | 431 | inline auto event() const -> std::optional<event> const& { return ev_; } |
| 432 | 432 | ||
| 433 | inline auto resolve_namespace(std::string_view prefix) | 433 | inline auto resolve_namespace(std::string_view prefix) |
| 434 | -> std::optional<std::string_view> | 434 | -> std::optional<std::string_view> |
| 435 | { | 435 | { |
| 436 | if (auto it = namespaces_.find(prefix); | 436 | if (auto it = namespaces_.find(prefix); |
| 437 | it != namespaces_.end() && !it->second.empty()) | 437 | it != namespaces_.end() && !it->second.empty()) |
| @@ -573,7 +573,7 @@ public: | |||
| 573 | return false; | 573 | return false; |
| 574 | } | 574 | } |
| 575 | auto await_suspend(std::coroutine_handle<promise<T>> h) | 575 | auto await_suspend(std::coroutine_handle<promise<T>> h) |
| 576 | -> std::coroutine_handle<> | 576 | -> std::coroutine_handle<> |
| 577 | { | 577 | { |
| 578 | // Passed coroutine handle will be the same as | 578 | // Passed coroutine handle will be the same as |
| 579 | // parser<T>::handle_type::from_promise(*this) | 579 | // parser<T>::handle_type::from_promise(*this) |
| @@ -621,13 +621,13 @@ using parser_result_t = T::result_type; | |||
| 621 | 621 | ||
| 622 | template <class T, class... Args> | 622 | template <class T, class... Args> |
| 623 | concept parser_invocable = | 623 | concept parser_invocable = |
| 624 | std::invocable<T, Args...> | 624 | std::invocable<T, Args...> |
| 625 | && parser_of<std::invoke_result_t<T, Args...>, unconstrained>; | 625 | && parser_of<std::invoke_result_t<T, Args...>, unconstrained>; |
| 626 | 626 | ||
| 627 | template <class Fn, class... Args> | 627 | template <class Fn, class... Args> |
| 628 | requires parser_invocable<Fn, Args...> | 628 | requires parser_invocable<Fn, Args...> |
| 629 | using parser_invoke_result_t = | 629 | using parser_invoke_result_t = |
| 630 | parser_result_t<std::invoke_result_t<Fn, Args...>>; | 630 | parser_result_t<std::invoke_result_t<Fn, Args...>>; |
| 631 | 631 | ||
| 632 | template <event_type T> | 632 | template <event_type T> |
| 633 | auto expect_event(executor_ref e) -> parser<T> | 633 | auto expect_event(executor_ref e) -> parser<T> |
| @@ -637,28 +637,28 @@ auto expect_event(executor_ref e) -> parser<T> | |||
| 637 | { | 637 | { |
| 638 | auto pos = e->position(); | 638 | auto pos = e->position(); |
| 639 | throw std::runtime_error{std::format( | 639 | throw std::runtime_error{std::format( |
| 640 | "at {}:{}: unexpected event type, have {}", pos.line, pos.col, | 640 | "at {}:{}: unexpected event type, have {}", pos.line, pos.col, |
| 641 | ev.index())}; | 641 | ev.index())}; |
| 642 | } | 642 | } |
| 643 | e->set_advance_flag(); | 643 | e->set_advance_flag(); |
| 644 | co_return std::get<T>(ev); | 644 | co_return std::get<T>(ev); |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | inline auto expect_start_element(executor_ref e, qname_view want) | 647 | inline auto expect_start_element(executor_ref e, qname_view want) |
| 648 | -> parser<attribute_view> | 648 | -> parser<attribute_view> |
| 649 | { | 649 | { |
| 650 | auto ev = co_await expect_event<start_element_event>(e); | 650 | auto ev = co_await expect_event<start_element_event>(e); |
| 651 | if (ev.name != want) | 651 | if (ev.name != want) |
| 652 | { | 652 | { |
| 653 | auto pos = e->position(); | 653 | auto pos = e->position(); |
| 654 | throw std::runtime_error{std::format( | 654 | throw std::runtime_error{std::format( |
| 655 | "at {}:{}: unexpected element started", pos.line, pos.col)}; | 655 | "at {}:{}: unexpected element started", pos.line, pos.col)}; |
| 656 | } | 656 | } |
| 657 | co_return ev.attrs; | 657 | co_return ev.attrs; |
| 658 | } | 658 | } |
| 659 | 659 | ||
| 660 | inline auto allow_start_element(executor_ref e, qname_view want) | 660 | inline auto allow_start_element(executor_ref e, qname_view want) |
| 661 | -> parser<std::optional<attribute_view>> | 661 | -> parser<std::optional<attribute_view>> |
| 662 | { | 662 | { |
| 663 | auto ev = co_await current_event(e); | 663 | auto ev = co_await current_event(e); |
| 664 | if (auto const* pev = std::get_if<start_element_event>(&ev)) | 664 | if (auto const* pev = std::get_if<start_element_event>(&ev)) |
| @@ -707,9 +707,9 @@ inline auto ignore_whitespace(executor_ref e) -> parser<void> | |||
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | auto expect_element( | 709 | auto expect_element( |
| 710 | executor_ref e, qname_view want, | 710 | executor_ref e, qname_view want, |
| 711 | parser_invocable<executor_ref, attribute_view> auto p) | 711 | parser_invocable<executor_ref, attribute_view> auto p) |
| 712 | -> parser<parser_invoke_result_t<decltype(p), executor_ref, attribute_view>> | 712 | -> parser<parser_invoke_result_t<decltype(p), executor_ref, attribute_view>> |
| 713 | { | 713 | { |
| 714 | co_await ignore_whitespace(e); | 714 | co_await ignore_whitespace(e); |
| 715 | auto attrs = co_await expect_start_element(e, want); | 715 | auto attrs = co_await expect_start_element(e, want); |
| @@ -717,14 +717,14 @@ auto expect_element( | |||
| 717 | co_await expect_end_element(e, want); | 717 | co_await expect_end_element(e, want); |
| 718 | co_await ignore_whitespace(e); | 718 | co_await ignore_whitespace(e); |
| 719 | co_return std::forward< | 719 | co_return std::forward< |
| 720 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>>(res); | 720 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>>(res); |
| 721 | } | 721 | } |
| 722 | 722 | ||
| 723 | auto allow_element( | 723 | auto allow_element( |
| 724 | executor_ref e, qname_view want, | 724 | executor_ref e, qname_view want, |
| 725 | parser_invocable<executor_ref, attribute_view> auto p) | 725 | parser_invocable<executor_ref, attribute_view> auto p) |
| 726 | -> parser<std::optional< | 726 | -> parser<std::optional< |
| 727 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>>> | 727 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>>> |
| 728 | { | 728 | { |
| 729 | co_await ignore_whitespace(e); | 729 | co_await ignore_whitespace(e); |
| 730 | if (auto mattrs = co_await allow_start_element(e, want)) | 730 | if (auto mattrs = co_await allow_start_element(e, want)) |
| @@ -733,18 +733,18 @@ auto allow_element( | |||
| 733 | co_await expect_end_element(e, want); | 733 | co_await expect_end_element(e, want); |
| 734 | co_await ignore_whitespace(e); | 734 | co_await ignore_whitespace(e); |
| 735 | co_return std::make_optional( | 735 | co_return std::make_optional( |
| 736 | std::forward< | 736 | std::forward< |
| 737 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>>( | 737 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>>( |
| 738 | res)); | 738 | res)); |
| 739 | } | 739 | } |
| 740 | co_return std::nullopt; | 740 | co_return std::nullopt; |
| 741 | } | 741 | } |
| 742 | 742 | ||
| 743 | auto allow_element( | 743 | auto allow_element( |
| 744 | executor_ref e, qname_view want, | 744 | executor_ref e, qname_view want, |
| 745 | parser_invocable<executor_ref, attribute_view> auto p) -> parser<bool> | 745 | parser_invocable<executor_ref, attribute_view> auto p) -> parser<bool> |
| 746 | requires std::is_void_v< | 746 | requires std::is_void_v< |
| 747 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>> | 747 | parser_invoke_result_t<decltype(p), executor_ref, attribute_view>> |
| 748 | { | 748 | { |
| 749 | co_await ignore_whitespace(e); | 749 | co_await ignore_whitespace(e); |
| 750 | if (auto mattrs = co_await allow_start_element(e, want)) | 750 | if (auto mattrs = co_await allow_start_element(e, want)) |
| @@ -759,7 +759,7 @@ auto allow_element( | |||
| 759 | 759 | ||
| 760 | inline auto | 760 | inline auto |
| 761 | ignore_contents(executor_ref e, std::optional<qname_view> muntil = std::nullopt) | 761 | ignore_contents(executor_ref e, std::optional<qname_view> muntil = std::nullopt) |
| 762 | -> parser<void> | 762 | -> parser<void> |
| 763 | { | 763 | { |
| 764 | std::size_t depth = 0; | 764 | std::size_t depth = 0; |
| 765 | while (true) | 765 | while (true) |
| @@ -791,7 +791,7 @@ ignore_contents(executor_ref e, std::optional<qname_view> muntil = std::nullopt) | |||
| 791 | } | 791 | } |
| 792 | } | 792 | } |
| 793 | inline auto ignore_element_contents(executor_ref e, attribute_view) | 793 | inline auto ignore_element_contents(executor_ref e, attribute_view) |
| 794 | -> parser<void> | 794 | -> parser<void> |
| 795 | { | 795 | { |
| 796 | co_await ignore_contents(e); | 796 | co_await ignore_contents(e); |
| 797 | } | 797 | } |
| @@ -814,7 +814,7 @@ inline auto read_string(executor_ref e) -> parser<std::string> | |||
| 814 | } | 814 | } |
| 815 | } | 815 | } |
| 816 | inline auto read_string_contents(executor_ref e, attribute_view) | 816 | inline auto read_string_contents(executor_ref e, attribute_view) |
| 817 | -> parser<std::string> | 817 | -> parser<std::string> |
| 818 | { | 818 | { |
| 819 | co_return co_await read_string(e); | 819 | co_return co_await read_string(e); |
| 820 | } | 820 | } |
| @@ -823,7 +823,7 @@ template <auto f> | |||
| 823 | auto hohalo() | 823 | auto hohalo() |
| 824 | { | 824 | { |
| 825 | return []<class... Args>( | 825 | return []<class... Args>( |
| 826 | Args&&... args) -> std::invoke_result_t<decltype(f), Args...> | 826 | Args&&... args) -> std::invoke_result_t<decltype(f), Args...> |
| 827 | { co_return co_await f(std::forward<Args>(args)...); }; | 827 | { co_return co_await f(std::forward<Args>(args)...); }; |
| 828 | } | 828 | } |
| 829 | 829 | ||