Unverified Commit a8398a71 authored by Niels Lohmann's avatar Niels Lohmann Committed by GitHub

Merge pull request #2550 from nlohmann/std_bytes

Allow parsing from std::byte containers
parents ff3863dc fc7e181c
...@@ -3,13 +3,61 @@ name: Ubuntu ...@@ -3,13 +3,61 @@ name: Ubuntu
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: gcc_build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: install_gcc
run: |
sudo apt update
sudo apt install gcc-10 g++-10
shell: bash
- name: cmake - name: cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
env:
CC: gcc-10
CXX: g++-10
- name: build
run: cmake --build build --parallel 10
- name: test
run: cd build ; ctest -j 10 --output-on-failure
clang_build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: install_gcc
run: |
sudo apt update
sudo apt install clang-10
shell: bash
- name: cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
env:
CC: clang-10
CXX: clang++-10
- name: build
run: cmake --build build --parallel 10
- name: test
run: cd build ; ctest -j 10 --output-on-failure
clang_build_cxx20:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: install_gcc
run: |
sudo apt update
sudo apt install clang-10
shell: bash
- name: cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_STANDARD_REQUIRED=ON
env:
CC: clang-10
CXX: clang++-10
- name: build - name: build
run: cmake --build build --parallel 10 run: cmake --build build --parallel 10
- name: test - name: test
......
...@@ -84,6 +84,7 @@ doctest: ...@@ -84,6 +84,7 @@ doctest:
# -Wno-missing-prototypes: for NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE # -Wno-missing-prototypes: for NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
# -Wno-padded: padding is nothing to warn about # -Wno-padded: padding is nothing to warn about
# -Wno-range-loop-analysis: items tests "for(const auto i...)" # -Wno-range-loop-analysis: items tests "for(const auto i...)"
# -Wno-extra-semi-stmt: spurious warnings for semicolons after JSON_ASSERT()
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches # -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
# -Wno-weak-vtables: exception class is defined inline, but has virtual method # -Wno-weak-vtables: exception class is defined inline, but has virtual method
pedantic_clang: pedantic_clang:
...@@ -100,6 +101,7 @@ pedantic_clang: ...@@ -100,6 +101,7 @@ pedantic_clang:
-Wno-missing-prototypes \ -Wno-missing-prototypes \
-Wno-padded \ -Wno-padded \
-Wno-range-loop-analysis \ -Wno-range-loop-analysis \
-Wno-extra-semi-stmt \
-Wno-switch-enum -Wno-covered-switch-default \ -Wno-switch-enum -Wno-covered-switch-default \
-Wno-weak-vtables" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -Wno-weak-vtables" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
cmake --build cmake-build-pedantic cmake --build cmake-build-pedantic
......
...@@ -374,7 +374,8 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte ...@@ -374,7 +374,8 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte
// Enables ADL on begin(container) and end(container) // Enables ADL on begin(container) and end(container)
// Encloses the using declarations in namespace for not to leak them to outside scope // Encloses the using declarations in namespace for not to leak them to outside scope
namespace container_input_adapter_factory_impl { namespace container_input_adapter_factory_impl
{
using std::begin; using std::begin;
using std::end; using std::end;
...@@ -384,15 +385,15 @@ struct container_input_adapter_factory {}; ...@@ -384,15 +385,15 @@ struct container_input_adapter_factory {};
template<typename ContainerType> template<typename ContainerType>
struct container_input_adapter_factory< ContainerType, struct container_input_adapter_factory< ContainerType,
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))> > void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
{ {
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
static adapter_type create(const ContainerType& container) static adapter_type create(const ContainerType& container)
{ {
return input_adapter(begin(container), end(container)); return input_adapter(begin(container), end(container));
} }
}; };
} }
......
...@@ -1541,17 +1541,17 @@ scan_number_done: ...@@ -1541,17 +1541,17 @@ scan_number_done:
// literals // literals
case 't': case 't':
{ {
std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}}; std::array<char_type, 4> true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}};
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
} }
case 'f': case 'f':
{ {
std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}}; std::array<char_type, 5> false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}};
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
} }
case 'n': case 'n':
{ {
std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}}; std::array<char_type, 4> null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}};
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
} }
......
...@@ -38,8 +38,10 @@ This class implements a both iterators (iterator and const_iterator) for the ...@@ -38,8 +38,10 @@ This class implements a both iterators (iterator and const_iterator) for the
template<typename BasicJsonType> template<typename BasicJsonType>
class iter_impl class iter_impl
{ {
/// the iterator with BasicJsonType of different const-ness
using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
/// allow basic_json to access private members /// allow basic_json to access private members
friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; friend other_iter_impl;
friend BasicJsonType; friend BasicJsonType;
friend iteration_proxy<iter_impl>; friend iteration_proxy<iter_impl>;
friend iteration_proxy_value<iter_impl>; friend iteration_proxy_value<iter_impl>;
...@@ -390,10 +392,11 @@ class iter_impl ...@@ -390,10 +392,11 @@ class iter_impl
} }
/*! /*!
@brief comparison: equal @brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator==(const iter_impl& other) const template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator==(const IterImpl& other) const
{ {
// if objects are not the same, the comparison is undefined // if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
...@@ -417,16 +420,17 @@ class iter_impl ...@@ -417,16 +420,17 @@ class iter_impl
} }
/*! /*!
@brief comparison: not equal @brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator!=(const iter_impl& other) const template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator!=(const IterImpl& other) const
{ {
return !operator==(other); return !operator==(other);
} }
/*! /*!
@brief comparison: smaller @brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator<(const iter_impl& other) const bool operator<(const iter_impl& other) const
...@@ -453,7 +457,7 @@ class iter_impl ...@@ -453,7 +457,7 @@ class iter_impl
} }
/*! /*!
@brief comparison: less than or equal @brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator<=(const iter_impl& other) const bool operator<=(const iter_impl& other) const
...@@ -462,7 +466,7 @@ class iter_impl ...@@ -462,7 +466,7 @@ class iter_impl
} }
/*! /*!
@brief comparison: greater than @brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator>(const iter_impl& other) const bool operator>(const iter_impl& other) const
...@@ -471,7 +475,7 @@ class iter_impl ...@@ -471,7 +475,7 @@ class iter_impl
} }
/*! /*!
@brief comparison: greater than or equal @brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator>=(const iter_impl& other) const bool operator>=(const iter_impl& other) const
...@@ -480,7 +484,7 @@ class iter_impl ...@@ -480,7 +484,7 @@ class iter_impl
} }
/*! /*!
@brief add to iterator @brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl& operator+=(difference_type i) iter_impl& operator+=(difference_type i)
...@@ -509,7 +513,7 @@ class iter_impl ...@@ -509,7 +513,7 @@ class iter_impl
} }
/*! /*!
@brief subtract from iterator @brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl& operator-=(difference_type i) iter_impl& operator-=(difference_type i)
...@@ -518,7 +522,7 @@ class iter_impl ...@@ -518,7 +522,7 @@ class iter_impl
} }
/*! /*!
@brief add to iterator @brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl operator+(difference_type i) const iter_impl operator+(difference_type i) const
...@@ -529,7 +533,7 @@ class iter_impl ...@@ -529,7 +533,7 @@ class iter_impl
} }
/*! /*!
@brief addition of distance and iterator @brief addition of distance and iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
friend iter_impl operator+(difference_type i, const iter_impl& it) friend iter_impl operator+(difference_type i, const iter_impl& it)
...@@ -540,7 +544,7 @@ class iter_impl ...@@ -540,7 +544,7 @@ class iter_impl
} }
/*! /*!
@brief subtract from iterator @brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl operator-(difference_type i) const iter_impl operator-(difference_type i) const
...@@ -551,7 +555,7 @@ class iter_impl ...@@ -551,7 +555,7 @@ class iter_impl
} }
/*! /*!
@brief return difference @brief return difference
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
difference_type operator-(const iter_impl& other) const difference_type operator-(const iter_impl& other) const
...@@ -572,7 +576,7 @@ class iter_impl ...@@ -572,7 +576,7 @@ class iter_impl
} }
/*! /*!
@brief access to successor @brief access to successor
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
reference operator[](difference_type n) const reference operator[](difference_type n) const
...@@ -603,7 +607,7 @@ class iter_impl ...@@ -603,7 +607,7 @@ class iter_impl
} }
/*! /*!
@brief return the key of an object iterator @brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
const typename object_t::key_type& key() const const typename object_t::key_type& key() const
...@@ -619,7 +623,7 @@ class iter_impl ...@@ -619,7 +623,7 @@ class iter_impl
} }
/*! /*!
@brief return the value of an iterator @brief return the value of an iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
reference value() const reference value() const
......
...@@ -5186,7 +5186,8 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte ...@@ -5186,7 +5186,8 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte
// Enables ADL on begin(container) and end(container) // Enables ADL on begin(container) and end(container)
// Encloses the using declarations in namespace for not to leak them to outside scope // Encloses the using declarations in namespace for not to leak them to outside scope
namespace container_input_adapter_factory_impl { namespace container_input_adapter_factory_impl
{
using std::begin; using std::begin;
using std::end; using std::end;
...@@ -5196,15 +5197,15 @@ struct container_input_adapter_factory {}; ...@@ -5196,15 +5197,15 @@ struct container_input_adapter_factory {};
template<typename ContainerType> template<typename ContainerType>
struct container_input_adapter_factory< ContainerType, struct container_input_adapter_factory< ContainerType,
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))> > void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
{ {
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
static adapter_type create(const ContainerType& container) static adapter_type create(const ContainerType& container)
{ {
return input_adapter(begin(container), end(container)); return input_adapter(begin(container), end(container));
} }
}; };
} }
...@@ -7532,17 +7533,17 @@ scan_number_done: ...@@ -7532,17 +7533,17 @@ scan_number_done:
// literals // literals
case 't': case 't':
{ {
std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}}; std::array<char_type, 4> true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}};
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
} }
case 'f': case 'f':
{ {
std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}}; std::array<char_type, 5> false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}};
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
} }
case 'n': case 'n':
{ {
std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}}; std::array<char_type, 4> null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}};
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
} }
...@@ -10924,8 +10925,10 @@ This class implements a both iterators (iterator and const_iterator) for the ...@@ -10924,8 +10925,10 @@ This class implements a both iterators (iterator and const_iterator) for the
template<typename BasicJsonType> template<typename BasicJsonType>
class iter_impl class iter_impl
{ {
/// the iterator with BasicJsonType of different const-ness
using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
/// allow basic_json to access private members /// allow basic_json to access private members
friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; friend other_iter_impl;
friend BasicJsonType; friend BasicJsonType;
friend iteration_proxy<iter_impl>; friend iteration_proxy<iter_impl>;
friend iteration_proxy_value<iter_impl>; friend iteration_proxy_value<iter_impl>;
...@@ -11276,10 +11279,11 @@ class iter_impl ...@@ -11276,10 +11279,11 @@ class iter_impl
} }
/*! /*!
@brief comparison: equal @brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator==(const iter_impl& other) const template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator==(const IterImpl& other) const
{ {
// if objects are not the same, the comparison is undefined // if objects are not the same, the comparison is undefined
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
...@@ -11303,16 +11307,17 @@ class iter_impl ...@@ -11303,16 +11307,17 @@ class iter_impl
} }
/*! /*!
@brief comparison: not equal @brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator!=(const iter_impl& other) const template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator!=(const IterImpl& other) const
{ {
return !operator==(other); return !operator==(other);
} }
/*! /*!
@brief comparison: smaller @brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator<(const iter_impl& other) const bool operator<(const iter_impl& other) const
...@@ -11339,7 +11344,7 @@ class iter_impl ...@@ -11339,7 +11344,7 @@ class iter_impl
} }
/*! /*!
@brief comparison: less than or equal @brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator<=(const iter_impl& other) const bool operator<=(const iter_impl& other) const
...@@ -11348,7 +11353,7 @@ class iter_impl ...@@ -11348,7 +11353,7 @@ class iter_impl
} }
/*! /*!
@brief comparison: greater than @brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator>(const iter_impl& other) const bool operator>(const iter_impl& other) const
...@@ -11357,7 +11362,7 @@ class iter_impl ...@@ -11357,7 +11362,7 @@ class iter_impl
} }
/*! /*!
@brief comparison: greater than or equal @brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
bool operator>=(const iter_impl& other) const bool operator>=(const iter_impl& other) const
...@@ -11366,7 +11371,7 @@ class iter_impl ...@@ -11366,7 +11371,7 @@ class iter_impl
} }
/*! /*!
@brief add to iterator @brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl& operator+=(difference_type i) iter_impl& operator+=(difference_type i)
...@@ -11395,7 +11400,7 @@ class iter_impl ...@@ -11395,7 +11400,7 @@ class iter_impl
} }
/*! /*!
@brief subtract from iterator @brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl& operator-=(difference_type i) iter_impl& operator-=(difference_type i)
...@@ -11404,7 +11409,7 @@ class iter_impl ...@@ -11404,7 +11409,7 @@ class iter_impl
} }
/*! /*!
@brief add to iterator @brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl operator+(difference_type i) const iter_impl operator+(difference_type i) const
...@@ -11415,7 +11420,7 @@ class iter_impl ...@@ -11415,7 +11420,7 @@ class iter_impl
} }
/*! /*!
@brief addition of distance and iterator @brief addition of distance and iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
friend iter_impl operator+(difference_type i, const iter_impl& it) friend iter_impl operator+(difference_type i, const iter_impl& it)
...@@ -11426,7 +11431,7 @@ class iter_impl ...@@ -11426,7 +11431,7 @@ class iter_impl
} }
/*! /*!
@brief subtract from iterator @brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
iter_impl operator-(difference_type i) const iter_impl operator-(difference_type i) const
...@@ -11437,7 +11442,7 @@ class iter_impl ...@@ -11437,7 +11442,7 @@ class iter_impl
} }
/*! /*!
@brief return difference @brief return difference
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
difference_type operator-(const iter_impl& other) const difference_type operator-(const iter_impl& other) const
...@@ -11458,7 +11463,7 @@ class iter_impl ...@@ -11458,7 +11463,7 @@ class iter_impl
} }
/*! /*!
@brief access to successor @brief access to successor
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
reference operator[](difference_type n) const reference operator[](difference_type n) const
...@@ -11489,7 +11494,7 @@ class iter_impl ...@@ -11489,7 +11494,7 @@ class iter_impl
} }
/*! /*!
@brief return the key of an object iterator @brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
const typename object_t::key_type& key() const const typename object_t::key_type& key() const
...@@ -11505,7 +11510,7 @@ class iter_impl ...@@ -11505,7 +11510,7 @@ class iter_impl
} }
/*! /*!
@brief return the value of an iterator @brief return the value of an iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`. @pre The iterator is initialized; i.e. `m_object != nullptr`.
*/ */
reference value() const reference value() const
...@@ -16822,7 +16827,7 @@ class basic_json ...@@ -16822,7 +16827,7 @@ class basic_json
detail::parser_callback_t<basic_json>cb = nullptr, detail::parser_callback_t<basic_json>cb = nullptr,
const bool allow_exceptions = true, const bool allow_exceptions = true,
const bool ignore_comments = false const bool ignore_comments = false
) )
{ {
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
std::move(cb), allow_exceptions, ignore_comments); std::move(cb), allow_exceptions, ignore_comments);
...@@ -25367,7 +25372,7 @@ template<> ...@@ -25367,7 +25372,7 @@ template<>
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept( inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value&& is_nothrow_move_constructible<nlohmann::json>::value&&
is_nothrow_move_assignable<nlohmann::json>::value is_nothrow_move_assignable<nlohmann::json>::value
) )
{ {
j1.swap(j2); j1.swap(j2);
} }
......
...@@ -509,7 +509,7 @@ TEST_CASE("parser class") ...@@ -509,7 +509,7 @@ TEST_CASE("parser class")
CHECK(parser_helper("\"\"").get<json::string_t>() == "€"); CHECK(parser_helper("\"\"").get<json::string_t>() == "€");
CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈"); CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");
CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == u8"\U00013060"); CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞"); CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
} }
} }
......
...@@ -1702,3 +1702,11 @@ TEST_CASE("JSON to enum mapping") ...@@ -1702,3 +1702,11 @@ TEST_CASE("JSON to enum mapping")
CHECK(TS_INVALID == json("what?").get<TaskState>()); CHECK(TS_INVALID == json("what?").get<TaskState>());
} }
} }
#ifdef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_17
#endif
#ifdef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_14
#endif
...@@ -1448,3 +1448,11 @@ TEST_CASE("items()") ...@@ -1448,3 +1448,11 @@ TEST_CASE("items()")
} }
} }
} }
#ifdef JSON_HAS_CPP_17
#undef JSON_HAS_CPP_17
#endif
#ifdef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_14
#endif
...@@ -400,7 +400,7 @@ TEST_CASE("regression tests 1") ...@@ -400,7 +400,7 @@ TEST_CASE("regression tests 1")
SECTION("issue #146 - character following a surrogate pair is skipped") SECTION("issue #146 - character following a surrogate pair is skipped")
{ {
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc"); CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == "\xf0\x93\x81\xa0\x61\x62\x63");
} }
SECTION("issue #171 - Cannot index by key of type static constexpr const char*") SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
......
...@@ -51,6 +51,10 @@ using nlohmann::json; ...@@ -51,6 +51,10 @@ using nlohmann::json;
#include <variant> #include <variant>
#endif #endif
#ifdef JSON_HAS_CPP_20
#include <span>
#endif
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// for #1021 // for #1021
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
...@@ -484,4 +488,14 @@ TEST_CASE("regression tests 2") ...@@ -484,4 +488,14 @@ TEST_CASE("regression tests 2")
json j = json::parse(ss, nullptr, true, true); json j = json::parse(ss, nullptr, true, true);
CHECK(j.dump() == "{}"); CHECK(j.dump() == "{}");
} }
#ifdef JSON_HAS_CPP_20
SECTION("issue #2546 - parsing containers of std::byte")
{
const char DATA[] = R"("Hello, world!")";
const auto s = std::as_bytes(std::span(DATA));
json j = json::parse(s);
CHECK(j.dump() == "\"Hello, world!\"");
}
#endif
} }
...@@ -112,13 +112,13 @@ static void to_json(BasicJsonType& j, country c) ...@@ -112,13 +112,13 @@ static void to_json(BasicJsonType& j, country c)
switch (c) switch (c)
{ {
case country::china: case country::china:
j = u8"中华人民共和国"; j = "中华人民共和国";
return; return;
case country::france: case country::france:
j = "France"; j = "France";
return; return;
case country::russia: case country::russia:
j = u8"Российская Федерация"; j = "Российская Федерация";
return; return;
default: default:
break; break;
...@@ -201,9 +201,9 @@ static void from_json(const BasicJsonType& j, country& c) ...@@ -201,9 +201,9 @@ static void from_json(const BasicJsonType& j, country& c)
const auto str = j.template get<std::string>(); const auto str = j.template get<std::string>();
static const std::map<std::string, country> m = static const std::map<std::string, country> m =
{ {
{u8"中华人民共和国", country::china}, {"中华人民共和国", country::china},
{"France", country::france}, {"France", country::france},
{u8"Российская Федерация", country::russia} {"Российская Федерация", country::russia}
}; };
const auto it = m.find(str); const auto it = m.find(str);
...@@ -248,7 +248,7 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) ...@@ -248,7 +248,7 @@ TEST_CASE("basic usage" * doctest::test_suite("udt"))
const udt::name n{"theo"}; const udt::name n{"theo"};
const udt::country c{udt::country::france}; const udt::country c{udt::country::france};
const udt::person sfinae_addict{a, n, c}; const udt::person sfinae_addict{a, n, c};
const udt::person senior_programmer{{42}, {u8"王芳"}, udt::country::china}; const udt::person senior_programmer{{42}, {"王芳"}, udt::country::china};
const udt::address addr{"Paris"}; const udt::address addr{"Paris"};
const udt::contact cpp_programmer{sfinae_addict, addr}; const udt::contact cpp_programmer{sfinae_addict, addr};
const udt::contact_book book{{"C++"}, {cpp_programmer, {senior_programmer, addr}}}; const udt::contact_book book{{"C++"}, {cpp_programmer, {senior_programmer, addr}}};
...@@ -265,14 +265,14 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) ...@@ -265,14 +265,14 @@ TEST_CASE("basic usage" * doctest::test_suite("udt"))
CHECK( CHECK(
json(book) == json(book) ==
u8R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json); R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json);
} }
SECTION("conversion from json via free-functions") SECTION("conversion from json via free-functions")
{ {
const auto big_json = const auto big_json =
u8R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json; R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json;
SECTION("via explicit calls to get") SECTION("via explicit calls to get")
{ {
const auto parsed_book = big_json.get<udt::contact_book>(); const auto parsed_book = big_json.get<udt::contact_book>();
......
...@@ -106,7 +106,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, met ...@@ -106,7 +106,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, met
class person_with_private_alphabet class person_with_private_alphabet
{ {
public: public:
bool operator==(const person_with_private_alphabet& other) bool operator==(const person_with_private_alphabet& other) const
{ {
return a == other.a && return a == other.a &&
b == other.b && b == other.b &&
...@@ -169,7 +169,7 @@ class person_with_private_alphabet ...@@ -169,7 +169,7 @@ class person_with_private_alphabet
class person_with_public_alphabet class person_with_public_alphabet
{ {
public: public:
bool operator==(const person_with_public_alphabet& other) bool operator==(const person_with_public_alphabet& other) const
{ {
return a == other.a && return a == other.a &&
b == other.b && b == other.b &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment