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:
parent
3b485d79f1
commit
d58921f756
3 changed files with 82 additions and 75 deletions
|
@ -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
|
||||||
|
|
25
ircd/json.cc
25
ircd/json.cc
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue