* Document that read() must not be given a view of the document itself basic_json_document::read() releases the previous text, the decoded strings and the edits before it parses its input. An input that points into them (source(), get_string(), number_token(), or a string of an edited document) is read after its memory was cleared or freed. A guard that copies such input costs about 1 ns per read() (5 % of a read of a 7-byte input), which this API exists to avoid, so state the precondition in read.md, lifetime.md and the pages of the views that hand out such strings instead, and show how to copy the string first. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Assert in debug builds that read() is not given its own text read() releases the document's text, decoded strings, owned image and edits before it parses, so an input that points into them is read after release. Without NDEBUG, read() now asserts that a borrowed input, a copied contiguous input and (before C++17) a string_ref input are not held by the document: its owned text, its decoded strings, an owned image, and the current buffer of edited strings. Release builds keep the documented precondition without a check, which would cost 2-4.5 % per read() of a small message. JSON_ASSERT is undefined at the end of json.hpp, so the view uses assert() through a new internal NLOHMANN_VIEW_ASSERT. Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
95 lines
3.9 KiB
C++
95 lines
3.9 KiB
C++
// __ _____ _____ _____
|
|
// __| | __| | | | JSON for Modern C++
|
|
// | | |__ | | | | | | version 3.12.0
|
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|
//
|
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#pragma once
|
|
|
|
// Macros of json_view.hpp and its detail headers. json.hpp undefines its own
|
|
// macros at its end (macro_unscope.hpp), so the view defines the few it needs
|
|
// under its own prefix; json_view.hpp undefines them all at its end
|
|
// (detail/view/macro_unscope.hpp). Configuration that json.hpp undefines is
|
|
// read from detail::abi_config instead.
|
|
|
|
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
|
#define NLOHMANN_VIEW_HAS_CPP_17 1
|
|
#else
|
|
#define NLOHMANN_VIEW_HAS_CPP_17 0
|
|
#endif
|
|
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#define NLOHMANN_VIEW_LIKELY(x) __builtin_expect(!!(x), 1)
|
|
#define NLOHMANN_VIEW_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
|
#define NLOHMANN_VIEW_ALWAYS_INLINE inline __attribute__((always_inline))
|
|
#define NLOHMANN_VIEW_NOINLINE __attribute__((noinline))
|
|
#elif defined(_MSC_VER)
|
|
#define NLOHMANN_VIEW_LIKELY(x) (x)
|
|
#define NLOHMANN_VIEW_UNLIKELY(x) (x)
|
|
// plain inline: __forceinline makes MSVC report C4714 (not inlined) for
|
|
// function templates it cannot inline, which is an error under /WX; the
|
|
// forced inlining is only a performance hint
|
|
#define NLOHMANN_VIEW_ALWAYS_INLINE inline
|
|
#define NLOHMANN_VIEW_NOINLINE __declspec(noinline)
|
|
#else
|
|
#define NLOHMANN_VIEW_LIKELY(x) (x)
|
|
#define NLOHMANN_VIEW_UNLIKELY(x) (x)
|
|
#define NLOHMANN_VIEW_ALWAYS_INLINE inline
|
|
#define NLOHMANN_VIEW_NOINLINE
|
|
#endif
|
|
|
|
// GCC: a function compiled as written, without the clones in which interprocedural
|
|
// constant propagation drops an argument that every caller passes as the same constant
|
|
// (calling such a clone changes the code GCC generates for the parse loop that calls it)
|
|
#if defined(__GNUC__) && !defined(__clang__)
|
|
#define NLOHMANN_VIEW_NOCLONE __attribute__((noclone))
|
|
#else
|
|
#define NLOHMANN_VIEW_NOCLONE
|
|
#endif
|
|
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#define NLOHMANN_VIEW_NODISCARD __attribute__((warn_unused_result))
|
|
#elif defined(_MSC_VER)
|
|
#define NLOHMANN_VIEW_NODISCARD _Check_return_
|
|
#else
|
|
#define NLOHMANN_VIEW_NODISCARD
|
|
#endif
|
|
|
|
// exceptions as in json.hpp (JSON_NOEXCEPTION, JSON_THROW_USER)
|
|
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
|
#define NLOHMANN_VIEW_THROW(exception) throw exception
|
|
#else
|
|
#include <cstdlib>
|
|
// (the exception is built first, so that the arguments of the throwing
|
|
// helpers count as used; the program ends anyway)
|
|
#define NLOHMANN_VIEW_THROW(exception) (static_cast<void>(exception), std::abort())
|
|
#endif
|
|
#if defined(JSON_THROW_USER)
|
|
#undef NLOHMANN_VIEW_THROW
|
|
#define NLOHMANN_VIEW_THROW JSON_THROW_USER
|
|
#endif
|
|
|
|
// debug checks of preconditions (assert(), off with NDEBUG): JSON_ASSERT is
|
|
// one of the macros that json.hpp undefines at its end
|
|
#include <cassert> // assert
|
|
#define NLOHMANN_VIEW_ASSERT(x) assert(x)
|
|
|
|
// the parser stores a node's first word at once where the layout of `node` is
|
|
// known to be little-endian (MSVC targets are); elsewhere field by field
|
|
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(_MSC_VER)
|
|
#define NLOHMANN_VIEW_LITTLE_ENDIAN 1
|
|
#else
|
|
#define NLOHMANN_VIEW_LITTLE_ENDIAN 0
|
|
#endif
|
|
|
|
/// eight checks at fixed offsets 0..7
|
|
#define NLOHMANN_VIEW_REPEAT_FIRST_8(X) X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7)
|
|
|
|
/// eight checks at fixed offsets 8..15
|
|
#define NLOHMANN_VIEW_REPEAT_SECOND_8(X) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15)
|
|
|
|
/// sixteen checks at fixed offsets 0..15
|
|
#define NLOHMANN_VIEW_REPEAT16(X) NLOHMANN_VIEW_REPEAT_FIRST_8(X) NLOHMANN_VIEW_REPEAT_SECOND_8(X)
|