// 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 <limits> // std::numeric_limits #include <string> #include <vector> #include <exception> #include <cstring> #include <ostream> #include <memory> // std::allocator #include <typeinfo> #include <cstring> // std::memcpy #include <algorithm> // std::swap #include <initializer_list> // std::initializer_list #include <utility> // std::move #include <type_traits> // std::enable_if #include <istream> // std::basic_istream #include <jsoncons/json_fwd.hpp> #include <jsoncons/json_type.hpp> #include <jsoncons/config/version.hpp> #include <jsoncons/json_type.hpp> #include <jsoncons/json_exception.hpp> #include <jsoncons/pretty_print.hpp> #include <jsoncons/json_object.hpp> #include <jsoncons/json_array.hpp> #include <jsoncons/bigint.hpp> #include <jsoncons/json_options.hpp> #include <jsoncons/json_encoder.hpp> #include <jsoncons/json_decoder.hpp> #include <jsoncons/json_reader.hpp> #include <jsoncons/json_type_traits.hpp> #include <jsoncons/byte_string.hpp> #include <jsoncons/json_error.hpp> #include <jsoncons/detail/string_wrapper.hpp> namespace jsoncons { namespace type_traits { namespace detail { template <class T> using basic_json_t = basic_json<typename T::char_type,typename T::implementation_policy,typename T::allocator_type>; } // namespace detail template<class T, class Enable = void> struct is_basic_json : std::false_type {}; template<class T> struct is_basic_json<T, typename std::enable_if<type_traits::is_detected<detail::basic_json_t,typename std::decay<T>::type>::value>::type > : std::true_type {}; } // namespace type_traits namespace detail { template <class Iterator,class Enable = void> class random_access_iterator_wrapper { }; template <class Iterator> class random_access_iterator_wrapper<Iterator, typename std::enable_if<std::is_same<typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>::value>::type> { Iterator it_; bool has_value_; template <class Iter,class Enable> friend class random_access_iterator_wrapper; public: using iterator_category = std::random_access_iterator_tag; using value_type = typename std::iterator_traits<Iterator>::value_type; using difference_type = typename std::iterator_traits<Iterator>::difference_type; using pointer = typename std::iterator_traits<Iterator>::pointer; using reference = typename std::iterator_traits<Iterator>::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 <class Iter, class=typename std::enable_if<!std::is_same<Iter,Iterator>::value && std::is_convertible<Iter,Iterator>::value>::type> random_access_iterator_wrapper(const random_access_iterator_wrapper<Iter>& 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<Iterator> operator+( difference_type offset, random_access_iterator_wrapper<Iterator> next) { return next += offset; } bool has_value() const { return has_value_; } }; } // namespace detail struct sorted_policy { template <class KeyT,class Json> using object = sorted_json_object<KeyT,Json,std::vector>; template <class Json> using array = json_array<Json,std::vector>; using parse_error_handler_type = default_json_parsing; }; struct order_preserving_policy { template <class KeyT,class Json> using object = order_preserving_json_object<KeyT,Json,std::vector>; template <class Json> using array = json_array<Json,std::vector>; using parse_error_handler_type = default_json_parsing; }; #if !defined(JSONCONS_NO_DEPRECATED) using preserve_order_policy = order_preserving_policy; #endif template <class IteratorT, class ConstIteratorT> class range { public: using iterator = IteratorT; using const_iterator = ConstIteratorT; using reverse_iterator = std::reverse_iterator<IteratorT>; using const_reverse_iterator = std::reverse_iterator<ConstIteratorT>; 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<class T, class Json, class Enable = void> struct is_proxy_of : std::false_type {}; template<class Proxy,class Json> struct is_proxy_of<Proxy,Json, typename std::enable_if<std::is_same<typename Proxy::proxied_type,Json>::value>::type > : std::true_type {}; // is_proxy template<class T, class Enable = void> struct is_proxy : std::false_type {}; template<class T> struct is_proxy<T,typename std::enable_if<is_proxy_of<T,typename T::proxied_type>::value>::type > : std::true_type {}; template <class CharT, class ImplementationPolicy, class Allocator> 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<char_type>; using string_view_type = jsoncons::basic_string_view<char_type,char_traits_type>; using char_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<char_type>; using key_type = std::basic_string<char_type,char_traits_type,char_allocator_type>; 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<key_type,basic_json>; #if !defined(JSONCONS_NO_DEPRECATED) JSONCONS_DEPRECATED_MSG("no replacement") typedef basic_json value_type; JSONCONS_DEPRECATED_MSG("no replacement") typedef std::basic_string<char_type> 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<basic_json>; using key_value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<key_value_type>; using object = typename ImplementationPolicy::template object<key_type,basic_json>; using object_iterator = jsoncons::detail::random_access_iterator_wrapper<typename object::iterator>; using const_object_iterator = jsoncons::detail::random_access_iterator_wrapper<typename object::const_iterator>; 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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t>(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<char_type,Allocator> s_; public: long_string_storage(semantic_tag tag, const char_type* data, std::size_t length, const Allocator& a) : storage_kind_(static_cast<uint8_t>(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<uint8_t,Allocator> 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<uint8_t>(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<Allocator>:: template rebind_alloc<array>; using pointer = typename std::allocator_traits<array_allocator>::pointer; pointer ptr_; template <typename... Args> void create(array_allocator alloc, Args&& ... args) { ptr_ = std::allocator_traits<array_allocator>::allocate(alloc, 1); JSONCONS_TRY { std::allocator_traits<array_allocator>::construct(alloc, type_traits::to_plain_pointer(ptr_), std::forward<Args>(args)...); } JSONCONS_CATCH(...) { std::allocator_traits<array_allocator>::deallocate(alloc, ptr_,1); JSONCONS_RETHROW; } } void destroy() noexcept { array_allocator alloc(ptr_->get_allocator()); std::allocator_traits<array_allocator>::destroy(alloc, type_traits::to_plain_pointer(ptr_)); std::allocator_traits<array_allocator>::deallocate(alloc, ptr_,1); } public: array_storage(const array& val, semantic_tag tag) : storage_kind_(static_cast<uint8_t>(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<uint8_t>(json_storage_kind::array_value)), length_(0), tag_(tag) { create(val.get_allocator(), std::forward<array>(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<Allocator>:: template rebind_alloc<object>; using pointer = typename std::allocator_traits<object_allocator>::pointer; pointer ptr_; template <typename... Args> void create(object_allocator alloc, Args&& ... args) { ptr_ = std::allocator_traits<object_allocator>::allocate(alloc, 1); JSONCONS_TRY { std::allocator_traits<object_allocator>::construct(alloc, type_traits::to_plain_pointer(ptr_), std::forward<Args>(args)...); } JSONCONS_CATCH(...) { std::allocator_traits<object_allocator>::deallocate(alloc, ptr_,1); JSONCONS_RETHROW; } } public: explicit object_storage(const object& val, semantic_tag tag) : storage_kind_(static_cast<uint8_t>(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<uint8_t>(json_storage_kind::object_value)), length_(0), tag_(tag) { create(val.get_allocator(), std::forward<object>(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<object_allocator>::destroy(alloc, type_traits::to_plain_pointer(ptr_)); std::allocator_traits<object_allocator>::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<uint8_t>(json_storage_kind::json_const_pointer)), length_(0), tag_(p->tag()), p_(p) { } const basic_json* value() const { return p_; } }; template <class ParentType> class proxy { friend class basic_json<char_type,implementation_policy,allocator_type>; 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<typename ParentType::proxy_type>; 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_iterator, const_object_iterator> object_range() { return evaluate().object_range(); } range<const_object_iterator, const_object_iterator> object_range() const { return evaluate().object_range(); } range<array_iterator, const_array_iterator> array_range() { return evaluate().array_range(); } range<const_array_iterator, const_array_iterator> 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 <class T> void resize(std::size_t n, T val) { evaluate().resize(n,val); } template<class T, class... Args> bool is(Args&&... args) const noexcept { if (!parent_.contains(key_)) { return false; } return evaluate().template is<T>(std::forward<Args>(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 <class SAllocator=std::allocator<char_type>> std::basic_string<char_type,char_traits_type,SAllocator> as_string() const { return evaluate().as_string(); } template <class SAllocator=std::allocator<char_type>> std::basic_string<char_type,char_traits_type,SAllocator> as_string(const SAllocator& alloc) const { return evaluate().as_string(alloc); } template <typename BAllocator=std::allocator<uint8_t>> basic_byte_string<BAllocator> as_byte_string() const { return evaluate().template as_byte_string<BAllocator>(); } template<class T> typename std::enable_if<is_json_type_traits_specialized<basic_json,T>::value,T>::type as() const { return evaluate().template as<T>(); } template<class T> typename std::enable_if<std::is_convertible<uint8_t,typename T::value_type>::value,T>::type as(byte_string_arg_t, semantic_tag hint) const { return evaluate().template as<T>(byte_string_arg, hint); } bool as_bool() const { return evaluate().as_bool(); } double as_double() const { return evaluate().as_double(); } template <class T> T as_integer() const { return evaluate().template as_integer<T>(); } template <class T> proxy& operator=(T&& val) { parent_.evaluate_with_default().insert_or_assign(key_, std::forward<T>(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 <class T,class U> T get_value_or(const string_view_type& name, U&& default_value) const { static_assert(std::is_copy_constructible<T>::value, "get_value_or: T must be copy constructible"); static_assert(std::is_convertible<U&&, T>::value, "get_value_or: U must be convertible to T"); return evaluate().template get_value_or<T,U>(name,std::forward<U>(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<basic_json>(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<basic_json>(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<basic_json>(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<basic_json>(source)); } template <class T> std::pair<object_iterator,bool> insert_or_assign(const string_view_type& name, T&& val) { return evaluate().insert_or_assign(name,std::forward<T>(val)); } // emplace template <class ... Args> std::pair<object_iterator,bool> try_emplace(const string_view_type& name, Args&&... args) { return evaluate().try_emplace(name,std::forward<Args>(args)...); } template <class T> object_iterator insert_or_assign(object_iterator hint, const string_view_type& name, T&& val) { return evaluate().insert_or_assign(hint, name, std::forward<T>(val)); } template <class ... Args> object_iterator try_emplace(object_iterator hint, const string_view_type& name, Args&&... args) { return evaluate().try_emplace(hint, name, std::forward<Args>(args)...); } template <class... Args> array_iterator emplace(const_array_iterator pos, Args&&... args) { evaluate_with_default().emplace(pos, std::forward<Args>(args)...); } template <class... Args> basic_json& emplace_back(Args&&... args) { return evaluate_with_default().emplace_back(std::forward<Args>(args)...); } template <class T> void push_back(T&& val) { evaluate_with_default().push_back(std::forward<T>(val)); } template <class T> array_iterator insert(const_array_iterator pos, T&& val) { return evaluate_with_default().insert(pos, std::forward<T>(val)); } template <class InputIt> array_iterator insert(const_array_iterator pos, InputIt first, InputIt last) { return evaluate_with_default().insert(pos, first, last); } template <class InputIt> void insert(InputIt first, InputIt last) { evaluate_with_default().insert(first, last); } template <class InputIt> void insert(sorted_unique_range_tag tag, InputIt first, InputIt last) { evaluate_with_default().insert(tag, first, last); } template <typename... Args> void dump(Args&& ... args) const { evaluate().dump(std::forward<Args>(args)...); } template <typename... Args> void dump_pretty(Args&& ... args) const { evaluate().dump_pretty(std::forward<Args>(args)...); } void swap(basic_json& val) { evaluate_with_default().swap(val); } friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const proxy& o) { o.dump(os); return os; } template <class T> T get_with_default(const string_view_type& name, const T& default_value) const { return evaluate().template get_with_default<T>(name,default_value); } template <class T = std::basic_string<char_type>> T get_with_default(const string_view_type& name, const char_type* default_value) const { return evaluate().template get_with_default<T>(name,default_value); } std::basic_string<char_type> to_string() const { return evaluate().to_string(); } template <class IntegerType> bool is_integer() const noexcept { if (!parent_.contains(key_)) { return false; } return evaluate().template is_integer<IntegerType>(); } #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 <class T> JSONCONS_DEPRECATED_MSG("Instead, use push_back(T&&)") void add(T&& val) { evaluate_with_default().push_back(std::forward<T>(val)); } template <class T> 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<T>(val)); } template <class T> JSONCONS_DEPRECATED_MSG("Instead, use insert_or_assign(const string_view_type&, T&&)") std::pair<object_iterator,bool> set(const string_view_type& name, T&& val) { return evaluate().insert_or_assign(name,std::forward<T>(val)); } template <class T> 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<T>(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<unsigned long long>()") bool is_ulonglong() const noexcept { if (!parent_.contains(key_)) { return false; } return evaluate().template is<unsigned long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use is<long long>()") bool is_longlong() const noexcept { if (!parent_.contains(key_)) { return false; } return evaluate().template is<long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<int>()") int as_int() const { return evaluate().template as<int>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<unsigned int>()") unsigned int as_uint() const { return evaluate().template as<unsigned int>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<long>()") long as_long() const { return evaluate().template as<long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<unsigned long>()") unsigned long as_ulong() const { return evaluate().template as<unsigned long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<long long>()") long long as_longlong() const { return evaluate().template as<long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<unsigned long long>()") unsigned long long as_ulonglong() const { return evaluate().template as<unsigned long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<uint64_t>()") uint64_t as_uinteger() const { return evaluate().template as<uint64_t>(); } JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor<char_type>&)") void write(basic_json_visitor<char_type>& visitor) const { evaluate().dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&)") void write(std::basic_ostream<char_type>& os) const { evaluate().dump(os); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&)") void write(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options) const { evaluate().dump(os, options); } JSONCONS_DEPRECATED_MSG("Instead, use dump_pretty(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&)") void write(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& 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<char_type>&)") void to_stream(basic_json_visitor<char_type>& visitor) const { evaluate().dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&)") void to_stream(std::basic_ostream<char_type>& os) const { evaluate().dump(os); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&)") void to_stream(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options) const { evaluate().dump(os,options); } JSONCONS_DEPRECATED_MSG("Instead, use dump_pretty(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&)") void to_stream(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& 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 <class T> 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<object_iterator, const_object_iterator> members() { return evaluate().object_range(); } JSONCONS_DEPRECATED_MSG("Instead, use object_range()") range<const_object_iterator, const_object_iterator> members() const { return evaluate().object_range(); } JSONCONS_DEPRECATED_MSG("Instead, use array_range()") range<array_iterator, const_array_iterator> elements() { return evaluate().array_range(); } JSONCONS_DEPRECATED_MSG("Instead, use array_range()") range<const_array_iterator, const_array_iterator> 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 <class T> 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<T>(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<basic_json>; 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<long_string_storage>(); break; case json_storage_kind::byte_string_value: destroy_var<byte_string_storage>(); break; case json_storage_kind::array_value: destroy_var<array_storage>(); break; case json_storage_kind::object_value: destroy_var<object_storage>(); break; default: break; } } template <class VariantType, class... Args> void construct(Args&&... args) { ::new (&cast<VariantType>()) VariantType(std::forward<Args>(args)...); } template <class T> void destroy_var() { cast<T>().~T(); } template <class T> struct identity { using type = T*; }; template <class T> T& cast() { return cast(identity<T>()); } template <class T> const T& cast() const { return cast(identity<T>()); } null_storage& cast(identity<null_storage>) { return null_stor_; } const null_storage& cast(identity<null_storage>) const { return null_stor_; } empty_object_storage& cast(identity<empty_object_storage>) { return empty_object_stor_; } const empty_object_storage& cast(identity<empty_object_storage>) const { return empty_object_stor_; } bool_storage& cast(identity<bool_storage>) { return bool_stor_; } const bool_storage& cast(identity<bool_storage>) const { return bool_stor_; } int64_storage& cast(identity<int64_storage>) { return int64_stor_; } const int64_storage& cast(identity<int64_storage>) const { return int64_stor_; } uint64_storage& cast(identity<uint64_storage>) { return uint64_stor_; } const uint64_storage& cast(identity<uint64_storage>) const { return uint64_stor_; } half_storage& cast(identity<half_storage>) { return half_stor_; } const half_storage& cast(identity<half_storage>) const { return half_stor_; } double_storage& cast(identity<double_storage>) { return double_stor_; } const double_storage& cast(identity<double_storage>) const { return double_stor_; } short_string_storage& cast(identity<short_string_storage>) { return short_string_stor_; } const short_string_storage& cast(identity<short_string_storage>) const { return short_string_stor_; } long_string_storage& cast(identity<long_string_storage>) { return long_string_stor_; } const long_string_storage& cast(identity<long_string_storage>) const { return long_string_stor_; } byte_string_storage& cast(identity<byte_string_storage>) { return byte_string_stor_; } const byte_string_storage& cast(identity<byte_string_storage>) const { return byte_string_stor_; } object_storage& cast(identity<object_storage>) { return object_stor_; } const object_storage& cast(identity<object_storage>) const { return object_stor_; } array_storage& cast(identity<array_storage>) { return array_stor_; } const array_storage& cast(identity<array_storage>) const { return array_stor_; } json_const_pointer_storage& cast(identity<json_const_pointer_storage>) { return json_const_pointer_stor_; } const json_const_pointer_storage& cast(identity<json_const_pointer_storage>) const { return json_const_pointer_stor_; } template <class TypeA, class TypeB> void swap_a_b(basic_json& other) { TypeA& curA = cast<TypeA>(); TypeB& curB = other.cast<TypeB>(); TypeB tmpB(std::move(curB)); other.construct<TypeA>(std::move(curA)); construct<TypeB>(std::move(tmpB)); } template <class TypeA> void swap_a(basic_json& other) { switch (other.storage_kind()) { case json_storage_kind::null_value : swap_a_b<TypeA, null_storage>(other); break; case json_storage_kind::empty_object_value : swap_a_b<TypeA, empty_object_storage>(other); break; case json_storage_kind::bool_value : swap_a_b<TypeA, bool_storage>(other); break; case json_storage_kind::int64_value : swap_a_b<TypeA, int64_storage>(other); break; case json_storage_kind::uint64_value : swap_a_b<TypeA, uint64_storage>(other); break; case json_storage_kind::half_value : swap_a_b<TypeA, half_storage>(other); break; case json_storage_kind::double_value : swap_a_b<TypeA, double_storage>(other); break; case json_storage_kind::short_string_value : swap_a_b<TypeA, short_string_storage>(other); break; case json_storage_kind::long_string_value : swap_a_b<TypeA, long_string_storage>(other); break; case json_storage_kind::byte_string_value : swap_a_b<TypeA, byte_string_storage>(other); break; case json_storage_kind::array_value : swap_a_b<TypeA, array_storage>(other); break; case json_storage_kind::object_value : swap_a_b<TypeA, object_storage>(other); break; case json_storage_kind::json_const_pointer : swap_a_b<TypeA, json_const_pointer_storage>(other); break; default: JSONCONS_UNREACHABLE(); break; } } void Init_(const basic_json& val) { switch (val.storage_kind()) { case json_storage_kind::null_value: construct<null_storage>(val.cast<null_storage>()); break; case json_storage_kind::empty_object_value: construct<empty_object_storage>(val.cast<empty_object_storage>()); break; case json_storage_kind::bool_value: construct<bool_storage>(val.cast<bool_storage>()); break; case json_storage_kind::int64_value: construct<int64_storage>(val.cast<int64_storage>()); break; case json_storage_kind::uint64_value: construct<uint64_storage>(val.cast<uint64_storage>()); break; case json_storage_kind::half_value: construct<half_storage>(val.cast<half_storage>()); break; case json_storage_kind::double_value: construct<double_storage>(val.cast<double_storage>()); break; case json_storage_kind::short_string_value: construct<short_string_storage>(val.cast<short_string_storage>()); break; case json_storage_kind::long_string_value: construct<long_string_storage>(val.cast<long_string_storage>()); break; case json_storage_kind::byte_string_value: construct<byte_string_storage>(val.cast<byte_string_storage>()); break; case json_storage_kind::object_value: construct<object_storage>(val.cast<object_storage>()); break; case json_storage_kind::array_value: construct<array_storage>(val.cast<array_storage>()); break; case json_storage_kind::json_const_pointer: construct<json_const_pointer_storage>(val.cast<json_const_pointer_storage>()); 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<long_string_storage>(val.cast<long_string_storage>(),a); break; case json_storage_kind::byte_string_value: construct<byte_string_storage>(val.cast<byte_string_storage>(),a); break; case json_storage_kind::array_value: construct<array_storage>(val.cast<array_storage>(),a); break; case json_storage_kind::object_value: construct<object_storage>(val.cast<object_storage>(),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<null_storage>(); swap(val); break; } default: JSONCONS_UNREACHABLE(); break; } } void Init_rv_(basic_json&& val, const Allocator&, std::true_type) noexcept { Init_rv_(std::forward<basic_json>(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<basic_json>(val)); break; case json_storage_kind::long_string_value: { if (a == val.cast<long_string_storage>().get_allocator()) { Init_rv_(std::forward<basic_json>(val), a, std::true_type()); } else { Init_(val,a); } break; } case json_storage_kind::byte_string_value: { if (a == val.cast<byte_string_storage>().get_allocator()) { Init_rv_(std::forward<basic_json>(val), a, std::true_type()); } else { Init_(val,a); } break; } case json_storage_kind::object_value: { if (a == val.cast<object_storage>().get_allocator()) { Init_rv_(std::forward<basic_json>(val), a, std::true_type()); } else { Init_(val,a); } break; } case json_storage_kind::array_value: { if (a == val.cast<array_storage>().get_allocator()) { Init_rv_(std::forward<basic_json>(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<json_storage_kind>(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<json_const_pointer_storage>().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<json_const_pointer_storage>().value()->tag(); default: return common_stor_.tag_; } } std::size_t size() const { switch (storage_kind()) { case json_storage_kind::array_value: return cast<array_storage>().value().size(); case json_storage_kind::empty_object_value: return 0; case json_storage_kind::object_value: return cast<object_storage>().value().size(); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().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<short_string_storage>().data(),cast<short_string_storage>().length()); case json_storage_kind::long_string_value: return string_view_type(cast<long_string_storage>().data(),cast<long_string_storage>().length()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_string_view(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not a string")); } } template <typename BAllocator=std::allocator<uint8_t>> basic_byte_string<BAllocator> as_byte_string() const { using byte_string_type = basic_byte_string<BAllocator>; converter<byte_string_type> 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<BAllocator>(cast<byte_string_storage>().data(),cast<byte_string_storage>().length()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_byte_string(); default: JSONCONS_THROW(json_runtime_error<std::domain_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<byte_string_storage>().data(),cast<byte_string_storage>().length()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_byte_string_view(); default: JSONCONS_THROW(json_runtime_error<std::domain_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<json_const_pointer_storage>().value())->compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return (cast<json_const_pointer_storage>().value())->compare(rhs); } break; case json_storage_kind::null_value: return static_cast<int>(storage_kind()) - static_cast<int>((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<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((int)rhs.storage_kind()); } break; case json_storage_kind::bool_value: switch (rhs.storage_kind()) { case json_storage_kind::bool_value: return static_cast<int>(cast<bool_storage>().value()) - static_cast<int>(rhs.cast<bool_storage>().value()); case json_storage_kind::json_const_pointer: return compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((int)rhs.storage_kind()); } break; case json_storage_kind::int64_value: switch (rhs.storage_kind()) { case json_storage_kind::int64_value: { if (cast<int64_storage>().value() == rhs.cast<int64_storage>().value()) return 0; return cast<int64_storage>().value() < rhs.cast<int64_storage>().value() ? -1 : 1; } case json_storage_kind::uint64_value: if (cast<int64_storage>().value() < 0) return -1; else if (static_cast<uint64_t>(cast<int64_storage>().value()) == rhs.cast<uint64_storage>().value()) return 0; else return static_cast<uint64_t>(cast<int64_storage>().value()) < rhs.cast<uint64_storage>().value() ? -1 : 1; case json_storage_kind::double_value: { double r = static_cast<double>(cast<int64_storage>().value()) - rhs.cast<double_storage>().value(); return r == 0.0 ? 0 : (r < 0.0 ? -1 : 1); } case json_storage_kind::json_const_pointer: return compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((int)rhs.storage_kind()); } break; case json_storage_kind::uint64_value: switch (rhs.storage_kind()) { case json_storage_kind::int64_value: if (rhs.cast<int64_storage>().value() < 0) return 1; else if (cast<uint64_storage>().value() == static_cast<uint64_t>(rhs.cast<int64_storage>().value())) return 0; else return cast<uint64_storage>().value() < static_cast<uint64_t>(rhs.cast<int64_storage>().value()) ? -1 : 1; case json_storage_kind::uint64_value: if (cast<uint64_storage>().value() == static_cast<uint64_t>(rhs.cast<int64_storage>().value())) return 0; else return cast<uint64_storage>().value() < static_cast<uint64_t>(rhs.cast<int64_storage>().value()) ? -1 : 1; case json_storage_kind::double_value: { auto r = static_cast<double>(cast<uint64_storage>().value()) - rhs.cast<double_storage>().value(); return r == 0 ? 0 : (r < 0.0 ? -1 : 1); } case json_storage_kind::json_const_pointer: return compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((int)rhs.storage_kind()); } break; case json_storage_kind::double_value: switch (rhs.storage_kind()) { case json_storage_kind::int64_value: { auto r = cast<double_storage>().value() - static_cast<double>(rhs.cast<int64_storage>().value()); return r == 0 ? 0 : (r < 0.0 ? -1 : 1); } case json_storage_kind::uint64_value: { auto r = cast<double_storage>().value() - static_cast<double>(rhs.cast<uint64_storage>().value()); return r == 0 ? 0 : (r < 0.0 ? -1 : 1); } case json_storage_kind::double_value: { auto r = cast<double_storage>().value() - rhs.cast<double_storage>().value(); return r == 0 ? 0 : (r < 0.0 ? -1 : 1); } case json_storage_kind::json_const_pointer: return compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((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<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((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<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((int)rhs.storage_kind()); } break; case json_storage_kind::array_value: switch (rhs.storage_kind()) { case json_storage_kind::array_value: { if (cast<array_storage>().value() == rhs.cast<array_storage>().value()) return 0; else return cast<array_storage>().value() < rhs.cast<array_storage>().value() ? -1 : 1; } case json_storage_kind::json_const_pointer: return compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((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<object_storage>().value() == rhs.cast<object_storage>().value()) return 0; else return cast<object_storage>().value() < rhs.cast<object_storage>().value() ? -1 : 1; } case json_storage_kind::json_const_pointer: return compare(*(rhs.cast<json_const_pointer_storage>().value())); default: return static_cast<int>(storage_kind()) - static_cast<int>((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<null_storage>(other); break; case json_storage_kind::empty_object_value : swap_a<empty_object_storage>(other); break; case json_storage_kind::bool_value: swap_a<bool_storage>(other); break; case json_storage_kind::int64_value: swap_a<int64_storage>(other); break; case json_storage_kind::uint64_value: swap_a<uint64_storage>(other); break; case json_storage_kind::half_value: swap_a<half_storage>(other); break; case json_storage_kind::double_value: swap_a<double_storage>(other); break; case json_storage_kind::short_string_value: swap_a<short_string_storage>(other); break; case json_storage_kind::long_string_value: swap_a<long_string_storage>(other); break; case json_storage_kind::byte_string_value: swap_a<byte_string_storage>(other); break; case json_storage_kind::array_value: swap_a<array_storage>(other); break; case json_storage_kind::object_value: swap_a<object_storage>(other); break; case json_storage_kind::json_const_pointer: swap_a<json_const_pointer_storage>(other); break; default: JSONCONS_UNREACHABLE(); break; } } // from string template <class Source> static typename std::enable_if<type_traits::is_sequence_of<Source,char_type>::value,basic_json>::type parse(const Source& s, const basic_json_decode_options<char_type>& options = basic_json_decode_options<CharT>(), std::function<bool(json_errc,const ser_context&)> err_handler = default_json_parsing()) { json_decoder<basic_json> decoder; basic_json_parser<char_type> 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 <class Source> static typename std::enable_if<type_traits::is_sequence_of<Source,char_type>::value,basic_json>::type parse(const Source& s, std::function<bool(json_errc,const ser_context&)> err_handler) { return parse(s, basic_json_decode_options<CharT>(), err_handler); } static basic_json parse(const char_type* s, const basic_json_decode_options<char_type>& options = basic_json_decode_options<char_type>(), std::function<bool(json_errc,const ser_context&)> err_handler = default_json_parsing()) { return parse(jsoncons::basic_string_view<char_type>(s), options, err_handler); } static basic_json parse(const char_type* s, std::function<bool(json_errc,const ser_context&)> err_handler) { return parse(jsoncons::basic_string_view<char_type>(s), basic_json_decode_options<char_type>(), err_handler); } // from stream static basic_json parse(std::basic_istream<char_type>& is, const basic_json_decode_options<char_type>& options = basic_json_decode_options<CharT>(), std::function<bool(json_errc,const ser_context&)> err_handler = default_json_parsing()) { json_decoder<basic_json> visitor; basic_json_reader<char_type,stream_source<char_type>> 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<char_type>& is, std::function<bool(json_errc,const ser_context&)> err_handler) { return parse(is, basic_json_decode_options<CharT>(), err_handler); } // from iterator template <class InputIt> static basic_json parse(InputIt first, InputIt last, const basic_json_decode_options<char_type>& options = basic_json_decode_options<CharT>(), std::function<bool(json_errc,const ser_context&)> err_handler = default_json_parsing()) { json_decoder<basic_json> visitor; basic_json_reader<char_type,iterator_source<InputIt>> reader(iterator_source<InputIt>(std::forward<InputIt>(first),std::forward<InputIt>(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 <class InputIt> static basic_json parse(InputIt first, InputIt last, std::function<bool(json_errc,const ser_context&)> err_handler) { return parse(first, last, basic_json_decode_options<CharT>(), 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<basic_json> 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 <class T> static basic_json make_array(std::size_t n, const T& val, const Allocator& alloc = Allocator()) { return basic_json::array(n, val,alloc); } template <std::size_t dim> static typename std::enable_if<dim==1,basic_json>::type make_array(std::size_t n) { return array(n); } template <std::size_t dim, class T> static typename std::enable_if<dim==1,basic_json>::type make_array(std::size_t n, const T& val, const Allocator& alloc = Allocator()) { return array(n,val,alloc); } template <std::size_t dim, typename... Args> 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<dim1>(std::forward<Args>(args)...); val.resize(n); for (std::size_t i = 0; i < n; ++i) { val[i] = make_array<dim1>(std::forward<Args>(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<empty_object_storage>(semantic_tag::none); } basic_json(semantic_tag tag) { construct<empty_object_storage>(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_storage>(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<basic_json>(other)); } basic_json(basic_json&& other, const Allocator&) noexcept { Init_rv_(std::forward<basic_json>(other)); } explicit basic_json(json_object_arg_t, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator()) { construct<object_storage>(object(alloc), tag); } template<class InputIt> basic_json(json_object_arg_t, InputIt first, InputIt last, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator()) { construct<object_storage>(object(first,last,alloc), tag); } basic_json(json_object_arg_t, std::initializer_list<std::pair<std::basic_string<char_type>,basic_json>> init, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator()) { construct<object_storage>(object(init,alloc), tag); } explicit basic_json(json_array_arg_t, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator()) { construct<array_storage>(array(alloc), tag); } template<class InputIt> basic_json(json_array_arg_t, InputIt first, InputIt last, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator()) { construct<array_storage>(array(first,last,alloc), tag); } basic_json(json_array_arg_t, std::initializer_list<basic_json> init, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator()) { construct<array_storage>(array(init,alloc), tag); } basic_json(json_const_pointer_arg_t, const basic_json* p) noexcept { if (p == nullptr) { construct<null_storage>(semantic_tag::none); } else { construct<json_const_pointer_storage>(p); } } basic_json(const array& val, semantic_tag tag = semantic_tag::none) { construct<array_storage>(val, tag); } basic_json(array&& val, semantic_tag tag = semantic_tag::none) { construct<array_storage>(std::forward<array>(val), tag); } basic_json(const object& val, semantic_tag tag = semantic_tag::none) { construct<object_storage>(val, tag); } basic_json(object&& val, semantic_tag tag = semantic_tag::none) { construct<object_storage>(std::forward<object>(val), tag); } template <class T, class = typename std::enable_if<!is_proxy_of<T,basic_json>::value && !type_traits::is_basic_json<T>::value>::type> basic_json(const T& val) : basic_json(json_type_traits<basic_json,T>::to_json(val)) { } template <class T, class = typename std::enable_if<!is_proxy_of<T,basic_json>::value && !type_traits::is_basic_json<T>::value>::type> basic_json(const T& val, const Allocator& alloc) : basic_json(json_type_traits<basic_json,T>::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<short_string_storage>(tag, s, static_cast<uint8_t>(length)); } else { construct<long_string_storage>(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<short_string_storage>(tag, s, static_cast<uint8_t>(length)); } else { construct<long_string_storage>(tag, s, length, alloc); } } basic_json(half_arg_t, uint16_t val, semantic_tag tag = semantic_tag::none) { construct<half_storage>(val, tag); } basic_json(double val, semantic_tag tag) { construct<double_storage>(val, tag); } template <class IntegerType> basic_json(IntegerType val, semantic_tag tag, typename std::enable_if<type_traits::is_unsigned_integer<IntegerType>::value && sizeof(IntegerType) <= sizeof(uint64_t), int>::type = 0) { construct<uint64_storage>(val, tag); } template <class IntegerType> basic_json(IntegerType val, semantic_tag tag, Allocator, typename std::enable_if<type_traits::is_unsigned_integer<IntegerType>::value && sizeof(IntegerType) <= sizeof(uint64_t), int>::type = 0) { construct<uint64_storage>(val, tag); } template <class IntegerType> basic_json(IntegerType val, semantic_tag, Allocator alloc = Allocator(), typename std::enable_if<type_traits::is_unsigned_integer<IntegerType>::value && sizeof(uint64_t) < sizeof(IntegerType), int>::type = 0) { std::basic_string<CharT> s; jsoncons::detail::from_integer(val, s); if (s.length() <= short_string_storage::max_length) { construct<short_string_storage>(semantic_tag::bigint, s.data(), static_cast<uint8_t>(s.length())); } else { construct<long_string_storage>(semantic_tag::bigint, s.data(), s.length(), alloc); } } template <class IntegerType> basic_json(IntegerType val, semantic_tag tag, typename std::enable_if<type_traits::is_signed_integer<IntegerType>::value && sizeof(IntegerType) <= sizeof(int64_t),int>::type = 0) { construct<int64_storage>(val, tag); } template <class IntegerType> basic_json(IntegerType val, semantic_tag tag, Allocator, typename std::enable_if<type_traits::is_signed_integer<IntegerType>::value && sizeof(IntegerType) <= sizeof(int64_t),int>::type = 0) { construct<int64_storage>(val, tag); } template <class IntegerType> basic_json(IntegerType val, semantic_tag, Allocator alloc = Allocator(), typename std::enable_if<type_traits::is_signed_integer<IntegerType>::value && sizeof(int64_t) < sizeof(IntegerType),int>::type = 0) { std::basic_string<CharT> s; jsoncons::detail::from_integer(val, s); if (s.length() <= short_string_storage::max_length) { construct<short_string_storage>(semantic_tag::bigint, s.data(), static_cast<uint8_t>(s.length())); } else { construct<long_string_storage>(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<null_storage>(tag); } basic_json(bool val, semantic_tag tag) { construct<bool_storage>(val,tag); } basic_json(const string_view_type& sv, semantic_tag tag, const Allocator& alloc) : basic_json(sv.data(), sv.length(), tag, alloc) { } template <class Source> basic_json(byte_string_arg_t, const Source& source, semantic_tag tag = semantic_tag::none, const Allocator& alloc = Allocator(), typename std::enable_if<type_traits::is_byte_sequence<Source>::value,int>::type = 0) { auto bytes = jsoncons::span<const uint8_t>(reinterpret_cast<const uint8_t*>(source.data()), source.size()); construct<byte_string_storage>(tag, bytes.data(), bytes.size(), 0, alloc); } template <class Source> basic_json(byte_string_arg_t, const Source& source, uint64_t ext_tag, const Allocator& alloc = Allocator(), typename std::enable_if<type_traits::is_byte_sequence<Source>::value,int>::type = 0) { auto bytes = jsoncons::span<const uint8_t>(reinterpret_cast<const uint8_t*>(source.data()), source.size()); construct<byte_string_storage>(semantic_tag::ext, bytes.data(), bytes.size(), ext_tag, alloc); } ~basic_json() noexcept { Destroy_(); } template <class T> basic_json& operator=(const T& val) { *this = json_type_traits<basic_json,T>::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 <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump(Container& s, const basic_json_encode_options<char_type>& options = basic_json_encode_options<CharT>()) const { std::error_code ec; dump(s, options, ec); if (ec) { JSONCONS_THROW(ser_error(ec)); } } template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump_pretty(Container& s, const basic_json_encode_options<char_type>& options = basic_json_encode_options<CharT>()) const { std::error_code ec; dump_pretty(s, options, ec); if (ec) { JSONCONS_THROW(ser_error(ec)); } } void dump(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options = basic_json_encode_options<CharT>()) const { std::error_code ec; dump(os, options, ec); if (ec) { JSONCONS_THROW(ser_error(ec)); } } void dump_pretty(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options = basic_json_encode_options<CharT>()) const { std::error_code ec; dump_pretty(os, options, ec); if (ec) { JSONCONS_THROW(ser_error(ec)); } } // Legacy template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::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 <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump(Container& s, const basic_json_encode_options<char_type>& 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<char_type>& 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<char_type>& os, const basic_json_encode_options<char_type>& 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<char_type>& visitor) const { std::error_code ec; dump(visitor, ec); if (ec) { JSONCONS_THROW(ser_error(ec)); } } // dump template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump(Container& s, const basic_json_encode_options<char_type>& options, std::error_code& ec) const { basic_compact_json_encoder<char_type,jsoncons::string_sink<Container>> encoder(s, options); dump(encoder, ec); } template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump(Container& s, std::error_code& ec) const { basic_compact_json_encoder<char_type,jsoncons::string_sink<Container>> encoder(s); dump(encoder, ec); } void dump(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options, std::error_code& ec) const { basic_compact_json_encoder<char_type> encoder(os, options); dump(encoder, ec); } void dump(std::basic_ostream<char_type>& os, std::error_code& ec) const { basic_compact_json_encoder<char_type> encoder(os); dump(encoder, ec); } // dump_pretty template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump_pretty(Container& s, const basic_json_encode_options<char_type>& options, std::error_code& ec) const { basic_json_encoder<char_type,jsoncons::string_sink<Container>> encoder(s, options); dump(encoder, ec); } template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump_pretty(Container& s, std::error_code& ec) const { dump_pretty(s, basic_json_encode_options<char_type>(), ec); } void dump_pretty(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options, std::error_code& ec) const { basic_json_encoder<char_type> encoder(os, options); dump(encoder, ec); } void dump_pretty(std::basic_ostream<char_type>& os, std::error_code& ec) const { dump_pretty(os, basic_json_encode_options<char_type>(), ec); } // legacy template <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::value>::type dump(Container& s, const basic_json_encode_options<char_type>& 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 <class Container> typename std::enable_if<type_traits::is_back_insertable_char_container<Container>::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<char_type>& os, const basic_json_encode_options<char_type>& 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<char_type>& 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<char_type>& 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<json_const_pointer_storage>().value()->is_null(); default: return false; } } allocator_type get_allocator() const { switch (storage_kind()) { case json_storage_kind::long_string_value: { return cast<long_string_storage>().get_allocator(); } case json_storage_kind::byte_string_value: { return cast<byte_string_storage>().get_allocator(); } case json_storage_kind::array_value: { return cast<array_storage>().get_allocator(); } case json_storage_kind::object_value: { return cast<object_storage>().get_allocator(); } default: return allocator_type(); } } uint64_t ext_tag() const { switch (storage_kind()) { case json_storage_kind::byte_string_value: { return cast<byte_string_storage>().ext_tag(); } case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().value()->count(key); default: return 0; } } template<class T, class... Args> bool is(Args&&... args) const noexcept { return json_type_traits<basic_json,T>::is(*this,std::forward<Args>(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<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().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<uint64_t>() <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().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<int64_t>() >= 0; case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().value()->is_number(); default: return false; } } bool empty() const noexcept { switch (storage_kind()) { case json_storage_kind::byte_string_value: return cast<byte_string_storage>().length() == 0; break; case json_storage_kind::short_string_value: return cast<short_string_storage>().length() == 0; case json_storage_kind::long_string_value: return cast<long_string_storage>().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<json_const_pointer_storage>().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<json_const_pointer_storage>().value()->capacity(); default: return 0; } } template<class U=Allocator> void create_object_implicitly() { create_object_implicitly(type_traits::is_stateless<U>()); } 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 <class T> 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<class T> typename std::enable_if<is_json_type_traits_specialized<basic_json,T>::value,T>::type as() const { T val = json_type_traits<basic_json,T>::as(*this); return val; } template<class T> typename std::enable_if<(!type_traits::is_basic_string<T>::value && type_traits::is_back_insertable_byte_container<T>::value) || type_traits::is_basic_byte_string<T>::value,T>::type as(byte_string_arg_t, semantic_tag hint) const { converter<T> 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<json_const_pointer_storage>().value()->template as<T>(byte_string_arg, hint); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not a byte string")); } } bool as_bool() const { switch (storage_kind()) { case json_storage_kind::bool_value: return cast<bool_storage>().value(); case json_storage_kind::int64_value: return cast<int64_storage>().value() != 0; case json_storage_kind::uint64_value: return cast<uint64_storage>().value() != 0; case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_bool(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not a bool")); } } template <class IntegerType> 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<std::runtime_error>(result.error_code().message())); } return val; } case json_storage_kind::half_value: return static_cast<IntegerType>(cast<half_storage>().value()); case json_storage_kind::double_value: return static_cast<IntegerType>(cast<double_storage>().value()); case json_storage_kind::int64_value: return static_cast<IntegerType>(cast<int64_storage>().value()); case json_storage_kind::uint64_value: return static_cast<IntegerType>(cast<uint64_storage>().value()); case json_storage_kind::bool_value: return static_cast<IntegerType>(cast<bool_storage>().value() ? 1 : 0); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->template as_integer<IntegerType>(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not an integer")); } } template <class IntegerType> typename std::enable_if<type_traits::is_signed_integer<IntegerType>::value && sizeof(IntegerType) <= sizeof(int64_t),bool>::type is_integer() const noexcept { switch (storage_kind()) { case json_storage_kind::int64_value: return (as_integer<int64_t>() >= (type_traits::integer_limits<IntegerType>::lowest)()) && (as_integer<int64_t>() <= (type_traits::integer_limits<IntegerType>::max)()); case json_storage_kind::uint64_value: return as_integer<uint64_t>() <= static_cast<uint64_t>((type_traits::integer_limits<IntegerType>::max)()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->template is_integer<IntegerType>(); default: return false; } } template <class IntegerType> typename std::enable_if<type_traits::is_signed_integer<IntegerType>::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<int64_t>() >= (type_traits::integer_limits<IntegerType>::lowest)()) && (as_integer<int64_t>() <= (type_traits::integer_limits<IntegerType>::max)()); case json_storage_kind::uint64_value: return as_integer<uint64_t>() <= static_cast<uint64_t>((type_traits::integer_limits<IntegerType>::max)()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->template is_integer<IntegerType>(); default: return false; } } template <class IntegerType> typename std::enable_if<type_traits::is_unsigned_integer<IntegerType>::value && sizeof(IntegerType) <= sizeof(int64_t),bool>::type is_integer() const noexcept { switch (storage_kind()) { case json_storage_kind::int64_value: return as_integer<int64_t>() >= 0 && static_cast<uint64_t>(as_integer<int64_t>()) <= (type_traits::integer_limits<IntegerType>::max)(); case json_storage_kind::uint64_value: return as_integer<uint64_t>() <= (type_traits::integer_limits<IntegerType>::max)(); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->template is_integer<IntegerType>(); default: return false; } } template <class IntegerType> typename std::enable_if<type_traits::is_unsigned_integer<IntegerType>::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<int64_t>() >= 0 && static_cast<uint64_t>(as_integer<int64_t>()) <= (type_traits::integer_limits<IntegerType>::max)(); case json_storage_kind::uint64_value: return as_integer<uint64_t>() <= (type_traits::integer_limits<IntegerType>::max)(); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->template is_integer<IntegerType>(); 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<half_storage>().value()); case json_storage_kind::double_value: return cast<double_storage>().value(); case json_storage_kind::int64_value: return static_cast<double>(cast<int64_storage>().value()); case json_storage_kind::uint64_value: return static_cast<double>(cast<uint64_storage>().value()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_double(); default: JSONCONS_THROW(json_runtime_error<std::invalid_argument>("Not a double")); } } template <class SAllocator=std::allocator<char_type>> std::basic_string<char_type,char_traits_type,SAllocator> as_string() const { return as_string(SAllocator()); } template <class SAllocator=std::allocator<char_type>> std::basic_string<char_type,char_traits_type,SAllocator> as_string(const SAllocator& alloc) const { using string_type = std::basic_string<char_type,char_traits_type,SAllocator>; converter<string_type> 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<char_type,jsoncons::string_sink<string_type>> encoder(s); dump(encoder); } return s; } case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_string(alloc); default: { string_type s(alloc); basic_compact_json_encoder<char_type,jsoncons::string_sink<string_type>> encoder(s); dump(encoder); return s; } } } const char_type* as_cstring() const { switch (storage_kind()) { case json_storage_kind::short_string_value: return cast<short_string_storage>().c_str(); case json_storage_kind::long_string_value: return cast<long_string_storage>().c_str(); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->as_cstring(); default: JSONCONS_THROW(json_runtime_error<std::domain_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<json_const_pointer_storage>().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<std::out_of_range>("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<std::domain_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<std::out_of_range>("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<json_const_pointer_storage>().value()->at(i); default: JSONCONS_THROW(json_runtime_error<std::domain_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<json_const_pointer_storage>().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<json_const_pointer_storage>().value()->at_or_null(key); default: { JSONCONS_THROW(not_an_object(key.data(),key.length())); } } } template <class T,class U> T get_value_or(const string_view_type& key, U&& default_value) const { static_assert(std::is_copy_constructible<T>::value, "get_value_or: T must be copy constructible"); static_assert(std::is_convertible<U&&, T>::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<T>(std::forward<U>(default_value)); } case json_storage_kind::object_value: { auto it = object_value().find(key); if (it != object_value().end()) { return it->value().template as<T>(); } else { return static_cast<T>(std::forward<U>(default_value)); } } case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->template get_value_or<T,U>(key,std::forward<U>(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<std::domain_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<std::domain_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<std::domain_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<std::domain_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 <class T> std::pair<object_iterator,bool> 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<T>(val)); return std::make_pair(object_iterator(result.first), result.second); } default: { JSONCONS_THROW(not_an_object(name.data(),name.length())); } } } template <class ... Args> std::pair<object_iterator,bool> 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>(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<std::domain_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<std::domain_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<std::domain_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<std::domain_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<std::domain_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<std::domain_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<std::domain_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<std::domain_error>("Attempting to merge or update a value that is not an object")); } } } template <class T> 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<T>(val))); default: { JSONCONS_THROW(not_an_object(name.data(),name.length())); } } } template <class ... Args> 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>(args)...)); default: { JSONCONS_THROW(not_an_object(name.data(),name.length())); } } } template <class T> 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<T>(val)); break; default: { JSONCONS_THROW(json_runtime_error<std::domain_error>("Attempting to insert into a value that is not an array")); } } } template <class InputIt> 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<std::domain_error>("Attempting to insert into a value that is not an array")); } } } template <class InputIt> 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<key_type,basic_json>()); break; default: { JSONCONS_THROW(json_runtime_error<std::domain_error>("Attempting to insert into a value that is not an object")); } } } template <class InputIt> 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<key_type,basic_json>()); break; default: { JSONCONS_THROW(json_runtime_error<std::domain_error>("Attempting to insert into a value that is not an object")); } } } template <class... Args> 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>(args)...); break; default: { JSONCONS_THROW(json_runtime_error<std::domain_error>("Attempting to insert into a value that is not an array")); } } } template <class... Args> basic_json& emplace_back(Args&&... args) { switch (storage_kind()) { case json_storage_kind::array_value: return array_value().emplace_back(std::forward<Args>(args)...); default: { JSONCONS_THROW(json_runtime_error<std::domain_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 <class T> void push_back(T&& val) { switch (storage_kind()) { case json_storage_kind::array_value: array_value().push_back(std::forward<T>(val)); break; default: { JSONCONS_THROW(json_runtime_error<std::domain_error>("Attempting to insert into a value that is not an array")); } } } template<class T> 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<T>(); } else { return default_value; } } case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->get_with_default(key, default_value); default: { JSONCONS_THROW(not_an_object(key.data(),key.length())); } } } template<class T = std::basic_string<char_type>> 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<T>(); } else { return T(default_value); } } case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->get_with_default(key, default_value); default: { JSONCONS_THROW(not_an_object(key.data(),key.length())); } } } std::basic_string<char_type> to_string() const noexcept { using string_type = std::basic_string<char_type>; string_type s; basic_compact_json_encoder<char_type, jsoncons::string_sink<string_type>> 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<bool(json_errc,const ser_context&)> err_handler) { return parse(string_view_type(s,length),err_handler); } JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream<char_type>&)") static basic_json parse_file(const std::basic_string<char_type,char_traits_type>& filename) { parse_error_handler_type err_handler; return parse_file(filename,err_handler); } JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream<char_type>&, std::function<bool(json_errc,const ser_context&)>)") static basic_json parse_file(const std::basic_string<char_type,char_traits_type>& filename, std::function<bool(json_errc,const ser_context&)> err_handler) { std::basic_ifstream<char_type> is(filename); return parse(is,err_handler); } JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream<char_type>&)") static basic_json parse_stream(std::basic_istream<char_type>& is) { return parse(is); } JSONCONS_DEPRECATED_MSG("Instead, use parse(std::basic_istream<char_type>&, std::function<bool(json_errc,const ser_context&)>)") static basic_json parse_stream(std::basic_istream<char_type>& is, std::function<bool(json_errc,const ser_context&)> 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<bool(json_errc,const ser_context&)>)") static const basic_json parse_string(const string_view_type& s, std::function<bool(json_errc,const ser_context&)> 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<class InputIterator> 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<char_type>&)") void dump_fragment(basic_json_visitor<char_type>& visitor) const { dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor<char_type>&)") void dump_body(basic_json_visitor<char_type>& visitor) const { dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, indenting)") void dump(std::basic_ostream<char_type>& os, bool pprint) const { if (pprint) { basic_json_encoder<char_type> encoder(os); dump(encoder); } else { basic_compact_json_encoder<char_type> encoder(os); dump(encoder); } } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&, indenting)") void dump(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options, bool pprint) const { if (pprint) { basic_json_encoder<char_type> encoder(os, options); dump(encoder); } else { basic_compact_json_encoder<char_type> encoder(os, options); dump(encoder); } } JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor<char_type>&)") void write_body(basic_json_visitor<char_type>& visitor) const { dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor<char_type>&)") void write(basic_json_visitor<char_type>& visitor) const { dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&)") void write(std::basic_ostream<char_type>& os) const { dump(os); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&)") void write(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options) const { dump(os,options); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&, indenting)") void write(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options, bool pprint) const { dump(os,options,pprint); } JSONCONS_DEPRECATED_MSG("Instead, use dump(basic_json_visitor<char_type>&)") void to_stream(basic_json_visitor<char_type>& visitor) const { dump(visitor); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&)") void to_stream(std::basic_ostream<char_type>& os) const { dump(os); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&)") void to_stream(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& options) const { dump(os,options); } JSONCONS_DEPRECATED_MSG("Instead, use dump(std::basic_ostream<char_type>&, const basic_json_encode_options<char_type>&, indenting)") void to_stream(std::basic_ostream<char_type>& os, const basic_json_encode_options<char_type>& 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<std::domain_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<std::domain_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>()") uint64_t as_uinteger() const { return as<uint64_t>(); } 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<std::domain_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<basic_json>(value)); } template <class T> JSONCONS_DEPRECATED_MSG("Instead, use push_back(T&&)") void add(T&& val) { push_back(std::forward<T>(val)); } template <class T> JSONCONS_DEPRECATED_MSG("Instead, use insert(const_array_iterator, T&&)") array_iterator add(const_array_iterator pos, T&& val) { return insert(pos, std::forward<T>(val)); } template <class T> JSONCONS_DEPRECATED_MSG("Instead, use insert_or_assign(const string_view_type&, T&&)") std::pair<object_iterator,bool> set(const string_view_type& name, T&& val) { return insert_or_assign(name, std::forward<T>(val)); } template <class T> 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<T>(val)); } JSONCONS_DEPRECATED_MSG("Instead, use resize(std::size_t)") void resize_array(std::size_t n) { resize(n); } template <class T> 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<class T> 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<T>(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<T>(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<long long>()") bool is_longlong() const noexcept { return is<long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use is<unsigned long long>()") bool is_ulonglong() const noexcept { return is<unsigned long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<long long>()") long long as_longlong() const { return as<long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<unsigned long long>()") unsigned long long as_ulonglong() const { return as<unsigned long long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<int>()") int as_int() const { return as<int>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<unsigned int>()") unsigned int as_uint() const { return as<unsigned int>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<long>()") long as_long() const { return as<long>(); } JSONCONS_DEPRECATED_MSG("Instead, use as<unsigned long>()") unsigned long as_ulong() const { return as<unsigned long>(); } 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<object_iterator, const_object_iterator> members() { return object_range(); } JSONCONS_DEPRECATED_MSG("Instead, use object_range()") range<const_object_iterator, const_object_iterator> members() const { return object_range(); } JSONCONS_DEPRECATED_MSG("Instead, use array_range()") range<array_iterator, const_array_iterator> elements() { return array_range(); } JSONCONS_DEPRECATED_MSG("Instead, use array_range()") range<const_array_iterator, const_array_iterator> 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_iterator, const_object_iterator> object_range() { switch (storage_kind()) { case json_storage_kind::empty_object_value: return range<object_iterator, const_object_iterator>(object_iterator(), object_iterator()); case json_storage_kind::object_value: return range<object_iterator, const_object_iterator>(object_iterator(object_value().begin()), object_iterator(object_value().end())); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not an object")); } } range<const_object_iterator, const_object_iterator> object_range() const { switch (storage_kind()) { case json_storage_kind::empty_object_value: return range<const_object_iterator, const_object_iterator>(const_object_iterator(), const_object_iterator()); case json_storage_kind::object_value: return range<const_object_iterator, const_object_iterator>(const_object_iterator(object_value().begin()), const_object_iterator(object_value().end())); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->object_range(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not an object")); } } range<array_iterator, const_array_iterator> array_range() { switch (storage_kind()) { case json_storage_kind::array_value: return range<array_iterator, const_array_iterator>(array_value().begin(),array_value().end()); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not an array")); } } range<const_array_iterator, const_array_iterator> array_range() const { switch (storage_kind()) { case json_storage_kind::array_value: return range<const_array_iterator, const_array_iterator>(array_value().begin(),array_value().end()); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->array_range(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Not an array")); } } array& array_value() { switch (storage_kind()) { case json_storage_kind::array_value: return cast<array_storage>().value(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Bad array cast")); break; } } const array& array_value() const { switch (storage_kind()) { case json_storage_kind::array_value: return cast<array_storage>().value(); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->array_value(); default: JSONCONS_THROW(json_runtime_error<std::domain_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<object_storage>().value(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Bad object cast")); break; } } const object& object_value() const { switch (storage_kind()) { case json_storage_kind::empty_object_value: const_cast<basic_json*>(this)->create_object_implicitly(); // HERE JSONCONS_FALLTHROUGH; case json_storage_kind::object_value: return cast<object_storage>().value(); case json_storage_kind::json_const_pointer: return cast<json_const_pointer_storage>().value()->object_value(); default: JSONCONS_THROW(json_runtime_error<std::domain_error>("Bad object cast")); break; } } private: void dump_noflush(basic_json_visitor<char_type>& 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<half_storage>().value(), tag(), context, ec); break; case json_storage_kind::double_value: visitor.double_value(cast<double_storage>().value(), tag(), context, ec); break; case json_storage_kind::int64_value: visitor.int64_value(cast<int64_storage>().value(), tag(), context, ec); break; case json_storage_kind::uint64_value: visitor.uint64_value(cast<uint64_storage>().value(), tag(), context, ec); break; case json_storage_kind::bool_value: visitor.bool_value(cast<bool_storage>().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<json_const_pointer_storage>().value()->dump_noflush(visitor, ec); default: break; } } friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const basic_json& o) { o.dump(os); return os; } friend std::basic_istream<char_type>& operator>>(std::basic_istream<char_type>& is, basic_json& o) { json_decoder<basic_json> visitor; basic_json_reader<char_type,stream_source<char_type>> reader(is, visitor); reader.read_next(); reader.check_done(); if (!visitor.is_valid()) { JSONCONS_THROW(json_runtime_error<std::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<json_const_pointer_storage>().value())); default: return other; } } }; // operator== template <class Json> typename std::enable_if<type_traits::is_basic_json<Json>::value,bool>::type operator==(const Json& lhs, const Json& rhs) noexcept { return lhs.compare(rhs) == 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && std::is_convertible<T,Json>::value,bool>::type operator==(const Json& lhs, const T& rhs) { return lhs.compare(rhs) == 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator==(const Json& lhs, const T& rhs) { return lhs.evaluate().compare(rhs) == 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,Json>::value,bool>::type operator==(const T& lhs, const Json& rhs) { return rhs.compare(lhs) == 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator==(const T& lhs, const Json& rhs) { return rhs.evaluate().compare(lhs) == 0; } // operator!= template <class Json> typename std::enable_if<type_traits::is_basic_json<Json>::value,bool>::type operator!=(const Json& lhs, const Json& rhs) noexcept { return lhs.compare(rhs) != 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && std::is_convertible<T,Json>::value,bool>::type operator!=(const Json& lhs, const T& rhs) { return lhs.compare(rhs) != 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator!=(const Json& lhs, const T& rhs) { return lhs.evaluate().compare(rhs) != 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,Json>::value,bool>::type operator!=(const T& lhs, const Json& rhs) { return rhs.compare(lhs) != 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator!=(const T& lhs, const Json& rhs) { return rhs.evaluate().compare(lhs) != 0; } // operator< template <class Json> typename std::enable_if<type_traits::is_basic_json<Json>::value,bool>::type operator<(const Json& lhs, const Json& rhs) noexcept { return lhs.compare(rhs) < 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && std::is_convertible<T,Json>::value,bool>::type operator<(const Json& lhs, const T& rhs) { return lhs.compare(rhs) < 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator<(const Json& lhs, const T& rhs) { return lhs.evaluate().compare(rhs) < 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,Json>::value,bool>::type operator<(const T& lhs, const Json& rhs) { return rhs.compare(lhs) > 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator<(const T& lhs, const Json& rhs) { return rhs.evaluate().compare(lhs) > 0; } // operator<= template <class Json> typename std::enable_if<type_traits::is_basic_json<Json>::value,bool>::type operator<=(const Json& lhs, const Json& rhs) noexcept { return lhs.compare(rhs) <= 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && std::is_convertible<T,Json>::value,bool>::type operator<=(const Json& lhs, const T& rhs) { return lhs.compare(rhs) <= 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator<=(const Json& lhs, const T& rhs) { return lhs.evaluate().compare(rhs) <= 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,Json>::value,bool>::type operator<=(const T& lhs, const Json& rhs) { return rhs.compare(lhs) >= 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator<=(const T& lhs, const Json& rhs) { return rhs.evaluate().compare(lhs) >= 0; } // operator> template <class Json> typename std::enable_if<type_traits::is_basic_json<Json>::value,bool>::type operator>(const Json& lhs, const Json& rhs) noexcept { return lhs.compare(rhs) > 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && std::is_convertible<T,Json>::value,bool>::type operator>(const Json& lhs, const T& rhs) { return lhs.compare(rhs) > 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator>(const Json& lhs, const T& rhs) { return lhs.evaluate().compare(rhs) > 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,Json>::value,bool>::type operator>(const T& lhs, const Json& rhs) { return rhs.compare(lhs) < 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator>(const T& lhs, const Json& rhs) { return rhs.evaluate().compare(lhs) < 0; } // operator>= template <class Json> typename std::enable_if<type_traits::is_basic_json<Json>::value,bool>::type operator>=(const Json& lhs, const Json& rhs) noexcept { return lhs.compare(rhs) >= 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && std::is_convertible<T,Json>::value,bool>::type operator>=(const Json& lhs, const T& rhs) { return lhs.compare(rhs) >= 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator>=(const Json& lhs, const T& rhs) { return lhs.evaluate().compare(rhs) >= 0; } template <class Json, class T> typename std::enable_if<type_traits::is_basic_json<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,Json>::value,bool>::type operator>=(const T& lhs, const Json& rhs) { return rhs.compare(lhs) <= 0; } template <class Json, class T> typename std::enable_if<is_proxy<Json>::value && !is_proxy<T>::value && !type_traits::is_basic_json<T>::value && std::is_convertible<T,typename Json::proxied_type>::value,bool>::type operator>=(const T& lhs, const Json& rhs) { return rhs.evaluate().compare(lhs) <= 0; } // swap template <class Json> void swap(typename Json::key_value_type& a, typename Json::key_value_type& b) noexcept { a.swap(b); } using json = basic_json<char,sorted_policy,std::allocator<char>>; using wjson = basic_json<wchar_t,sorted_policy,std::allocator<char>>; using ojson = basic_json<char, order_preserving_policy, std::allocator<char>>; using wojson = basic_json<wchar_t, order_preserving_policy, std::allocator<char>>; #if !defined(JSONCONS_NO_DEPRECATED) JSONCONS_DEPRECATED_MSG("Instead, use wojson") typedef basic_json<wchar_t, order_preserving_policy, std::allocator<wchar_t>> owjson; JSONCONS_DEPRECATED_MSG("Instead, use json_decoder<json>") typedef json_decoder<json> json_deserializer; JSONCONS_DEPRECATED_MSG("Instead, use json_decoder<wjson>") typedef json_decoder<wjson> wjson_deserializer; JSONCONS_DEPRECATED_MSG("Instead, use json_decoder<ojson>") typedef json_decoder<ojson> ojson_deserializer; JSONCONS_DEPRECATED_MSG("Instead, use json_decoder<wojson>") typedef json_decoder<wojson> 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