0
0
Fork 0
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:
Jason Volk 2020-05-23 07:34:35 -07:00
parent 24d73428c8
commit 4ca481a5fc

View file

@ -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);
st.quote |= !st.mode & (in == '"');
st.escape |= !st.mode & (in == '\\');
goto *
(
st.leave? &&Lleave:
sst.escaped? &&Lescaped:
st.ctrl? &&Lctrl:
st.quote? &&Lquote:
st.escape? &&Lescape:
&&Lpass
);
Lpass:
out = in; out = in;
st.leave = true; st.mode =
return; st.mode != mode::PASS? st.mode:
sst.escaped? mode::ESCAPED:
in < 0x20U? mode::CTRL:
in == '"'? mode::QUOTE:
in == '\\'? mode::ESCAPE:
mode::PASS;
switch(st.mode)
{
[[likely]]
case mode::PASS:
st.mode = mode::LEAVE;
break; // mode::PASS
Lleave: [[likely]]
//assert(st.leave); case mode::LEAVE:
ret = false; ret = false;
sst.pos++; sst.pos++;
return; assert(sst.pos <= str.size());
break; // mode::LEAVE
Lctrl: case mode::CTRL:
out = st.ctrl_tab[uint8_t(in)][st.pos++]; out = st.ctrl_tab[in][st.pos++];
ret &= out != '\0'; // break loop at this iteration ret &= out != '\0'; // break loop at this iteration
sst.pos += !ret; sst.pos += !ret;
return; assert(st.pos <= 8);
break; // mode::CTRL
Lquote: case mode::QUOTE:
out = "\\\""_sv[st.pos++]; out = "\\\""_sv[st.pos++];
ret &= out != '\0'; // break loop at this iteration ret &= out != '\0'; // break loop at this iteration
sst.pos += !ret; sst.pos += !ret;
return; assert(st.pos <= 8);
break; // mode::QUOTE
Lescape: case mode::ESCAPE:
out = in; st.mode = sst.pos + 1 < str.size()?
mode::LEAVE:
mode::PASS; // must spin if last char of string is esc
sst.escaped = true; sst.escaped = true;
st.leave = sst.pos + 1 < str.size(); // must spin if last char of string is esc assert(sst.pos < str.size());
return; break; // mode::ESCAPE
Lescaped: case mode::ESCAPED:
{ {
const auto ok const bool ok(in == 'u' | in == '"' | in == '\\');
{
in == 'u' | in == '"' | in == '\\'
};
out = ok? in : '\\';
st.leave = ok;
sst.escaped = false; sst.escaped = false;
return; out = ok? out: '\\';
st.mode = ok?
mode::LEAVE:
mode::PASS;
break; // mode::ESCAPED
}
} }
} }