0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-02-18 01:30:12 +01:00

ircd::spirit: Abstract common generator call into template.

This commit is contained in:
Jason Volk 2020-05-26 03:03:18 -07:00
parent 93ee6a9f04
commit b698f80067
3 changed files with 123 additions and 102 deletions

View file

@ -62,6 +62,13 @@ __attribute__((visibility("default")))
class it = const char *,
class... args>
bool parse(args&&...);
template<class gen,
class... attr>
bool generate(mutable_buffer &out, gen&&, attr&&...);
template<class gen>
bool generate(mutable_buffer &out, gen&&);
}
namespace ircd {
@ -139,6 +146,16 @@ __attribute__((visibility("hidden")))
using karma::buffer;
using karma::skip;
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<char *, prop_mask, unused_type>;
template<size_t idx,
class semantic_context>
auto &
@ -162,6 +179,7 @@ namespace ircd {
namespace spirit
__attribute__((visibility("default")))
{
extern thread_local mutable_buffer *sink_buffer;
}}
struct ircd::spirit::substring_view
@ -223,6 +241,70 @@ ircd::spirit::expectation_failure<parent>::expectation_failure(const qi::expecta
}
{}
template<class gen>
inline bool
ircd::generate(mutable_buffer &out,
gen&& g)
{
using namespace ircd::spirit;
assert(!sink_buffer);
const scope_restore _sink_buffer
{
sink_buffer, &out
};
sink_type sink
{
begin(out)
};
const auto gg
{
karma::maxwidth(size(out))[std::forward<gen>(g)]
};
const auto ret
{
karma::generate(sink, gg)
};
return ret;
}
template<class gen,
class... attr>
inline bool
ircd::generate(mutable_buffer &out,
gen&& g,
attr&&... a)
{
using namespace ircd::spirit;
assert(!sink_buffer);
const scope_restore _sink_buffer
{
sink_buffer, &out
};
sink_type sink
{
begin(out)
};
const auto gg
{
karma::maxwidth(size(out))[std::forward<gen>(g)]
};
const auto ret
{
karma::generate(sink, gg, std::forward<attr>(a)...)
};
return ret;
}
template<class parent_error,
class it,
class... args>
@ -253,4 +335,37 @@ ircd::spirit::attr_at(semantic_context&& c)
return boost::fusion::at_c<idx>(c.attributes);
}
template<>
[[gnu::visibility("internal")]]
inline bool
boost::spirit::karma::detail::buffer_sink::copy(ircd::spirit::sink_type &sink,
size_t maxwidth)
const
{
assert(ircd::spirit::sink_buffer);
return true;
}
template<>
[[gnu::visibility("internal")]]
inline bool
boost::spirit::karma::detail::buffer_sink::copy_rest(ircd::spirit::sink_type &sink,
size_t start_at)
const
{
assert(ircd::spirit::sink_buffer);
assert(false);
return true;
}
template<>
[[gnu::visibility("internal")]]
inline void
boost::spirit::karma::detail::buffer_sink::output(const char &value)
{
assert(ircd::spirit::sink_buffer);
auto &buf(*ircd::spirit::sink_buffer);
ircd::consume(buf, ircd::copy(buf, value));
}
#endif // HAVE_IRCD_SPIRIT_H

View file

@ -210,16 +210,6 @@ ircd::json::printer
:karma::grammar<char *, unused_type>
{
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<it, prop_mask, unused_type>;
static thread_local mutable_buffer *sink_buffer;
template<class T = unused_type,
class... A>
@ -468,43 +458,6 @@ 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<class gen,
class... attr>
[[gnu::visibility("internal")]]
@ -525,33 +478,7 @@ const
};
}};
const auto maxwidth
{
karma::maxwidth(size(out))
};
const auto gg
{
maxwidth[std::forward<gen>(g)]
};
assert(!sink_buffer);
const scope_restore set_sink_buffer
{
sink_buffer, &out
};
sink_type sink
{
begin(out)
};
const auto ret
{
karma::generate(sink, gg | eps[throws], std::forward<attr>(a)...)
};
return ret;
return ircd::generate(out, std::forward<gen>(g) | eps[throws], std::forward<attr>(a)...);
}
template<class gen>
@ -571,33 +498,7 @@ const
};
}};
const auto maxwidth
{
karma::maxwidth(size(out))
};
const auto gg
{
maxwidth[std::forward<gen>(g)]
};
assert(!sink_buffer);
const scope_restore set_sink_buffer
{
sink_buffer, &out
};
sink_type sink
{
begin(out)
};
const auto ret
{
karma::generate(sink, gg | eps[throws])
};
return ret;
return ircd::generate(out, std::forward<gen>(g) | eps[throws]);
}
template<class it_a,

View file

@ -23,9 +23,14 @@
* USA
*/
decltype(ircd::spirit::rulebuf) thread_local
thread_local
decltype(ircd::spirit::rulebuf)
ircd::spirit::rulebuf;
thread_local
decltype(ircd::spirit::sink_buffer)
ircd::spirit::sink_buffer;
//
// Museum of historical comments
//