mirror of
https://github.com/nlohmann/json.git
synced 2026-10-16 03:07:12 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
649961c8fe | ||
|
|
48d5e59adf | ||
|
|
5423dd8de3 |
No files matched your search
@@ -1734,10 +1734,6 @@ scan_number_done:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// materialize the token exactly as scan_number() would. reset() already
|
|
||||||
// cleared token_buffer, so append() fills it (assign() is avoided
|
|
||||||
// because custom string_t types need not provide it)
|
|
||||||
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
|
||||||
decimal_point_position = dot_index;
|
decimal_point_position = dot_index;
|
||||||
|
|
||||||
bulk_consume(data + 1, len - 1);
|
bulk_consume(data + 1, len - 1);
|
||||||
@@ -1753,10 +1749,27 @@ scan_number_done:
|
|||||||
s.negative = data[0] == '-';
|
s.negative = data[0] == '-';
|
||||||
if (convert_accumulated_float(s, std::integral_constant<bool, has_native_float_format<number_float_t>::value> {}))
|
if (convert_accumulated_float(s, std::integral_constant<bool, has_native_float_format<number_float_t>::value> {}))
|
||||||
{
|
{
|
||||||
|
// the token text is only copied into token_buffer when
|
||||||
|
// get_string() asks for it; the library's own SAX handlers
|
||||||
|
// ignore it. A window into a stream may be refilled by the
|
||||||
|
// next read, so there the text is copied right away.
|
||||||
|
if (bulk_window)
|
||||||
|
{
|
||||||
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pending_number_text = data;
|
||||||
|
pending_number_length = len;
|
||||||
|
}
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// materialize the token exactly as scan_number() would. reset() already
|
||||||
|
// cleared token_buffer, so append() fills it (assign() is avoided
|
||||||
|
// because custom string_t types need not provide it)
|
||||||
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
||||||
return convert_number(number_type, mantissa_end);
|
return convert_number(number_type, mantissa_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1856,6 +1869,7 @@ scan_number_done:
|
|||||||
void reset() noexcept
|
void reset() noexcept
|
||||||
{
|
{
|
||||||
token_buffer.clear();
|
token_buffer.clear();
|
||||||
|
pending_number_text = nullptr;
|
||||||
decimal_point_position = std::string::npos;
|
decimal_point_position = std::string::npos;
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
@@ -2115,10 +2129,30 @@ scan_number_done:
|
|||||||
/// return current string value
|
/// return current string value
|
||||||
string_t& get_string()
|
string_t& get_string()
|
||||||
{
|
{
|
||||||
|
if (pending_number_text != nullptr)
|
||||||
|
{
|
||||||
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(pending_number_text), pending_number_length);
|
||||||
|
pending_number_text = nullptr;
|
||||||
|
}
|
||||||
// a number token holds '.' regardless of the locale (#4084)
|
// a number token holds '.' regardless of the locale (#4084)
|
||||||
return token_buffer;
|
return token_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// the value of a string token (key or string), which never has pending
|
||||||
|
/// number text, so get_string()'s check is not needed
|
||||||
|
string_t& get_string_token() noexcept
|
||||||
|
{
|
||||||
|
JSON_ASSERT(pending_number_text == nullptr);
|
||||||
|
return token_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the text of a float token for a SAX handler that ignores it (the
|
||||||
|
/// library's own handlers): empty, without copying the token
|
||||||
|
const string_t& get_ignored_number_text() const noexcept
|
||||||
|
{
|
||||||
|
return token_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// diagnostics
|
// diagnostics
|
||||||
/////////////////////
|
/////////////////////
|
||||||
@@ -2514,6 +2548,11 @@ scan_number_done:
|
|||||||
/// whether the next get() call should just return current
|
/// whether the next get() call should just return current
|
||||||
bool next_unget = false;
|
bool next_unget = false;
|
||||||
|
|
||||||
|
/// the text of the current float token in the input, not yet copied into
|
||||||
|
/// token_buffer (see get_string()), or nullptr
|
||||||
|
const char* pending_number_text = nullptr;
|
||||||
|
std::size_t pending_number_length = 0;
|
||||||
|
|
||||||
/// the start position of the current token
|
/// the start position of the current token
|
||||||
position_t position {};
|
position_t position {};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,20 @@ template<typename BasicJsonType>
|
|||||||
using parser_callback_t =
|
using parser_callback_t =
|
||||||
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
|
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
|
||||||
|
|
||||||
|
/// whether a SAX handler ignores the text of float tokens (the library's own
|
||||||
|
/// handlers do), so that the parser need not materialize it
|
||||||
|
template<typename SAX>
|
||||||
|
struct sax_ignores_number_text : std::false_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename InputAdapterType>
|
||||||
|
struct sax_ignores_number_text<json_sax_dom_parser<BasicJsonType, InputAdapterType>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename InputAdapterType>
|
||||||
|
struct sax_ignores_number_text<json_sax_dom_callback_parser<BasicJsonType, InputAdapterType>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
struct sax_ignores_number_text<json_sax_acceptor<BasicJsonType>> : std::true_type {};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief syntax analysis
|
@brief syntax analysis
|
||||||
|
|
||||||
@@ -171,6 +185,23 @@ class parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// the text of the current float token for @a sax (see sax_ignores_number_text)
|
||||||
|
template<typename SAX>
|
||||||
|
const string_t& number_float_text(SAX* /*sax*/)
|
||||||
|
{
|
||||||
|
return number_float_text(std::integral_constant<bool, sax_ignores_number_text<SAX>::value> {});
|
||||||
|
}
|
||||||
|
|
||||||
|
const string_t& number_float_text(std::true_type /*ignored*/) const noexcept
|
||||||
|
{
|
||||||
|
return m_lexer.get_ignored_number_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
string_t& number_float_text(std::false_type /*ignored*/)
|
||||||
|
{
|
||||||
|
return m_lexer.get_string();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief run a DOM SAX parser to completion and position the lexer
|
@brief run a DOM SAX parser to completion and position the lexer
|
||||||
|
|
||||||
@@ -247,7 +278,7 @@ class parser
|
|||||||
{
|
{
|
||||||
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string_token())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -301,7 +332,7 @@ class parser
|
|||||||
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
|
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, number_float_text(sax))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -347,7 +378,7 @@ class parser
|
|||||||
|
|
||||||
case token_type::value_string:
|
case token_type::value_string:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string_token())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -456,7 +487,7 @@ class parser
|
|||||||
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string_token())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+78
-8
@@ -13220,10 +13220,6 @@ scan_number_done:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// materialize the token exactly as scan_number() would. reset() already
|
|
||||||
// cleared token_buffer, so append() fills it (assign() is avoided
|
|
||||||
// because custom string_t types need not provide it)
|
|
||||||
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
|
||||||
decimal_point_position = dot_index;
|
decimal_point_position = dot_index;
|
||||||
|
|
||||||
bulk_consume(data + 1, len - 1);
|
bulk_consume(data + 1, len - 1);
|
||||||
@@ -13239,10 +13235,27 @@ scan_number_done:
|
|||||||
s.negative = data[0] == '-';
|
s.negative = data[0] == '-';
|
||||||
if (convert_accumulated_float(s, std::integral_constant<bool, has_native_float_format<number_float_t>::value> {}))
|
if (convert_accumulated_float(s, std::integral_constant<bool, has_native_float_format<number_float_t>::value> {}))
|
||||||
{
|
{
|
||||||
|
// the token text is only copied into token_buffer when
|
||||||
|
// get_string() asks for it; the library's own SAX handlers
|
||||||
|
// ignore it. A window into a stream may be refilled by the
|
||||||
|
// next read, so there the text is copied right away.
|
||||||
|
if (bulk_window)
|
||||||
|
{
|
||||||
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pending_number_text = data;
|
||||||
|
pending_number_length = len;
|
||||||
|
}
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// materialize the token exactly as scan_number() would. reset() already
|
||||||
|
// cleared token_buffer, so append() fills it (assign() is avoided
|
||||||
|
// because custom string_t types need not provide it)
|
||||||
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
||||||
return convert_number(number_type, mantissa_end);
|
return convert_number(number_type, mantissa_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13342,6 +13355,7 @@ scan_number_done:
|
|||||||
void reset() noexcept
|
void reset() noexcept
|
||||||
{
|
{
|
||||||
token_buffer.clear();
|
token_buffer.clear();
|
||||||
|
pending_number_text = nullptr;
|
||||||
decimal_point_position = std::string::npos;
|
decimal_point_position = std::string::npos;
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
@@ -13601,10 +13615,30 @@ scan_number_done:
|
|||||||
/// return current string value
|
/// return current string value
|
||||||
string_t& get_string()
|
string_t& get_string()
|
||||||
{
|
{
|
||||||
|
if (pending_number_text != nullptr)
|
||||||
|
{
|
||||||
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(pending_number_text), pending_number_length);
|
||||||
|
pending_number_text = nullptr;
|
||||||
|
}
|
||||||
// a number token holds '.' regardless of the locale (#4084)
|
// a number token holds '.' regardless of the locale (#4084)
|
||||||
return token_buffer;
|
return token_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// the value of a string token (key or string), which never has pending
|
||||||
|
/// number text, so get_string()'s check is not needed
|
||||||
|
string_t& get_string_token() noexcept
|
||||||
|
{
|
||||||
|
JSON_ASSERT(pending_number_text == nullptr);
|
||||||
|
return token_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the text of a float token for a SAX handler that ignores it (the
|
||||||
|
/// library's own handlers): empty, without copying the token
|
||||||
|
const string_t& get_ignored_number_text() const noexcept
|
||||||
|
{
|
||||||
|
return token_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// diagnostics
|
// diagnostics
|
||||||
/////////////////////
|
/////////////////////
|
||||||
@@ -14000,6 +14034,11 @@ scan_number_done:
|
|||||||
/// whether the next get() call should just return current
|
/// whether the next get() call should just return current
|
||||||
bool next_unget = false;
|
bool next_unget = false;
|
||||||
|
|
||||||
|
/// the text of the current float token in the input, not yet copied into
|
||||||
|
/// token_buffer (see get_string()), or nullptr
|
||||||
|
const char* pending_number_text = nullptr;
|
||||||
|
std::size_t pending_number_length = 0;
|
||||||
|
|
||||||
/// the start position of the current token
|
/// the start position of the current token
|
||||||
position_t position {};
|
position_t position {};
|
||||||
|
|
||||||
@@ -19868,6 +19907,20 @@ template<typename BasicJsonType>
|
|||||||
using parser_callback_t =
|
using parser_callback_t =
|
||||||
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
|
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
|
||||||
|
|
||||||
|
/// whether a SAX handler ignores the text of float tokens (the library's own
|
||||||
|
/// handlers do), so that the parser need not materialize it
|
||||||
|
template<typename SAX>
|
||||||
|
struct sax_ignores_number_text : std::false_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename InputAdapterType>
|
||||||
|
struct sax_ignores_number_text<json_sax_dom_parser<BasicJsonType, InputAdapterType>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename InputAdapterType>
|
||||||
|
struct sax_ignores_number_text<json_sax_dom_callback_parser<BasicJsonType, InputAdapterType>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
struct sax_ignores_number_text<json_sax_acceptor<BasicJsonType>> : std::true_type {};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief syntax analysis
|
@brief syntax analysis
|
||||||
|
|
||||||
@@ -19988,6 +20041,23 @@ class parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// the text of the current float token for @a sax (see sax_ignores_number_text)
|
||||||
|
template<typename SAX>
|
||||||
|
const string_t& number_float_text(SAX* /*sax*/)
|
||||||
|
{
|
||||||
|
return number_float_text(std::integral_constant<bool, sax_ignores_number_text<SAX>::value> {});
|
||||||
|
}
|
||||||
|
|
||||||
|
const string_t& number_float_text(std::true_type /*ignored*/) const noexcept
|
||||||
|
{
|
||||||
|
return m_lexer.get_ignored_number_text();
|
||||||
|
}
|
||||||
|
|
||||||
|
string_t& number_float_text(std::false_type /*ignored*/)
|
||||||
|
{
|
||||||
|
return m_lexer.get_string();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief run a DOM SAX parser to completion and position the lexer
|
@brief run a DOM SAX parser to completion and position the lexer
|
||||||
|
|
||||||
@@ -20064,7 +20134,7 @@ class parser
|
|||||||
{
|
{
|
||||||
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string_token())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -20118,7 +20188,7 @@ class parser
|
|||||||
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
|
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, number_float_text(sax))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -20164,7 +20234,7 @@ class parser
|
|||||||
|
|
||||||
case token_type::value_string:
|
case token_type::value_string:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string_token())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -20273,7 +20343,7 @@ class parser
|
|||||||
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string_token())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ using nlohmann::json;
|
|||||||
#include <valarray>
|
#include <valarray>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -2450,6 +2452,79 @@ std::string parse_error_message_range(IteratorType first, IteratorType last)
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("text of float tokens")
|
||||||
|
{
|
||||||
|
// For contiguous input, the lexer copies the text of a float token into
|
||||||
|
// its buffer only when a SAX handler asks for it (the library's own
|
||||||
|
// handlers do not). A user handler must still see the exact text, for
|
||||||
|
// every input adapter and in every position of a document.
|
||||||
|
const std::string doc = R"([1.5, -0.0, 0.1, 1e5, -2.5E-4, 12345678901234567890.5, 0.12345678901234567890123,
|
||||||
|
{"a": 3.25, "b": [6.02e23, 1]}, "x", true, 7e-1])";
|
||||||
|
const std::vector<std::string> expected_floats =
|
||||||
|
{
|
||||||
|
"number_float(1.5)", "number_float(-0.0)", "number_float(0.1)", "number_float(1e5)", "number_float(-2.5E-4)",
|
||||||
|
"number_float(12345678901234567890.5)", "number_float(0.12345678901234567890123)", "number_float(3.25)",
|
||||||
|
"number_float(6.02e23)", "number_float(7e-1)"
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto floats = [](const std::vector<std::string>& events)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
std::copy_if(events.begin(), events.end(), std::back_inserter(result), [](const std::string & e)
|
||||||
|
{
|
||||||
|
return e.compare(0, 13, "number_float(") == 0;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("contiguous input")
|
||||||
|
{
|
||||||
|
SaxEventLogger l;
|
||||||
|
CHECK(json::sax_parse(doc, &l));
|
||||||
|
CHECK(floats(l.events) == expected_floats);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("byte input")
|
||||||
|
{
|
||||||
|
const std::vector<std::uint8_t> bytes(doc.begin(), doc.end());
|
||||||
|
SaxEventLogger l;
|
||||||
|
CHECK(json::sax_parse(bytes, &l));
|
||||||
|
CHECK(floats(l.events) == expected_floats);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("stream input")
|
||||||
|
{
|
||||||
|
std::istringstream is(doc);
|
||||||
|
SaxEventLogger l;
|
||||||
|
CHECK(json::sax_parse(is, &l));
|
||||||
|
CHECK(floats(l.events) == expected_floats);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("non-contiguous iterators")
|
||||||
|
{
|
||||||
|
const std::list<char> chars(doc.begin(), doc.end());
|
||||||
|
SaxEventLogger l;
|
||||||
|
CHECK(json::sax_parse(chars.begin(), chars.end(), &l));
|
||||||
|
CHECK(floats(l.events) == expected_floats);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("the library's own handlers do not need the text")
|
||||||
|
{
|
||||||
|
using lexer_adapter = nlohmann::detail::iterator_input_adapter<const char*>;
|
||||||
|
CHECK(nlohmann::detail::sax_ignores_number_text<nlohmann::detail::json_sax_dom_parser<json, lexer_adapter>>::value);
|
||||||
|
CHECK(nlohmann::detail::sax_ignores_number_text<nlohmann::detail::json_sax_dom_callback_parser<json, lexer_adapter>>::value);
|
||||||
|
CHECK(nlohmann::detail::sax_ignores_number_text<nlohmann::detail::json_sax_acceptor<json>>::value);
|
||||||
|
CHECK_FALSE(nlohmann::detail::sax_ignores_number_text<SaxEventLogger>::value);
|
||||||
|
|
||||||
|
// and the values are the same as when the text is read
|
||||||
|
const json j = json::parse(doc);
|
||||||
|
CHECK(j[0] == 1.5);
|
||||||
|
CHECK(j[5].get<double>() == 12345678901234567890.5);
|
||||||
|
CHECK(j[7]["b"][0] == 6.02e23);
|
||||||
|
CHECK(json::accept(doc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("last-read diagnostics are identical across input adapters")
|
TEST_CASE("last-read diagnostics are identical across input adapters")
|
||||||
{
|
{
|
||||||
// The lexer reconstructs the "last read" token lazily for seekable adapters
|
// The lexer reconstructs the "last read" token lazily for seekable adapters
|
||||||
|
|||||||
Reference in new issue
Block a user