Skip to content

Commit

Permalink
Implement correct handling of std::streambuf int_type, eof()
Browse files Browse the repository at this point in the history
o Make no assumptions about eof(), other than that it is somewhere
  outside of the valid range of char_type.
  • Loading branch information
pjkundert committed Oct 5, 2017
1 parent 184dab6 commit 1b43a45
Showing 1 changed file with 14 additions and 11 deletions.
25 changes: 14 additions & 11 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,7 @@ constexpr T static_const<T>::value;
/// abstract input adapter interface
struct input_adapter_protocol
{
virtual int get_character() = 0; // returns characters in range [0,255], or eof() (a -'ve value)
virtual int get_character() = 0; // returns characters in range [0,255], or eof()
virtual void unget_character() = 0; // restore the last non-eof() character to input
virtual ~input_adapter_protocol() = default;
};
Expand Down Expand Up @@ -1447,10 +1447,13 @@ class input_stream_adapter : public input_adapter_protocol
}
}

// delete because of pointer members
input_stream_adapter(const input_stream_adapter&) = delete;
input_stream_adapter& operator=(input_stream_adapter&) = delete;

int get_character() override
{
int c = sb->sbumpc(); // Avoided for performance: int c = is.get();
return c < 0 ? c : ( c & 0xFF ); // faster than == std::char_traits<char>::eof()
return reinterpret_cast<int>( sb->sbumpc() );
}

void unget_character() override
Expand Down Expand Up @@ -1486,10 +1489,10 @@ class input_buffer_adapter : public input_adapter_protocol
{
if (JSON_LIKELY(cursor < limit))
{
return *(cursor++) & 0xFF;
return reinterpret_cast<int>(std::char_traits<char>::to_int_type(*(cursor++)));
}

return std::char_traits<char>::eof();
return reinterpret_cast<int>(std::char_traits<char>::eof());
}

void unget_character() noexcept override
Expand Down Expand Up @@ -2668,9 +2671,9 @@ class lexer
{
++chars_read;
current = ia->get_character();
if (JSON_LIKELY(current >= 0)) // faster than: != std::char_traits<char>::eof()))
if (JSON_LIKELY( current != std::char_traits<char>::eof()))
{
token_string.push_back(static_cast<char>(current));
token_string.push_back(std::char_traits<char>::to_char_type(current));
}
return current;
}
Expand All @@ -2679,7 +2682,7 @@ class lexer
void unget()
{
--chars_read;
if (JSON_LIKELY(current >= 0)) // faster than: != std::char_traits<char>::eof()))
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
ia->unget_character();
assert(token_string.size() != 0);
Expand All @@ -2690,7 +2693,7 @@ class lexer
/// add a character to yytext
void add(int c)
{
yytext.push_back(static_cast<char>(c));
yytext.push_back(std::char_traits<char>::to_char_type(c));
}

public:
Expand Down Expand Up @@ -5460,14 +5463,14 @@ class binary_reader
{
if (expect_eof)
{
if (JSON_UNLIKELY(current >= 0 )) // faster than: != std::char_traits<char>::eof()))
if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
{
JSON_THROW(parse_error::create(110, chars_read, "expected end of input"));
}
}
else
{
if (JSON_UNLIKELY(current < 0)) // faster than: == std::char_traits<char>::eof()))
if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
{
JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
}
Expand Down

0 comments on commit 1b43a45

Please sign in to comment.