Merge pull request #1153 from theodelrieu/refactor/no_virtual_sax

Refactor/no virtual sax
This commit is contained in:
Niels Lohmann 2018-08-16 17:47:55 +02:00 committed by GitHub
commit d5b21b051c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 795 additions and 339 deletions

View file

@ -21,7 +21,10 @@ SRCS = include/nlohmann/json.hpp \
include/nlohmann/detail/json_ref.hpp \
include/nlohmann/detail/macro_scope.hpp \
include/nlohmann/detail/macro_unscope.hpp \
include/nlohmann/detail/meta.hpp \
include/nlohmann/detail/meta/cpp_future.hpp \
include/nlohmann/detail/meta/detected.hpp \
include/nlohmann/detail/meta/type_traits.hpp \
include/nlohmann/detail/meta/void_t.hpp \
include/nlohmann/detail/output/binary_writer.hpp \
include/nlohmann/detail/output/output_adapters.hpp \
include/nlohmann/detail/output/serializer.hpp \

View file

@ -15,7 +15,8 @@
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann

View file

@ -8,7 +8,8 @@
#include <valarray> // valarray
#include <vector> // vector
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>

View file

@ -17,6 +17,7 @@
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@ -30,14 +31,14 @@ namespace detail
/*!
@brief deserialization of CBOR, MessagePack, and UBJSON values
*/
template<typename BasicJsonType>
template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
class binary_reader
{
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using json_sax_t = json_sax<BasicJsonType>;
using json_sax_t = SAX;
public:
/*!
@ -47,6 +48,7 @@ class binary_reader
*/
explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
assert(ia);
}
@ -321,7 +323,7 @@ class binary_reader
}
case 0x9F: // array (indefinite length)
return get_cbor_array(json_sax_t::no_limit);
return get_cbor_array(std::size_t(-1));
// map (0x00..0x17 pairs of data items follow)
case 0xA0:
@ -375,7 +377,7 @@ class binary_reader
}
case 0xBF: // map (indefinite length)
return get_cbor_object(json_sax_t::no_limit);
return get_cbor_object(std::size_t(-1));
case 0xF4: // false
return sax->boolean(false);
@ -1020,7 +1022,7 @@ class binary_reader
}
/*!
@param[in] len the length of the array or json_sax_t::no_limit for an
@param[in] len the length of the array or std::size_t(-1) for an
array of indefinite size
@return whether array creation completed
*/
@ -1031,7 +1033,7 @@ class binary_reader
return false;
}
if (len != json_sax_t::no_limit)
if (len != std::size_t(-1))
for (std::size_t i = 0; i < len; ++i)
{
if (JSON_UNLIKELY(not parse_cbor_internal()))
@ -1054,7 +1056,7 @@ class binary_reader
}
/*!
@param[in] len the length of the object or json_sax_t::no_limit for an
@param[in] len the length of the object or std::size_t(-1) for an
object of indefinite size
@return whether object creation completed
*/
@ -1066,7 +1068,7 @@ class binary_reader
}
string_t key;
if (len != json_sax_t::no_limit)
if (len != std::size_t(-1))
{
for (std::size_t i = 0; i < len; ++i)
{
@ -1558,7 +1560,7 @@ class binary_reader
}
else
{
if (JSON_UNLIKELY(not sax->start_array()))
if (JSON_UNLIKELY(not sax->start_array(-1)))
{
return false;
}
@ -1628,7 +1630,7 @@ class binary_reader
}
else
{
if (JSON_UNLIKELY(not sax->start_object()))
if (JSON_UNLIKELY(not sax->start_object(-1)))
{
return false;
}

View file

@ -25,9 +25,6 @@ struct json_sax
/// type for strings
using string_t = typename BasicJsonType::string_t;
/// constant to indicate that no size limit is given for array or object
static constexpr auto no_limit = std::size_t(-1);
/*!
@brief a null value was read
@return whether parsing should proceed
@ -72,11 +69,11 @@ struct json_sax
/*!
@brief the beginning of an object was read
@param[in] elements number of object elements or no_limit if unknown
@param[in] elements number of object elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_object(std::size_t elements = no_limit) = 0;
virtual bool start_object(std::size_t elements) = 0;
/*!
@brief an object key was read
@ -93,11 +90,11 @@ struct json_sax
/*!
@brief the beginning of an array was read
@param[in] elements number of array elements or no_limit if unknown
@param[in] elements number of array elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_array(std::size_t elements = no_limit) = 0;
virtual bool start_array(std::size_t elements) = 0;
/*!
@brief the end of an array was read
@ -136,7 +133,7 @@ constructor contains the parsed value.
@tparam BasicJsonType the JSON type
*/
template<typename BasicJsonType>
class json_sax_dom_parser : public json_sax<BasicJsonType>
class json_sax_dom_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
@ -153,47 +150,47 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
: root(r), allow_exceptions(allow_exceptions_)
{}
bool null() override
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val) override
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val) override
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val) override
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t&) override
bool number_float(number_float_t val, const string_t&)
{
handle_value(val);
return true;
}
bool string(string_t& val) override
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool start_object(std::size_t len) override
bool start_object(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
@ -202,24 +199,24 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
return true;
}
bool key(string_t& val) override
bool key(string_t& val)
{
// add null at given key and store the reference for later
object_element = &(ref_stack.back()->m_value.object->operator[](val));
return true;
}
bool end_object() override
bool end_object()
{
ref_stack.pop_back();
return true;
}
bool start_array(std::size_t len) override
bool start_array(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
@ -228,14 +225,14 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
return true;
}
bool end_array() override
bool end_array()
{
ref_stack.pop_back();
return true;
}
bool parse_error(std::size_t, const std::string&,
const detail::exception& ex) override
const detail::exception& ex)
{
errored = true;
if (allow_exceptions)
@ -310,7 +307,7 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
};
template<typename BasicJsonType>
class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
class json_sax_dom_callback_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
@ -328,43 +325,43 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
keep_stack.push_back(true);
}
bool null() override
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val) override
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val) override
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val) override
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t&) override
bool number_float(number_float_t val, const string_t&)
{
handle_value(val);
return true;
}
bool string(string_t& val) override
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool start_object(std::size_t len) override
bool start_object(std::size_t len)
{
// check callback for object start
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
@ -376,7 +373,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
// check object limit
if (ref_stack.back())
{
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
@ -386,7 +383,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool key(string_t& val) override
bool key(string_t& val)
{
BasicJsonType k = BasicJsonType(val);
@ -403,7 +400,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool end_object() override
bool end_object()
{
if (ref_stack.back())
{
@ -438,7 +435,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool start_array(std::size_t len) override
bool start_array(std::size_t len)
{
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
keep_stack.push_back(keep);
@ -449,7 +446,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
// check array limit
if (ref_stack.back())
{
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
@ -459,7 +456,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool end_array() override
bool end_array()
{
bool keep = true;
@ -491,7 +488,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
}
bool parse_error(std::size_t, const std::string&,
const detail::exception& ex) override
const detail::exception& ex)
{
errored = true;
if (allow_exceptions)
@ -614,7 +611,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
};
template<typename BasicJsonType>
class json_sax_acceptor : public json_sax<BasicJsonType>
class json_sax_acceptor
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
@ -622,62 +619,62 @@ class json_sax_acceptor : public json_sax<BasicJsonType>
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
bool null() override
bool null()
{
return true;
}
bool boolean(bool) override
bool boolean(bool)
{
return true;
}
bool number_integer(number_integer_t) override
bool number_integer(number_integer_t)
{
return true;
}
bool number_unsigned(number_unsigned_t) override
bool number_unsigned(number_unsigned_t)
{
return true;
}
bool number_float(number_float_t, const string_t&) override
bool number_float(number_float_t, const string_t&)
{
return true;
}
bool string(string_t&) override
bool string(string_t&)
{
return true;
}
bool start_object(std::size_t) override
bool start_object(std::size_t = -1)
{
return true;
}
bool key(string_t&) override
bool key(string_t&)
{
return true;
}
bool end_object() override
bool end_object()
{
return true;
}
bool start_array(std::size_t) override
bool start_array(std::size_t = -1)
{
return true;
}
bool end_array() override
bool end_array()
{
return true;
}
bool parse_error(std::size_t, const std::string&, const detail::exception&) override
bool parse_error(std::size_t, const std::string&, const detail::exception&)
{
return false;
}

View file

@ -9,6 +9,7 @@
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/input/lexer.hpp>
@ -54,8 +55,6 @@ class parser
value
};
using json_sax_t = json_sax<BasicJsonType>;
using parser_callback_t =
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
@ -144,8 +143,10 @@ class parser
return sax_parse(&sax_acceptor, strict);
}
bool sax_parse(json_sax_t* sax, const bool strict = true)
template <typename SAX>
bool sax_parse(SAX* sax, const bool strict = true)
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType>{};
const bool result = sax_parse_internal(sax);
// strict mode: next byte must be EOF
@ -160,7 +161,8 @@ class parser
}
private:
bool sax_parse_internal(json_sax_t* sax)
template <typename SAX>
bool sax_parse_internal(SAX* sax)
{
// stack to remember the hieararchy of structured values we are parsing
// true = array; false = object
@ -177,7 +179,7 @@ class parser
{
case token_type::begin_object:
{
if (JSON_UNLIKELY(not sax->start_object()))
if (JSON_UNLIKELY(not sax->start_object(-1)))
{
return false;
}
@ -225,7 +227,7 @@ class parser
case token_type::begin_array:
{
if (JSON_UNLIKELY(not sax->start_array()))
if (JSON_UNLIKELY(not sax->start_array(-1)))
{
return false;
}

View file

@ -8,7 +8,7 @@
#include <nlohmann/detail/iterators/internal_iterator.hpp>
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann

View file

@ -0,0 +1,83 @@
#pragma once
#include <ciso646> // not
#include <cstddef> // size_t
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
namespace nlohmann
{
namespace detail
{
// alias templates to reduce boilerplate
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template<typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// implementation of C++14 index_sequence and affiliates
// source: https://stackoverflow.com/a/32223343
template<std::size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = std::size_t;
static constexpr std::size_t size() noexcept
{
return sizeof...(Ints);
}
};
template<class Sequence1, class Sequence2>
struct merge_and_renumber;
template<std::size_t... I1, std::size_t... I2>
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence < I1..., (sizeof...(I1) + I2)... > {};
template<std::size_t N>
struct make_index_sequence
: merge_and_renumber < typename make_index_sequence < N / 2 >::type,
typename make_index_sequence < N - N / 2 >::type > {};
template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
template<typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
/*
Implementation of two C++17 constructs: conjunction, negation. This is needed
to avoid evaluating all the traits in a condition
For example: not std::is_same<void, T>::value and has_value_type<T>::value
will not compile when T = void (on MSVC at least). Whereas
conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
stop evaluating if negation<...>::value == false
Please note that those constructs must be used with caution, since symbols can
become very long quickly (which can slow down compilation and cause MSVC
internal compiler errors). Only use it when you have to (see example ahead).
*/
template<class...> struct conjunction : std::true_type {};
template<class B1> struct conjunction<B1> : B1 {};
template<class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template<class B> struct negation : std::integral_constant<bool, not B::value> {};
// dispatch utility (taken from ranges-v3)
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
// taken from ranges-v3
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
}
}

View file

@ -0,0 +1,56 @@
#pragma once
#include <type_traits>
#include <nlohmann/detail/meta/void_t.hpp>
// http://en.cppreference.com/w/cpp/experimental/is_detected
namespace nlohmann
{
namespace detail
{
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
template <class Default,
class AlwaysVoid,
template <class...> class Op,
class... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
using value_t = std::true_type;
using type = Op<Args...>;
};
template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
template <class Default, template <class...> class Op, class... Args>
using detected_or = detector<Default, void, Op, Args...>;
template <class Default, template <class...> class Op, class... Args>
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template <class Expected, template <class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template <class To, template <class...> class Op, class... Args>
using is_detected_convertible =
std::is_convertible<detected_t<Op, Args...>, To>;
}
}

View file

@ -0,0 +1,141 @@
#pragma once
#include <cstdint> // size_t
#include <utility> // declval
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
namespace nlohmann
{
namespace detail
{
template <typename T>
using null_function_t = decltype(std::declval<T&>().null());
template <typename T>
using boolean_function_t =
decltype(std::declval<T&>().boolean(std::declval<bool>()));
template <typename T, typename Integer>
using number_integer_function_t =
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
template <typename T, typename Unsigned>
using number_unsigned_function_t =
decltype(std::declval<T &>().number_unsigned(std::declval<Unsigned>()));
template <typename T, typename Float, typename String>
using number_float_function_t = decltype(std::declval<T &>().number_float(
std::declval<Float>(), std::declval<const String &>()));
template <typename T, typename String>
using string_function_t =
decltype(std::declval<T &>().string(std::declval<String &>()));
template <typename T>
using start_object_function_t =
decltype(std::declval<T &>().start_object(std::declval<std::size_t>()));
template <typename T, typename String>
using key_function_t =
decltype(std::declval<T &>().key(std::declval<String &>()));
template <typename T>
using end_object_function_t = decltype(std::declval<T &>().end_object());
template <typename T>
using start_array_function_t =
decltype(std::declval<T &>().start_array(std::declval<std::size_t>()));
template <typename T>
using end_array_function_t = decltype(std::declval<T &>().end_array());
template <typename T, typename Exception>
using parse_error_function_t = decltype(std::declval<T &>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string &>(),
std::declval<const Exception &>()));
template <typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template <typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
number_float_t, string_t>::value,
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
static_assert(
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
"Missing/invalid function: bool string(string_t&)");
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
"Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
"Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
"Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
"Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
"Missing/invalid function: bool end_array()");
static_assert(
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
};
}
}

View file

@ -1,12 +1,12 @@
#pragma once
#include <ciso646> // not
#include <cstddef> // size_t
#include <limits> // numeric_limits
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
@ -30,68 +30,6 @@ template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
// alias templates to reduce boilerplate
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template<typename T>
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// implementation of C++14 index_sequence and affiliates
// source: https://stackoverflow.com/a/32223343
template<std::size_t... Ints>
struct index_sequence
{
using type = index_sequence;
using value_type = std::size_t;
static constexpr std::size_t size() noexcept
{
return sizeof...(Ints);
}
};
template<class Sequence1, class Sequence2>
struct merge_and_renumber;
template<std::size_t... I1, std::size_t... I2>
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence < I1..., (sizeof...(I1) + I2)... > {};
template<std::size_t N>
struct make_index_sequence
: merge_and_renumber < typename make_index_sequence < N / 2 >::type,
typename make_index_sequence < N - N / 2 >::type > {};
template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
template<typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
/*
Implementation of two C++17 constructs: conjunction, negation. This is needed
to avoid evaluating all the traits in a condition
For example: not std::is_same<void, T>::value and has_value_type<T>::value
will not compile when T = void (on MSVC at least). Whereas
conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
stop evaluating if negation<...>::value == false
Please note that those constructs must be used with caution, since symbols can
become very long quickly (which can slow down compilation and cause MSVC
internal compiler errors). Only use it when you have to (see example ahead).
*/
template<class...> struct conjunction : std::true_type {};
template<class B1> struct conjunction<B1> : B1 {};
template<class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template<class B> struct negation : std::integral_constant<bool, not B::value> {};
// dispatch utility (taken from ranges-v3)
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
////////////////////////
// has_/is_ functions //
////////////////////////
@ -264,15 +202,5 @@ struct is_compatible_type
is_compatible_complete_type<BasicJsonType, CompatibleType>>
{
};
// taken from ranges-v3
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
}
}

View file

@ -0,0 +1,10 @@
#pragma once
namespace nlohmann
{
namespace detail
{
template <typename...>
using void_t = void;
}
}

View file

@ -16,7 +16,7 @@
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/conversions/to_chars.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
#include <nlohmann/detail/value_t.hpp>

View file

@ -48,7 +48,8 @@ SOFTWARE.
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/conversions/from_json.hpp>
@ -170,7 +171,7 @@ class basic_json
friend class ::nlohmann::detail::iter_impl;
template<typename BasicJsonType, typename CharType>
friend class ::nlohmann::detail::binary_writer;
template<typename BasicJsonType>
template<typename BasicJsonType, typename SAX>
friend class ::nlohmann::detail::binary_reader;
template<typename BasicJsonType>
friend class ::nlohmann::detail::json_sax_dom_parser;
@ -211,6 +212,7 @@ class basic_json
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
using input_format_t = detail::input_format_t;
using json_sax_t = json_sax<basic_json>;
////////////////
// exceptions //
@ -1112,8 +1114,6 @@ class basic_json
*/
using parser_callback_t = typename parser::parser_callback_t;
using json_sax_t = typename parser::json_sax_t;
//////////////////
// constructors //
//////////////////
@ -6013,7 +6013,8 @@ class basic_json
return parser(i).accept(true);
}
static bool sax_parse(detail::input_adapter&& i, json_sax_t* sax,
template <typename SAX>
static bool sax_parse(detail::input_adapter&& i, SAX* sax,
input_format_t format = input_format_t::json,
const bool strict = true)
{
@ -6023,7 +6024,7 @@ class basic_json
case input_format_t::json:
return parser(std::move(i)).sax_parse(sax, strict);
default:
return binary_reader(std::move(i)).sax_parse(format, sax, strict);
return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
}
}
@ -6096,11 +6097,11 @@ class basic_json
return parser(detail::input_adapter(first, last)).accept(true);
}
template<class IteratorType, typename std::enable_if<
template<class IteratorType, class SAX, typename std::enable_if<
std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
static bool sax_parse(IteratorType first, IteratorType last, json_sax_t* sax)
static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
{
return parser(detail::input_adapter(first, last)).sax_parse(sax);
}

View file

@ -238,41 +238,17 @@ contains a `mapped_type`, whereas `std::vector` fails the test.
std::is_integral<decltype(detect(std::declval<T>()))>::value; \
}
// #include <nlohmann/detail/meta.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
#include <ciso646> // not
#include <cstddef> // size_t
#include <limits> // numeric_limits
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
#include <utility> // declval
// #include <nlohmann/json_fwd.hpp>
// #include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
/*!
@brief detail namespace with internal helper functions
This namespace collects functions that should not be exposed,
implementations of some @ref basic_json methods, and meta-programming helpers.
@since version 2.1.0
*/
namespace detail
{
/////////////
// helpers //
/////////////
template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
// alias templates to reduce boilerplate
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
@ -335,6 +311,54 @@ template<class B> struct negation : std::integral_constant<bool, not B::value> {
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
// taken from ranges-v3
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
}
}
// #include <nlohmann/detail/meta/type_traits.hpp>
#include <ciso646> // not
#include <limits> // numeric_limits
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
// #include <nlohmann/json_fwd.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
/*!
@brief detail namespace with internal helper functions
This namespace collects functions that should not be exposed,
implementations of some @ref basic_json methods, and meta-programming helpers.
@since version 2.1.0
*/
namespace detail
{
/////////////
// helpers //
/////////////
template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
////////////////////////
// has_/is_ functions //
////////////////////////
@ -507,16 +531,6 @@ struct is_compatible_type
is_compatible_complete_type<BasicJsonType, CompatibleType>>
{
};
// taken from ranges-v3
template<typename T>
struct static_const
{
static constexpr T value{};
};
template<typename T>
constexpr T static_const<T>::value;
}
}
@ -950,7 +964,9 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/value_t.hpp>
@ -1335,7 +1351,9 @@ constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::va
#include <valarray> // valarray
#include <vector> // vector
// #include <nlohmann/detail/meta.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/value_t.hpp>
@ -3539,6 +3557,218 @@ scan_number_done:
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/is_sax.hpp>
#include <cstdint> // size_t
#include <utility> // declval
// #include <nlohmann/detail/meta/detected.hpp>
#include <type_traits>
// #include <nlohmann/detail/meta/void_t.hpp>
namespace nlohmann
{
namespace detail
{
template <typename...>
using void_t = void;
}
}
// http://en.cppreference.com/w/cpp/experimental/is_detected
namespace nlohmann
{
namespace detail
{
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
template <class Default,
class AlwaysVoid,
template <class...> class Op,
class... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template <class Default, template <class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
using value_t = std::true_type;
using type = Op<Args...>;
};
template <template <class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
template <template <class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
template <class Default, template <class...> class Op, class... Args>
using detected_or = detector<Default, void, Op, Args...>;
template <class Default, template <class...> class Op, class... Args>
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
template <class Expected, template <class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template <class To, template <class...> class Op, class... Args>
using is_detected_convertible =
std::is_convertible<detected_t<Op, Args...>, To>;
}
}
// #include <nlohmann/detail/meta/type_traits.hpp>
namespace nlohmann
{
namespace detail
{
template <typename T>
using null_function_t = decltype(std::declval<T&>().null());
template <typename T>
using boolean_function_t =
decltype(std::declval<T&>().boolean(std::declval<bool>()));
template <typename T, typename Integer>
using number_integer_function_t =
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
template <typename T, typename Unsigned>
using number_unsigned_function_t =
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
template <typename T, typename Float, typename String>
using number_float_function_t = decltype(std::declval<T&>().number_float(
std::declval<Float>(), std::declval<const String&>()));
template <typename T, typename String>
using string_function_t =
decltype(std::declval<T&>().string(std::declval<String&>()));
template <typename T>
using start_object_function_t =
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
template <typename T, typename String>
using key_function_t =
decltype(std::declval<T&>().key(std::declval<String&>()));
template <typename T>
using end_object_function_t = decltype(std::declval<T&>().end_object());
template <typename T>
using start_array_function_t =
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
template <typename T>
using end_array_function_t = decltype(std::declval<T&>().end_array());
template <typename T, typename Exception>
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string&>(),
std::declval<const Exception&>()));
template <typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template <typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
number_float_t, string_t>::value,
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
static_assert(
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
"Missing/invalid function: bool string(string_t&)");
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
"Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
"Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
"Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
"Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
"Missing/invalid function: bool end_array()");
static_assert(
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
};
}
}
// #include <nlohmann/detail/input/input_adapters.hpp>
// #include <nlohmann/detail/input/json_sax.hpp>
@ -3571,9 +3801,6 @@ struct json_sax
/// type for strings
using string_t = typename BasicJsonType::string_t;
/// constant to indicate that no size limit is given for array or object
static constexpr auto no_limit = std::size_t(-1);
/*!
@brief a null value was read
@return whether parsing should proceed
@ -3618,11 +3845,11 @@ struct json_sax
/*!
@brief the beginning of an object was read
@param[in] elements number of object elements or no_limit if unknown
@param[in] elements number of object elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_object(std::size_t elements = no_limit) = 0;
virtual bool start_object(std::size_t elements) = 0;
/*!
@brief an object key was read
@ -3639,11 +3866,11 @@ struct json_sax
/*!
@brief the beginning of an array was read
@param[in] elements number of array elements or no_limit if unknown
@param[in] elements number of array elements or -1 if unknown
@return whether parsing should proceed
@note binary formats may report the number of elements
*/
virtual bool start_array(std::size_t elements = no_limit) = 0;
virtual bool start_array(std::size_t elements) = 0;
/*!
@brief the end of an array was read
@ -3682,7 +3909,7 @@ constructor contains the parsed value.
@tparam BasicJsonType the JSON type
*/
template<typename BasicJsonType>
class json_sax_dom_parser : public json_sax<BasicJsonType>
class json_sax_dom_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
@ -3699,47 +3926,47 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
: root(r), allow_exceptions(allow_exceptions_)
{}
bool null() override
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val) override
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val) override
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val) override
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t&) override
bool number_float(number_float_t val, const string_t&)
{
handle_value(val);
return true;
}
bool string(string_t& val) override
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool start_object(std::size_t len) override
bool start_object(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
@ -3748,24 +3975,24 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
return true;
}
bool key(string_t& val) override
bool key(string_t& val)
{
// add null at given key and store the reference for later
object_element = &(ref_stack.back()->m_value.object->operator[](val));
return true;
}
bool end_object() override
bool end_object()
{
ref_stack.pop_back();
return true;
}
bool start_array(std::size_t len) override
bool start_array(std::size_t len)
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
@ -3774,14 +4001,14 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
return true;
}
bool end_array() override
bool end_array()
{
ref_stack.pop_back();
return true;
}
bool parse_error(std::size_t, const std::string&,
const detail::exception& ex) override
const detail::exception& ex)
{
errored = true;
if (allow_exceptions)
@ -3856,7 +4083,7 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
};
template<typename BasicJsonType>
class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
class json_sax_dom_callback_parser
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
@ -3874,43 +4101,43 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
keep_stack.push_back(true);
}
bool null() override
bool null()
{
handle_value(nullptr);
return true;
}
bool boolean(bool val) override
bool boolean(bool val)
{
handle_value(val);
return true;
}
bool number_integer(number_integer_t val) override
bool number_integer(number_integer_t val)
{
handle_value(val);
return true;
}
bool number_unsigned(number_unsigned_t val) override
bool number_unsigned(number_unsigned_t val)
{
handle_value(val);
return true;
}
bool number_float(number_float_t val, const string_t&) override
bool number_float(number_float_t val, const string_t&)
{
handle_value(val);
return true;
}
bool string(string_t& val) override
bool string(string_t& val)
{
handle_value(val);
return true;
}
bool start_object(std::size_t len) override
bool start_object(std::size_t len)
{
// check callback for object start
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
@ -3922,7 +4149,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
// check object limit
if (ref_stack.back())
{
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
@ -3932,7 +4159,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool key(string_t& val) override
bool key(string_t& val)
{
BasicJsonType k = BasicJsonType(val);
@ -3949,7 +4176,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool end_object() override
bool end_object()
{
if (ref_stack.back())
{
@ -3984,7 +4211,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool start_array(std::size_t len) override
bool start_array(std::size_t len)
{
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
keep_stack.push_back(keep);
@ -3995,7 +4222,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
// check array limit
if (ref_stack.back())
{
if (JSON_UNLIKELY(len != json_sax<BasicJsonType>::no_limit and len > ref_stack.back()->max_size()))
if (JSON_UNLIKELY(len != -1 and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
@ -4005,7 +4232,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
return true;
}
bool end_array() override
bool end_array()
{
bool keep = true;
@ -4037,7 +4264,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
}
bool parse_error(std::size_t, const std::string&,
const detail::exception& ex) override
const detail::exception& ex)
{
errored = true;
if (allow_exceptions)
@ -4160,7 +4387,7 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
};
template<typename BasicJsonType>
class json_sax_acceptor : public json_sax<BasicJsonType>
class json_sax_acceptor
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
@ -4168,62 +4395,62 @@ class json_sax_acceptor : public json_sax<BasicJsonType>
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
bool null() override
bool null()
{
return true;
}
bool boolean(bool) override
bool boolean(bool)
{
return true;
}
bool number_integer(number_integer_t) override
bool number_integer(number_integer_t)
{
return true;
}
bool number_unsigned(number_unsigned_t) override
bool number_unsigned(number_unsigned_t)
{
return true;
}
bool number_float(number_float_t, const string_t&) override
bool number_float(number_float_t, const string_t&)
{
return true;
}
bool string(string_t&) override
bool string(string_t&)
{
return true;
}
bool start_object(std::size_t) override
bool start_object(std::size_t = -1)
{
return true;
}
bool key(string_t&) override
bool key(string_t&)
{
return true;
}
bool end_object() override
bool end_object()
{
return true;
}
bool start_array(std::size_t) override
bool start_array(std::size_t = -1)
{
return true;
}
bool end_array() override
bool end_array()
{
return true;
}
bool parse_error(std::size_t, const std::string&, const detail::exception&) override
bool parse_error(std::size_t, const std::string&, const detail::exception&)
{
return false;
}
@ -4277,8 +4504,6 @@ class parser
value
};
using json_sax_t = json_sax<BasicJsonType>;
using parser_callback_t =
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
@ -4367,8 +4592,10 @@ class parser
return sax_parse(&sax_acceptor, strict);
}
bool sax_parse(json_sax_t* sax, const bool strict = true)
template <typename SAX>
bool sax_parse(SAX* sax, const bool strict = true)
{
// (void)detail::is_sax_static_asserts<SAX, BasicJsonType>{};
const bool result = sax_parse_internal(sax);
// strict mode: next byte must be EOF
@ -4383,7 +4610,8 @@ class parser
}
private:
bool sax_parse_internal(json_sax_t* sax)
template <typename SAX>
bool sax_parse_internal(SAX* sax)
{
// stack to remember the hieararchy of structured values we are parsing
// true = array; false = object
@ -4400,7 +4628,7 @@ class parser
{
case token_type::begin_object:
{
if (JSON_UNLIKELY(not sax->start_object()))
if (JSON_UNLIKELY(not sax->start_object(-1)))
{
return false;
}
@ -4448,7 +4676,7 @@ class parser
case token_type::begin_array:
{
if (JSON_UNLIKELY(not sax->start_array()))
if (JSON_UNLIKELY(not sax->start_array(-1)))
{
return false;
}
@ -4873,7 +5101,7 @@ template<typename BasicJsonType> struct internal_iterator
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/value_t.hpp>
@ -5742,6 +5970,8 @@ class output_adapter
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta/is_sax.hpp>
// #include <nlohmann/detail/value_t.hpp>
@ -5756,14 +5986,14 @@ namespace detail
/*!
@brief deserialization of CBOR, MessagePack, and UBJSON values
*/
template<typename BasicJsonType>
template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
class binary_reader
{
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using json_sax_t = json_sax<BasicJsonType>;
using json_sax_t = SAX;
public:
/*!
@ -5773,6 +6003,7 @@ class binary_reader
*/
explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
assert(ia);
}
@ -6047,7 +6278,7 @@ class binary_reader
}
case 0x9F: // array (indefinite length)
return get_cbor_array(json_sax_t::no_limit);
return get_cbor_array(std::size_t(-1));
// map (0x00..0x17 pairs of data items follow)
case 0xA0:
@ -6101,7 +6332,7 @@ class binary_reader
}
case 0xBF: // map (indefinite length)
return get_cbor_object(json_sax_t::no_limit);
return get_cbor_object(std::size_t(-1));
case 0xF4: // false
return sax->boolean(false);
@ -6746,7 +6977,7 @@ class binary_reader
}
/*!
@param[in] len the length of the array or json_sax_t::no_limit for an
@param[in] len the length of the array or std::size_t(-1) for an
array of indefinite size
@return whether array creation completed
*/
@ -6757,7 +6988,7 @@ class binary_reader
return false;
}
if (len != json_sax_t::no_limit)
if (len != std::size_t(-1))
for (std::size_t i = 0; i < len; ++i)
{
if (JSON_UNLIKELY(not parse_cbor_internal()))
@ -6780,7 +7011,7 @@ class binary_reader
}
/*!
@param[in] len the length of the object or json_sax_t::no_limit for an
@param[in] len the length of the object or std::size_t(-1) for an
object of indefinite size
@return whether object creation completed
*/
@ -6792,7 +7023,7 @@ class binary_reader
}
string_t key;
if (len != json_sax_t::no_limit)
if (len != std::size_t(-1))
{
for (std::size_t i = 0; i < len; ++i)
{
@ -7284,7 +7515,7 @@ class binary_reader
}
else
{
if (JSON_UNLIKELY(not sax->start_array()))
if (JSON_UNLIKELY(not sax->start_array(-1)))
{
return false;
}
@ -7354,7 +7585,7 @@ class binary_reader
}
else
{
if (JSON_UNLIKELY(not sax->start_object()))
if (JSON_UNLIKELY(not sax->start_object(-1)))
{
return false;
}
@ -9488,7 +9719,7 @@ char* to_chars(char* first, char* last, FloatType value)
// #include <nlohmann/detail/macro_scope.hpp>
// #include <nlohmann/detail/meta.hpp>
// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/output/output_adapters.hpp>
@ -11022,7 +11253,7 @@ class basic_json
friend class ::nlohmann::detail::iter_impl;
template<typename BasicJsonType, typename CharType>
friend class ::nlohmann::detail::binary_writer;
template<typename BasicJsonType>
template<typename BasicJsonType, typename SAX>
friend class ::nlohmann::detail::binary_reader;
template<typename BasicJsonType>
friend class ::nlohmann::detail::json_sax_dom_parser;
@ -11063,6 +11294,7 @@ class basic_json
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
using input_format_t = detail::input_format_t;
using json_sax_t = json_sax<basic_json>;
////////////////
// exceptions //
@ -11964,8 +12196,6 @@ class basic_json
*/
using parser_callback_t = typename parser::parser_callback_t;
using json_sax_t = typename parser::json_sax_t;
//////////////////
// constructors //
//////////////////
@ -16865,7 +17095,8 @@ class basic_json
return parser(i).accept(true);
}
static bool sax_parse(detail::input_adapter&& i, json_sax_t* sax,
template <typename SAX>
static bool sax_parse(detail::input_adapter&& i, SAX* sax,
input_format_t format = input_format_t::json,
const bool strict = true)
{
@ -16875,7 +17106,7 @@ class basic_json
case input_format_t::json:
return parser(std::move(i)).sax_parse(sax, strict);
default:
return binary_reader(std::move(i)).sax_parse(format, sax, strict);
return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
}
}
@ -16948,11 +17179,11 @@ class basic_json
return parser(detail::input_adapter(first, last)).accept(true);
}
template<class IteratorType, typename std::enable_if<
template<class IteratorType, class SAX, typename std::enable_if<
std::is_base_of<
std::random_access_iterator_tag,
typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
static bool sax_parse(IteratorType first, IteratorType last, json_sax_t* sax)
static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
{
return parser(detail::input_adapter(first, last)).sax_parse(sax);
}

View file

@ -34,68 +34,68 @@ using nlohmann::json;
#include <fstream>
class SaxCountdown : public nlohmann::json::json_sax_t
class SaxCountdown
{
public:
explicit SaxCountdown(const int count) : events_left(count)
{}
bool null() override
bool null()
{
return events_left-- > 0;
}
bool boolean(bool) override
bool boolean(bool)
{
return events_left-- > 0;
}
bool number_integer(json::number_integer_t) override
bool number_integer(json::number_integer_t)
{
return events_left-- > 0;
}
bool number_unsigned(json::number_unsigned_t) override
bool number_unsigned(json::number_unsigned_t)
{
return events_left-- > 0;
}
bool number_float(json::number_float_t, const std::string&) override
bool number_float(json::number_float_t, const std::string&)
{
return events_left-- > 0;
}
bool string(std::string&) override
bool string(std::string&)
{
return events_left-- > 0;
}
bool start_object(std::size_t) override
bool start_object(std::size_t)
{
return events_left-- > 0;
}
bool key(std::string&) override
bool key(std::string&)
{
return events_left-- > 0;
}
bool end_object() override
bool end_object()
{
return events_left-- > 0;
}
bool start_array(std::size_t) override
bool start_array(std::size_t)
{
return events_left-- > 0;
}
bool end_array() override
bool end_array()
{
return events_left-- > 0;
}
bool parse_error(std::size_t, const std::string&, const json::exception&) override
bool parse_error(std::size_t, const std::string&, const json::exception&)
{
return false;
}

View file

@ -35,48 +35,48 @@ using nlohmann::json;
#include <valarray>
class SaxEventLogger : public nlohmann::json::json_sax_t
class SaxEventLogger
{
public:
bool null() override
bool null()
{
events.push_back("null()");
return true;
}
bool boolean(bool val) override
bool boolean(bool val)
{
events.push_back(val ? "boolean(true)" : "boolean(false)");
return true;
}
bool number_integer(json::number_integer_t val) override
bool number_integer(json::number_integer_t val)
{
events.push_back("number_integer(" + std::to_string(val) + ")");
return true;
}
bool number_unsigned(json::number_unsigned_t val) override
bool number_unsigned(json::number_unsigned_t val)
{
events.push_back("number_unsigned(" + std::to_string(val) + ")");
return true;
}
bool number_float(json::number_float_t, const std::string& s) override
bool number_float(json::number_float_t, const std::string& s)
{
events.push_back("number_float(" + s + ")");
return true;
}
bool string(std::string& val) override
bool string(std::string& val)
{
events.push_back("string(" + val + ")");
return true;
}
bool start_object(std::size_t elements) override
bool start_object(std::size_t elements)
{
if (elements == no_limit)
if (elements == std::size_t(-1))
{
events.push_back("start_object()");
}
@ -87,21 +87,21 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
return true;
}
bool key(std::string& val) override
bool key(std::string& val)
{
events.push_back("key(" + val + ")");
return true;
}
bool end_object() override
bool end_object()
{
events.push_back("end_object()");
return true;
}
bool start_array(std::size_t elements) override
bool start_array(std::size_t elements)
{
if (elements == no_limit)
if (elements == std::size_t(-1))
{
events.push_back("start_array()");
}
@ -112,13 +112,13 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
return true;
}
bool end_array() override
bool end_array()
{
events.push_back("end_array()");
return true;
}
bool parse_error(std::size_t position, const std::string&, const json::exception&) override
bool parse_error(std::size_t position, const std::string&, const json::exception&)
{
errored = true;
events.push_back("parse_error(" + std::to_string(position) + ")");

View file

@ -35,45 +35,45 @@ using nlohmann::json;
#include <iostream>
#include <valarray>
struct SaxEventLogger : public nlohmann::json::json_sax_t
struct SaxEventLogger
{
bool null() override
bool null()
{
events.push_back("null()");
return true;
}
bool boolean(bool val) override
bool boolean(bool val)
{
events.push_back(val ? "boolean(true)" : "boolean(false)");
return true;
}
bool number_integer(json::number_integer_t val) override
bool number_integer(json::number_integer_t val)
{
events.push_back("number_integer(" + std::to_string(val) + ")");
return true;
}
bool number_unsigned(json::number_unsigned_t val) override
bool number_unsigned(json::number_unsigned_t val)
{
events.push_back("number_unsigned(" + std::to_string(val) + ")");
return true;
}
bool number_float(json::number_float_t, const std::string& s) override
bool number_float(json::number_float_t, const std::string& s)
{
events.push_back("number_float(" + s + ")");
return true;
}
bool string(std::string& val) override
bool string(std::string& val)
{
events.push_back("string(" + val + ")");
return true;
}
bool start_object(std::size_t elements) override
bool start_object(std::size_t elements)
{
if (elements == std::size_t(-1))
{
@ -86,19 +86,19 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t
return true;
}
bool key(std::string& val) override
bool key(std::string& val)
{
events.push_back("key(" + val + ")");
return true;
}
bool end_object()override
bool end_object()
{
events.push_back("end_object()");
return true;
}
bool start_array(std::size_t elements) override
bool start_array(std::size_t elements)
{
if (elements == std::size_t(-1))
{
@ -111,13 +111,13 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t
return true;
}
bool end_array() override
bool end_array()
{
events.push_back("end_array()");
return true;
}
bool parse_error(std::size_t position, const std::string&, const json::exception&) override
bool parse_error(std::size_t position, const std::string&, const json::exception&)
{
events.push_back("parse_error(" + std::to_string(position) + ")");
return false;
@ -128,9 +128,9 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
{
bool start_object(std::size_t elements) override
bool start_object(std::size_t elements)
{
if (elements == no_limit)
if (elements == -1)
{
events.push_back("start_object()");
}
@ -144,7 +144,7 @@ struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
struct SaxEventLoggerExitAfterKey : public SaxEventLogger
{
bool key(std::string& val) override
bool key(std::string& val)
{
events.push_back("key(" + val + ")");
return false;
@ -153,9 +153,9 @@ struct SaxEventLoggerExitAfterKey : public SaxEventLogger
struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
{
bool start_array(std::size_t elements) override
bool start_array(std::size_t elements)
{
if (elements == no_limit)
if (elements == -1)
{
events.push_back("start_array()");
}

View file

@ -317,8 +317,8 @@ TEST_CASE("object inspection")
SECTION("round trips")
{
for (const auto& s :
{"3.141592653589793", "1000000000000000010E5"
})
{"3.141592653589793", "1000000000000000010E5"
})
{
json j1 = json::parse(s);
std::string s1 = j1.dump();

View file

@ -34,68 +34,68 @@ using nlohmann::json;
#include <fstream>
class SaxCountdown : public nlohmann::json::json_sax_t
class SaxCountdown
{
public:
explicit SaxCountdown(const int count) : events_left(count)
{}
bool null() override
bool null()
{
return events_left-- > 0;
}
bool boolean(bool) override
bool boolean(bool)
{
return events_left-- > 0;
}
bool number_integer(json::number_integer_t) override
bool number_integer(json::number_integer_t)
{
return events_left-- > 0;
}
bool number_unsigned(json::number_unsigned_t) override
bool number_unsigned(json::number_unsigned_t)
{
return events_left-- > 0;
}
bool number_float(json::number_float_t, const std::string&) override
bool number_float(json::number_float_t, const std::string&)
{
return events_left-- > 0;
}
bool string(std::string&) override
bool string(std::string&)
{
return events_left-- > 0;
}
bool start_object(std::size_t) override
bool start_object(std::size_t)
{
return events_left-- > 0;
}
bool key(std::string&) override
bool key(std::string&)
{
return events_left-- > 0;
}
bool end_object() override
bool end_object()
{
return events_left-- > 0;
}
bool start_array(std::size_t) override
bool start_array(std::size_t)
{
return events_left-- > 0;
}
bool end_array() override
bool end_array()
{
return events_left-- > 0;
}
bool parse_error(std::size_t, const std::string&, const json::exception&) override
bool parse_error(std::size_t, const std::string&, const json::exception&)
{
return false;
}

View file

@ -34,68 +34,68 @@ using nlohmann::json;
#include <fstream>
class SaxCountdown : public nlohmann::json::json_sax_t
class SaxCountdown
{
public:
explicit SaxCountdown(const int count) : events_left(count)
{}
bool null() override
bool null()
{
return events_left-- > 0;
}
bool boolean(bool) override
bool boolean(bool)
{
return events_left-- > 0;
}
bool number_integer(json::number_integer_t) override
bool number_integer(json::number_integer_t)
{
return events_left-- > 0;
}
bool number_unsigned(json::number_unsigned_t) override
bool number_unsigned(json::number_unsigned_t)
{
return events_left-- > 0;
}
bool number_float(json::number_float_t, const std::string&) override
bool number_float(json::number_float_t, const std::string&)
{
return events_left-- > 0;
}
bool string(std::string&) override
bool string(std::string&)
{
return events_left-- > 0;
}
bool start_object(std::size_t) override
bool start_object(std::size_t)
{
return events_left-- > 0;
}
bool key(std::string&) override
bool key(std::string&)
{
return events_left-- > 0;
}
bool end_object() override
bool end_object()
{
return events_left-- > 0;
}
bool start_array(std::size_t) override
bool start_array(std::size_t)
{
return events_left-- > 0;
}
bool end_array() override
bool end_array()
{
return events_left-- > 0;
}
bool parse_error(std::size_t, const std::string&, const json::exception&) override
bool parse_error(std::size_t, const std::string&, const json::exception&)
{
return false;
}