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); 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
}
} }
} }