mirror of
https://github.com/matrix-construct/construct
synced 2024-11-18 07:50:57 +01:00
ircd::json: Use switch statement over enumeration in character_dfa. (related 24d73428c8
)
This commit is contained in:
parent
24d73428c8
commit
4ca481a5fc
1 changed files with 66 additions and 64 deletions
130
ircd/json.cc
130
ircd/json.cc
|
@ -277,7 +277,7 @@ ircd::json::printer
|
||||||
|
|
||||||
// string
|
// string
|
||||||
struct string_state;
|
struct string_state;
|
||||||
union character_state;
|
struct character_state;
|
||||||
using character_prototype = char(const string_view &, string_state &);
|
using character_prototype = char(const string_view &, string_state &);
|
||||||
template<class context> static void character_dfa(char &, context &, bool &) noexcept;
|
template<class context> static void character_dfa(char &, context &, bool &) noexcept;
|
||||||
const rule<character_prototype, locals<character_state>> character
|
const rule<character_prototype, locals<character_state>> character
|
||||||
|
@ -363,19 +363,21 @@ struct ircd::json::printer::string_state
|
||||||
bool escaped {0};
|
bool escaped {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
union ircd::json::printer::character_state
|
struct ircd::json::printer::character_state
|
||||||
{
|
{
|
||||||
static const char ctrl_tab[0x20][8];
|
static const char ctrl_tab[0x20][8];
|
||||||
|
|
||||||
uint64_t mode {0}; struct
|
enum mode
|
||||||
{
|
{
|
||||||
bool leave;
|
PASS,
|
||||||
bool ctrl;
|
LEAVE,
|
||||||
bool quote;
|
CTRL,
|
||||||
bool escape;
|
QUOTE,
|
||||||
bool escaped;
|
ESCAPE,
|
||||||
uint8_t pos;
|
ESCAPED,
|
||||||
};
|
}
|
||||||
|
mode {PASS};
|
||||||
|
uint8_t pos {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
decltype(ircd::json::printer::character_state::ctrl_tab)
|
decltype(ircd::json::printer::character_state::ctrl_tab)
|
||||||
|
@ -406,72 +408,72 @@ ircd::json::printer::character_dfa(char &out,
|
||||||
bool &ret)
|
bool &ret)
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
__label__ Lpass, Lleave, Lctrl, Lquote, Lescape, Lescaped;
|
using mode = decltype(character_state::mode);
|
||||||
|
|
||||||
#if __has_builtin(__builtin_assume)
|
#if __has_builtin(__builtin_assume)
|
||||||
__builtin_assume(ret == true);
|
__builtin_assume(ret == true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const string_view &str(attr_at<1>(g)); // Whole input string.
|
const string_view &str(attr_at<1>(g)); // Whole input string.
|
||||||
const char &in(attr_at<0>(g)); // Current character in input.
|
const uint8_t &in(attr_at<0>(g)); // Current character in input.
|
||||||
|
|
||||||
string_state &sst(attr_at<2>(g)); // Whole input string state.
|
string_state &sst(attr_at<2>(g)); // Whole input string state.
|
||||||
auto &st(local_at<0>(g)); // Current character state.
|
auto &st(local_at<0>(g)); // Current character state.
|
||||||
|
|
||||||
st.ctrl |= !st.mode & (in < 0x20);
|
out = in;
|
||||||
st.quote |= !st.mode & (in == '"');
|
st.mode =
|
||||||
st.escape |= !st.mode & (in == '\\');
|
st.mode != mode::PASS? st.mode:
|
||||||
|
sst.escaped? mode::ESCAPED:
|
||||||
goto *
|
in < 0x20U? mode::CTRL:
|
||||||
(
|
in == '"'? mode::QUOTE:
|
||||||
st.leave? &&Lleave:
|
in == '\\'? mode::ESCAPE:
|
||||||
sst.escaped? &&Lescaped:
|
mode::PASS;
|
||||||
st.ctrl? &&Lctrl:
|
switch(st.mode)
|
||||||
st.quote? &&Lquote:
|
|
||||||
st.escape? &&Lescape:
|
|
||||||
&&Lpass
|
|
||||||
);
|
|
||||||
|
|
||||||
Lpass:
|
|
||||||
out = in;
|
|
||||||
st.leave = true;
|
|
||||||
return;
|
|
||||||
|
|
||||||
Lleave:
|
|
||||||
//assert(st.leave);
|
|
||||||
ret = false;
|
|
||||||
sst.pos++;
|
|
||||||
return;
|
|
||||||
|
|
||||||
Lctrl:
|
|
||||||
out = st.ctrl_tab[uint8_t(in)][st.pos++];
|
|
||||||
ret &= out != '\0'; // break loop at this iteration
|
|
||||||
sst.pos += !ret;
|
|
||||||
return;
|
|
||||||
|
|
||||||
Lquote:
|
|
||||||
out = "\\\""_sv[st.pos++];
|
|
||||||
ret &= out != '\0'; // break loop at this iteration
|
|
||||||
sst.pos += !ret;
|
|
||||||
return;
|
|
||||||
|
|
||||||
Lescape:
|
|
||||||
out = in;
|
|
||||||
sst.escaped = true;
|
|
||||||
st.leave = sst.pos + 1 < str.size(); // must spin if last char of string is esc
|
|
||||||
return;
|
|
||||||
|
|
||||||
Lescaped:
|
|
||||||
{
|
{
|
||||||
const auto ok
|
[[likely]]
|
||||||
{
|
case mode::PASS:
|
||||||
in == 'u' | in == '"' | in == '\\'
|
st.mode = mode::LEAVE;
|
||||||
};
|
break; // mode::PASS
|
||||||
|
|
||||||
out = ok? in : '\\';
|
[[likely]]
|
||||||
st.leave = ok;
|
case mode::LEAVE:
|
||||||
sst.escaped = false;
|
ret = false;
|
||||||
return;
|
sst.pos++;
|
||||||
|
assert(sst.pos <= str.size());
|
||||||
|
break; // mode::LEAVE
|
||||||
|
|
||||||
|
case mode::CTRL:
|
||||||
|
out = st.ctrl_tab[in][st.pos++];
|
||||||
|
ret &= out != '\0'; // break loop at this iteration
|
||||||
|
sst.pos += !ret;
|
||||||
|
assert(st.pos <= 8);
|
||||||
|
break; // mode::CTRL
|
||||||
|
|
||||||
|
case mode::QUOTE:
|
||||||
|
out = "\\\""_sv[st.pos++];
|
||||||
|
ret &= out != '\0'; // break loop at this iteration
|
||||||
|
sst.pos += !ret;
|
||||||
|
assert(st.pos <= 8);
|
||||||
|
break; // mode::QUOTE
|
||||||
|
|
||||||
|
case mode::ESCAPE:
|
||||||
|
st.mode = sst.pos + 1 < str.size()?
|
||||||
|
mode::LEAVE:
|
||||||
|
mode::PASS; // must spin if last char of string is esc
|
||||||
|
sst.escaped = true;
|
||||||
|
assert(sst.pos < str.size());
|
||||||
|
break; // mode::ESCAPE
|
||||||
|
|
||||||
|
case mode::ESCAPED:
|
||||||
|
{
|
||||||
|
const bool ok(in == 'u' | in == '"' | in == '\\');
|
||||||
|
sst.escaped = false;
|
||||||
|
out = ok? out: '\\';
|
||||||
|
st.mode = ok?
|
||||||
|
mode::LEAVE:
|
||||||
|
mode::PASS;
|
||||||
|
break; // mode::ESCAPED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue