From 1d055261b4144dbf86b2658437015b15d4dd9bff Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 4 Sep 2022 00:32:56 +0100 Subject: initial --- include/jsoncons/basic_json.hpp | 5839 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 5839 insertions(+) create mode 100644 include/jsoncons/basic_json.hpp (limited to 'include/jsoncons/basic_json.hpp') diff --git a/include/jsoncons/basic_json.hpp b/include/jsoncons/basic_json.hpp new file mode 100644 index 0000000..31de47b --- /dev/null +++ b/include/jsoncons/basic_json.hpp @@ -0,0 +1,5839 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_BASIC_JSON_HPP +#define JSONCONS_BASIC_JSON_HPP + +#include // std::numeric_limits +#include +#include +#include +#include +#include +#include // std::allocator +#include +#include // std::memcpy +#include // std::swap +#include // std::initializer_list +#include // std::move +#include // std::enable_if +#include // std::basic_istream +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace jsoncons { + + namespace type_traits { + + namespace detail { + + template + using + basic_json_t = basic_json; + + } // namespace detail + + template + struct is_basic_json : std::false_type {}; + + template + struct is_basic_json::type>::value>::type + > : std::true_type {}; + + } // namespace type_traits + + namespace detail { + + template + class random_access_iterator_wrapper + { + }; + + template + class random_access_iterator_wrapper::iterator_category, + std::random_access_iterator_tag>::value>::type> + { + Iterator it_; + bool has_value_; + + template + friend class random_access_iterator_wrapper; + public: + using iterator_category = std::random_access_iterator_tag; + + using value_type = typename std::iterator_traits::value_type; + using difference_type = typename std::iterator_traits::difference_type; + using pointer = typename std::iterator_traits::pointer; + using reference = typename std::iterator_traits::reference; + + random_access_iterator_wrapper() : it_(), has_value_(false) + { + } + + explicit random_access_iterator_wrapper(Iterator ptr) : it_(ptr), has_value_(true) + { + } + + random_access_iterator_wrapper(const random_access_iterator_wrapper&) = default; + random_access_iterator_wrapper(random_access_iterator_wrapper&&) = default; + random_access_iterator_wrapper& operator=(const random_access_iterator_wrapper&) = default; + random_access_iterator_wrapper& operator=(random_access_iterator_wrapper&&) = default; + + template ::value && std::is_convertible::value>::type> + random_access_iterator_wrapper(const random_access_iterator_wrapper& other) + : it_(other.it_), has_value_(other.has_value_) + { + } + + operator Iterator() const + { + return it_; + } + + reference operator*() const + { + return *it_; + } + + pointer operator->() const + { + return &(*it_); + } + + random_access_iterator_wrapper& operator++() + { + ++it_; + return *this; + } + + random_access_iterator_wrapper operator++(int) + { + random_access_iterator_wrapper temp = *this; + ++*this; + return temp; + } + + random_access_iterator_wrapper& operator--() + { + --it_; + return *this; + } + + random_access_iterator_wrapper operator--(int) + { + random_access_iterator_wrapper temp = *this; + --*this; + return temp; + } + + random_access_iterator_wrapper& operator+=(const difference_type offset) + { + it_ += offset; + return *this; + } + + random_access_iterator_wrapper operator+(const difference_type offset) const + { + random_access_iterator_wrapper temp = *this; + return temp += offset; + } + + random_access_iterator_wrapper& operator-=(const difference_type offset) + { + return *this += -offset; + } + + random_access_iterator_wrapper operator-(const difference_type offset) const + { + random_access_iterator_wrapper temp = *this; + return temp -= offset; + } + + difference_type operator-(const random_access_iterator_wrapper& rhs) const noexcept + { + return it_ - rhs.it_; + } + + reference operator[](const difference_type offset) const noexcept + { + return *(*this + offset); + } + + bool operator==(const random_access_iterator_wrapper& rhs) const noexcept + { + if (!has_value_ || !rhs.has_value_) + { + return has_value_ == rhs.has_value_ ? true : false; + } + else + { + return it_ == rhs.it_; + } + } + + bool operator!=(const random_access_iterator_wrapper& rhs) const noexcept + { + return !(*this == rhs); + } + + bool operator<(const random_access_iterator_wrapper& rhs) const noexcept + { + if (!has_value_ || !rhs.has_value_) + { + return has_value_ == rhs.has_value_ ? false :(has_value_ ? false : true); + } + else + { + return it_ < rhs.it_; + } + } + + bool operator>(const random_access_iterator_wrapper& rhs) const noexcept + { + return rhs < *this; + } + + bool operator<=(const random_access_iterator_wrapper& rhs) const noexcept + { + return !(rhs < *this); + } + + bool operator>=(const random_access_iterator_wrapper& rhs) const noexcept + { + return !(*this < rhs); + } + + inline + friend random_access_iterator_wrapper operator+( + difference_type offset, random_access_iterator_wrapper next) + { + return next += offset; + } + + bool has_value() const + { + return has_value_; + } + }; + } // namespace detail + + struct sorted_policy + { + template + using object = sorted_json_object; + + template + using array = json_array; + + using parse_error_handler_type = default_json_parsing; + }; + + struct order_preserving_policy + { + template + using object = order_preserving_json_object; + + template + using array = json_array; + + using parse_error_handler_type = default_json_parsing; + }; + + #if !defined(JSONCONS_NO_DEPRECATED) + using preserve_order_policy = order_preserving_policy; + #endif + + template + class range + { + public: + using iterator = IteratorT; + using const_iterator = ConstIteratorT; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + private: + iterator first_; + iterator last_; + public: + range(const IteratorT& first, const IteratorT& last) + : first_(first), last_(last) + { + } + + iterator begin() + { + return first_; + } + iterator end() + { + return last_; + } + const_iterator cbegin() + { + return first_; + } + const_iterator cend() + { + return last_; + } + reverse_iterator rbegin() + { + return reverse_iterator(last_); + } + reverse_iterator rend() + { + return reverse_iterator(first_); + } + const_reverse_iterator crbegin() + { + return reverse_iterator(last_); + } + const_reverse_iterator crend() + { + return reverse_iterator(first_); + } + }; + + // is_proxy_of + + template + struct is_proxy_of : std::false_type {}; + + template + struct is_proxy_of::value>::type + > : std::true_type {}; + + + // is_proxy + + template + struct is_proxy : std::false_type {}; + + template + struct is_proxy::value>::type + > : std::true_type {}; + + template + class basic_json + { + public: + + using allocator_type = Allocator; + + using implementation_policy = ImplementationPolicy; + + using parse_error_handler_type = typename ImplementationPolicy::parse_error_handler_type; + + using char_type = CharT; + using char_traits_type = std::char_traits; + using string_view_type = jsoncons::basic_string_view; + + using char_allocator_type = typename std::allocator_traits:: template rebind_alloc; + + using key_type = std::basic_string; + + + using reference = basic_json&; + using const_reference = const basic_json&; + using pointer = basic_json*; + using const_pointer = const basic_json*; + + using key_value_type = key_value; + + #if !defined(JSONCONS_NO_DEPRECATED) + JSONCONS_DEPRECATED_MSG("no replacement") typedef basic_json value_type; + JSONCONS_DEPRECATED_MSG("no replacement") typedef std::basic_string string_type; + JSONCONS_DEPRECATED_MSG("Instead, use key_value_type") typedef key_value_type kvp_type; + JSONCONS_DEPRECATED_MSG("Instead, use key_value_type") typedef key_value_type member_type; + #endif + + using array = typename ImplementationPolicy::template array; + + using key_value_allocator_type = typename std::allocator_traits:: template rebind_alloc; + + using object = typename ImplementationPolicy::template object; + + using object_iterator = jsoncons::detail::random_access_iterator_wrapper; + using const_object_iterator = jsoncons::detail::random_access_iterator_wrapper; + using array_iterator = typename array::iterator; + using const_array_iterator = typename array::const_iterator; + + private: + + static constexpr uint8_t major_type_shift = 0x04; + static constexpr uint8_t additional_information_mask = (1U << 4) - 1; + + class common_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + }; + + class null_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + + null_storage(semantic_tag tag = semantic_tag::none) + : storage_kind_(static_cast(json_storage_kind::null_value)), length_(0), tag_(tag) + { + } + }; + + class empty_object_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + + empty_object_storage(semantic_tag tag) + : storage_kind_(static_cast(json_storage_kind::empty_object_value)), length_(0), tag_(tag) + { + } + }; + + class bool_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + bool val_; + public: + bool_storage(bool val, semantic_tag tag) + : storage_kind_(static_cast(json_storage_kind::bool_value)), length_(0), tag_(tag), + val_(val) + { + } + + bool value() const + { + return val_; + } + + }; + + class int64_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + int64_t val_; + public: + int64_storage(int64_t val, + semantic_tag tag = semantic_tag::none) + : storage_kind_(static_cast(json_storage_kind::int64_value)), length_(0), tag_(tag), + val_(val) + { + } + + int64_t value() const + { + return val_; + } + }; + + class uint64_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + uint64_t val_; + public: + uint64_storage(uint64_t val, + semantic_tag tag = semantic_tag::none) + : storage_kind_(static_cast(json_storage_kind::uint64_value)), length_(0), tag_(tag), + val_(val) + { + } + + uint64_t value() const + { + return val_; + } + }; + + class half_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + uint16_t val_; + public: + half_storage(uint16_t val, semantic_tag tag = semantic_tag::none) + : storage_kind_(static_cast(json_storage_kind::half_value)), length_(0), tag_(tag), + val_(val) + { + } + + uint16_t value() const + { + return val_; + } + }; + + class double_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + double val_; + public: + double_storage(double val, + semantic_tag tag = semantic_tag::none) + : storage_kind_(static_cast(json_storage_kind::double_value)), length_(0), tag_(tag), + val_(val) + { + } + + double value() const + { + return val_; + } + }; + + class short_string_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + static constexpr size_t capacity = (2*sizeof(uint64_t) - 2*sizeof(uint8_t))/sizeof(char_type); + char_type data_[capacity]; + public: + static constexpr size_t max_length = capacity - 1; + + short_string_storage(semantic_tag tag, const char_type* p, uint8_t length) + : storage_kind_(static_cast(json_storage_kind::short_string_value)), length_(length), tag_(tag) + { + JSONCONS_ASSERT(length <= max_length); + std::memcpy(data_,p,length*sizeof(char_type)); + data_[length] = 0; + } + + short_string_storage(const short_string_storage& val) + : storage_kind_(val.storage_kind_), length_(val.length_), tag_(val.tag_) + { + std::memcpy(data_,val.data_,val.length_*sizeof(char_type)); + data_[length_] = 0; + } + + short_string_storage& operator=(const short_string_storage& val) = delete; + + uint8_t length() const + { + return length_; + } + + const char_type* data() const + { + return data_; + } + + const char_type* c_str() const + { + return data_; + } + }; + + // long_string_storage + class long_string_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + jsoncons::detail::string_wrapper s_; + public: + + long_string_storage(semantic_tag tag, const char_type* data, std::size_t length, const Allocator& a) + : storage_kind_(static_cast(json_storage_kind::long_string_value)), length_(0), tag_(tag), + s_(data, length, a) + { + } + + long_string_storage(const long_string_storage& val) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + s_(val.s_) + { + } + + long_string_storage(long_string_storage&& val) noexcept + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + s_(nullptr) + { + swap(val); + } + + long_string_storage(const long_string_storage& val, const Allocator& a) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + s_(val.s_, a) + { + } + + ~long_string_storage() noexcept + { + } + + long_string_storage& operator=(const long_string_storage& val) = delete; + + long_string_storage& operator=(long_string_storage&& val) noexcept = delete; + + void swap(long_string_storage& val) noexcept + { + s_.swap(val.s_); + } + + const char_type* data() const + { + return s_.data(); + } + + const char_type* c_str() const + { + return s_.c_str(); + } + + std::size_t length() const + { + return s_.length(); + } + + allocator_type get_allocator() const + { + return s_.get_allocator(); + } + }; + + // byte_string_storage + class byte_string_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + jsoncons::detail::tagged_string_wrapper s_; + public: + + byte_string_storage(semantic_tag tag, const uint8_t* data, std::size_t length, uint64_t ext_tag, const Allocator& alloc) + : storage_kind_(static_cast(json_storage_kind::byte_string_value)), length_(0), tag_(tag), + s_(data, length, ext_tag, alloc) + { + } + + byte_string_storage(const byte_string_storage& val) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + s_(val.s_) + { + } + + byte_string_storage(byte_string_storage&& val) noexcept + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + s_(nullptr) + { + swap(val); + } + + byte_string_storage(const byte_string_storage& val, const Allocator& a) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + s_(val.s_, a) + { + } + + ~byte_string_storage() noexcept + { + } + + void swap(byte_string_storage& val) noexcept + { + s_.swap(val.s_); + } + + const uint8_t* data() const + { + return s_.data(); + } + + std::size_t length() const + { + return s_.length(); + } + + uint64_t ext_tag() const + { + return s_.tag(); + } + + allocator_type get_allocator() const + { + return s_.get_allocator(); + } + }; + + // array_storage + class array_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + using array_allocator = typename std::allocator_traits:: template rebind_alloc; + using pointer = typename std::allocator_traits::pointer; + + pointer ptr_; + + template + void create(array_allocator alloc, Args&& ... args) + { + ptr_ = std::allocator_traits::allocate(alloc, 1); + JSONCONS_TRY + { + std::allocator_traits::construct(alloc, type_traits::to_plain_pointer(ptr_), std::forward(args)...); + } + JSONCONS_CATCH(...) + { + std::allocator_traits::deallocate(alloc, ptr_,1); + JSONCONS_RETHROW; + } + } + + void destroy() noexcept + { + array_allocator alloc(ptr_->get_allocator()); + std::allocator_traits::destroy(alloc, type_traits::to_plain_pointer(ptr_)); + std::allocator_traits::deallocate(alloc, ptr_,1); + } + public: + array_storage(const array& val, semantic_tag tag) + : storage_kind_(static_cast(json_storage_kind::array_value)), length_(0), tag_(tag) + { + create(val.get_allocator(), val); + } + + array_storage(array&& val, semantic_tag tag) + : storage_kind_(static_cast(json_storage_kind::array_value)), length_(0), tag_(tag) + { + create(val.get_allocator(), std::forward(val)); + } + + array_storage(const array& val, semantic_tag tag, const Allocator& a) + : storage_kind_(val.storage_kind_), length_(0), tag_(tag) + { + create(array_allocator(a), val, a); + } + + array_storage(const array_storage& val) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_) + { + create(val.ptr_->get_allocator(), *(val.ptr_)); + } + + array_storage(array_storage&& val) noexcept + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + ptr_(nullptr) + { + std::swap(val.ptr_, ptr_); + } + + array_storage(const array_storage& val, const Allocator& a) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_) + { + create(array_allocator(a), *(val.ptr_), a); + } + ~array_storage() noexcept + { + if (ptr_ != nullptr) + { + destroy(); + } + } + + allocator_type get_allocator() const + { + return ptr_->get_allocator(); + } + + void swap(array_storage& val) noexcept + { + std::swap(val.ptr_,ptr_); + } + + array& value() + { + return *ptr_; + } + + const array& value() const + { + return *ptr_; + } + }; + + // object_storage + class object_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + using object_allocator = typename std::allocator_traits:: template rebind_alloc; + using pointer = typename std::allocator_traits::pointer; + + pointer ptr_; + + template + void create(object_allocator alloc, Args&& ... args) + { + ptr_ = std::allocator_traits::allocate(alloc, 1); + JSONCONS_TRY + { + std::allocator_traits::construct(alloc, type_traits::to_plain_pointer(ptr_), std::forward(args)...); + } + JSONCONS_CATCH(...) + { + std::allocator_traits::deallocate(alloc, ptr_,1); + JSONCONS_RETHROW; + } + } + public: + explicit object_storage(const object& val, semantic_tag tag) + : storage_kind_(static_cast(json_storage_kind::object_value)), length_(0), tag_(tag) + { + create(val.get_allocator(), val); + } + + explicit object_storage(object&& val, semantic_tag tag) + : storage_kind_(static_cast(json_storage_kind::object_value)), length_(0), tag_(tag) + { + create(val.get_allocator(), std::forward(val)); + } + + explicit object_storage(const object& val, semantic_tag tag, const Allocator& a) + : storage_kind_(val.storage_kind_), length_(0), tag_(tag) + { + create(object_allocator(a), val, a); + } + + explicit object_storage(const object_storage& val) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_) + { + create(val.ptr_->get_allocator(), *(val.ptr_)); + } + + explicit object_storage(object_storage&& val) noexcept + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_), + ptr_(nullptr) + { + std::swap(val.ptr_,ptr_); + } + + explicit object_storage(const object_storage& val, const Allocator& a) + : storage_kind_(val.storage_kind_), length_(0), tag_(val.tag_) + { + create(object_allocator(a), *(val.ptr_), a); + } + + ~object_storage() noexcept + { + if (ptr_ != nullptr) + { + destroy(); + } + } + + void swap(object_storage& val) noexcept + { + std::swap(val.ptr_,ptr_); + } + + object& value() + { + return *ptr_; + } + + const object& value() const + { + return *ptr_; + } + + allocator_type get_allocator() const + { + return ptr_->get_allocator(); + } + private: + + void destroy() noexcept + { + object_allocator alloc(ptr_->get_allocator()); + std::allocator_traits::destroy(alloc, type_traits::to_plain_pointer(ptr_)); + std::allocator_traits::deallocate(alloc, ptr_,1); + } + }; + + class json_const_pointer_storage final + { + public: + uint8_t storage_kind_:4; + uint8_t length_:4; + semantic_tag tag_; + private: + const basic_json* p_; + public: + json_const_pointer_storage(const basic_json* p) + : storage_kind_(static_cast(json_storage_kind::json_const_pointer)), length_(0), tag_(p->tag()), + p_(p) + { + } + + const basic_json* value() const + { + return p_; + } + }; + + template + class proxy + { + friend class basic_json; + + ParentType& parent_; + string_view_type key_; + + proxy() = delete; + + proxy(const proxy& other) = default; + proxy(proxy&& other) = default; + proxy& operator = (const proxy& other) = delete; + proxy& operator = (proxy&& other) = delete; + + proxy(ParentType& parent, const string_view_type& key) + : parent_(parent), key_(key) + { + } + + basic_json& evaluate_with_default() + { + basic_json& val = parent_.evaluate_with_default(); + auto it = val.find(key_); + if (it == val.object_range().end()) + { + auto r = val.try_emplace(key_, json_object_arg, semantic_tag::none, val.object_value().get_allocator()); + return r.first->value(); + } + else + { + return it->value(); + } + } + + basic_json& evaluate(std::size_t index) + { + return evaluate().at(index); + } + + const basic_json& evaluate(std::size_t index) const + { + return evaluate().at(index); + } + + basic_json& evaluate(const string_view_type& index) + { + return evaluate().at(index); + } + + const basic_json& evaluate(const string_view_type& index) const + { + return evaluate().at(index); + } + public: + using proxied_type = basic_json; + using proxy_type = proxy; + + basic_json& evaluate() + { + return parent_.evaluate(key_); + } + + const basic_json& evaluate() const + { + return parent_.evaluate(key_); + } + + operator basic_json&() + { + return evaluate(); + } + + operator const basic_json&() const + { + return evaluate(); + } + + range object_range() + { + return evaluate().object_range(); + } + + range object_range() const + { + return evaluate().object_range(); + } + + range array_range() + { + return evaluate().array_range(); + } + + range array_range() const + { + return evaluate().array_range(); + } + + std::size_t size() const noexcept + { + if (!parent_.contains(key_)) + { + return 0; + } + return evaluate().size(); + } + + json_storage_kind storage_kind() const + { + return evaluate().storage_kind(); + } + + semantic_tag tag() const + { + return evaluate().tag(); + } + + json_type type() const + { + return evaluate().type(); + } + + std::size_t count(const string_view_type& name) const + { + return evaluate().count(name); + } + + allocator_type get_allocator() const + { + return evaluate().get_allocator(); + } + + uint64_t ext_tag() const + { + return evaluate().ext_tag(); + } + + bool contains(const string_view_type& key) const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + + return evaluate().contains(key); + } + + bool is_null() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_null(); + } + + bool empty() const noexcept + { + if (!parent_.contains(key_)) + { + return true; + } + return evaluate().empty(); + } + + std::size_t capacity() const + { + return evaluate().capacity(); + } + + void reserve(std::size_t n) + { + evaluate().reserve(n); + } + + void resize(std::size_t n) + { + evaluate().resize(n); + } + + template + void resize(std::size_t n, T val) + { + evaluate().resize(n,val); + } + + template + bool is(Args&&... args) const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().template is(std::forward(args)...); + } + + bool is_string() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_string(); + } + + bool is_string_view() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_string_view(); + } + + bool is_byte_string() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_byte_string(); + } + + bool is_byte_string_view() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_byte_string_view(); + } + + bool is_bignum() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_bignum(); + } + + bool is_number() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_number(); + } + bool is_bool() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_bool(); + } + + bool is_object() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_object(); + } + + bool is_array() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_array(); + } + + bool is_int64() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_int64(); + } + + bool is_uint64() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_uint64(); + } + + bool is_half() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_half(); + } + + bool is_double() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().is_double(); + } + + string_view_type as_string_view() const + { + return evaluate().as_string_view(); + } + + byte_string_view as_byte_string_view() const + { + return evaluate().as_byte_string_view(); + } + + template > + std::basic_string as_string() const + { + return evaluate().as_string(); + } + + template > + std::basic_string as_string(const SAllocator& alloc) const + { + return evaluate().as_string(alloc); + } + + template > + basic_byte_string as_byte_string() const + { + return evaluate().template as_byte_string(); + } + + template + typename std::enable_if::value,T>::type + as() const + { + return evaluate().template as(); + } + + template + typename std::enable_if::value,T>::type + as(byte_string_arg_t, semantic_tag hint) const + { + return evaluate().template as(byte_string_arg, hint); + } + + bool as_bool() const + { + return evaluate().as_bool(); + } + + double as_double() const + { + return evaluate().as_double(); + } + + template + T as_integer() const + { + return evaluate().template as_integer(); + } + + template + proxy& operator=(T&& val) + { + parent_.evaluate_with_default().insert_or_assign(key_, std::forward(val)); + return *this; + } + + basic_json& operator[](std::size_t i) + { + return evaluate_with_default().at(i); + } + + const basic_json& operator[](std::size_t i) const + { + return evaluate().at(i); + } + + proxy_type operator[](const string_view_type& key) + { + return proxy_type(*this,key); + } + + const basic_json& operator[](const string_view_type& name) const + { + return at(name); + } + + basic_json& at(const string_view_type& name) + { + return evaluate().at(name); + } + + const basic_json& at(const string_view_type& name) const + { + return evaluate().at(name); + } + + const basic_json& at_or_null(const string_view_type& name) const + { + return evaluate().at_or_null(name); + } + + const basic_json& at(std::size_t index) + { + return evaluate().at(index); + } + + const basic_json& at(std::size_t index) const + { + return evaluate().at(index); + } + + object_iterator find(const string_view_type& name) + { + return evaluate().find(name); + } + + const_object_iterator find(const string_view_type& name) const + { + return evaluate().find(name); + } + + template + T get_value_or(const string_view_type& name, U&& default_value) const + { + static_assert(std::is_copy_constructible::value, + "get_value_or: T must be copy constructible"); + static_assert(std::is_convertible::value, + "get_value_or: U must be convertible to T"); + return evaluate().template get_value_or(name,std::forward(default_value)); + } + + void shrink_to_fit() + { + evaluate_with_default().shrink_to_fit(); + } + + void clear() + { + evaluate().clear(); + } + // Remove all elements from an array or object + + object_iterator erase(const_object_iterator pos) + { + return evaluate().erase(pos); + } + // Remove a range of elements from an object + + object_iterator erase(const_object_iterator first, const_object_iterator last) + { + return evaluate().erase(first, last); + } + // Remove a range of elements from an object + + void erase(const string_view_type& name) + { + evaluate().erase(name); + } + + array_iterator erase(const_array_iterator pos) + { + return evaluate().erase(pos); + } + // Removes the element at pos + + array_iterator erase(const_array_iterator first, const_array_iterator last) + { + return evaluate().erase(first, last); + } + // Remove a range of elements from an array + + // merge + + void merge(const basic_json& source) + { + return evaluate().merge(source); + } + + void merge(basic_json&& source) + { + return evaluate().merge(std::forward(source)); + } + + void merge(object_iterator hint, const basic_json& source) + { + return evaluate().merge(hint, source); + } + + void merge(object_iterator hint, basic_json&& source) + { + return evaluate().merge(hint, std::forward(source)); + } + + // merge_or_update + + void merge_or_update(const basic_json& source) + { + return evaluate().merge_or_update(source); + } + + void merge_or_update(basic_json&& source) + { + return evaluate().merge_or_update(std::forward(source)); + } + + void merge_or_update(object_iterator hint, const basic_json& source) + { + return evaluate().merge_or_update(hint, source); + } + + void merge_or_update(object_iterator hint, basic_json&& source) + { + return evaluate().merge_or_update(hint, std::forward(source)); + } + + template + std::pair insert_or_assign(const string_view_type& name, T&& val) + { + return evaluate().insert_or_assign(name,std::forward(val)); + } + + // emplace + + template + std::pair try_emplace(const string_view_type& name, Args&&... args) + { + return evaluate().try_emplace(name,std::forward(args)...); + } + + template + object_iterator insert_or_assign(object_iterator hint, const string_view_type& name, T&& val) + { + return evaluate().insert_or_assign(hint, name, std::forward(val)); + } + + template + object_iterator try_emplace(object_iterator hint, const string_view_type& name, Args&&... args) + { + return evaluate().try_emplace(hint, name, std::forward(args)...); + } + + template + array_iterator emplace(const_array_iterator pos, Args&&... args) + { + evaluate_with_default().emplace(pos, std::forward(args)...); + } + + template + basic_json& emplace_back(Args&&... args) + { + return evaluate_with_default().emplace_back(std::forward(args)...); + } + + template + void push_back(T&& val) + { + evaluate_with_default().push_back(std::forward(val)); + } + + template + array_iterator insert(const_array_iterator pos, T&& val) + { + return evaluate_with_default().insert(pos, std::forward(val)); + } + + template + array_iterator insert(const_array_iterator pos, InputIt first, InputIt last) + { + return evaluate_with_default().insert(pos, first, last); + } + + template + void insert(InputIt first, InputIt last) + { + evaluate_with_default().insert(first, last); + } + + template + void insert(sorted_unique_range_tag tag, InputIt first, InputIt last) + { + evaluate_with_default().insert(tag, first, last); + } + + template + void dump(Args&& ... args) const + { + evaluate().dump(std::forward(args)...); + } + + template + void dump_pretty(Args&& ... args) const + { + evaluate().dump_pretty(std::forward(args)...); + } + + void swap(basic_json& val) + { + evaluate_with_default().swap(val); + } + + friend std::basic_ostream& operator<<(std::basic_ostream& os, const proxy& o) + { + o.dump(os); + return os; + } + + template + T get_with_default(const string_view_type& name, const T& default_value) const + { + return evaluate().template get_with_default(name,default_value); + } + + template > + T get_with_default(const string_view_type& name, const char_type* default_value) const + { + return evaluate().template get_with_default(name,default_value); + } + + std::basic_string to_string() const + { + return evaluate().to_string(); + } + + template + bool is_integer() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().template is_integer(); + } + + #if !defined(JSONCONS_NO_DEPRECATED) + + const basic_json& get_with_default(const string_view_type& name) const + { + return evaluate().at_or_null(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use tag()") + semantic_tag get_semantic_tag() const + { + return evaluate().tag(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use tag() == semantic_tag::datetime") + bool is_datetime() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().tag() == semantic_tag::datetime; + } + + JSONCONS_DEPRECATED_MSG("Instead, use tag() == semantic_tag::epoch_second") + bool is_epoch_time() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().tag() == semantic_tag::epoch_second; + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use push_back(T&&)") + void add(T&& val) + { + evaluate_with_default().push_back(std::forward(val)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use insert(const_array_iterator, T&&)") + array_iterator add(const_array_iterator pos, T&& val) + { + return evaluate_with_default().insert(pos, std::forward(val)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use insert_or_assign(const string_view_type&, T&&)") + std::pair set(const string_view_type& name, T&& val) + { + return evaluate().insert_or_assign(name,std::forward(val)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use insert_or_assign(object_iterator, const string_view_type&, T&&)") + object_iterator set(object_iterator hint, const string_view_type& name, T&& val) + { + return evaluate().insert_or_assign(hint, name, std::forward(val)); + } + + JSONCONS_DEPRECATED_MSG("Instead, use contains(const string_view_type&)") + bool has_key(const string_view_type& name) const noexcept + { + return contains(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use is()") + bool is_ulonglong() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().template is(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use is()") + bool is_longlong() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return evaluate().template is(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + int as_int() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + unsigned int as_uint() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + long as_long() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + unsigned long as_ulong() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + long long as_longlong() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + unsigned long long as_ulonglong() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + uint64_t as_uinteger() const + { + return evaluate().template as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void write(basic_json_visitor& visitor) const + { + evaluate().dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&)") + void write(std::basic_ostream& os) const + { + evaluate().dump(os); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&)") + void write(std::basic_ostream& os, const basic_json_encode_options& options) const + { + evaluate().dump(os, options); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump_pretty(std::basic_ostream&, const basic_json_encode_options&)") + void write(std::basic_ostream& os, const basic_json_encode_options& options, bool pprint) const + { + if (pprint) + { + evaluate().dump_pretty(os, options); + } + else + { + evaluate().dump(os, options); + } + } + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void to_stream(basic_json_visitor& visitor) const + { + evaluate().dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&)") + void to_stream(std::basic_ostream& os) const + { + evaluate().dump(os); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&)") + void to_stream(std::basic_ostream& os, const basic_json_encode_options& options) const + { + evaluate().dump(os,options); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump_pretty(std::basic_ostream&, const basic_json_encode_options&)") + void to_stream(std::basic_ostream& os, const basic_json_encode_options& options, bool pprint) const + { + if (pprint) + { + evaluate().dump_pretty(os,options); + } + else + { + evaluate().dump(os,options); + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use resize(std::size_t)") + void resize_array(std::size_t n) + { + evaluate().resize(n); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use resize(std::size_t, T)") + void resize_array(std::size_t n, T val) + { + evaluate().resize(n,val); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range()") + range members() + { + return evaluate().object_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range()") + range members() const + { + return evaluate().object_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range()") + range elements() + { + return evaluate().array_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range()") + range elements() const + { + return evaluate().array_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().begin()") + object_iterator begin_members() + { + return evaluate().object_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().begin()") + const_object_iterator begin_members() const + { + return evaluate().object_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().end()") + object_iterator end_members() + { + return evaluate().object_range().end(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().end()") + const_object_iterator end_members() const + { + return evaluate().object_range().end(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().begin()") + array_iterator begin_elements() + { + return evaluate().array_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().begin()") + const_array_iterator begin_elements() const + { + return evaluate().array_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().end()") + array_iterator end_elements() + { + return evaluate().array_range().end(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().end()") + const_array_iterator end_elements() const + { + return evaluate().array_range().end(); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use get_with_default(const string_view_type&, T&&)") + basic_json get(const string_view_type& name, T&& default_value) const + { + return evaluate().get_with_default(name,std::forward(default_value)); + } + + JSONCONS_DEPRECATED_MSG("Instead, use at_or_null(const string_view_type&)") + const basic_json& get(const string_view_type& name) const + { + return evaluate().at_or_null(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use contains(const string_view_type&)") + bool has_member(const string_view_type& name) const noexcept + { + return contains(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use erase(const_object_iterator, const_object_iterator)") + void remove_range(std::size_t from_index, std::size_t to_index) + { + evaluate().remove_range(from_index, to_index); + } + JSONCONS_DEPRECATED_MSG("Instead, use erase(const string_view_type& name)") + void remove(const string_view_type& name) + { + evaluate().remove(name); + } + JSONCONS_DEPRECATED_MSG("Instead, use erase(const string_view_type& name)") + void remove_member(const string_view_type& name) + { + evaluate().remove(name); + } + JSONCONS_DEPRECATED_MSG("Instead, use empty()") + bool is_empty() const noexcept + { + return empty(); + } + JSONCONS_DEPRECATED_MSG("Instead, use is_number()") + bool is_numeric() const noexcept + { + if (!parent_.contains(key_)) + { + return false; + } + return is_number(); + } + #endif + }; + + using proxy_type = proxy; + + union + { + common_storage common_stor_; + null_storage null_stor_; + bool_storage bool_stor_; + int64_storage int64_stor_; + uint64_storage uint64_stor_; + half_storage half_stor_; + double_storage double_stor_; + short_string_storage short_string_stor_; + long_string_storage long_string_stor_; + byte_string_storage byte_string_stor_; + array_storage array_stor_; + object_storage object_stor_; + empty_object_storage empty_object_stor_; + json_const_pointer_storage json_const_pointer_stor_; + }; + + void Destroy_() + { + switch (storage_kind()) + { + case json_storage_kind::long_string_value: + destroy_var(); + break; + case json_storage_kind::byte_string_value: + destroy_var(); + break; + case json_storage_kind::array_value: + destroy_var(); + break; + case json_storage_kind::object_value: + destroy_var(); + break; + default: + break; + } + } + + template + void construct(Args&&... args) + { + ::new (&cast()) VariantType(std::forward(args)...); + } + + template + void destroy_var() + { + cast().~T(); + } + + template + struct identity { using type = T*; }; + + template + T& cast() + { + return cast(identity()); + } + + template + const T& cast() const + { + return cast(identity()); + } + + null_storage& cast(identity) + { + return null_stor_; + } + + const null_storage& cast(identity) const + { + return null_stor_; + } + + empty_object_storage& cast(identity) + { + return empty_object_stor_; + } + + const empty_object_storage& cast(identity) const + { + return empty_object_stor_; + } + + bool_storage& cast(identity) + { + return bool_stor_; + } + + const bool_storage& cast(identity) const + { + return bool_stor_; + } + + int64_storage& cast(identity) + { + return int64_stor_; + } + + const int64_storage& cast(identity) const + { + return int64_stor_; + } + + uint64_storage& cast(identity) + { + return uint64_stor_; + } + + const uint64_storage& cast(identity) const + { + return uint64_stor_; + } + + half_storage& cast(identity) + { + return half_stor_; + } + + const half_storage& cast(identity) const + { + return half_stor_; + } + + double_storage& cast(identity) + { + return double_stor_; + } + + const double_storage& cast(identity) const + { + return double_stor_; + } + + short_string_storage& cast(identity) + { + return short_string_stor_; + } + + const short_string_storage& cast(identity) const + { + return short_string_stor_; + } + + long_string_storage& cast(identity) + { + return long_string_stor_; + } + + const long_string_storage& cast(identity) const + { + return long_string_stor_; + } + + byte_string_storage& cast(identity) + { + return byte_string_stor_; + } + + const byte_string_storage& cast(identity) const + { + return byte_string_stor_; + } + + object_storage& cast(identity) + { + return object_stor_; + } + + const object_storage& cast(identity) const + { + return object_stor_; + } + + array_storage& cast(identity) + { + return array_stor_; + } + + const array_storage& cast(identity) const + { + return array_stor_; + } + + json_const_pointer_storage& cast(identity) + { + return json_const_pointer_stor_; + } + + const json_const_pointer_storage& cast(identity) const + { + return json_const_pointer_stor_; + } + + template + void swap_a_b(basic_json& other) + { + TypeA& curA = cast(); + TypeB& curB = other.cast(); + TypeB tmpB(std::move(curB)); + other.construct(std::move(curA)); + construct(std::move(tmpB)); + } + + template + void swap_a(basic_json& other) + { + switch (other.storage_kind()) + { + case json_storage_kind::null_value : swap_a_b(other); break; + case json_storage_kind::empty_object_value : swap_a_b(other); break; + case json_storage_kind::bool_value : swap_a_b(other); break; + case json_storage_kind::int64_value : swap_a_b(other); break; + case json_storage_kind::uint64_value : swap_a_b(other); break; + case json_storage_kind::half_value : swap_a_b(other); break; + case json_storage_kind::double_value : swap_a_b(other); break; + case json_storage_kind::short_string_value : swap_a_b(other); break; + case json_storage_kind::long_string_value : swap_a_b(other); break; + case json_storage_kind::byte_string_value : swap_a_b(other); break; + case json_storage_kind::array_value : swap_a_b(other); break; + case json_storage_kind::object_value : swap_a_b(other); break; + case json_storage_kind::json_const_pointer : swap_a_b(other); break; + default: + JSONCONS_UNREACHABLE(); + break; + } + } + + void Init_(const basic_json& val) + { + switch (val.storage_kind()) + { + case json_storage_kind::null_value: + construct(val.cast()); + break; + case json_storage_kind::empty_object_value: + construct(val.cast()); + break; + case json_storage_kind::bool_value: + construct(val.cast()); + break; + case json_storage_kind::int64_value: + construct(val.cast()); + break; + case json_storage_kind::uint64_value: + construct(val.cast()); + break; + case json_storage_kind::half_value: + construct(val.cast()); + break; + case json_storage_kind::double_value: + construct(val.cast()); + break; + case json_storage_kind::short_string_value: + construct(val.cast()); + break; + case json_storage_kind::long_string_value: + construct(val.cast()); + break; + case json_storage_kind::byte_string_value: + construct(val.cast()); + break; + case json_storage_kind::object_value: + construct(val.cast()); + break; + case json_storage_kind::array_value: + construct(val.cast()); + break; + case json_storage_kind::json_const_pointer: + construct(val.cast()); + break; + default: + break; + } + } + + void Init_(const basic_json& val, const Allocator& a) + { + switch (val.storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + case json_storage_kind::bool_value: + case json_storage_kind::int64_value: + case json_storage_kind::uint64_value: + case json_storage_kind::half_value: + case json_storage_kind::double_value: + case json_storage_kind::short_string_value: + case json_storage_kind::json_const_pointer: + Init_(val); + break; + case json_storage_kind::long_string_value: + construct(val.cast(),a); + break; + case json_storage_kind::byte_string_value: + construct(val.cast(),a); + break; + case json_storage_kind::array_value: + construct(val.cast(),a); + break; + case json_storage_kind::object_value: + construct(val.cast(),a); + break; + default: + break; + } + } + + void Init_rv_(basic_json&& val) noexcept + { + switch (val.storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + case json_storage_kind::half_value: + case json_storage_kind::double_value: + case json_storage_kind::int64_value: + case json_storage_kind::uint64_value: + case json_storage_kind::bool_value: + case json_storage_kind::short_string_value: + case json_storage_kind::json_const_pointer: + Init_(val); + break; + case json_storage_kind::long_string_value: + case json_storage_kind::byte_string_value: + case json_storage_kind::array_value: + case json_storage_kind::object_value: + { + construct(); + swap(val); + break; + } + default: + JSONCONS_UNREACHABLE(); + break; + } + } + + void Init_rv_(basic_json&& val, const Allocator&, std::true_type) noexcept + { + Init_rv_(std::forward(val)); + } + + void Init_rv_(basic_json&& val, const Allocator& a, std::false_type) noexcept + { + switch (val.storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + case json_storage_kind::half_value: + case json_storage_kind::double_value: + case json_storage_kind::int64_value: + case json_storage_kind::uint64_value: + case json_storage_kind::bool_value: + case json_storage_kind::short_string_value: + case json_storage_kind::json_const_pointer: + Init_(std::forward(val)); + break; + case json_storage_kind::long_string_value: + { + if (a == val.cast().get_allocator()) + { + Init_rv_(std::forward(val), a, std::true_type()); + } + else + { + Init_(val,a); + } + break; + } + case json_storage_kind::byte_string_value: + { + if (a == val.cast().get_allocator()) + { + Init_rv_(std::forward(val), a, std::true_type()); + } + else + { + Init_(val,a); + } + break; + } + case json_storage_kind::object_value: + { + if (a == val.cast().get_allocator()) + { + Init_rv_(std::forward(val), a, std::true_type()); + } + else + { + Init_(val,a); + } + break; + } + case json_storage_kind::array_value: + { + if (a == val.cast().get_allocator()) + { + Init_rv_(std::forward(val), a, std::true_type()); + } + else + { + Init_(val,a); + } + break; + } + default: + break; + } + } + + basic_json& evaluate_with_default() + { + return *this; + } + + basic_json& evaluate(const string_view_type& name) + { + return at(name); + } + + const basic_json& evaluate(const string_view_type& name) const + { + return at(name); + } + + public: + + basic_json& evaluate() + { + return *this; + } + + const basic_json& evaluate() const + { + return *this; + } + + basic_json& operator=(const basic_json& val) + { + if (this != &val) + { + Destroy_(); + Init_(val); + } + return *this; + } + + basic_json& operator=(basic_json&& val) noexcept + { + if (this !=&val) + { + swap(val); + } + return *this; + } + + json_storage_kind storage_kind() const + { + // It is legal to access 'common_stor_.storage_kind_' even though + // common_stor_ is not the active member of the union because 'storage_kind_' + // is a part of the common initial sequence of all union members + // as defined in 11.4-25 of the Standard. + return static_cast(common_stor_.storage_kind_); + } + + json_type type() const + { + switch(storage_kind()) + { + case json_storage_kind::null_value: + return json_type::null_value; + case json_storage_kind::bool_value: + return json_type::bool_value; + case json_storage_kind::int64_value: + return json_type::int64_value; + case json_storage_kind::uint64_value: + return json_type::uint64_value; + case json_storage_kind::half_value: + return json_type::half_value; + case json_storage_kind::double_value: + return json_type::double_value; + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + return json_type::string_value; + case json_storage_kind::byte_string_value: + return json_type::byte_string_value; + case json_storage_kind::array_value: + return json_type::array_value; + case json_storage_kind::empty_object_value: + case json_storage_kind::object_value: + return json_type::object_value; + case json_storage_kind::json_const_pointer: + return cast().value()->type(); + default: + JSONCONS_UNREACHABLE(); + break; + } + } + + semantic_tag tag() const + { + // It is legal to access 'common_stor_.tag_' even though + // common_stor_ is not the active member of the union because 'tag_' + // is a part of the common initial sequence of all union members + // as defined in 11.4-25 of the Standard. + switch(storage_kind()) + { + case json_storage_kind::json_const_pointer: + return cast().value()->tag(); + default: + return common_stor_.tag_; + } + } + + std::size_t size() const + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return cast().value().size(); + case json_storage_kind::empty_object_value: + return 0; + case json_storage_kind::object_value: + return cast().value().size(); + case json_storage_kind::json_const_pointer: + return cast().value()->size(); + default: + return 0; + } + } + + string_view_type as_string_view() const + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + return string_view_type(cast().data(),cast().length()); + case json_storage_kind::long_string_value: + return string_view_type(cast().data(),cast().length()); + case json_storage_kind::json_const_pointer: + return cast().value()->as_string_view(); + default: + JSONCONS_THROW(json_runtime_error("Not a string")); + } + } + + template > + basic_byte_string as_byte_string() const + { + using byte_string_type = basic_byte_string; + converter convert; + std::error_code ec; + + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + byte_string_type v = convert.from(as_string_view(),tag(),ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + return v; + } + case json_storage_kind::byte_string_value: + return basic_byte_string(cast().data(),cast().length()); + case json_storage_kind::json_const_pointer: + return cast().value()->as_byte_string(); + default: + JSONCONS_THROW(json_runtime_error("Not a byte string")); + } + } + + byte_string_view as_byte_string_view() const + { + switch (storage_kind()) + { + case json_storage_kind::byte_string_value: + return byte_string_view(cast().data(),cast().length()); + case json_storage_kind::json_const_pointer: + return cast().value()->as_byte_string_view(); + default: + JSONCONS_THROW(json_runtime_error("Not a byte string")); + } + } + + int compare(const basic_json& rhs) const noexcept + { + if (this == &rhs) + { + return 0; + } + switch (storage_kind()) + { + case json_storage_kind::json_const_pointer: + switch (rhs.storage_kind()) + { + case json_storage_kind::json_const_pointer: + return (cast().value())->compare(*(rhs.cast().value())); + default: + return (cast().value())->compare(rhs); + } + break; + case json_storage_kind::null_value: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + case json_storage_kind::empty_object_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::empty_object_value: + return 0; + case json_storage_kind::object_value: + return rhs.empty() ? 0 : -1; + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::bool_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::bool_value: + return static_cast(cast().value()) - static_cast(rhs.cast().value()); + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::int64_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::int64_value: + { + if (cast().value() == rhs.cast().value()) + return 0; + return cast().value() < rhs.cast().value() ? -1 : 1; + } + case json_storage_kind::uint64_value: + if (cast().value() < 0) + return -1; + else if (static_cast(cast().value()) == rhs.cast().value()) + return 0; + else + return static_cast(cast().value()) < rhs.cast().value() ? -1 : 1; + case json_storage_kind::double_value: + { + double r = static_cast(cast().value()) - rhs.cast().value(); + return r == 0.0 ? 0 : (r < 0.0 ? -1 : 1); + } + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::uint64_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::int64_value: + if (rhs.cast().value() < 0) + return 1; + else if (cast().value() == static_cast(rhs.cast().value())) + return 0; + else + return cast().value() < static_cast(rhs.cast().value()) ? -1 : 1; + case json_storage_kind::uint64_value: + if (cast().value() == static_cast(rhs.cast().value())) + return 0; + else + return cast().value() < static_cast(rhs.cast().value()) ? -1 : 1; + case json_storage_kind::double_value: + { + auto r = static_cast(cast().value()) - rhs.cast().value(); + return r == 0 ? 0 : (r < 0.0 ? -1 : 1); + } + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::double_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::int64_value: + { + auto r = cast().value() - static_cast(rhs.cast().value()); + return r == 0 ? 0 : (r < 0.0 ? -1 : 1); + } + case json_storage_kind::uint64_value: + { + auto r = cast().value() - static_cast(rhs.cast().value()); + return r == 0 ? 0 : (r < 0.0 ? -1 : 1); + } + case json_storage_kind::double_value: + { + auto r = cast().value() - rhs.cast().value(); + return r == 0 ? 0 : (r < 0.0 ? -1 : 1); + } + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::short_string_value: + return as_string_view().compare(rhs.as_string_view()); + case json_storage_kind::long_string_value: + return as_string_view().compare(rhs.as_string_view()); + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::byte_string_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::byte_string_value: + { + return as_byte_string_view().compare(rhs.as_byte_string_view()); + } + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::array_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::array_value: + { + if (cast().value() == rhs.cast().value()) + return 0; + else + return cast().value() < rhs.cast().value() ? -1 : 1; + } + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + case json_storage_kind::object_value: + switch (rhs.storage_kind()) + { + case json_storage_kind::empty_object_value: + return empty() ? 0 : 1; + case json_storage_kind::object_value: + { + if (cast().value() == rhs.cast().value()) + return 0; + else + return cast().value() < rhs.cast().value() ? -1 : 1; + } + case json_storage_kind::json_const_pointer: + return compare(*(rhs.cast().value())); + default: + return static_cast(storage_kind()) - static_cast((int)rhs.storage_kind()); + } + break; + default: + JSONCONS_UNREACHABLE(); + break; + } + } + + void swap(basic_json& other) noexcept + { + if (this == &other) + { + return; + } + + switch (storage_kind()) + { + case json_storage_kind::null_value: swap_a(other); break; + case json_storage_kind::empty_object_value : swap_a(other); break; + case json_storage_kind::bool_value: swap_a(other); break; + case json_storage_kind::int64_value: swap_a(other); break; + case json_storage_kind::uint64_value: swap_a(other); break; + case json_storage_kind::half_value: swap_a(other); break; + case json_storage_kind::double_value: swap_a(other); break; + case json_storage_kind::short_string_value: swap_a(other); break; + case json_storage_kind::long_string_value: swap_a(other); break; + case json_storage_kind::byte_string_value: swap_a(other); break; + case json_storage_kind::array_value: swap_a(other); break; + case json_storage_kind::object_value: swap_a(other); break; + case json_storage_kind::json_const_pointer: swap_a(other); break; + default: + JSONCONS_UNREACHABLE(); + break; + } + } + // from string + + template + static + typename std::enable_if::value,basic_json>::type + parse(const Source& s, + const basic_json_decode_options& options = basic_json_decode_options(), + std::function err_handler = default_json_parsing()) + { + json_decoder decoder; + basic_json_parser parser(options,err_handler); + + auto r = unicode_traits::detect_encoding_from_bom(s.data(), s.size()); + if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected)) + { + JSONCONS_THROW(ser_error(json_errc::illegal_unicode_character,parser.line(),parser.column())); + } + std::size_t offset = (r.ptr - s.data()); + parser.update(s.data()+offset,s.size()-offset); + parser.parse_some(decoder); + parser.finish_parse(decoder); + parser.check_done(); + if (!decoder.is_valid()) + { + JSONCONS_THROW(ser_error(json_errc::source_error, "Failed to parse json string")); + } + return decoder.get_result(); + } + + template + static + typename std::enable_if::value,basic_json>::type + parse(const Source& s, + std::function err_handler) + { + return parse(s, basic_json_decode_options(), err_handler); + } + + static basic_json parse(const char_type* s, + const basic_json_decode_options& options = basic_json_decode_options(), + std::function err_handler = default_json_parsing()) + { + return parse(jsoncons::basic_string_view(s), options, err_handler); + } + + static basic_json parse(const char_type* s, + std::function err_handler) + { + return parse(jsoncons::basic_string_view(s), basic_json_decode_options(), err_handler); + } + + // from stream + + static basic_json parse(std::basic_istream& is, + const basic_json_decode_options& options = basic_json_decode_options(), + std::function err_handler = default_json_parsing()) + { + json_decoder visitor; + basic_json_reader> reader(is, visitor, options, err_handler); + reader.read_next(); + reader.check_done(); + if (!visitor.is_valid()) + { + JSONCONS_THROW(ser_error(json_errc::source_error, "Failed to parse json stream")); + } + return visitor.get_result(); + } + + static basic_json parse(std::basic_istream& is, std::function err_handler) + { + return parse(is, basic_json_decode_options(), err_handler); + } + + // from iterator + + template + static basic_json parse(InputIt first, InputIt last, + const basic_json_decode_options& options = basic_json_decode_options(), + std::function err_handler = default_json_parsing()) + { + json_decoder visitor; + basic_json_reader> reader(iterator_source(std::forward(first),std::forward(last)), visitor, options, err_handler); + reader.read_next(); + reader.check_done(); + if (!visitor.is_valid()) + { + JSONCONS_THROW(ser_error(json_errc::source_error, "Failed to parse json from iterator pair")); + } + return visitor.get_result(); + } + + template + static basic_json parse(InputIt first, InputIt last, + std::function err_handler) + { + return parse(first, last, basic_json_decode_options(), err_handler); + } + + static basic_json make_array() + { + return basic_json(array()); + } + + static basic_json make_array(const array& a) + { + return basic_json(a); + } + + static basic_json make_array(const array& a, allocator_type alloc) + { + return basic_json(a, semantic_tag::none, alloc); + } + + static basic_json make_array(std::initializer_list init, const Allocator& alloc = Allocator()) + { + return array(std::move(init),alloc); + } + + static basic_json make_array(std::size_t n, const Allocator& alloc = Allocator()) + { + return array(n,alloc); + } + + template + static basic_json make_array(std::size_t n, const T& val, const Allocator& alloc = Allocator()) + { + return basic_json::array(n, val,alloc); + } + + template + static typename std::enable_if::type make_array(std::size_t n) + { + return array(n); + } + + template + static typename std::enable_if::type make_array(std::size_t n, const T& val, const Allocator& alloc = Allocator()) + { + return array(n,val,alloc); + } + + template + static typename std::enable_if<(dim>1),basic_json>::type make_array(std::size_t n, Args... args) + { + const size_t dim1 = dim - 1; + + basic_json val = make_array(std::forward(args)...); + val.resize(n); + for (std::size_t i = 0; i < n; ++i) + { + val[i] = make_array(std::forward(args)...); + } + return val; + } + + static const basic_json& null() + { + static const basic_json a_null = basic_json(null_type(), semantic_tag::none); + return a_null; + } + + basic_json() + { + construct(semantic_tag::none); + } + + basic_json(semantic_tag tag) + { + construct(tag); + } + + #if !defined(JSONCONS_NO_DEPRECATED) + + JSONCONS_DEPRECATED_MSG("Instead, use basic_json(json_object_t,semantic_tag,const Allocator&)") + explicit basic_json(const Allocator& alloc, semantic_tag tag = semantic_tag::none) + { + construct(object(alloc), tag); + } + + #endif + + basic_json(const basic_json& other) + { + Init_(other); + } + + basic_json(const basic_json& other, const Allocator& alloc) + { + Init_(other,alloc); + } + + basic_json(basic_json&& other) noexcept + { + Init_rv_(std::forward(other)); + } + + basic_json(basic_json&& other, const Allocator&) noexcept + { + Init_rv_(std::forward(other)); + } + + explicit basic_json(json_object_arg_t, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator()) + { + construct(object(alloc), tag); + } + + template + basic_json(json_object_arg_t, + InputIt first, InputIt last, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator()) + { + construct(object(first,last,alloc), tag); + } + + basic_json(json_object_arg_t, + std::initializer_list,basic_json>> init, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator()) + { + construct(object(init,alloc), tag); + } + + explicit basic_json(json_array_arg_t, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator()) + { + construct(array(alloc), tag); + } + + template + basic_json(json_array_arg_t, + InputIt first, InputIt last, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator()) + { + construct(array(first,last,alloc), tag); + } + + basic_json(json_array_arg_t, + std::initializer_list init, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator()) + { + construct(array(init,alloc), tag); + } + + basic_json(json_const_pointer_arg_t, const basic_json* p) noexcept + { + if (p == nullptr) + { + construct(semantic_tag::none); + } + else + { + construct(p); + } + } + + basic_json(const array& val, semantic_tag tag = semantic_tag::none) + { + construct(val, tag); + } + + basic_json(array&& val, semantic_tag tag = semantic_tag::none) + { + construct(std::forward(val), tag); + } + + basic_json(const object& val, semantic_tag tag = semantic_tag::none) + { + construct(val, tag); + } + + basic_json(object&& val, semantic_tag tag = semantic_tag::none) + { + construct(std::forward(val), tag); + } + + template ::value && !type_traits::is_basic_json::value>::type> + basic_json(const T& val) + : basic_json(json_type_traits::to_json(val)) + { + } + + template ::value && !type_traits::is_basic_json::value>::type> + basic_json(const T& val, const Allocator& alloc) + : basic_json(json_type_traits::to_json(val,alloc)) + { + } + + basic_json(const char_type* s, semantic_tag tag = semantic_tag::none) + : basic_json(s, char_traits_type::length(s), tag) + { + } + + basic_json(const char_type* s, const Allocator& alloc) + : basic_json(s, char_traits_type::length(s), semantic_tag::none, alloc) + { + } + + basic_json(const char_type* s, std::size_t length, semantic_tag tag = semantic_tag::none) + { + if (length <= short_string_storage::max_length) + { + construct(tag, s, static_cast(length)); + } + else + { + construct(tag, s, length, char_allocator_type()); + } + } + + basic_json(const char_type* s, std::size_t length, semantic_tag tag, const Allocator& alloc) + { + if (length <= short_string_storage::max_length) + { + construct(tag, s, static_cast(length)); + } + else + { + construct(tag, s, length, alloc); + } + } + + basic_json(half_arg_t, uint16_t val, semantic_tag tag = semantic_tag::none) + { + construct(val, tag); + } + + basic_json(double val, semantic_tag tag) + { + construct(val, tag); + } + + template + basic_json(IntegerType val, semantic_tag tag, + typename std::enable_if::value && sizeof(IntegerType) <= sizeof(uint64_t), int>::type = 0) + { + construct(val, tag); + } + + template + basic_json(IntegerType val, semantic_tag tag, Allocator, + typename std::enable_if::value && sizeof(IntegerType) <= sizeof(uint64_t), int>::type = 0) + { + construct(val, tag); + } + + template + basic_json(IntegerType val, semantic_tag, Allocator alloc = Allocator(), + typename std::enable_if::value && sizeof(uint64_t) < sizeof(IntegerType), int>::type = 0) + { + std::basic_string s; + jsoncons::detail::from_integer(val, s); + if (s.length() <= short_string_storage::max_length) + { + construct(semantic_tag::bigint, s.data(), static_cast(s.length())); + } + else + { + construct(semantic_tag::bigint, s.data(), s.length(), alloc); + } + } + + template + basic_json(IntegerType val, semantic_tag tag, + typename std::enable_if::value && sizeof(IntegerType) <= sizeof(int64_t),int>::type = 0) + { + construct(val, tag); + } + + template + basic_json(IntegerType val, semantic_tag tag, Allocator, + typename std::enable_if::value && sizeof(IntegerType) <= sizeof(int64_t),int>::type = 0) + { + construct(val, tag); + } + + template + basic_json(IntegerType val, semantic_tag, Allocator alloc = Allocator(), + typename std::enable_if::value && sizeof(int64_t) < sizeof(IntegerType),int>::type = 0) + { + std::basic_string s; + jsoncons::detail::from_integer(val, s); + if (s.length() <= short_string_storage::max_length) + { + construct(semantic_tag::bigint, s.data(), static_cast(s.length())); + } + else + { + construct(semantic_tag::bigint, s.data(), s.length(), alloc); + } + } + + basic_json(const string_view_type& sv, semantic_tag tag) + : basic_json(sv.data(), sv.length(), tag) + { + } + + basic_json(null_type, semantic_tag tag) + { + construct(tag); + } + + basic_json(bool val, semantic_tag tag) + { + construct(val,tag); + } + + basic_json(const string_view_type& sv, semantic_tag tag, const Allocator& alloc) + : basic_json(sv.data(), sv.length(), tag, alloc) + { + } + + template + basic_json(byte_string_arg_t, const Source& source, + semantic_tag tag = semantic_tag::none, + const Allocator& alloc = Allocator(), + typename std::enable_if::value,int>::type = 0) + { + auto bytes = jsoncons::span(reinterpret_cast(source.data()), source.size()); + construct(tag, bytes.data(), bytes.size(), 0, alloc); + } + + template + basic_json(byte_string_arg_t, const Source& source, + uint64_t ext_tag, + const Allocator& alloc = Allocator(), + typename std::enable_if::value,int>::type = 0) + { + auto bytes = jsoncons::span(reinterpret_cast(source.data()), source.size()); + construct(semantic_tag::ext, bytes.data(), bytes.size(), ext_tag, alloc); + } + + ~basic_json() noexcept + { + Destroy_(); + } + + template + basic_json& operator=(const T& val) + { + *this = json_type_traits::to_json(val); + return *this; + } + + basic_json& operator=(const char_type* s) + { + *this = basic_json(s, char_traits_type::length(s), semantic_tag::none); + return *this; + } + + basic_json& operator[](std::size_t i) + { + return at(i); + } + + const basic_json& operator[](std::size_t i) const + { + return at(i); + } + + proxy_type operator[](const string_view_type& name) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + return proxy_type(*this, name); + break; + default: + JSONCONS_THROW(not_an_object(name.data(),name.length())); + break; + } + } + + const basic_json& operator[](const string_view_type& name) const + { + return at(name); + } + + + template + typename std::enable_if::value>::type + dump(Container& s, + const basic_json_encode_options& options = basic_json_encode_options()) const + { + std::error_code ec; + dump(s, options, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + template + typename std::enable_if::value>::type + dump_pretty(Container& s, + const basic_json_encode_options& options = basic_json_encode_options()) const + { + std::error_code ec; + dump_pretty(s, options, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + void dump(std::basic_ostream& os, + const basic_json_encode_options& options = basic_json_encode_options()) const + { + std::error_code ec; + dump(os, options, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + void dump_pretty(std::basic_ostream& os, + const basic_json_encode_options& options = basic_json_encode_options()) const + { + std::error_code ec; + dump_pretty(os, options, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + // Legacy + + template + typename std::enable_if::value>::type + dump(Container& s, + indenting line_indent) const + { + std::error_code ec; + + dump(s, line_indent, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + template + typename std::enable_if::value>::type + dump(Container& s, + const basic_json_encode_options& options, + indenting line_indent) const + { + std::error_code ec; + + dump(s, options, line_indent, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + void dump(std::basic_ostream& os, + indenting line_indent) const + { + std::error_code ec; + + dump(os, line_indent, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + void dump(std::basic_ostream& os, + const basic_json_encode_options& options, + indenting line_indent) const + { + std::error_code ec; + + dump(os, options, line_indent, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + // end legacy + + void dump(basic_json_visitor& visitor) const + { + std::error_code ec; + dump(visitor, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + } + + // dump + template + typename std::enable_if::value>::type + dump(Container& s, + const basic_json_encode_options& options, + std::error_code& ec) const + { + basic_compact_json_encoder> encoder(s, options); + dump(encoder, ec); + } + + template + typename std::enable_if::value>::type + dump(Container& s, + std::error_code& ec) const + { + basic_compact_json_encoder> encoder(s); + dump(encoder, ec); + } + + void dump(std::basic_ostream& os, + const basic_json_encode_options& options, + std::error_code& ec) const + { + basic_compact_json_encoder encoder(os, options); + dump(encoder, ec); + } + + void dump(std::basic_ostream& os, + std::error_code& ec) const + { + basic_compact_json_encoder encoder(os); + dump(encoder, ec); + } + + // dump_pretty + + template + typename std::enable_if::value>::type + dump_pretty(Container& s, + const basic_json_encode_options& options, + std::error_code& ec) const + { + basic_json_encoder> encoder(s, options); + dump(encoder, ec); + } + + template + typename std::enable_if::value>::type + dump_pretty(Container& s, + std::error_code& ec) const + { + dump_pretty(s, basic_json_encode_options(), ec); + } + + void dump_pretty(std::basic_ostream& os, + const basic_json_encode_options& options, + std::error_code& ec) const + { + basic_json_encoder encoder(os, options); + dump(encoder, ec); + } + + void dump_pretty(std::basic_ostream& os, + std::error_code& ec) const + { + dump_pretty(os, basic_json_encode_options(), ec); + } + + // legacy + template + typename std::enable_if::value>::type + dump(Container& s, + const basic_json_encode_options& options, + indenting line_indent, + std::error_code& ec) const + { + if (line_indent == indenting::indent) + { + dump_pretty(s, options, ec); + } + else + { + dump(s, options, ec); + } + } + + template + typename std::enable_if::value>::type + dump(Container& s, + indenting line_indent, + std::error_code& ec) const + { + if (line_indent == indenting::indent) + { + dump_pretty(s, ec); + } + else + { + dump(s, ec); + } + } + + void dump(std::basic_ostream& os, + const basic_json_encode_options& options, + indenting line_indent, + std::error_code& ec) const + { + if (line_indent == indenting::indent) + { + dump_pretty(os, options, ec); + } + else + { + dump(os, options, ec); + } + } + + void dump(std::basic_ostream& os, + indenting line_indent, + std::error_code& ec) const + { + if (line_indent == indenting::indent) + { + dump_pretty(os, ec); + } + else + { + dump(os, ec); + } + } + // end legacy + + void dump(basic_json_visitor& visitor, + std::error_code& ec) const + { + dump_noflush(visitor, ec); + if (ec) + { + return; + } + visitor.flush(); + } + + bool is_null() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::null_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_null(); + default: + return false; + } + } + + allocator_type get_allocator() const + { + switch (storage_kind()) + { + case json_storage_kind::long_string_value: + { + return cast().get_allocator(); + } + case json_storage_kind::byte_string_value: + { + return cast().get_allocator(); + } + case json_storage_kind::array_value: + { + return cast().get_allocator(); + } + case json_storage_kind::object_value: + { + return cast().get_allocator(); + } + default: + return allocator_type(); + } + } + + uint64_t ext_tag() const + { + switch (storage_kind()) + { + case json_storage_kind::byte_string_value: + { + return cast().ext_tag(); + } + case json_storage_kind::json_const_pointer: + return cast().value()->ext_tag(); + default: + return 0; + } + } + + bool contains(const string_view_type& key) const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + return it != object_value().end(); + } + case json_storage_kind::json_const_pointer: + return cast().value()->contains(key); + default: + return false; + } + } + + std::size_t count(const string_view_type& key) const + { + switch (storage_kind()) + { + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + if (it == object_value().end()) + { + return 0; + } + std::size_t count = 0; + while (it != object_value().end()&& it->key() == key) + { + ++count; + ++it; + } + return count; + } + case json_storage_kind::json_const_pointer: + return cast().value()->count(key); + default: + return 0; + } + } + + template + bool is(Args&&... args) const noexcept + { + return json_type_traits::is(*this,std::forward(args)...); + } + + bool is_string() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_string(); + default: + return false; + } + } + + bool is_string_view() const noexcept + { + return is_string(); + } + + bool is_byte_string() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::byte_string_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_byte_string(); + default: + return false; + } + } + + bool is_byte_string_view() const noexcept + { + return is_byte_string(); + } + + bool is_bignum() const + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + return jsoncons::detail::is_base10(as_string_view().data(), as_string_view().length()); + case json_storage_kind::int64_value: + case json_storage_kind::uint64_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_bignum(); + default: + return false; + } + } + + bool is_bool() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::bool_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_bool(); + default: + return false; + } + } + + bool is_object() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + case json_storage_kind::object_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_object(); + default: + return false; + } + } + + bool is_array() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_array(); + default: + return false; + } + } + + bool is_int64() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::int64_value: + return true; + case json_storage_kind::uint64_value: + return as_integer() <= static_cast((std::numeric_limits::max)()); + case json_storage_kind::json_const_pointer: + return cast().value()->is_int64(); + default: + return false; + } + } + + bool is_uint64() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::uint64_value: + return true; + case json_storage_kind::int64_value: + return as_integer() >= 0; + case json_storage_kind::json_const_pointer: + return cast().value()->is_uint64(); + default: + return false; + } + } + + bool is_half() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::half_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_half(); + default: + return false; + } + } + + bool is_double() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::double_value: + return true; + case json_storage_kind::json_const_pointer: + return cast().value()->is_double(); + default: + return false; + } + } + + bool is_number() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::int64_value: + case json_storage_kind::uint64_value: + case json_storage_kind::half_value: + case json_storage_kind::double_value: + return true; + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + return tag() == semantic_tag::bigint || + tag() == semantic_tag::bigdec || + tag() == semantic_tag::bigfloat; + case json_storage_kind::json_const_pointer: + return cast().value()->is_number(); + default: + return false; + } + } + + bool empty() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::byte_string_value: + return cast().length() == 0; + break; + case json_storage_kind::short_string_value: + return cast().length() == 0; + case json_storage_kind::long_string_value: + return cast().length() == 0; + case json_storage_kind::array_value: + return array_value().empty(); + case json_storage_kind::empty_object_value: + return true; + case json_storage_kind::object_value: + return object_value().empty(); + case json_storage_kind::json_const_pointer: + return cast().value()->empty(); + default: + return false; + } + } + + std::size_t capacity() const + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().capacity(); + case json_storage_kind::object_value: + return object_value().capacity(); + case json_storage_kind::json_const_pointer: + return cast().value()->capacity(); + default: + return 0; + } + } + + template + void create_object_implicitly() + { + create_object_implicitly(type_traits::is_stateless()); + } + + void create_object_implicitly(std::false_type) + { + static_assert(std::true_type::value, "Cannot create object implicitly - alloc is stateful."); + } + + void create_object_implicitly(std::true_type) + { + *this = basic_json(json_object_arg, tag()); + } + + void reserve(std::size_t n) + { + if (n > 0) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().reserve(n); + break; + case json_storage_kind::empty_object_value: + { + create_object_implicitly(); + object_value().reserve(n); + } + break; + case json_storage_kind::object_value: + { + object_value().reserve(n); + } + break; + default: + break; + } + } + } + + void resize(std::size_t n) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().resize(n); + break; + default: + break; + } + } + + template + void resize(std::size_t n, T val) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().resize(n, val); + break; + default: + break; + } + } + + template + typename std::enable_if::value,T>::type + as() const + { + T val = json_type_traits::as(*this); + return val; + } + + template + typename std::enable_if<(!type_traits::is_basic_string::value && + type_traits::is_back_insertable_byte_container::value) || + type_traits::is_basic_byte_string::value,T>::type + as(byte_string_arg_t, semantic_tag hint) const + { + converter convert; + std::error_code ec; + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + switch (tag()) + { + case semantic_tag::base16: + case semantic_tag::base64: + case semantic_tag::base64url: + { + T v = convert.from(as_string_view(),tag(),ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + return v; + } + default: + { + T v = convert.from(as_string_view(), hint, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + return T(v.begin(),v.end()); + } + break; + } + break; + } + case json_storage_kind::byte_string_value: + return T(as_byte_string_view().begin(), as_byte_string_view().end()); + case json_storage_kind::json_const_pointer: + return cast().value()->template as(byte_string_arg, hint); + default: + JSONCONS_THROW(json_runtime_error("Not a byte string")); + } + } + + bool as_bool() const + { + switch (storage_kind()) + { + case json_storage_kind::bool_value: + return cast().value(); + case json_storage_kind::int64_value: + return cast().value() != 0; + case json_storage_kind::uint64_value: + return cast().value() != 0; + case json_storage_kind::json_const_pointer: + return cast().value()->as_bool(); + default: + JSONCONS_THROW(json_runtime_error("Not a bool")); + } + } + + template + IntegerType as_integer() const + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + IntegerType val; + auto result = jsoncons::detail::to_integer(as_string_view().data(), as_string_view().length(), val); + if (!result) + { + JSONCONS_THROW(json_runtime_error(result.error_code().message())); + } + return val; + } + case json_storage_kind::half_value: + return static_cast(cast().value()); + case json_storage_kind::double_value: + return static_cast(cast().value()); + case json_storage_kind::int64_value: + return static_cast(cast().value()); + case json_storage_kind::uint64_value: + return static_cast(cast().value()); + case json_storage_kind::bool_value: + return static_cast(cast().value() ? 1 : 0); + case json_storage_kind::json_const_pointer: + return cast().value()->template as_integer(); + default: + JSONCONS_THROW(json_runtime_error("Not an integer")); + } + } + + template + typename std::enable_if::value && sizeof(IntegerType) <= sizeof(int64_t),bool>::type + is_integer() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::int64_value: + return (as_integer() >= (type_traits::integer_limits::lowest)()) && (as_integer() <= (type_traits::integer_limits::max)()); + case json_storage_kind::uint64_value: + return as_integer() <= static_cast((type_traits::integer_limits::max)()); + case json_storage_kind::json_const_pointer: + return cast().value()->template is_integer(); + default: + return false; + } + } + + template + typename std::enable_if::value && sizeof(int64_t) < sizeof(IntegerType),bool>::type + is_integer() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + IntegerType val; + auto result = jsoncons::detail::to_integer(as_string_view().data(), as_string_view().length(), val); + return result ? true : false; + } + case json_storage_kind::int64_value: + return (as_integer() >= (type_traits::integer_limits::lowest)()) && (as_integer() <= (type_traits::integer_limits::max)()); + case json_storage_kind::uint64_value: + return as_integer() <= static_cast((type_traits::integer_limits::max)()); + case json_storage_kind::json_const_pointer: + return cast().value()->template is_integer(); + default: + return false; + } + } + + template + typename std::enable_if::value && sizeof(IntegerType) <= sizeof(int64_t),bool>::type + is_integer() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::int64_value: + return as_integer() >= 0 && static_cast(as_integer()) <= (type_traits::integer_limits::max)(); + case json_storage_kind::uint64_value: + return as_integer() <= (type_traits::integer_limits::max)(); + case json_storage_kind::json_const_pointer: + return cast().value()->template is_integer(); + default: + return false; + } + } + + template + typename std::enable_if::value && sizeof(int64_t) < sizeof(IntegerType),bool>::type + is_integer() const noexcept + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + IntegerType val; + auto result = jsoncons::detail::to_integer(as_string_view().data(), as_string_view().length(), val); + return result ? true : false; + } + case json_storage_kind::int64_value: + return as_integer() >= 0 && static_cast(as_integer()) <= (type_traits::integer_limits::max)(); + case json_storage_kind::uint64_value: + return as_integer() <= (type_traits::integer_limits::max)(); + case json_storage_kind::json_const_pointer: + return cast().value()->template is_integer(); + default: + return false; + } + } + + double as_double() const + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + jsoncons::detail::chars_to to_double; + // to_double() throws std::invalid_argument if conversion fails + return to_double(as_cstring(), as_string_view().length()); + } + case json_storage_kind::half_value: + return binary::decode_half(cast().value()); + case json_storage_kind::double_value: + return cast().value(); + case json_storage_kind::int64_value: + return static_cast(cast().value()); + case json_storage_kind::uint64_value: + return static_cast(cast().value()); + case json_storage_kind::json_const_pointer: + return cast().value()->as_double(); + default: + JSONCONS_THROW(json_runtime_error("Not a double")); + } + } + + template > + std::basic_string as_string() const + { + return as_string(SAllocator()); + } + + template > + std::basic_string as_string(const SAllocator& alloc) const + { + using string_type = std::basic_string; + + converter convert; + std::error_code ec; + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + { + return string_type(as_string_view().data(),as_string_view().length(),alloc); + } + case json_storage_kind::byte_string_value: + { + auto s = convert.from(as_byte_string_view(), tag(), alloc, ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec)); + } + return s; + } + case json_storage_kind::array_value: + { + string_type s(alloc); + { + basic_compact_json_encoder> encoder(s); + dump(encoder); + } + return s; + } + case json_storage_kind::json_const_pointer: + return cast().value()->as_string(alloc); + default: + { + string_type s(alloc); + basic_compact_json_encoder> encoder(s); + dump(encoder); + return s; + } + } + } + + const char_type* as_cstring() const + { + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + return cast().c_str(); + case json_storage_kind::long_string_value: + return cast().c_str(); + case json_storage_kind::json_const_pointer: + return cast().value()->as_cstring(); + default: + JSONCONS_THROW(json_runtime_error("Not a cstring")); + } + } + + basic_json& at(const string_view_type& name) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + JSONCONS_THROW(key_not_found(name.data(),name.length())); + case json_storage_kind::object_value: + { + auto it = object_value().find(name); + if (it == object_value().end()) + { + JSONCONS_THROW(key_not_found(name.data(),name.length())); + } + return it->value(); + } + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + const basic_json& at(const string_view_type& key) const + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + JSONCONS_THROW(key_not_found(key.data(),key.length())); + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + if (it == object_value().end()) + { + JSONCONS_THROW(key_not_found(key.data(),key.length())); + } + return it->value(); + } + case json_storage_kind::json_const_pointer: + return cast().value()->at(key); + default: + { + JSONCONS_THROW(not_an_object(key.data(),key.length())); + } + } + } + + basic_json& at(std::size_t i) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + if (i >= array_value().size()) + { + JSONCONS_THROW(json_runtime_error("Invalid array subscript")); + } + return array_value().operator[](i); + case json_storage_kind::object_value: + return object_value().at(i); + default: + JSONCONS_THROW(json_runtime_error("Index on non-array value not supported")); + } + } + + const basic_json& at(std::size_t i) const + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + if (i >= array_value().size()) + { + JSONCONS_THROW(json_runtime_error("Invalid array subscript")); + } + return array_value().operator[](i); + case json_storage_kind::object_value: + return object_value().at(i); + case json_storage_kind::json_const_pointer: + return cast().value()->at(i); + default: + JSONCONS_THROW(json_runtime_error("Index on non-array value not supported")); + } + } + + object_iterator find(const string_view_type& name) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return object_range().end(); + case json_storage_kind::object_value: + return object_iterator(object_value().find(name)); + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + const_object_iterator find(const string_view_type& key) const + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return object_range().end(); + case json_storage_kind::object_value: + return const_object_iterator(object_value().find(key)); + case json_storage_kind::json_const_pointer: + return cast().value()->find(key); + default: + { + JSONCONS_THROW(not_an_object(key.data(),key.length())); + } + } + } + + const basic_json& at_or_null(const string_view_type& key) const + { + switch (storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + { + return null(); + } + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + if (it != object_value().end()) + { + return it->value(); + } + else + { + return null(); + } + } + case json_storage_kind::json_const_pointer: + return cast().value()->at_or_null(key); + default: + { + JSONCONS_THROW(not_an_object(key.data(),key.length())); + } + } + } + + template + T get_value_or(const string_view_type& key, U&& default_value) const + { + static_assert(std::is_copy_constructible::value, + "get_value_or: T must be copy constructible"); + static_assert(std::is_convertible::value, + "get_value_or: U must be convertible to T"); + switch (storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + { + return static_cast(std::forward(default_value)); + } + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + if (it != object_value().end()) + { + return it->value().template as(); + } + else + { + return static_cast(std::forward(default_value)); + } + } + case json_storage_kind::json_const_pointer: + return cast().value()->template get_value_or(key,std::forward(default_value)); + default: + { + JSONCONS_THROW(not_an_object(key.data(),key.length())); + } + } + } + + // Modifiers + + void shrink_to_fit() + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().shrink_to_fit(); + break; + case json_storage_kind::object_value: + object_value().shrink_to_fit(); + break; + default: + break; + } + } + + void clear() + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().clear(); + break; + case json_storage_kind::object_value: + object_value().clear(); + break; + default: + break; + } + } + + object_iterator erase(const_object_iterator pos) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return object_range().end(); + case json_storage_kind::object_value: + return object_iterator(object_value().erase(pos)); + default: + JSONCONS_THROW(json_runtime_error("Not an object")); + break; + } + } + + object_iterator erase(const_object_iterator first, const_object_iterator last) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return object_range().end(); + case json_storage_kind::object_value: + return object_iterator(object_value().erase(first, last)); + default: + JSONCONS_THROW(json_runtime_error("Not an object")); + break; + } + } + + array_iterator erase(const_array_iterator pos) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().erase(pos); + default: + JSONCONS_THROW(json_runtime_error("Not an array")); + } + } + + array_iterator erase(const_array_iterator first, const_array_iterator last) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().erase(first, last); + default: + JSONCONS_THROW(json_runtime_error("Not an array")); + break; + } + } + + // Removes all elements from an array value whose index is between from_index, inclusive, and to_index, exclusive. + + void erase(const string_view_type& name) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + break; + case json_storage_kind::object_value: + object_value().erase(name); + break; + default: + JSONCONS_THROW(not_an_object(name.data(),name.length())); + break; + } + } + + template + std::pair insert_or_assign(const string_view_type& name, T&& val) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + { + auto result = object_value().insert_or_assign(name, std::forward(val)); + return std::make_pair(object_iterator(result.first), result.second); + } + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + template + std::pair try_emplace(const string_view_type& name, Args&&... args) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + { + auto result = object_value().try_emplace(name, std::forward(args)...); + return std::make_pair(object_iterator(result.first),result.second); + } + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + // merge + + void merge(const basic_json& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge(source.object_value()); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge a value that is not an object")); + } + } + } + + void merge(basic_json&& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge(std::move(source.object_value())); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge a value that is not an object")); + } + } + } + + void merge(object_iterator hint, const basic_json& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge(hint, source.object_value()); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge a value that is not an object")); + } + } + } + + void merge(object_iterator hint, basic_json&& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge(hint, std::move(source.object_value())); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge a value that is not an object")); + } + } + } + + // merge_or_update + + void merge_or_update(const basic_json& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge_or_update(source.object_value()); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge or update a value that is not an object")); + } + } + } + + void merge_or_update(basic_json&& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge_or_update(std::move(source.object_value())); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge or update a value that is not an object")); + } + } + } + + void merge_or_update(object_iterator hint, const basic_json& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge_or_update(hint, source.object_value()); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge or update a value that is not an object")); + } + } + } + + void merge_or_update(object_iterator hint, basic_json&& source) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + object_value().merge_or_update(hint, std::move(source.object_value())); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to merge or update a value that is not an object")); + } + } + } + + template + object_iterator insert_or_assign(object_iterator hint, const string_view_type& name, T&& val) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + return object_iterator(object_value().insert_or_assign(hint, name, std::forward(val))); + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + template + object_iterator try_emplace(object_iterator hint, const string_view_type& name, Args&&... args) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + return object_iterator(object_value().try_emplace(hint, name, std::forward(args)...)); + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + template + array_iterator insert(const_array_iterator pos, T&& val) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().insert(pos, std::forward(val)); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an array")); + } + } + } + + template + array_iterator insert(const_array_iterator pos, InputIt first, InputIt last) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().insert(pos, first, last); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an array")); + } + } + } + + template + void insert(InputIt first, InputIt last) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + case json_storage_kind::object_value: + object_value().insert(first, last, get_key_value()); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an object")); + } + } + } + + template + void insert(sorted_unique_range_tag tag, InputIt first, InputIt last) + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + case json_storage_kind::object_value: + object_value().insert(tag, first, last, get_key_value()); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an object")); + } + } + } + + template + array_iterator emplace(const_array_iterator pos, Args&&... args) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().emplace(pos, std::forward(args)...); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an array")); + } + } + } + + template + basic_json& emplace_back(Args&&... args) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return array_value().emplace_back(std::forward(args)...); + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an array")); + } + } + } + + friend void swap(basic_json& a, basic_json& b) noexcept + { + a.swap(b); + } + + template + void push_back(T&& val) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().push_back(std::forward(val)); + break; + default: + { + JSONCONS_THROW(json_runtime_error("Attempting to insert into a value that is not an array")); + } + } + } + + template + T get_with_default(const string_view_type& key, const T& default_value) const + { + switch (storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + { + return default_value; + } + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + if (it != object_value().end()) + { + return it->value().template as(); + } + else + { + return default_value; + } + } + case json_storage_kind::json_const_pointer: + return cast().value()->get_with_default(key, default_value); + default: + { + JSONCONS_THROW(not_an_object(key.data(),key.length())); + } + } + } + + template> + T get_with_default(const string_view_type& key, const char_type* default_value) const + { + switch (storage_kind()) + { + case json_storage_kind::null_value: + case json_storage_kind::empty_object_value: + { + return T(default_value); + } + case json_storage_kind::object_value: + { + auto it = object_value().find(key); + if (it != object_value().end()) + { + return it->value().template as(); + } + else + { + return T(default_value); + } + } + case json_storage_kind::json_const_pointer: + return cast().value()->get_with_default(key, default_value); + default: + { + JSONCONS_THROW(not_an_object(key.data(),key.length())); + } + } + } + + std::basic_string to_string() const noexcept + { + using string_type = std::basic_string; + string_type s; + basic_compact_json_encoder> encoder(s); + dump(encoder); + return s; + } + + #if !defined(JSONCONS_NO_DEPRECATED) + JSONCONS_DEPRECATED_MSG("Instead, use basic_json(byte_string_arg_t, const Source&, semantic_tag=semantic_tag::none,const Allocator& = Allocator())") + basic_json(const byte_string_view& bytes, + semantic_tag tag, + const Allocator& alloc = Allocator()) + : basic_json(byte_string_arg, bytes, tag, alloc) + { + } + + JSONCONS_DEPRECATED_MSG("Instead, use at_or_null(const string_view_type&)") + const basic_json& get_with_default(const string_view_type& name) const + { + return at_or_null(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(const string_view_type&)") + static basic_json parse(const char_type* s, std::size_t length) + { + parse_error_handler_type err_handler; + return parse(s,length,err_handler); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(const string_view_type&, parse_error_handler)") + static basic_json parse(const char_type* s, std::size_t length, std::function err_handler) + { + return parse(string_view_type(s,length),err_handler); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream&)") + static basic_json parse_file(const std::basic_string& filename) + { + parse_error_handler_type err_handler; + return parse_file(filename,err_handler); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream&, std::function)") + static basic_json parse_file(const std::basic_string& filename, + std::function err_handler) + { + std::basic_ifstream is(filename); + return parse(is,err_handler); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream&)") + static basic_json parse_stream(std::basic_istream& is) + { + return parse(is); + } + JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream&, std::function)") + static basic_json parse_stream(std::basic_istream& is, std::function err_handler) + { + return parse(is,err_handler); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(const string_view_type&)") + static basic_json parse_string(const string_view_type& s) + { + return parse(s); + } + + JSONCONS_DEPRECATED_MSG("Instead, use parse(parse(const string_view_type&, std::function)") + static const basic_json parse_string(const string_view_type& s, std::function err_handler) + { + return parse(s,err_handler); + } + + JSONCONS_DEPRECATED_MSG("Instead, use basic_json(double)") + basic_json(double val, uint8_t) + : basic_json(val, semantic_tag::none) + { + } + + JSONCONS_DEPRECATED_MSG("Instead, use basic_json(const byte_string_view& ,semantic_tag)") + basic_json(const byte_string_view& bytes, + byte_string_chars_format encoding_hint, + semantic_tag tag = semantic_tag::none) + : basic_json(bytes, tag) + { + switch (encoding_hint) + { + case byte_string_chars_format::base16: + *this = basic_json(bytes, semantic_tag::base16); + break; + case byte_string_chars_format::base64: + *this = basic_json(bytes, semantic_tag::base64); + break; + case byte_string_chars_format::base64url: + *this = basic_json(bytes, semantic_tag::base64url); + break; + default: + break; + } + } + + template + basic_json(InputIterator first, InputIterator last, const Allocator& alloc = Allocator()) + : basic_json(json_array_arg,first,last,alloc) + { + } + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void dump_fragment(basic_json_visitor& visitor) const + { + dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void dump_body(basic_json_visitor& visitor) const + { + dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, indenting)") + void dump(std::basic_ostream& os, bool pprint) const + { + if (pprint) + { + basic_json_encoder encoder(os); + dump(encoder); + } + else + { + basic_compact_json_encoder encoder(os); + dump(encoder); + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&, indenting)") + void dump(std::basic_ostream& os, const basic_json_encode_options& options, bool pprint) const + { + if (pprint) + { + basic_json_encoder encoder(os, options); + dump(encoder); + } + else + { + basic_compact_json_encoder encoder(os, options); + dump(encoder); + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void write_body(basic_json_visitor& visitor) const + { + dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void write(basic_json_visitor& visitor) const + { + dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&)") + void write(std::basic_ostream& os) const + { + dump(os); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&)") + void write(std::basic_ostream& os, const basic_json_encode_options& options) const + { + dump(os,options); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&, indenting)") + void write(std::basic_ostream& os, const basic_json_encode_options& options, bool pprint) const + { + dump(os,options,pprint); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor&)") + void to_stream(basic_json_visitor& visitor) const + { + dump(visitor); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&)") + void to_stream(std::basic_ostream& os) const + { + dump(os); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&)") + void to_stream(std::basic_ostream& os, const basic_json_encode_options& options) const + { + dump(os,options); + } + + JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream&, const basic_json_encode_options&, indenting)") + void to_stream(std::basic_ostream& os, const basic_json_encode_options& options, bool pprint) const + { + dump(os,options,pprint ? indenting::indent : indenting::no_indent); + } + + JSONCONS_DEPRECATED_MSG("No replacement") + std::size_t precision() const + { + switch (storage_kind()) + { + case json_storage_kind::double_value: + return 0; + default: + JSONCONS_THROW(json_runtime_error("Not a double")); + } + } + + JSONCONS_DEPRECATED_MSG("No replacement") + std::size_t decimal_places() const + { + switch (storage_kind()) + { + case json_storage_kind::double_value: + return 0; + default: + JSONCONS_THROW(json_runtime_error("Not a double")); + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use tag() == semantic_tag::datetime") + bool is_datetime() const noexcept + { + return tag() == semantic_tag::datetime; + } + + JSONCONS_DEPRECATED_MSG("Instead, use tag() == semantic_tag::epoch_second") + bool is_epoch_time() const noexcept + { + return tag() == semantic_tag::epoch_second; + } + + JSONCONS_DEPRECATED_MSG("Instead, use contains(const string_view_type&)") + bool has_key(const string_view_type& name) const noexcept + { + return contains(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + uint64_t as_uinteger() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("No replacement") + std::size_t double_precision() const + { + switch (storage_kind()) + { + case json_storage_kind::double_value: + return 0; + default: + JSONCONS_THROW(json_runtime_error("Not a double")); + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use insert(const_array_iterator, T&&)") + void add(std::size_t index, const basic_json& value) + { + evaluate_with_default().add(index, value); + } + + JSONCONS_DEPRECATED_MSG("Instead, use insert(const_array_iterator, T&&)") + void add(std::size_t index, basic_json&& value) + { + evaluate_with_default().add(index, std::forward(value)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use push_back(T&&)") + void add(T&& val) + { + push_back(std::forward(val)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use insert(const_array_iterator, T&&)") + array_iterator add(const_array_iterator pos, T&& val) + { + return insert(pos, std::forward(val)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use insert_or_assign(const string_view_type&, T&&)") + std::pair set(const string_view_type& name, T&& val) + { + return insert_or_assign(name, std::forward(val)); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use insert_or_assign(const string_view_type&, T&&)") + object_iterator set(object_iterator hint, const string_view_type& name, T&& val) + { + return insert_or_assign(hint, name, std::forward(val)); + } + + JSONCONS_DEPRECATED_MSG("Instead, use resize(std::size_t)") + void resize_array(std::size_t n) + { + resize(n); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use resize(std::size_t, T)") + void resize_array(std::size_t n, T val) + { + resize(n,val); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().begin()") + object_iterator begin_members() + { + return object_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().begin()") + const_object_iterator begin_members() const + { + return object_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().end()") + object_iterator end_members() + { + return object_range().end(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range().end()") + const_object_iterator end_members() const + { + return object_range().end(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().begin()") + array_iterator begin_elements() + { + return array_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().begin()") + const_array_iterator begin_elements() const + { + return array_range().begin(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().end()") + array_iterator end_elements() + { + return array_range().end(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range().end()") + const_array_iterator end_elements() const + { + return array_range().end(); + } + + template + JSONCONS_DEPRECATED_MSG("Instead, use get_with_default(const string_view_type&, T&&)") + basic_json get(const string_view_type& name, T&& default_value) const + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + { + return basic_json(std::forward(default_value)); + } + case json_storage_kind::object_value: + { + auto it = object_value().find(name); + if (it != object_value().end()) + { + return it->value(); + } + else + { + return basic_json(std::forward(default_value)); + } + } + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use at_or_null(const string_view_type&)") + const basic_json& get(const string_view_type& name) const + { + static const basic_json a_null = null_type(); + + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return a_null; + case json_storage_kind::object_value: + { + auto it = object_value().find(name); + return it != object_value().end() ? it->value() : a_null; + } + default: + { + JSONCONS_THROW(not_an_object(name.data(),name.length())); + } + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use is()") + bool is_longlong() const noexcept + { + return is(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use is()") + bool is_ulonglong() const noexcept + { + return is(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + long long as_longlong() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + unsigned long long as_ulonglong() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + int as_int() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + unsigned int as_uint() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + long as_long() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use as()") + unsigned long as_ulong() const + { + return as(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use contains(const string_view_type&)") + bool has_member(const string_view_type& key) const noexcept + { + return contains(key); + } + + JSONCONS_DEPRECATED_MSG("Instead, use erase(const_object_iterator, const_object_iterator)") + void remove_range(std::size_t from_index, std::size_t to_index) + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + array_value().remove_range(from_index, to_index); + break; + default: + break; + } + } + + JSONCONS_DEPRECATED_MSG("Instead, use erase(const string_view_type& name)") + void remove(const string_view_type& name) + { + erase(name); + } + + JSONCONS_DEPRECATED_MSG("Instead, use erase(const string_view_type& name)") + void remove_member(const string_view_type& name) + { + erase(name); + } + // Removes a member from an object value + + JSONCONS_DEPRECATED_MSG("Instead, use empty()") + bool is_empty() const noexcept + { + return empty(); + } + JSONCONS_DEPRECATED_MSG("Instead, use is_number()") + bool is_numeric() const noexcept + { + return is_number(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range()") + range members() + { + return object_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use object_range()") + range members() const + { + return object_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range()") + range elements() + { + return array_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use array_range()") + range elements() const + { + return array_range(); + } + + JSONCONS_DEPRECATED_MSG("Instead, use storage_kind()") + json_storage_kind get_stor_type() const + { + return storage_kind(); + } + #endif + + range object_range() + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return range(object_iterator(), object_iterator()); + case json_storage_kind::object_value: + return range(object_iterator(object_value().begin()), + object_iterator(object_value().end())); + default: + JSONCONS_THROW(json_runtime_error("Not an object")); + } + } + + range object_range() const + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + return range(const_object_iterator(), const_object_iterator()); + case json_storage_kind::object_value: + return range(const_object_iterator(object_value().begin()), + const_object_iterator(object_value().end())); + case json_storage_kind::json_const_pointer: + return cast().value()->object_range(); + default: + JSONCONS_THROW(json_runtime_error("Not an object")); + } + } + + range array_range() + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return range(array_value().begin(),array_value().end()); + default: + JSONCONS_THROW(json_runtime_error("Not an array")); + } + } + + range array_range() const + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return range(array_value().begin(),array_value().end()); + case json_storage_kind::json_const_pointer: + return cast().value()->array_range(); + default: + JSONCONS_THROW(json_runtime_error("Not an array")); + } + } + + array& array_value() + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return cast().value(); + default: + JSONCONS_THROW(json_runtime_error("Bad array cast")); + break; + } + } + + const array& array_value() const + { + switch (storage_kind()) + { + case json_storage_kind::array_value: + return cast().value(); + case json_storage_kind::json_const_pointer: + return cast().value()->array_value(); + default: + JSONCONS_THROW(json_runtime_error("Bad array cast")); + break; + } + } + + object& object_value() + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + create_object_implicitly(); + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + return cast().value(); + default: + JSONCONS_THROW(json_runtime_error("Bad object cast")); + break; + } + } + + const object& object_value() const + { + switch (storage_kind()) + { + case json_storage_kind::empty_object_value: + const_cast(this)->create_object_implicitly(); // HERE + JSONCONS_FALLTHROUGH; + case json_storage_kind::object_value: + return cast().value(); + case json_storage_kind::json_const_pointer: + return cast().value()->object_value(); + default: + JSONCONS_THROW(json_runtime_error("Bad object cast")); + break; + } + } + + private: + + void dump_noflush(basic_json_visitor& visitor, std::error_code& ec) const + { + const ser_context context{}; + switch (storage_kind()) + { + case json_storage_kind::short_string_value: + case json_storage_kind::long_string_value: + visitor.string_value(as_string_view(), tag(), context, ec); + break; + case json_storage_kind::byte_string_value: + if (tag() == semantic_tag::ext) + { + visitor.byte_string_value(as_byte_string_view(), ext_tag(), context, ec); + } + else + { + visitor.byte_string_value(as_byte_string_view(), tag(), context, ec); + } + break; + case json_storage_kind::half_value: + visitor.half_value(cast().value(), tag(), context, ec); + break; + case json_storage_kind::double_value: + visitor.double_value(cast().value(), + tag(), context, ec); + break; + case json_storage_kind::int64_value: + visitor.int64_value(cast().value(), tag(), context, ec); + break; + case json_storage_kind::uint64_value: + visitor.uint64_value(cast().value(), tag(), context, ec); + break; + case json_storage_kind::bool_value: + visitor.bool_value(cast().value(), tag(), context, ec); + break; + case json_storage_kind::null_value: + visitor.null_value(tag(), context, ec); + break; + case json_storage_kind::empty_object_value: + visitor.begin_object(0, tag(), context, ec); + visitor.end_object(context, ec); + break; + case json_storage_kind::object_value: + { + bool more = visitor.begin_object(size(), tag(), context, ec); + const object& o = object_value(); + for (auto it = o.begin(); more && it != o.end(); ++it) + { + visitor.key(string_view_type((it->key()).data(),it->key().length()), context, ec); + it->value().dump_noflush(visitor, ec); + } + if (more) + { + visitor.end_object(context, ec); + } + break; + } + case json_storage_kind::array_value: + { + bool more = visitor.begin_array(size(), tag(), context, ec); + const array& o = array_value(); + for (const_array_iterator it = o.begin(); more && it != o.end(); ++it) + { + it->dump_noflush(visitor, ec); + } + if (more) + { + visitor.end_array(context, ec); + } + break; + } + case json_storage_kind::json_const_pointer: + return cast().value()->dump_noflush(visitor, ec); + default: + break; + } + } + + friend std::basic_ostream& operator<<(std::basic_ostream& os, const basic_json& o) + { + o.dump(os); + return os; + } + + friend std::basic_istream& operator>>(std::basic_istream& is, basic_json& o) + { + json_decoder visitor; + basic_json_reader> reader(is, visitor); + reader.read_next(); + reader.check_done(); + if (!visitor.is_valid()) + { + JSONCONS_THROW(json_runtime_error("Failed to parse json stream")); + } + o = visitor.get_result(); + return is; + } + + friend basic_json deep_copy(const basic_json& other) + { + switch (other.storage_kind()) + { + case json_storage_kind::array_value: + { + basic_json j(json_array_arg, other.tag(), other.get_allocator()); + j.reserve(other.size()); + + for (const auto& item : other.array_range()) + { + j.push_back(deep_copy(item)); + } + return j; + } + case json_storage_kind::object_value: + { + basic_json j(json_object_arg, other.tag(), other.get_allocator()); + j.reserve(other.size()); + + for (const auto& item : other.object_range()) + { + j.try_emplace(item.key(), deep_copy(item.value())); + } + return j; + } + case json_storage_kind::json_const_pointer: + return deep_copy(*(other.cast().value())); + default: + return other; + } + } + }; + + // operator== + + template + typename std::enable_if::value,bool>::type + operator==(const Json& lhs, const Json& rhs) noexcept + { + return lhs.compare(rhs) == 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator==(const Json& lhs, const T& rhs) + { + return lhs.compare(rhs) == 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator==(const Json& lhs, const T& rhs) + { + return lhs.evaluate().compare(rhs) == 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator==(const T& lhs, const Json& rhs) + { + return rhs.compare(lhs) == 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator==(const T& lhs, const Json& rhs) + { + return rhs.evaluate().compare(lhs) == 0; + } + + // operator!= + + template + typename std::enable_if::value,bool>::type + operator!=(const Json& lhs, const Json& rhs) noexcept + { + return lhs.compare(rhs) != 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator!=(const Json& lhs, const T& rhs) + { + return lhs.compare(rhs) != 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator!=(const Json& lhs, const T& rhs) + { + return lhs.evaluate().compare(rhs) != 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator!=(const T& lhs, const Json& rhs) + { + return rhs.compare(lhs) != 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator!=(const T& lhs, const Json& rhs) + { + return rhs.evaluate().compare(lhs) != 0; + } + + // operator< + + template + typename std::enable_if::value,bool>::type + operator<(const Json& lhs, const Json& rhs) noexcept + { + return lhs.compare(rhs) < 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator<(const Json& lhs, const T& rhs) + { + return lhs.compare(rhs) < 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator<(const Json& lhs, const T& rhs) + { + return lhs.evaluate().compare(rhs) < 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator<(const T& lhs, const Json& rhs) + { + return rhs.compare(lhs) > 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator<(const T& lhs, const Json& rhs) + { + return rhs.evaluate().compare(lhs) > 0; + } + + // operator<= + + template + typename std::enable_if::value,bool>::type + operator<=(const Json& lhs, const Json& rhs) noexcept + { + return lhs.compare(rhs) <= 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator<=(const Json& lhs, const T& rhs) + { + return lhs.compare(rhs) <= 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator<=(const Json& lhs, const T& rhs) + { + return lhs.evaluate().compare(rhs) <= 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator<=(const T& lhs, const Json& rhs) + { + return rhs.compare(lhs) >= 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator<=(const T& lhs, const Json& rhs) + { + return rhs.evaluate().compare(lhs) >= 0; + } + + // operator> + + template + typename std::enable_if::value,bool>::type + operator>(const Json& lhs, const Json& rhs) noexcept + { + return lhs.compare(rhs) > 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator>(const Json& lhs, const T& rhs) + { + return lhs.compare(rhs) > 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator>(const Json& lhs, const T& rhs) + { + return lhs.evaluate().compare(rhs) > 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator>(const T& lhs, const Json& rhs) + { + return rhs.compare(lhs) < 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator>(const T& lhs, const Json& rhs) + { + return rhs.evaluate().compare(lhs) < 0; + } + + // operator>= + + template + typename std::enable_if::value,bool>::type + operator>=(const Json& lhs, const Json& rhs) noexcept + { + return lhs.compare(rhs) >= 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator>=(const Json& lhs, const T& rhs) + { + return lhs.compare(rhs) >= 0; + } + + template + typename std::enable_if::value && std::is_convertible::value,bool>::type + operator>=(const Json& lhs, const T& rhs) + { + return lhs.evaluate().compare(rhs) >= 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator>=(const T& lhs, const Json& rhs) + { + return rhs.compare(lhs) <= 0; + } + + template + typename std::enable_if::value && !is_proxy::value && !type_traits::is_basic_json::value && std::is_convertible::value,bool>::type + operator>=(const T& lhs, const Json& rhs) + { + return rhs.evaluate().compare(lhs) <= 0; + } + + // swap + + template + void swap(typename Json::key_value_type& a, typename Json::key_value_type& b) noexcept + { + a.swap(b); + } + + using json = basic_json>; + using wjson = basic_json>; + using ojson = basic_json>; + using wojson = basic_json>; + + #if !defined(JSONCONS_NO_DEPRECATED) + JSONCONS_DEPRECATED_MSG("Instead, use wojson") typedef basic_json> owjson; + JSONCONS_DEPRECATED_MSG("Instead, use json_decoder") typedef json_decoder json_deserializer; + JSONCONS_DEPRECATED_MSG("Instead, use json_decoder") typedef json_decoder wjson_deserializer; + JSONCONS_DEPRECATED_MSG("Instead, use json_decoder") typedef json_decoder ojson_deserializer; + JSONCONS_DEPRECATED_MSG("Instead, use json_decoder") typedef json_decoder wojson_deserializer; + #endif + + inline namespace literals { + + inline + jsoncons::json operator "" _json(const char* s, std::size_t n) + { + return jsoncons::json::parse(jsoncons::json::string_view_type(s, n)); + } + + inline + jsoncons::wjson operator "" _json(const wchar_t* s, std::size_t n) + { + return jsoncons::wjson::parse(jsoncons::wjson::string_view_type(s, n)); + } + + inline + jsoncons::ojson operator "" _ojson(const char* s, std::size_t n) + { + return jsoncons::ojson::parse(jsoncons::ojson::string_view_type(s, n)); + } + + inline + jsoncons::wojson operator "" _ojson(const wchar_t* s, std::size_t n) + { + return jsoncons::wojson::parse(jsoncons::wojson::string_view_type(s, n)); + } + + } // inline namespace literals + +} // namespace jsoncons + +#endif -- cgit v1.2.3