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