mirror of
https://github.com/nlohmann/json.git
synced 2026-10-31 09:55:42 +00:00
json_view: pass accept()'s validate-only request as a parameter
Address review of #5970: - build() takes validate_only as an argument; the validate_only members of document_data and basic_json_document are removed, so neither grows - the internal read path takes an on_error mode (discard, raise, validate) instead of allow_exceptions; accept() calls it with on_error::validate - build_with() has no default for Store - drop the unneeded static_casts in push_node() - name the NulIsEnd argument so astyle keeps build<...> intact - explain in the docs and code why comments/trailing commas keep the index Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N5NasF8Toq7uBWUMCrSjXV
This commit is contained in:
6 files changed
+109
-79
No files matched your search
@@ -13,12 +13,16 @@ function never throws an exception for invalid input, and the returned `#!cpp bo
|
||||
is returned.
|
||||
|
||||
The result is the same as that of `BasicJsonType::accept()` by design; the difference is how the check is made. This
|
||||
function runs the document's builder, which checks the text as [`parse()`](parse.md) does but writes no index (for
|
||||
input without comments and trailing commas; with either option it builds the index and discards it), while
|
||||
function runs the document's builder, which checks the text as [`parse()`](parse.md) does, while
|
||||
`BasicJsonType::accept()` runs the SAX parser with a handler that ignores every event. Use this one if you go on to
|
||||
parse the same input with [`parse()`](parse.md) anyway, so that both use the same code; either is fine for a plain
|
||||
yes/no answer.
|
||||
|
||||
When both `ignore_comments` and `ignore_trailing_commas` are `#!cpp false` (the default), the builder writes no index.
|
||||
With either option set, it builds the index as [`parse()`](parse.md) does and discards it: the result is the same, only
|
||||
the time differs. (Neither option needs the index; the variant that skips it exists only for the default options to
|
||||
keep the code size down.)
|
||||
|
||||
## Template parameters
|
||||
|
||||
`InputType`
|
||||
|
||||
@@ -1051,11 +1051,6 @@ indent_done:
|
||||
{
|
||||
// accept(): nothing is stored, so what computes the arguments is not run either. base and out stay
|
||||
// null: their difference, which open() takes, is 0.
|
||||
static_cast<void>(k);
|
||||
static_cast<void>(flags);
|
||||
static_cast<void>(extra);
|
||||
static_cast<void>(off);
|
||||
static_cast<void>(second);
|
||||
return out;
|
||||
}
|
||||
if (NLOHMANN_VIEW_UNLIKELY(out == cap))
|
||||
@@ -1296,7 +1291,7 @@ indent_done:
|
||||
};
|
||||
|
||||
/// run the builder with compile-time options
|
||||
template<typename FloatType, bool Comments, bool TrailingCommas, bool NulIsEnd, bool Store = true>
|
||||
template<typename FloatType, bool Comments, bool TrailingCommas, bool NulIsEnd, bool Store>
|
||||
inline bool build_with(document_data& d, const char* src, std::size_t size, bool sentinel, parse_failure& failure)
|
||||
{
|
||||
if (sentinel)
|
||||
@@ -1313,22 +1308,27 @@ inline bool build_with(document_data& d, const char* src, std::size_t size, bool
|
||||
}
|
||||
|
||||
/// sentinel: src[size] is readable and 0 (e.g. std::string); FloatType: the
|
||||
/// number_float_t of the document
|
||||
/// number_float_t of the document; validate_only: accept(), only the result is
|
||||
/// used
|
||||
template<typename FloatType, bool NulIsEnd>
|
||||
inline bool build(document_data& d, const char* src, std::size_t size, bool comments, bool trailing_commas, bool sentinel, parse_failure& failure)
|
||||
inline bool build(document_data& d, const char* src, std::size_t size, bool comments, bool trailing_commas, bool sentinel, bool validate_only,
|
||||
parse_failure& failure)
|
||||
{
|
||||
if (d.validate_only && !comments && !trailing_commas)
|
||||
if (validate_only && !comments && !trailing_commas)
|
||||
{
|
||||
// accept() of plain JSON: nothing is stored (the other option sets keep the builder that stores)
|
||||
// accept() of plain JSON: nothing is stored. The other option sets
|
||||
// could skip the stores just as well; they keep the builder that
|
||||
// stores only so that there are two more instantiations of the parse
|
||||
// loop, not eight.
|
||||
return build_with<FloatType, false, false, NulIsEnd, false>(d, src, size, sentinel, failure);
|
||||
}
|
||||
if (comments)
|
||||
{
|
||||
return trailing_commas ? build_with<FloatType, true, true, NulIsEnd>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, true, false, NulIsEnd>(d, src, size, sentinel, failure);
|
||||
return trailing_commas ? build_with<FloatType, true, true, NulIsEnd, true>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, true, false, NulIsEnd, true>(d, src, size, sentinel, failure);
|
||||
}
|
||||
return trailing_commas ? build_with<FloatType, false, true, NulIsEnd>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, false, false, NulIsEnd>(d, src, size, sentinel, failure);
|
||||
return trailing_commas ? build_with<FloatType, false, true, NulIsEnd, true>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, false, false, NulIsEnd, true>(d, src, size, sentinel, failure);
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
|
||||
@@ -58,7 +58,6 @@ struct document_data
|
||||
std::vector<std::uint32_t> large_objects; ///< positions of the objects to index (noted while parsing)
|
||||
std::array<const char*, 4> base = {{nullptr, nullptr, nullptr, nullptr}}; ///< string bases: source, arena, edit arena, unused (indexed by flags & node_flags::storage)
|
||||
bool discarded = true;
|
||||
bool validate_only = false; ///< accept(): build() checks the text and stores no nodes (next to `discarded`: no member moves)
|
||||
|
||||
/// The storage of edits (editable documents only; see edit_storage.hpp).
|
||||
/// No edit moves or resizes the parsed index, and the nodes of values
|
||||
|
||||
@@ -1060,7 +1060,7 @@ class basic_json_document
|
||||
const bool ignore_trailing_commas = false)
|
||||
{
|
||||
basic_json_document d;
|
||||
d.read_range(first, last, allow_exceptions, ignore_comments, ignore_trailing_commas);
|
||||
d.read_range(first, last, error_mode(allow_exceptions), ignore_comments, ignore_trailing_commas);
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -1075,7 +1075,7 @@ class basic_json_document
|
||||
basic_json_document d;
|
||||
std::string buf;
|
||||
append_input(buf, std::forward<InputType>(input));
|
||||
d.build_owned(std::move(buf), allow_exceptions, ignore_comments, ignore_trailing_commas);
|
||||
d.build_owned(std::move(buf), error_mode(allow_exceptions), ignore_comments, ignore_trailing_commas);
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -1088,8 +1088,8 @@ class basic_json_document
|
||||
static bool accept(InputType&& input, const bool ignore_comments = false, const bool ignore_trailing_commas = false)
|
||||
{
|
||||
basic_json_document d;
|
||||
d.m_validate_only = true; // (nothing is stored: only the result is used)
|
||||
d.read(std::forward<InputType>(input), false, ignore_comments, ignore_trailing_commas);
|
||||
d.read_kind(std::forward<InputType>(input), on_error::validate, ignore_comments, ignore_trailing_commas,
|
||||
std::integral_constant<detail::view::input_kind, detail::view::classify_input<InputType>::value> {});
|
||||
return !d.is_discarded();
|
||||
}
|
||||
|
||||
@@ -1105,7 +1105,7 @@ class basic_json_document
|
||||
const bool ignore_comments = false,
|
||||
const bool ignore_trailing_commas = false)
|
||||
{
|
||||
read_kind(std::forward<InputType>(input), allow_exceptions, ignore_comments, ignore_trailing_commas,
|
||||
read_kind(std::forward<InputType>(input), error_mode(allow_exceptions), ignore_comments, ignore_trailing_commas,
|
||||
std::integral_constant<detail::view::input_kind, detail::view::classify_input<InputType>::value> {});
|
||||
}
|
||||
|
||||
@@ -1464,6 +1464,22 @@ class basic_json_document
|
||||
return idx;
|
||||
}
|
||||
|
||||
/// what a failed parse does
|
||||
enum class on_error : std::uint8_t
|
||||
{
|
||||
discard, ///< the document is discarded
|
||||
raise, ///< parse_error is thrown
|
||||
validate ///< accept(): the document is discarded, and no node is stored while parsing
|
||||
};
|
||||
|
||||
static on_error error_mode(bool allow_exceptions) noexcept
|
||||
{
|
||||
return allow_exceptions ? on_error::raise : on_error::discard;
|
||||
}
|
||||
|
||||
/// NulIsEnd of the builder: a null byte ends the input unless strict_nul_handling
|
||||
static constexpr bool nul_is_end = !detail::abi_config::strict_nul_handling;
|
||||
|
||||
/// create the storage (sized for the input) on first use
|
||||
void ensure_data(const char* src, std::size_t size)
|
||||
{
|
||||
@@ -1475,7 +1491,7 @@ class basic_json_document
|
||||
|
||||
/// parse a buffer the document takes ownership of (it replaces the
|
||||
/// previous owned copy)
|
||||
void build_owned(std::string&& buf, bool allow_exceptions, bool comments, bool trailing_commas)
|
||||
void build_owned(std::string&& buf, on_error allow_exceptions, bool comments, bool trailing_commas)
|
||||
{
|
||||
ensure_data(buf.data(), buf.size());
|
||||
m_data->owned = std::move(buf);
|
||||
@@ -1485,7 +1501,7 @@ class basic_json_document
|
||||
/// parse a copy of the input; the copy is appended to the cleared owned
|
||||
/// buffer, so that its capacity is reused
|
||||
template<typename T>
|
||||
void build_copy(T&& input, bool allow_exceptions, bool comments, bool trailing_commas)
|
||||
void build_copy(T&& input, on_error allow_exceptions, bool comments, bool trailing_commas)
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
@@ -1506,7 +1522,7 @@ class basic_json_document
|
||||
}
|
||||
|
||||
/// sentinel: src[size] is readable and 0 (std::string, C strings)
|
||||
void build(const char* src, std::size_t size, bool allow_exceptions, bool comments, bool trailing_commas, bool owned, bool sentinel)
|
||||
void build(const char* src, std::size_t size, on_error allow_exceptions, bool comments, bool trailing_commas, bool owned, bool sentinel)
|
||||
{
|
||||
ensure_data(src, size);
|
||||
document_data& d = *m_data;
|
||||
@@ -1533,9 +1549,8 @@ class basic_json_document
|
||||
}
|
||||
else
|
||||
{
|
||||
d.validate_only = m_validate_only;
|
||||
ok = detail::view::build < typename BasicJsonType::number_float_t, !detail::abi_config::strict_nul_handling > (d, src, size, comments, trailing_commas, sentinel, failure);
|
||||
d.validate_only = false;
|
||||
ok = detail::view::build<typename BasicJsonType::number_float_t, nul_is_end>(d, src, size, comments, trailing_commas, sentinel,
|
||||
allow_exceptions == on_error::validate, failure);
|
||||
}
|
||||
if (NLOHMANN_VIEW_LIKELY(ok))
|
||||
{
|
||||
@@ -1548,7 +1563,7 @@ class basic_json_document
|
||||
return;
|
||||
}
|
||||
std::vector<std::uint32_t>().swap(d.large_objects);
|
||||
if (allow_exceptions)
|
||||
if (allow_exceptions == on_error::raise)
|
||||
{
|
||||
detail::view::throw_parse_failure<BasicJsonType>(failure, src, size, comments, trailing_commas);
|
||||
}
|
||||
@@ -1556,13 +1571,13 @@ class basic_json_document
|
||||
|
||||
// --- input dispatch (see detail::view::input_kind) ---
|
||||
|
||||
void read_kind(std::string&& s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::move_string> /*unused*/)
|
||||
void read_kind(std::string&& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::move_string> /*unused*/)
|
||||
{
|
||||
build_owned(std::move(s), ae, c, tc);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
void read_kind(CharT* s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::c_string> /*unused*/)
|
||||
void read_kind(CharT* s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::c_string> /*unused*/)
|
||||
{
|
||||
if (s == nullptr)
|
||||
{
|
||||
@@ -1576,7 +1591,7 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename Array>
|
||||
void read_kind(Array& a, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::char_array> /*unused*/)
|
||||
void read_kind(Array& a, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::char_array> /*unused*/)
|
||||
{
|
||||
using CharT = typename std::remove_cv<typename std::remove_extent<Array>::type>::type;
|
||||
const std::size_t n = std::extent<Array>::value;
|
||||
@@ -1587,7 +1602,7 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_kind(const T& s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::borrow_range> /*unused*/)
|
||||
void read_kind(const T& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::borrow_range> /*unused*/)
|
||||
{
|
||||
// std::basic_string guarantees data()[size()] == 0: use it as sentinel
|
||||
const auto size = static_cast<std::size_t>(s.size());
|
||||
@@ -1596,13 +1611,13 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_kind(const T& s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::copy_range> /*unused*/)
|
||||
void read_kind(const T& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::copy_range> /*unused*/)
|
||||
{
|
||||
build_copy(s, ae, c, tc);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
void read_kind(CharT* s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::wide_c_string> /*unused*/)
|
||||
void read_kind(CharT* s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::wide_c_string> /*unused*/)
|
||||
{
|
||||
if (s == nullptr)
|
||||
{
|
||||
@@ -1614,13 +1629,13 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_kind(T&& input, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::adapter> /*unused*/)
|
||||
void read_kind(T&& input, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::adapter> /*unused*/)
|
||||
{
|
||||
build_copy(std::forward<T>(input), ae, c, tc);
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range(IteratorType first, IteratorType last, bool ae, bool c, bool tc)
|
||||
void read_range(IteratorType first, IteratorType last, on_error ae, bool c, bool tc)
|
||||
{
|
||||
using value_type = typename std::remove_cv<typename std::iterator_traits<IteratorType>::value_type>::type;
|
||||
// borrow the range where the library's input adapter scans it as one
|
||||
@@ -1631,14 +1646,14 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range_impl(IteratorType first, IteratorType last, bool ae, bool c, bool tc, std::true_type /*contiguous bytes*/)
|
||||
void read_range_impl(IteratorType first, IteratorType last, on_error ae, bool c, bool tc, std::true_type /*contiguous bytes*/)
|
||||
{
|
||||
const auto size = static_cast<std::size_t>(std::distance(first, last));
|
||||
build(size == 0 ? "" : reinterpret_cast<const char*>(&*first), size, ae, c, tc, false, size == 0); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range_impl(IteratorType first, IteratorType last, bool ae, bool c, bool tc, std::false_type /*other*/)
|
||||
void read_range_impl(IteratorType first, IteratorType last, on_error ae, bool c, bool tc, std::false_type /*other*/)
|
||||
{
|
||||
build_copy(detail::view::make_adapter_input(detail::input_adapter(first, last)), ae, c, tc);
|
||||
}
|
||||
@@ -1696,7 +1711,6 @@ class basic_json_document
|
||||
}
|
||||
|
||||
std::unique_ptr<document_data, document_data::deleter> m_data{}; // NOLINT(readability-redundant-member-init)
|
||||
bool m_validate_only = false; ///< set by accept(): build() stores no nodes
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
Generated
+51
-38
@@ -389,7 +389,6 @@ struct document_data
|
||||
std::vector<std::uint32_t> large_objects; ///< positions of the objects to index (noted while parsing)
|
||||
std::array<const char*, 4> base = {{nullptr, nullptr, nullptr, nullptr}}; ///< string bases: source, arena, edit arena, unused (indexed by flags & node_flags::storage)
|
||||
bool discarded = true;
|
||||
bool validate_only = false; ///< accept(): build() checks the text and stores no nodes (next to `discarded`: no member moves)
|
||||
|
||||
/// The storage of edits (editable documents only; see edit_storage.hpp).
|
||||
/// No edit moves or resizes the parsed index, and the nodes of values
|
||||
@@ -2294,11 +2293,6 @@ indent_done:
|
||||
{
|
||||
// accept(): nothing is stored, so what computes the arguments is not run either. base and out stay
|
||||
// null: their difference, which open() takes, is 0.
|
||||
static_cast<void>(k);
|
||||
static_cast<void>(flags);
|
||||
static_cast<void>(extra);
|
||||
static_cast<void>(off);
|
||||
static_cast<void>(second);
|
||||
return out;
|
||||
}
|
||||
if (NLOHMANN_VIEW_UNLIKELY(out == cap))
|
||||
@@ -2539,7 +2533,7 @@ indent_done:
|
||||
};
|
||||
|
||||
/// run the builder with compile-time options
|
||||
template<typename FloatType, bool Comments, bool TrailingCommas, bool NulIsEnd, bool Store = true>
|
||||
template<typename FloatType, bool Comments, bool TrailingCommas, bool NulIsEnd, bool Store>
|
||||
inline bool build_with(document_data& d, const char* src, std::size_t size, bool sentinel, parse_failure& failure)
|
||||
{
|
||||
if (sentinel)
|
||||
@@ -2556,22 +2550,27 @@ inline bool build_with(document_data& d, const char* src, std::size_t size, bool
|
||||
}
|
||||
|
||||
/// sentinel: src[size] is readable and 0 (e.g. std::string); FloatType: the
|
||||
/// number_float_t of the document
|
||||
/// number_float_t of the document; validate_only: accept(), only the result is
|
||||
/// used
|
||||
template<typename FloatType, bool NulIsEnd>
|
||||
inline bool build(document_data& d, const char* src, std::size_t size, bool comments, bool trailing_commas, bool sentinel, parse_failure& failure)
|
||||
inline bool build(document_data& d, const char* src, std::size_t size, bool comments, bool trailing_commas, bool sentinel, bool validate_only,
|
||||
parse_failure& failure)
|
||||
{
|
||||
if (d.validate_only && !comments && !trailing_commas)
|
||||
if (validate_only && !comments && !trailing_commas)
|
||||
{
|
||||
// accept() of plain JSON: nothing is stored (the other option sets keep the builder that stores)
|
||||
// accept() of plain JSON: nothing is stored. The other option sets
|
||||
// could skip the stores just as well; they keep the builder that
|
||||
// stores only so that there are two more instantiations of the parse
|
||||
// loop, not eight.
|
||||
return build_with<FloatType, false, false, NulIsEnd, false>(d, src, size, sentinel, failure);
|
||||
}
|
||||
if (comments)
|
||||
{
|
||||
return trailing_commas ? build_with<FloatType, true, true, NulIsEnd>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, true, false, NulIsEnd>(d, src, size, sentinel, failure);
|
||||
return trailing_commas ? build_with<FloatType, true, true, NulIsEnd, true>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, true, false, NulIsEnd, true>(d, src, size, sentinel, failure);
|
||||
}
|
||||
return trailing_commas ? build_with<FloatType, false, true, NulIsEnd>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, false, false, NulIsEnd>(d, src, size, sentinel, failure);
|
||||
return trailing_commas ? build_with<FloatType, false, true, NulIsEnd, true>(d, src, size, sentinel, failure)
|
||||
: build_with<FloatType, false, false, NulIsEnd, true>(d, src, size, sentinel, failure);
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
@@ -10211,7 +10210,7 @@ class basic_json_document
|
||||
const bool ignore_trailing_commas = false)
|
||||
{
|
||||
basic_json_document d;
|
||||
d.read_range(first, last, allow_exceptions, ignore_comments, ignore_trailing_commas);
|
||||
d.read_range(first, last, error_mode(allow_exceptions), ignore_comments, ignore_trailing_commas);
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -10226,7 +10225,7 @@ class basic_json_document
|
||||
basic_json_document d;
|
||||
std::string buf;
|
||||
append_input(buf, std::forward<InputType>(input));
|
||||
d.build_owned(std::move(buf), allow_exceptions, ignore_comments, ignore_trailing_commas);
|
||||
d.build_owned(std::move(buf), error_mode(allow_exceptions), ignore_comments, ignore_trailing_commas);
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -10239,8 +10238,8 @@ class basic_json_document
|
||||
static bool accept(InputType&& input, const bool ignore_comments = false, const bool ignore_trailing_commas = false)
|
||||
{
|
||||
basic_json_document d;
|
||||
d.m_validate_only = true; // (nothing is stored: only the result is used)
|
||||
d.read(std::forward<InputType>(input), false, ignore_comments, ignore_trailing_commas);
|
||||
d.read_kind(std::forward<InputType>(input), on_error::validate, ignore_comments, ignore_trailing_commas,
|
||||
std::integral_constant<detail::view::input_kind, detail::view::classify_input<InputType>::value> {});
|
||||
return !d.is_discarded();
|
||||
}
|
||||
|
||||
@@ -10256,7 +10255,7 @@ class basic_json_document
|
||||
const bool ignore_comments = false,
|
||||
const bool ignore_trailing_commas = false)
|
||||
{
|
||||
read_kind(std::forward<InputType>(input), allow_exceptions, ignore_comments, ignore_trailing_commas,
|
||||
read_kind(std::forward<InputType>(input), error_mode(allow_exceptions), ignore_comments, ignore_trailing_commas,
|
||||
std::integral_constant<detail::view::input_kind, detail::view::classify_input<InputType>::value> {});
|
||||
}
|
||||
|
||||
@@ -10615,6 +10614,22 @@ class basic_json_document
|
||||
return idx;
|
||||
}
|
||||
|
||||
/// what a failed parse does
|
||||
enum class on_error : std::uint8_t
|
||||
{
|
||||
discard, ///< the document is discarded
|
||||
raise, ///< parse_error is thrown
|
||||
validate ///< accept(): the document is discarded, and no node is stored while parsing
|
||||
};
|
||||
|
||||
static on_error error_mode(bool allow_exceptions) noexcept
|
||||
{
|
||||
return allow_exceptions ? on_error::raise : on_error::discard;
|
||||
}
|
||||
|
||||
/// NulIsEnd of the builder: a null byte ends the input unless strict_nul_handling
|
||||
static constexpr bool nul_is_end = !detail::abi_config::strict_nul_handling;
|
||||
|
||||
/// create the storage (sized for the input) on first use
|
||||
void ensure_data(const char* src, std::size_t size)
|
||||
{
|
||||
@@ -10626,7 +10641,7 @@ class basic_json_document
|
||||
|
||||
/// parse a buffer the document takes ownership of (it replaces the
|
||||
/// previous owned copy)
|
||||
void build_owned(std::string&& buf, bool allow_exceptions, bool comments, bool trailing_commas)
|
||||
void build_owned(std::string&& buf, on_error allow_exceptions, bool comments, bool trailing_commas)
|
||||
{
|
||||
ensure_data(buf.data(), buf.size());
|
||||
m_data->owned = std::move(buf);
|
||||
@@ -10636,7 +10651,7 @@ class basic_json_document
|
||||
/// parse a copy of the input; the copy is appended to the cleared owned
|
||||
/// buffer, so that its capacity is reused
|
||||
template<typename T>
|
||||
void build_copy(T&& input, bool allow_exceptions, bool comments, bool trailing_commas)
|
||||
void build_copy(T&& input, on_error allow_exceptions, bool comments, bool trailing_commas)
|
||||
{
|
||||
if (!m_data)
|
||||
{
|
||||
@@ -10657,7 +10672,7 @@ class basic_json_document
|
||||
}
|
||||
|
||||
/// sentinel: src[size] is readable and 0 (std::string, C strings)
|
||||
void build(const char* src, std::size_t size, bool allow_exceptions, bool comments, bool trailing_commas, bool owned, bool sentinel)
|
||||
void build(const char* src, std::size_t size, on_error allow_exceptions, bool comments, bool trailing_commas, bool owned, bool sentinel)
|
||||
{
|
||||
ensure_data(src, size);
|
||||
document_data& d = *m_data;
|
||||
@@ -10684,9 +10699,8 @@ class basic_json_document
|
||||
}
|
||||
else
|
||||
{
|
||||
d.validate_only = m_validate_only;
|
||||
ok = detail::view::build < typename BasicJsonType::number_float_t, !detail::abi_config::strict_nul_handling > (d, src, size, comments, trailing_commas, sentinel, failure);
|
||||
d.validate_only = false;
|
||||
ok = detail::view::build<typename BasicJsonType::number_float_t, nul_is_end>(d, src, size, comments, trailing_commas, sentinel,
|
||||
allow_exceptions == on_error::validate, failure);
|
||||
}
|
||||
if (NLOHMANN_VIEW_LIKELY(ok))
|
||||
{
|
||||
@@ -10699,7 +10713,7 @@ class basic_json_document
|
||||
return;
|
||||
}
|
||||
std::vector<std::uint32_t>().swap(d.large_objects);
|
||||
if (allow_exceptions)
|
||||
if (allow_exceptions == on_error::raise)
|
||||
{
|
||||
detail::view::throw_parse_failure<BasicJsonType>(failure, src, size, comments, trailing_commas);
|
||||
}
|
||||
@@ -10707,13 +10721,13 @@ class basic_json_document
|
||||
|
||||
// --- input dispatch (see detail::view::input_kind) ---
|
||||
|
||||
void read_kind(std::string&& s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::move_string> /*unused*/)
|
||||
void read_kind(std::string&& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::move_string> /*unused*/)
|
||||
{
|
||||
build_owned(std::move(s), ae, c, tc);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
void read_kind(CharT* s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::c_string> /*unused*/)
|
||||
void read_kind(CharT* s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::c_string> /*unused*/)
|
||||
{
|
||||
if (s == nullptr)
|
||||
{
|
||||
@@ -10727,7 +10741,7 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename Array>
|
||||
void read_kind(Array& a, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::char_array> /*unused*/)
|
||||
void read_kind(Array& a, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::char_array> /*unused*/)
|
||||
{
|
||||
using CharT = typename std::remove_cv<typename std::remove_extent<Array>::type>::type;
|
||||
const std::size_t n = std::extent<Array>::value;
|
||||
@@ -10738,7 +10752,7 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_kind(const T& s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::borrow_range> /*unused*/)
|
||||
void read_kind(const T& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::borrow_range> /*unused*/)
|
||||
{
|
||||
// std::basic_string guarantees data()[size()] == 0: use it as sentinel
|
||||
const auto size = static_cast<std::size_t>(s.size());
|
||||
@@ -10747,13 +10761,13 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_kind(const T& s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::copy_range> /*unused*/)
|
||||
void read_kind(const T& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::copy_range> /*unused*/)
|
||||
{
|
||||
build_copy(s, ae, c, tc);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
void read_kind(CharT* s, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::wide_c_string> /*unused*/)
|
||||
void read_kind(CharT* s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::wide_c_string> /*unused*/)
|
||||
{
|
||||
if (s == nullptr)
|
||||
{
|
||||
@@ -10765,13 +10779,13 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_kind(T&& input, bool ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::adapter> /*unused*/)
|
||||
void read_kind(T&& input, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::adapter> /*unused*/)
|
||||
{
|
||||
build_copy(std::forward<T>(input), ae, c, tc);
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range(IteratorType first, IteratorType last, bool ae, bool c, bool tc)
|
||||
void read_range(IteratorType first, IteratorType last, on_error ae, bool c, bool tc)
|
||||
{
|
||||
using value_type = typename std::remove_cv<typename std::iterator_traits<IteratorType>::value_type>::type;
|
||||
// borrow the range where the library's input adapter scans it as one
|
||||
@@ -10782,14 +10796,14 @@ class basic_json_document
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range_impl(IteratorType first, IteratorType last, bool ae, bool c, bool tc, std::true_type /*contiguous bytes*/)
|
||||
void read_range_impl(IteratorType first, IteratorType last, on_error ae, bool c, bool tc, std::true_type /*contiguous bytes*/)
|
||||
{
|
||||
const auto size = static_cast<std::size_t>(std::distance(first, last));
|
||||
build(size == 0 ? "" : reinterpret_cast<const char*>(&*first), size, ae, c, tc, false, size == 0); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range_impl(IteratorType first, IteratorType last, bool ae, bool c, bool tc, std::false_type /*other*/)
|
||||
void read_range_impl(IteratorType first, IteratorType last, on_error ae, bool c, bool tc, std::false_type /*other*/)
|
||||
{
|
||||
build_copy(detail::view::make_adapter_input(detail::input_adapter(first, last)), ae, c, tc);
|
||||
}
|
||||
@@ -10847,7 +10861,6 @@ class basic_json_document
|
||||
}
|
||||
|
||||
std::unique_ptr<document_data, document_data::deleter> m_data{}; // NOLINT(readability-redundant-member-init)
|
||||
bool m_validate_only = false; ///< set by accept(): build() stores no nodes
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -59,7 +59,7 @@ built build(const std::string& text, bool comments, bool trailing_commas, bool s
|
||||
r.copy.assign(text.begin(), text.end());
|
||||
src = r.copy.data();
|
||||
}
|
||||
r.ok = nlohmann::detail::view::build < FloatType, !nlohmann::detail::abi_config::strict_nul_handling > (*r.data, src, text.size(), comments, trailing_commas, sentinel, r.failure);
|
||||
r.ok = nlohmann::detail::view::build < FloatType, !nlohmann::detail::abi_config::strict_nul_handling > (*r.data, src, text.size(), comments, trailing_commas, sentinel, false, r.failure);
|
||||
r.data->src = src;
|
||||
r.data->base[0] = src;
|
||||
r.data->base[1] = r.data->arena.data();
|
||||
|
||||
Reference in new issue
Block a user