diff --git a/ircd/json.cc b/ircd/json.cc index 263ca5228..2e23e8967 100644 --- a/ircd/json.cc +++ b/ircd/json.cc @@ -210,6 +210,16 @@ ircd::json::printer :karma::grammar { using it = char *; + using prop_mask = mpl_::int_ + < + karma::generator_properties::no_properties + | karma::generator_properties::buffering + | karma::generator_properties::counting + | karma::generator_properties::tracking + | karma::generator_properties::disabling + >; + using sink_type = karma::detail::output_iterator; + static thread_local mutable_buffer *sink_buffer; template @@ -454,6 +464,43 @@ noexcept } } +thread_local +decltype(ircd::json::printer::sink_buffer) +ircd::json::printer::sink_buffer; + +template<> +[[gnu::visibility("internal")]] +inline bool +boost::spirit::karma::detail::buffer_sink::copy(ircd::json::printer::sink_type &sink, + size_t maxwidth) +const +{ + assert(ircd::json::printer::sink_buffer); + return true; +} + +template<> +[[gnu::visibility("internal")]] +inline bool +boost::spirit::karma::detail::buffer_sink::copy_rest(ircd::json::printer::sink_type &sink, + size_t start_at) +const +{ + assert(ircd::json::printer::sink_buffer); + assert(false); + return true; +} + +template<> +[[gnu::visibility("internal")]] +inline void +boost::spirit::karma::detail::buffer_sink::output(const char &value) +{ + assert(ircd::json::printer::sink_buffer); + auto &buf(*ircd::json::printer::sink_buffer); + ircd::consume(buf, ircd::copy(buf, value)); +} + template [[gnu::visibility("internal")]] @@ -463,16 +510,6 @@ ircd::json::printer::operator()(mutable_buffer &out, attr&&... a) const { - const auto maxwidth - { - karma::maxwidth(size(out)) - }; - - const auto gg - { - maxwidth[std::forward(g)] - }; - const auto throws{[&out] { throw print_panic @@ -484,9 +521,30 @@ const }; }}; + const auto maxwidth + { + karma::maxwidth(size(out)) + }; + + const auto gg + { + maxwidth[std::forward(g)] + }; + + assert(!sink_buffer); + const scope_restore set_sink_buffer + { + sink_buffer, &out + }; + + sink_type sink + { + begin(out) + }; + const auto ret { - karma::generate(begin(out), gg | eps[throws], std::forward(a)...) + karma::generate(sink, gg | eps[throws], std::forward(a)...) }; return ret; @@ -499,16 +557,6 @@ ircd::json::printer::operator()(mutable_buffer &out, gen&& g) const { - const auto maxwidth - { - karma::maxwidth(size(out)) - }; - - const auto gg - { - maxwidth[std::forward(g)] - }; - const auto throws{[&out] { throw print_panic @@ -519,9 +567,30 @@ const }; }}; + const auto maxwidth + { + karma::maxwidth(size(out)) + }; + + const auto gg + { + maxwidth[std::forward(g)] + }; + + assert(!sink_buffer); + const scope_restore set_sink_buffer + { + sink_buffer, &out + }; + + sink_type sink + { + begin(out) + }; + const auto ret { - karma::generate(begin(out), gg | eps[throws]) + karma::generate(sink, gg | eps[throws]) }; return ret;