0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-16 06:51:08 +01:00

ircd::spirit: Add exceptions; move epsilon into generate abstraction; minor cleanup.

This commit is contained in:
Jason Volk 2020-05-26 08:21:56 -07:00
parent 3b485d79f1
commit d58921f756
3 changed files with 82 additions and 75 deletions

View file

@ -52,7 +52,14 @@ __attribute__((visibility("default")))
struct substring_view; struct substring_view;
template<class parent_error> struct expectation_failure; template<class parent_error> struct expectation_failure;
extern thread_local char rulebuf[64]; // parse.cc IRCD_EXCEPTION(ircd::error, error);
IRCD_EXCEPTION(error, generator_error);
IRCD_EXCEPTION(generator_error, buffer_overrun);
// parse.cc
extern thread_local char rulebuf[64];
extern thread_local mutable_buffer *sink_buffer;
extern thread_local size_t sink_consumed;
}} }}
namespace ircd namespace ircd
@ -66,9 +73,6 @@ __attribute__((visibility("default")))
template<class gen, template<class gen,
class... attr> class... attr>
bool generate(mutable_buffer &out, gen&&, attr&&...); bool generate(mutable_buffer &out, gen&&, attr&&...);
template<class gen>
bool generate(mutable_buffer &out, gen&&);
} }
namespace ircd { namespace ircd {
@ -154,6 +158,7 @@ __attribute__((visibility("hidden")))
| karma::generator_properties::tracking | karma::generator_properties::tracking
| karma::generator_properties::disabling | karma::generator_properties::disabling
>; >;
using sink_type = karma::detail::output_iterator<char *, prop_mask, unused_type>; using sink_type = karma::detail::output_iterator<char *, prop_mask, unused_type>;
template<size_t idx, template<size_t idx,
@ -179,7 +184,6 @@ namespace ircd {
namespace spirit namespace spirit
__attribute__((visibility("default"))) __attribute__((visibility("default")))
{ {
extern thread_local mutable_buffer *sink_buffer;
}} }}
struct ircd::spirit::substring_view struct ircd::spirit::substring_view
@ -241,50 +245,29 @@ 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, template<class gen,
class... attr> class... attr>
inline bool inline bool
ircd::generate(mutable_buffer &out, ircd::generate(mutable_buffer &out,
gen&& g, gen&& g,
attr&&... a) attr&&... a)
{ {
using namespace ircd::spirit; using namespace ircd::spirit;
assert(!sink_buffer); const scope_restore sink_buffer_
const scope_restore _sink_buffer
{ {
sink_buffer, &out sink_buffer, std::addressof(out)
};
const scope_restore sink_consumed_
{
sink_consumed, 0UL
};
const size_t max
{
size(out)
}; };
sink_type sink sink_type sink
@ -292,15 +275,21 @@ ircd::generate(mutable_buffer &out,
begin(out) begin(out)
}; };
const auto gg const bool ret
{ {
karma::maxwidth(size(out))[std::forward<gen>(g)] karma::generate(sink, std::forward<gen>(g), std::forward<attr>(a)...)
}; };
const auto ret if(unlikely(sink_consumed > max))
{ {
karma::generate(sink, gg, std::forward<attr>(a)...) char pbuf[2][48];
}; throw spirit::buffer_overrun
{
"Insufficient buffer of %s for %s",
pretty(pbuf[0], iec(max)),
pretty(pbuf[1], iec(sink_consumed)),
};
}
return ret; return ret;
} }
@ -336,36 +325,59 @@ ircd::spirit::attr_at(semantic_context&& c)
} }
template<> template<>
[[gnu::visibility("internal")]] inline void
inline bool boost::spirit::karma::detail::buffer_sink::output(const char &value)
boost::spirit::karma::detail::buffer_sink::copy(ircd::spirit::sink_type &sink,
size_t maxwidth)
const
{ {
assert(ircd::spirit::sink_buffer); assert(ircd::spirit::sink_buffer);
#if __has_builtin(__builtin_assume)
__builtin_assume(ircd::spirit::sink_buffer != nullptr);
#endif
auto &sink_buffer
{
*ircd::spirit::sink_buffer
};
auto &sink_consumed
{
ircd::spirit::sink_consumed
};
const auto consumed
{
ircd::consume(sink_buffer, ircd::copy(sink_buffer, value))
};
this->width += consumed;
sink_consumed++;
}
template<>
inline bool
ircd::spirit::sink_type::good()
const
{
return true; return true;
} }
template<> template<>
[[gnu::visibility("internal")]]
inline bool inline bool
boost::spirit::karma::detail::buffer_sink::copy_rest(ircd::spirit::sink_type &sink, boost::spirit::karma::detail::buffer_sink::copy_rest(ircd::spirit::sink_type &sink,
size_t start_at) size_t start_at)
const const
{ {
assert(ircd::spirit::sink_buffer);
assert(false); assert(false);
return true; return true; //sink.good();
} }
template<> template<>
[[gnu::visibility("internal")]] inline bool
inline void boost::spirit::karma::detail::buffer_sink::copy(ircd::spirit::sink_type &sink,
boost::spirit::karma::detail::buffer_sink::output(const char &value) size_t maxwidth)
const
{ {
assert(ircd::spirit::sink_buffer); return true; //sink.good();
auto &buf(*ircd::spirit::sink_buffer);
ircd::consume(buf, ircd::copy(buf, value));
} }
#endif // HAVE_IRCD_SPIRIT_H #endif // HAVE_IRCD_SPIRIT_H

View file

@ -467,18 +467,13 @@ ircd::json::printer::operator()(mutable_buffer &out,
attr&&... a) attr&&... a)
const const
{ {
const auto throws{[&out] if(unlikely(!ircd::generate(out, std::forward<gen>(g), std::forward<attr>(a)...)))
{ throw print_error
throw print_panic
{ {
"Failed to print attributes '%s' generator '%s' (%zd bytes in buffer)", "Failed to generate JSON"
demangle<decltype(a)...>(),
demangle<decltype(g)>(),
size(out)
}; };
}};
return ircd::generate(out, std::forward<gen>(g) | eps[throws], std::forward<attr>(a)...); return true;
} }
template<class gen> template<class gen>
@ -488,17 +483,13 @@ ircd::json::printer::operator()(mutable_buffer &out,
gen&& g) gen&& g)
const const
{ {
const auto throws{[&out] if(unlikely(!ircd::generate(out, std::forward<gen>(g))))
{ throw print_error
throw print_panic
{ {
"Failed to print generator '%s' (%zd bytes in buffer)", "Failed to generate JSON"
demangle<decltype(g)>(),
size(out)
}; };
}};
return ircd::generate(out, std::forward<gen>(g) | eps[throws]); return true;
} }
template<class it_a, template<class it_a,

View file

@ -31,6 +31,10 @@ thread_local
decltype(ircd::spirit::sink_buffer) decltype(ircd::spirit::sink_buffer)
ircd::spirit::sink_buffer; ircd::spirit::sink_buffer;
thread_local
decltype(ircd::spirit::sink_consumed)
ircd::spirit::sink_consumed;
// //
// Museum of historical comments // Museum of historical comments
// //