feat: use character literal in character_either

using `std::vector` for this scanner requires many times of memory
allocation and free.
This commit is contained in:
ToruNiina
2025-02-04 23:57:12 +09:00
parent 45209aae4a
commit 7f6913dafe
4 changed files with 43 additions and 54 deletions

View File

@@ -98,22 +98,10 @@ class character_either final : public scanner_base
public:
explicit character_either(std::initializer_list<char_type> cs) noexcept
: chars_(std::move(cs))
{
assert(! this->chars_.empty());
}
template<std::size_t N>
explicit character_either(const char (&cs)[N]) noexcept
: chars_(N-1, '\0')
{
static_assert(N >= 1, "");
for(std::size_t i=0; i+1<N; ++i)
{
chars_.at(i) = char_type(cs[i]);
}
}
: value_(cs), size_(N-1) // remove null character at the end
{}
~character_either() override = default;
region scan(location& loc) const override;
@@ -122,12 +110,11 @@ class character_either final : public scanner_base
scanner_base* clone() const override;
void push_back(const char_type c);
std::string name() const override;
private:
std::vector<char_type> chars_;
const char* value_;
std::size_t size_;
};
// ----------------------------------------------------------------------------

View File

@@ -87,8 +87,9 @@ TOML11_INLINE region character_either::scan(location& loc) const
{
if(loc.eof()) {return region{};}
for(const auto c : this->chars_)
for(std::size_t i=0; i<this->size_; ++i)
{
const auto c = char_type(this->value_[i]);
if(loc.current() == c)
{
const auto first = loc;
@@ -101,30 +102,32 @@ TOML11_INLINE region character_either::scan(location& loc) const
TOML11_INLINE std::string character_either::expected_chars(location&) const
{
assert( ! chars_.empty());
assert( this->value_ );
assert( this->size_ != 0 );
std::string expected;
if(chars_.size() == 1)
if(this->size_ == 1)
{
expected += show_char(chars_.at(0));
expected += show_char(char_type(value_[0]));
}
else if(chars_.size() == 2)
else if(this->size_ == 2)
{
expected += show_char(chars_.at(0)) + " or " + show_char(chars_.at(1));
expected += show_char(char_type(value_[0])) + " or " +
show_char(char_type(value_[1]));
}
else
{
for(std::size_t i=0; i<chars_.size(); ++i)
for(std::size_t i=0; i<this->size_; ++i)
{
if(i != 0)
{
expected += ", ";
}
if(i + 1 == chars_.size())
if(i + 1 == this->size_)
{
expected += "or ";
}
expected += show_char(chars_.at(i));
expected += show_char(char_type(value_[i]));
}
}
return expected;
@@ -135,20 +138,16 @@ TOML11_INLINE scanner_base* character_either::clone() const
return new character_either(*this);
}
TOML11_INLINE void character_either::push_back(const char_type c)
{
chars_.push_back(c);
}
TOML11_INLINE std::string character_either::name() const
{
std::string n("character_either{");
for(const auto c : this->chars_)
for(std::size_t i=0; i<this->size_; ++i)
{
const auto c = char_type(this->value_[i]);
n += show_char(c);
n += ", ";
}
if( ! this->chars_.empty())
if(this->size_ != 0)
{
n.pop_back();
n.pop_back();

View File

@@ -59,7 +59,7 @@ TOML11_INLINE non_ascii::non_ascii(const spec& s) noexcept
TOML11_INLINE character_either wschar(const spec&)
{
return character_either{char_type(' '), char_type('\t')};
return character_either(" \t");
}
TOML11_INLINE repeat_at_least ws(const spec& s)
@@ -172,7 +172,7 @@ TOML11_INLINE sequence dec_int(const spec& s)
return character_in_range(char_type('1'), char_type('9'));
};
return sequence(
maybe(character_either{char_type('-'), char_type('+')}),
maybe(character_either("+-")),
either(
sequence(
digit19(),
@@ -222,7 +222,7 @@ TOML11_INLINE sequence oct_int(const spec&)
TOML11_INLINE sequence bin_int(const spec&)
{
const auto digit01 = []() {
return character_either{char_type('0'), char_type('1')};
return character_either("01");
};
return sequence(
literal("0b"),
@@ -274,8 +274,8 @@ TOML11_INLINE sequence fractional_part(const spec& s)
TOML11_INLINE sequence exponent_part(const spec& s)
{
return sequence(
character_either{char_type('e'), char_type('E')},
maybe(character_either{char_type('+'), char_type('-')}),
character_either("eE"),
maybe(character_either("+-")),
zero_prefixable_int(s)
);
}
@@ -291,9 +291,9 @@ TOML11_INLINE sequence hex_floating(const spec& s)
// - 0x(int)p[+-](int)
return sequence(
maybe(character_either{char_type('+'), char_type('-')}),
maybe(character_either("+-")),
character('0'),
character_either{char_type('x'), char_type('X')},
character_either("xX"),
either(
sequence(
repeat_at_least(0, hexdig(s)),
@@ -305,8 +305,8 @@ TOML11_INLINE sequence hex_floating(const spec& s)
maybe(character('.'))
)
),
character_either{char_type('p'), char_type('P')},
maybe(character_either{char_type('+'), char_type('-')}),
character_either("pP"),
maybe(character_either("+-")),
repeat_at_least(1, character_in_range('0', '9'))
);
}
@@ -322,7 +322,7 @@ TOML11_INLINE either floating(const spec& s)
)
),
sequence(
maybe(character_either{char_type('-'), char_type('+')}),
maybe(character_either("+-")),
either(literal("inf"), literal("nan"))
)
);
@@ -371,8 +371,8 @@ TOML11_INLINE sequence local_time(const spec& s)
TOML11_INLINE either time_offset(const spec& s)
{
return either(
character_either{'Z', 'z'},
sequence(character_either{'+', '-'},
character_either("zZ"),
sequence(character_either("+-"),
repeat_exact(2, digit(s)),
character(':'),
repeat_exact(2, digit(s))
@@ -385,7 +385,7 @@ TOML11_INLINE sequence full_time(const spec& s)
}
TOML11_INLINE character_either time_delim(const spec&)
{
return character_either{'T', 't', ' '};
return character_either("Tt ");
}
TOML11_INLINE sequence local_datetime(const spec& s)
{
@@ -401,16 +401,19 @@ TOML11_INLINE sequence offset_datetime(const spec& s)
TOML11_INLINE sequence escaped(const spec& s)
{
character_either escape_char{
'\"','\\', 'b', 'f', 'n', 'r', 't'
const auto escape_char = [&s] {
if(s.v1_1_0_add_escape_sequence_e)
{
return character_either("\"\'bfnrte");
}
else
{
return character_either("\"\'bfnrt");
}
};
if(s.v1_1_0_add_escape_sequence_e)
{
escape_char.push_back(char_type('e'));
}
either escape_seq(
std::move(escape_char),
escape_char(),
sequence(character('u'), repeat_exact(4, hexdig(s))),
sequence(character('U'), repeat_exact(8, hexdig(s)))
);

View File

@@ -2679,7 +2679,7 @@ guess_number_type(const location& first, const context<TC>& ctx)
if('0' <= c && c <= '9')
{
return err(make_syntax_error("bad datetime: missing T or space",
character_either{'T', 't', ' '}, loc, std::string(
character_either("Tt "), loc, std::string(
"Hint: valid : 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999\n"
"Hint: invalid: 1979-05-27T7:32:00, 1979-05-27 17:32\n")));
}