/src/jsoncons/include/jsoncons/json_object.hpp
Line | Count | Source |
1 | | // Copyright 2013-2025 Daniel Parker |
2 | | // Distributed under the Boost license, Version 1.0. |
3 | | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
4 | | |
5 | | // See https://github.com/danielaparker/jsoncons for latest version |
6 | | |
7 | | #ifndef JSONCONS_JSON_OBJECT_HPP |
8 | | #define JSONCONS_JSON_OBJECT_HPP |
9 | | |
10 | | #include <algorithm> // std::sort, std::stable_sort, std::lower_bound, std::unique |
11 | | #include <cassert> // assert |
12 | | #include <cstring> |
13 | | #include <initializer_list> |
14 | | #include <iterator> // std::iterator_traits |
15 | | #include <memory> // std::allocator |
16 | | #include <string> |
17 | | #include <tuple> |
18 | | #include <type_traits> // std::enable_if |
19 | | #include <unordered_set> |
20 | | #include <utility> |
21 | | #include <utility> // std::move |
22 | | #include <vector> |
23 | | |
24 | | #include <jsoncons/config/compiler_support.hpp> |
25 | | #include <jsoncons/allocator_holder.hpp> |
26 | | #include <jsoncons/json_array.hpp> |
27 | | #include <jsoncons/json_exception.hpp> |
28 | | |
29 | | namespace jsoncons { |
30 | | |
31 | | template <typename Json> |
32 | | struct index_key_value |
33 | | { |
34 | | using key_type = typename Json::key_type; |
35 | | using allocator_type = typename Json::allocator_type; |
36 | | |
37 | | key_type name; |
38 | | int64_t index; |
39 | | Json value; |
40 | | |
41 | | template <typename... Args> |
42 | | index_key_value(key_type&& Name, int64_t Index, Args&& ... args) |
43 | 187M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) |
44 | 187M | { |
45 | 187M | } jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::json_object_arg_t const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::json_object_arg_t const&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 17.3M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 17.3M | { | 45 | 17.3M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::json_array_arg_t const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::json_array_arg_t const&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 11.1M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 11.1M | { | 45 | 11.1M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::null_type, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::null_type&&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 37.0M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 37.0M | { | 45 | 37.0M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<bool&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, bool&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 6.23M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 6.23M | { | 45 | 6.23M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 4.45M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 4.45M | { | 45 | 4.45M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 3.04M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 3.04M | { | 45 | 3.04M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, unsigned long&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, unsigned long&) Line | Count | Source | 43 | 143k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 143k | { | 45 | 143k | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<unsigned long&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, unsigned long&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 42.7M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 42.7M | { | 45 | 42.7M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<long&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, long&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 17.6M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 17.6M | { | 45 | 17.6M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::half_arg_t const&, unsigned short&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::half_arg_t const&, unsigned short&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 17.5M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 17.5M | { | 45 | 17.5M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<double&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, double&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 783k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 783k | { | 45 | 783k | } |
Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::json_object_arg_t const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::json_object_arg_t const&, jsoncons::semantic_tag&) jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::json_array_arg_t const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::json_array_arg_t const&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 2.01M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 2.01M | { | 45 | 2.01M | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::null_type, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::null_type&&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 29.6k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 29.6k | { | 45 | 29.6k | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<bool&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, bool&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 52.5k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 52.5k | { | 45 | 52.5k | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 26.7M | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 26.7M | { | 45 | 26.7M | } |
Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, jsoncons::semantic_tag&) Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, unsigned long&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, unsigned long&) jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<unsigned long&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, unsigned long&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 188k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 188k | { | 45 | 188k | } |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<long&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, long&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 340k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 340k | { | 45 | 340k | } |
Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::half_arg_t const&, unsigned short&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::half_arg_t const&, unsigned short&, jsoncons::semantic_tag&) jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value<double&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, double&, jsoncons::semantic_tag&) Line | Count | Source | 43 | 95.9k | : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...) | 44 | 95.9k | { | 45 | 95.9k | } |
|
46 | | |
47 | | index_key_value() = default; |
48 | | index_key_value(const index_key_value&) = default; |
49 | 336M | index_key_value(index_key_value&&) = default; jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >&&) Line | Count | Source | 49 | 283M | index_key_value(index_key_value&&) = default; |
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::index_key_value(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >&&) Line | Count | Source | 49 | 52.8M | index_key_value(index_key_value&&) = default; |
|
50 | | index_key_value(const index_key_value& other, const allocator_type& alloc) |
51 | | : name(other.name, alloc), index(0), value(other.value, alloc) |
52 | | { |
53 | | } |
54 | | index_key_value(index_key_value&& other, const allocator_type& alloc) |
55 | | : name(std::move(other.name), alloc), index(0), value(std::move(other.value), alloc) |
56 | | { |
57 | | |
58 | | } |
59 | | index_key_value& operator=(const index_key_value&) = default; |
60 | 132M | index_key_value& operator=(index_key_value&&) = default; jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::operator=(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >&&) Line | Count | Source | 60 | 132M | index_key_value& operator=(index_key_value&&) = default; |
Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::operator=(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >&&) |
61 | | }; |
62 | | |
63 | | struct sorted_unique_range_tag |
64 | | { |
65 | | explicit sorted_unique_range_tag() = default; |
66 | | }; |
67 | | |
68 | | // key_value |
69 | | |
70 | | template <typename KeyT,typename ValueT> |
71 | | class key_value |
72 | | { |
73 | | public: |
74 | | using key_type = KeyT; |
75 | | using value_type = ValueT; |
76 | | using string_view_type = typename value_type::string_view_type; |
77 | | using allocator_type = typename ValueT::allocator_type; |
78 | | private: |
79 | | |
80 | | key_type key_; |
81 | | value_type value_; |
82 | | public: |
83 | | |
84 | | template <typename... Args> |
85 | | key_value(key_type&& name, Args&& ... args) |
86 | 367k | : key_(std::move(name)), value_(std::forward<Args>(args)...) |
87 | 367k | { |
88 | 367k | } jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >&&) Line | Count | Source | 86 | 367k | : key_(std::move(name)), value_(std::forward<Args>(args)...) | 87 | 367k | { | 88 | 367k | } |
Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >&&) |
89 | | key_value(const key_value& member) |
90 | | : key_(member.key_), value_(member.value_) |
91 | | { |
92 | | } |
93 | | |
94 | | key_value(const key_value& member, const allocator_type& alloc) |
95 | | : key_(member.key_, alloc), value_(member.value_, alloc) |
96 | | { |
97 | | } |
98 | | |
99 | | key_value(key_value&& member) noexcept |
100 | 0 | : key_(std::move(member.key_)), value_(std::move(member.value_)) |
101 | 0 | { |
102 | 0 | } Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::key_value(jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >&&) Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::key_value(jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >&&) |
103 | | |
104 | | key_value(key_value&& member, const allocator_type& alloc) noexcept |
105 | | : key_(std::move(member.key_), alloc), value_(std::move(member.value_), alloc) |
106 | | { |
107 | | } |
108 | | |
109 | | const key_type& key() const |
110 | | { |
111 | | return key_; |
112 | | } |
113 | | |
114 | | value_type& value() |
115 | 579k | { |
116 | 579k | return value_; |
117 | 579k | } jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::value() Line | Count | Source | 115 | 579k | { | 116 | 579k | return value_; | 117 | 579k | } |
Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > >::value() Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::value() Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::value() |
118 | | |
119 | | const value_type& value() const |
120 | | { |
121 | | return value_; |
122 | | } |
123 | | |
124 | | template <typename T> |
125 | | void value(T&& newValue) |
126 | | { |
127 | | value_ = std::forward<T>(newValue); |
128 | | } |
129 | | |
130 | | void swap(key_value& member) noexcept |
131 | | { |
132 | | key_.swap(member.key_); |
133 | | value_.swap(member.value_); |
134 | | } |
135 | | |
136 | | key_value& operator=(const key_value& member) |
137 | | { |
138 | | if (this != & member) |
139 | | { |
140 | | key_ = member.key_; |
141 | | value_ = member.value_; |
142 | | } |
143 | | return *this; |
144 | | } |
145 | | |
146 | | key_value& operator=(key_value&& member) noexcept |
147 | | { |
148 | | if (this != &member) |
149 | | { |
150 | | key_.swap(member.key_); |
151 | | value_.swap(member.value_); |
152 | | } |
153 | | return *this; |
154 | | } |
155 | | |
156 | | void shrink_to_fit() |
157 | | { |
158 | | key_.shrink_to_fit(); |
159 | | value_.shrink_to_fit(); |
160 | | } |
161 | | |
162 | | friend bool operator==(const key_value& lhs, const key_value& rhs) noexcept |
163 | | { |
164 | | return lhs.key_ == rhs.key_ && lhs.value_ == rhs.value_; |
165 | | } |
166 | | |
167 | | friend bool operator!=(const key_value& lhs, const key_value& rhs) noexcept |
168 | | { |
169 | | return !(lhs == rhs); |
170 | | } |
171 | | |
172 | | friend bool operator<(const key_value& lhs, const key_value& rhs) noexcept |
173 | | { |
174 | | if (lhs.key_ < rhs.key_) |
175 | | { |
176 | | return true; |
177 | | } |
178 | | if (lhs.key_ == rhs.key_ && lhs.value_ < rhs.value_) |
179 | | { |
180 | | return true; |
181 | | } |
182 | | return false; |
183 | | } |
184 | | |
185 | | friend bool operator<=(const key_value& lhs, const key_value& rhs) noexcept |
186 | | { |
187 | | return !(rhs < lhs); |
188 | | } |
189 | | |
190 | | friend bool operator>(const key_value& lhs, const key_value& rhs) noexcept |
191 | | { |
192 | | return !(lhs <= rhs); |
193 | | } |
194 | | |
195 | | friend bool operator>=(const key_value& lhs, const key_value& rhs) noexcept |
196 | | { |
197 | | return !(lhs < rhs); |
198 | | } |
199 | | |
200 | | friend void swap(key_value& a, key_value& b) noexcept( |
201 | | noexcept(std::declval<key_value&>().swap(std::declval<key_value&>()))) |
202 | | { |
203 | | a.swap(b); |
204 | | } |
205 | | }; |
206 | | |
207 | | // Structured Bindings Support |
208 | | // See https://blog.tartanllama.xyz/structured-bindings/ |
209 | | template<std::size_t N,typename Key,typename Value,typename std::enable_if<N == 0, int>::type = 0> |
210 | | auto get(const key_value<Key,Value>& i) -> decltype(i.key()) |
211 | | { |
212 | | return i.key(); |
213 | | } |
214 | | // Structured Bindings Support |
215 | | // See https://blog.tartanllama.xyz/structured-bindings/ |
216 | | template<std::size_t N,typename Key,typename Value,typename std::enable_if<N == 1, int>::type = 0> |
217 | | auto get(const key_value<Key,Value>& i) -> decltype(i.value()) |
218 | | { |
219 | | return i.value(); |
220 | | } |
221 | | |
222 | | } // namespace jsoncons |
223 | | |
224 | | namespace std |
225 | | { |
226 | | #if defined(__clang__) |
227 | | // Fix: https://github.com/nlohmann/json/issues/1401 |
228 | | #pragma clang diagnostic push |
229 | | #pragma clang diagnostic ignored "-Wmismatched-tags" |
230 | | #endif |
231 | | |
232 | | template <typename Key,typename Value> |
233 | | struct tuple_size<jsoncons::key_value<Key,Value>> |
234 | | : public std::integral_constant<std::size_t, 2> {}; |
235 | | |
236 | | template <typename Key,typename Value> struct tuple_element<0, jsoncons::key_value<Key,Value>> { using type = Key; }; |
237 | | template <typename Key,typename Value> struct tuple_element<1, jsoncons::key_value<Key,Value>> { using type = Value; }; |
238 | | |
239 | | #if defined(__clang__) |
240 | | #pragma clang diagnostic pop |
241 | | #endif |
242 | | |
243 | | } // namespace std |
244 | | |
245 | | namespace jsoncons { |
246 | | |
247 | | template <typename KeyT,typename ValueT> |
248 | | struct make_key_value |
249 | | { |
250 | | using key_value_type = key_value<KeyT,ValueT>; |
251 | | |
252 | | template <typename T1,typename T2> |
253 | | key_value_type operator()(const std::pair<T1,T2>& p) |
254 | | { |
255 | | return key_value_type(KeyT(p.first),p.second); |
256 | | } |
257 | | |
258 | | template <typename T1,typename T2, typename Alloc> |
259 | | key_value_type operator()(const std::pair<T1,T2>& p, const Alloc& alloc) |
260 | | { |
261 | | return key_value_type(jsoncons::make_obj_using_allocator<KeyT>(alloc, p.first), |
262 | | p.second, alloc); |
263 | | } |
264 | | |
265 | | template <typename T1,typename T2> |
266 | | key_value_type operator()(std::pair<T1,T2>&& p) |
267 | | { |
268 | | return key_value_type(std::forward<T1>(p.first),std::forward<T2>(p.second)); |
269 | | } |
270 | | |
271 | | template <typename T1,typename T2, typename Alloc> |
272 | | key_value_type operator()(std::pair<T1,T2>&& p, const Alloc& alloc) |
273 | | { |
274 | | return key_value_type(jsoncons::make_obj_using_allocator<KeyT>(alloc, std::forward<T1>(p.first)), |
275 | | std::forward<T2>(p.second), alloc); |
276 | | } |
277 | | |
278 | | template <typename T1,typename T2> |
279 | | const key_value_type& operator()(const key_value<T1,T2>& p) |
280 | | { |
281 | | return p; |
282 | | } |
283 | | template <typename T1,typename T2> |
284 | | key_value_type operator()(key_value<T1,T2>&& p) |
285 | | { |
286 | | return std::move(p); |
287 | | } |
288 | | }; |
289 | | |
290 | | struct sort_key_order |
291 | | { |
292 | | explicit sort_key_order() = default; |
293 | | }; |
294 | | |
295 | | struct preserve_key_order |
296 | | { |
297 | | explicit preserve_key_order() = default; |
298 | | }; |
299 | | |
300 | | |
301 | | // Sort keys |
302 | | template <typename KeyT,typename Json,template <typename,typename> class SequenceContainer = std::vector> |
303 | | class sorted_json_object : public allocator_holder<typename Json::allocator_type> |
304 | | { |
305 | | public: |
306 | | using allocator_type = typename Json::allocator_type; |
307 | | using key_type = KeyT; |
308 | | using key_value_type = key_value<KeyT,Json>; |
309 | | using char_type = typename Json::char_type; |
310 | | using string_view_type = typename Json::string_view_type; |
311 | | private: |
312 | | struct Comp |
313 | | { |
314 | | bool operator() (const key_value_type& kv, string_view_type k) const { return kv.key() < k; } |
315 | | bool operator() (string_view_type k, const key_value_type& kv) const { return k < kv.key(); } |
316 | | }; |
317 | | |
318 | | using key_value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<key_value_type>; |
319 | | using key_value_container_type = SequenceContainer<key_value_type,key_value_allocator_type>; |
320 | | |
321 | | key_value_container_type members_; |
322 | | public: |
323 | | using iterator = typename key_value_container_type::iterator; |
324 | | using const_iterator = typename key_value_container_type::const_iterator; |
325 | | |
326 | | using allocator_holder<allocator_type>::get_allocator; |
327 | | |
328 | | sorted_json_object() |
329 | 17.3M | { |
330 | 17.3M | } |
331 | | |
332 | | explicit sorted_json_object(const allocator_type& alloc) |
333 | | : allocator_holder<allocator_type>(alloc), |
334 | | members_(key_value_allocator_type(alloc)) |
335 | | { |
336 | | } |
337 | | |
338 | | sorted_json_object(const sorted_json_object& other) |
339 | | : allocator_holder<allocator_type>(other.get_allocator()), |
340 | | members_(other.members_) |
341 | | { |
342 | | } |
343 | | |
344 | | sorted_json_object(const sorted_json_object& other, const allocator_type& alloc) |
345 | | : allocator_holder<allocator_type>(alloc), |
346 | | members_(other.members_,key_value_allocator_type(alloc)) |
347 | | { |
348 | | } |
349 | | |
350 | | sorted_json_object(sorted_json_object&& other) noexcept |
351 | | : allocator_holder<allocator_type>(other.get_allocator()), |
352 | | members_(std::move(other.members_)) |
353 | | { |
354 | | } |
355 | | |
356 | | sorted_json_object(sorted_json_object&& other,const allocator_type& alloc) |
357 | | : allocator_holder<allocator_type>(alloc), members_(std::move(other.members_),key_value_allocator_type(alloc)) |
358 | | { |
359 | | } |
360 | | |
361 | | sorted_json_object& operator=(const sorted_json_object& other) |
362 | | { |
363 | | members_ = other.members_; |
364 | | return *this; |
365 | | } |
366 | | |
367 | | sorted_json_object& operator=(sorted_json_object&& other) noexcept |
368 | | { |
369 | | other.swap(*this); |
370 | | return *this; |
371 | | } |
372 | | |
373 | | template <typename InputIt> |
374 | | sorted_json_object(InputIt first, InputIt last) |
375 | | { |
376 | | std::size_t count = std::distance(first,last); |
377 | | members_.reserve(count); |
378 | | for (auto it = first; it != last; ++it) |
379 | | { |
380 | | auto kv = make_key_value<KeyT,Json>()(*it); |
381 | | members_.emplace_back(std::move(kv)); |
382 | | } |
383 | | std::stable_sort(members_.begin(),members_.end(), |
384 | | [](const key_value_type& a, const key_value_type& b) -> bool {return a.key().compare(b.key()) < 0;}); |
385 | | auto last2 = std::unique(members_.begin(), members_.end(), |
386 | | [](const key_value_type& a, const key_value_type& b) -> bool { return !(a.key().compare(b.key()));}); |
387 | | members_.erase(last2, members_.end()); |
388 | | } |
389 | | |
390 | | template <typename InputIt> |
391 | | sorted_json_object(InputIt first, InputIt last, const allocator_type& alloc) |
392 | | : allocator_holder<allocator_type>(alloc), |
393 | | members_(key_value_allocator_type(alloc)) |
394 | | { |
395 | | std::size_t count = std::distance(first,last); |
396 | | members_.reserve(count); |
397 | | for (auto it = first; it != last; ++it) |
398 | | { |
399 | | auto kv = make_key_value<KeyT,Json>()(*it, alloc); |
400 | | members_.emplace_back(std::move(kv)); |
401 | | } |
402 | | std::stable_sort(members_.begin(), members_.end(), |
403 | | [](const key_value_type& a, const key_value_type& b) -> bool {return a.key().compare(b.key()) < 0;}); |
404 | | auto last2 = std::unique(members_.begin(), members_.end(), |
405 | | [](const key_value_type& a, const key_value_type& b) -> bool { return !(a.key().compare(b.key()));}); |
406 | | members_.erase(last2, members_.end()); |
407 | | } |
408 | | |
409 | | sorted_json_object(const std::initializer_list<std::pair<std::basic_string<char_type>,Json>>& init, |
410 | | const allocator_type& alloc = allocator_type()) |
411 | | : allocator_holder<allocator_type>(alloc), |
412 | | members_(key_value_allocator_type(alloc)) |
413 | | { |
414 | | members_.reserve(init.size()); |
415 | | for (auto& item : init) |
416 | | { |
417 | | insert_or_assign(item.first, item.second); |
418 | | } |
419 | | } |
420 | | |
421 | | ~sorted_json_object() noexcept |
422 | 17.3M | { |
423 | 17.3M | flatten_and_destroy(); |
424 | 17.3M | } |
425 | | |
426 | | bool empty() const |
427 | 70.7k | { |
428 | 70.7k | return members_.empty(); |
429 | 70.7k | } jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const Line | Count | Source | 427 | 70.7k | { | 428 | 70.7k | return members_.empty(); | 429 | 70.7k | } |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const |
430 | | |
431 | | void swap(sorted_json_object& other) noexcept |
432 | | { |
433 | | members_.swap(other.members_); |
434 | | } |
435 | | |
436 | | iterator begin() |
437 | 6.09M | { |
438 | 6.09M | return members_.begin(); |
439 | 6.09M | } jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::begin() Line | Count | Source | 437 | 6.09M | { | 438 | 6.09M | return members_.begin(); | 439 | 6.09M | } |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::begin() |
440 | | |
441 | | iterator end() |
442 | 6.09M | { |
443 | 6.09M | return members_.end(); |
444 | 6.09M | } jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::end() Line | Count | Source | 442 | 6.09M | { | 443 | 6.09M | return members_.end(); | 444 | 6.09M | } |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::end() |
445 | | |
446 | | const_iterator begin() const |
447 | | { |
448 | | return members_.begin(); |
449 | | } |
450 | | |
451 | | const_iterator end() const |
452 | | { |
453 | | return members_.end(); |
454 | | } |
455 | | |
456 | | std::size_t size() const {return members_.size();} |
457 | | |
458 | | std::size_t capacity() const {return members_.capacity();} |
459 | | |
460 | 6.09M | void clear() {members_.clear();}jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::clear() Line | Count | Source | 460 | 6.09M | void clear() {members_.clear();} |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::clear() |
461 | | |
462 | | void shrink_to_fit() |
463 | | { |
464 | | for (std::size_t i = 0; i < members_.size(); ++i) |
465 | | { |
466 | | members_[i].shrink_to_fit(); |
467 | | } |
468 | | members_.shrink_to_fit(); |
469 | | } |
470 | | |
471 | 0 | void reserve(std::size_t n) {members_.reserve(n);}Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long) Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long) |
472 | | |
473 | | Json& at(std::size_t i) |
474 | | { |
475 | | if (i >= members_.size()) |
476 | | { |
477 | | JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript")); |
478 | | } |
479 | | return members_[i].value(); |
480 | | } |
481 | | |
482 | | const Json& at(std::size_t i) const |
483 | | { |
484 | | if (i >= members_.size()) |
485 | | { |
486 | | JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript")); |
487 | | } |
488 | | return members_[i].value(); |
489 | | } |
490 | | |
491 | | iterator find(const string_view_type& name) noexcept |
492 | | { |
493 | | auto p = std::equal_range(members_.begin(),members_.end(), name, |
494 | | Comp()); |
495 | | return p.first == p.second ? members_.end() : p.first; |
496 | | } |
497 | | |
498 | | const_iterator find(const string_view_type& name) const noexcept |
499 | | { |
500 | | auto p = std::equal_range(members_.begin(),members_.end(), name, |
501 | | Comp()); |
502 | | return p.first == p.second ? members_.end() : p.first; |
503 | | } |
504 | | |
505 | | iterator erase(const_iterator pos) |
506 | | { |
507 | | return members_.erase(pos); |
508 | | } |
509 | | |
510 | | iterator erase(const_iterator first, const_iterator last) |
511 | | { |
512 | | return members_.erase(first,last); |
513 | | } |
514 | | |
515 | | void erase(const string_view_type& name) |
516 | | { |
517 | | auto it = find(name); |
518 | | if (it != members_.end()) |
519 | | { |
520 | | members_.erase(it); |
521 | | } |
522 | | } |
523 | | |
524 | | static bool compare(const index_key_value<Json>& item1, const index_key_value<Json>& item2) |
525 | 542M | { |
526 | 542M | int comp = item1.name.compare(item2.name); |
527 | 542M | if (comp < 0) return true; |
528 | 535M | if (comp == 0) return item1.index < item2.index; |
529 | | |
530 | 5.03M | return false; |
531 | 535M | } jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::compare(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > const&) Line | Count | Source | 525 | 542M | { | 526 | 542M | int comp = item1.name.compare(item2.name); | 527 | 542M | if (comp < 0) return true; | 528 | 535M | if (comp == 0) return item1.index < item2.index; | 529 | | | 530 | 5.03M | return false; | 531 | 535M | } |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::compare(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > > const&) |
532 | | |
533 | | void uninitialized_init(index_key_value<Json>* items, std::size_t count) |
534 | 94.3k | { |
535 | 94.3k | if (count > 0) |
536 | 94.3k | { |
537 | 94.3k | members_.reserve(count); |
538 | | |
539 | 94.3k | std::sort(items, items+count, compare); |
540 | 94.3k | members_.emplace_back(key_type(items[0].name.data(), items[0].name.size(), get_allocator()), std::move(items[0].value)); |
541 | | |
542 | 24.4M | for (std::size_t i = 1; i < count; ++i) |
543 | 24.3M | { |
544 | 24.3M | auto& item = items[i]; |
545 | 24.3M | if (item.name != items[i-1].name) |
546 | 273k | { |
547 | 273k | members_.emplace_back(key_type(item.name.data(), item.name.size(), get_allocator()), std::move(item.value)); |
548 | 273k | } |
549 | 24.3M | } |
550 | 94.3k | } |
551 | 94.3k | } jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >*, unsigned long) Line | Count | Source | 534 | 94.3k | { | 535 | 94.3k | if (count > 0) | 536 | 94.3k | { | 537 | 94.3k | members_.reserve(count); | 538 | | | 539 | 94.3k | std::sort(items, items+count, compare); | 540 | 94.3k | members_.emplace_back(key_type(items[0].name.data(), items[0].name.size(), get_allocator()), std::move(items[0].value)); | 541 | | | 542 | 24.4M | for (std::size_t i = 1; i < count; ++i) | 543 | 24.3M | { | 544 | 24.3M | auto& item = items[i]; | 545 | 24.3M | if (item.name != items[i-1].name) | 546 | 273k | { | 547 | 273k | members_.emplace_back(key_type(item.name.data(), item.name.size(), get_allocator()), std::move(item.value)); | 548 | 273k | } | 549 | 24.3M | } | 550 | 94.3k | } | 551 | 94.3k | } |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > >*, unsigned long) |
552 | | |
553 | | template <typename InputIt> |
554 | | void insert(InputIt first, InputIt last) |
555 | | { |
556 | | for (auto it = first; it != last; ++it) |
557 | | { |
558 | | members_.emplace_back(key_type((*it).first.c_str(), (*it).first.size(), get_allocator()), (*it).second); |
559 | | } |
560 | | std::stable_sort(members_.begin(),members_.end(), |
561 | | [](const key_value_type& a, const key_value_type& b) -> bool {return a.key().compare(b.key()) < 0;}); |
562 | | auto last2 = std::unique(members_.begin(), members_.end(), |
563 | | [](const key_value_type& a, const key_value_type& b) -> bool { return !(a.key().compare(b.key()));}); |
564 | | members_.erase(last2, members_.end()); |
565 | | } |
566 | | |
567 | | template <typename InputIt> |
568 | | void insert(sorted_unique_range_tag, InputIt first, InputIt last) |
569 | | { |
570 | | if (first != last) |
571 | | { |
572 | | auto it = find(convert(*first).key()); |
573 | | if (it != members_.end()) |
574 | | { |
575 | | for (auto s = first; s != last; ++s) |
576 | | { |
577 | | it = members_.emplace(it, key_type(s->first, get_allocator()), s->second); |
578 | | } |
579 | | } |
580 | | else |
581 | | { |
582 | | for (auto s = first; s != last; ++s) |
583 | | { |
584 | | members_.emplace_back(convert(*s)); |
585 | | } |
586 | | } |
587 | | } |
588 | | } |
589 | | |
590 | | // insert_or_assign |
591 | | |
592 | | template <typename T,typename A=allocator_type> |
593 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
594 | | insert_or_assign(const string_view_type& name, T&& value) |
595 | | { |
596 | | bool inserted; |
597 | | auto it = std::lower_bound(members_.begin(),members_.end(), name, Comp()); |
598 | | if (it == members_.end()) |
599 | | { |
600 | | members_.emplace_back(key_type(name.begin(),name.end()), std::forward<T>(value)); |
601 | | inserted = true; |
602 | | it = members_.begin() + members_.size() - 1; |
603 | | } |
604 | | else if ((*it).key() == name) |
605 | | { |
606 | | (*it).value(Json(std::forward<T>(value))); |
607 | | inserted = false; // assigned |
608 | | } |
609 | | else |
610 | | { |
611 | | it = members_.emplace(it, key_type(name.begin(),name.end()), std::forward<T>(value)); |
612 | | inserted = true; |
613 | | } |
614 | | return std::make_pair(it,inserted); |
615 | | } |
616 | | |
617 | | template <typename T,typename A=allocator_type> |
618 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
619 | | insert_or_assign(const string_view_type& name, T&& value) |
620 | | { |
621 | | bool inserted; |
622 | | auto it = std::lower_bound(members_.begin(),members_.end(), name, |
623 | | Comp()); |
624 | | if (it == members_.end()) |
625 | | { |
626 | | members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), std::forward<T>(value)); |
627 | | inserted = true; |
628 | | it = members_.begin() + members_.size() - 1; |
629 | | } |
630 | | else if ((*it).key() == name) |
631 | | { |
632 | | (*it).value(Json(std::forward<T>(value), get_allocator())); |
633 | | inserted = false; // assigned |
634 | | } |
635 | | else |
636 | | { |
637 | | it = members_.emplace(it, key_type(name.begin(),name.end(), get_allocator()), |
638 | | std::forward<T>(value)); |
639 | | inserted = true; |
640 | | } |
641 | | return std::make_pair(it,inserted); |
642 | | } |
643 | | |
644 | | // try_emplace |
645 | | |
646 | | template <typename A=allocator_type,typename... Args> |
647 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
648 | | try_emplace(const string_view_type& name, Args&&... args) |
649 | | { |
650 | | bool inserted; |
651 | | auto it = std::lower_bound(members_.begin(),members_.end(), name, |
652 | | Comp()); |
653 | | if (it == members_.end()) |
654 | | { |
655 | | members_.emplace_back(key_type(name.begin(),name.end()), std::forward<Args>(args)...); |
656 | | it = members_.begin() + members_.size() - 1; |
657 | | inserted = true; |
658 | | } |
659 | | else if ((*it).key() == name) |
660 | | { |
661 | | inserted = false; |
662 | | } |
663 | | else |
664 | | { |
665 | | it = members_.emplace(it, key_type(name.begin(),name.end()), |
666 | | std::forward<Args>(args)...); |
667 | | inserted = true; |
668 | | } |
669 | | return std::make_pair(it,inserted); |
670 | | } |
671 | | |
672 | | template <typename A=allocator_type,typename... Args> |
673 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
674 | | try_emplace(const string_view_type& name, Args&&... args) |
675 | | { |
676 | | bool inserted; |
677 | | auto it = std::lower_bound(members_.begin(),members_.end(), name, |
678 | | Comp()); |
679 | | if (it == members_.end()) |
680 | | { |
681 | | members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), std::forward<Args>(args)...); |
682 | | it = members_.begin() + members_.size() - 1; |
683 | | inserted = true; |
684 | | } |
685 | | else if ((*it).key() == name) |
686 | | { |
687 | | inserted = false; |
688 | | } |
689 | | else |
690 | | { |
691 | | it = members_.emplace(it, |
692 | | key_type(name.begin(),name.end(), get_allocator()), |
693 | | std::forward<Args>(args)...); |
694 | | inserted = true; |
695 | | } |
696 | | return std::make_pair(it,inserted); |
697 | | } |
698 | | |
699 | | template <typename A=allocator_type,typename ... Args> |
700 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type |
701 | | try_emplace(iterator hint, const string_view_type& name, Args&&... args) |
702 | | { |
703 | | iterator it = hint; |
704 | | |
705 | | if (hint != members_.end() && hint->key() <= name) |
706 | | { |
707 | | it = std::lower_bound(hint,members_.end(), name, |
708 | | Comp()); |
709 | | } |
710 | | else |
711 | | { |
712 | | it = std::lower_bound(members_.begin(),members_.end(), name, |
713 | | Comp()); |
714 | | } |
715 | | |
716 | | if (it == members_.end()) |
717 | | { |
718 | | members_.emplace_back(key_type(name.begin(),name.end()), |
719 | | std::forward<Args>(args)...); |
720 | | it = members_.begin() + (members_.size() - 1); |
721 | | } |
722 | | else if ((*it).key() == name) |
723 | | { |
724 | | } |
725 | | else |
726 | | { |
727 | | it = members_.emplace(it, |
728 | | key_type(name.begin(),name.end()), |
729 | | std::forward<Args>(args)...); |
730 | | } |
731 | | |
732 | | return it; |
733 | | } |
734 | | |
735 | | template <typename A=allocator_type,typename ... Args> |
736 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type |
737 | | try_emplace(iterator hint, const string_view_type& name, Args&&... args) |
738 | | { |
739 | | iterator it = hint; |
740 | | if (hint != members_.end() && hint->key() <= name) |
741 | | { |
742 | | it = std::lower_bound(hint,members_.end(), name, |
743 | | Comp()); |
744 | | } |
745 | | else |
746 | | { |
747 | | it = std::lower_bound(members_.begin(),members_.end(), name, |
748 | | Comp()); |
749 | | } |
750 | | |
751 | | if (it == members_.end()) |
752 | | { |
753 | | members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), |
754 | | std::forward<Args>(args)...); |
755 | | it = members_.begin() + (members_.size() - 1); |
756 | | } |
757 | | else if ((*it).key() == name) |
758 | | { |
759 | | } |
760 | | else |
761 | | { |
762 | | it = members_.emplace(it, |
763 | | key_type(name.begin(),name.end(), get_allocator()), |
764 | | std::forward<Args>(args)...); |
765 | | } |
766 | | return it; |
767 | | } |
768 | | |
769 | | // insert_or_assign |
770 | | |
771 | | template <typename T,typename A=allocator_type> |
772 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type |
773 | | insert_or_assign(iterator hint, const string_view_type& name, T&& value) |
774 | | { |
775 | | iterator it; |
776 | | if (hint != members_.end() && hint->key() <= name) |
777 | | { |
778 | | it = std::lower_bound(hint,members_.end(), name, |
779 | | [](const key_value_type& a, const string_view_type& k) -> bool {return string_view_type(a.key()).compare(k) < 0;}); |
780 | | } |
781 | | else |
782 | | { |
783 | | it = std::lower_bound(members_.begin(),members_.end(), name, |
784 | | [](const key_value_type& a, const string_view_type& k) -> bool {return string_view_type(a.key()).compare(k) < 0;}); |
785 | | } |
786 | | |
787 | | if (it == members_.end()) |
788 | | { |
789 | | members_.emplace_back(key_type(name.begin(),name.end()), std::forward<T>(value)); |
790 | | it = members_.begin() + (members_.size() - 1); |
791 | | } |
792 | | else if ((*it).key() == name) |
793 | | { |
794 | | (*it).value(Json(std::forward<T>(value))); |
795 | | } |
796 | | else |
797 | | { |
798 | | it = members_.emplace(it, key_type(name.begin(),name.end()), std::forward<T>(value)); |
799 | | } |
800 | | return it; |
801 | | } |
802 | | |
803 | | template <typename T,typename A=allocator_type> |
804 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type |
805 | | insert_or_assign(iterator hint, const string_view_type& name, T&& value) |
806 | | { |
807 | | iterator it; |
808 | | if (hint != members_.end() && hint->key() <= name) |
809 | | { |
810 | | it = std::lower_bound(hint,members_.end(), name, |
811 | | Comp()); |
812 | | } |
813 | | else |
814 | | { |
815 | | it = std::lower_bound(members_.begin(),members_.end(), name, |
816 | | Comp()); |
817 | | } |
818 | | |
819 | | if (it == members_.end()) |
820 | | { |
821 | | members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), std::forward<T>(value)); |
822 | | it = members_.begin() + (members_.size() - 1); |
823 | | } |
824 | | else if ((*it).key() == name) |
825 | | { |
826 | | (*it).value(Json(std::forward<T>(value),get_allocator())); |
827 | | } |
828 | | else |
829 | | { |
830 | | it = members_.emplace(it, key_type(name.begin(),name.end(), get_allocator()), |
831 | | std::forward<T>(value)); |
832 | | } |
833 | | return it; |
834 | | } |
835 | | |
836 | | // merge |
837 | | |
838 | | void merge(const sorted_json_object& source) |
839 | | { |
840 | | for (auto it = source.begin(); it != source.end(); ++it) |
841 | | { |
842 | | try_emplace((*it).key(),(*it).value()); |
843 | | } |
844 | | } |
845 | | |
846 | | void merge(sorted_json_object&& source) |
847 | | { |
848 | | auto it = std::make_move_iterator(source.begin()); |
849 | | auto end = std::make_move_iterator(source.end()); |
850 | | for (; it != end; ++it) |
851 | | { |
852 | | auto pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), |
853 | | Comp()); |
854 | | if (pos == members_.end()) |
855 | | { |
856 | | members_.emplace_back(*it); |
857 | | } |
858 | | else if ((*it).key() != pos->key()) |
859 | | { |
860 | | members_.emplace(pos,*it); |
861 | | } |
862 | | } |
863 | | } |
864 | | |
865 | | void merge(iterator hint, const sorted_json_object& source) |
866 | | { |
867 | | for (auto it = source.begin(); it != source.end(); ++it) |
868 | | { |
869 | | hint = try_emplace(hint, (*it).key(),(*it).value()); |
870 | | } |
871 | | } |
872 | | |
873 | | void merge(iterator hint, sorted_json_object&& source) |
874 | | { |
875 | | auto it = std::make_move_iterator(source.begin()); |
876 | | auto end = std::make_move_iterator(source.end()); |
877 | | for (; it != end; ++it) |
878 | | { |
879 | | iterator pos; |
880 | | if (hint != members_.end() && hint->key() <= (*it).key()) |
881 | | { |
882 | | pos = std::lower_bound(hint,members_.end(), (*it).key(), |
883 | | Comp()); |
884 | | } |
885 | | else |
886 | | { |
887 | | pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), |
888 | | Comp()); |
889 | | } |
890 | | if (pos == members_.end()) |
891 | | { |
892 | | members_.emplace_back(*it); |
893 | | hint = members_.begin() + (members_.size() - 1); |
894 | | } |
895 | | else if ((*it).key() != pos->key()) |
896 | | { |
897 | | hint = members_.emplace(pos,*it); |
898 | | } |
899 | | } |
900 | | } |
901 | | |
902 | | // merge_or_update |
903 | | |
904 | | void merge_or_update(const sorted_json_object& source) |
905 | | { |
906 | | for (auto it = source.begin(); it != source.end(); ++it) |
907 | | { |
908 | | insert_or_assign((*it).key(),(*it).value()); |
909 | | } |
910 | | } |
911 | | |
912 | | void merge_or_update(sorted_json_object&& source) |
913 | | { |
914 | | auto it = std::make_move_iterator(source.begin()); |
915 | | auto end = std::make_move_iterator(source.end()); |
916 | | for (; it != end; ++it) |
917 | | { |
918 | | auto pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), |
919 | | Comp()); |
920 | | if (pos == members_.end()) |
921 | | { |
922 | | members_.emplace_back(*it); |
923 | | } |
924 | | else |
925 | | { |
926 | | pos->value((*it).value()); |
927 | | } |
928 | | } |
929 | | } |
930 | | |
931 | | void merge_or_update(iterator hint, const sorted_json_object& source) |
932 | | { |
933 | | for (auto it = source.begin(); it != source.end(); ++it) |
934 | | { |
935 | | hint = insert_or_assign(hint, (*it).key(),(*it).value()); |
936 | | } |
937 | | } |
938 | | |
939 | | void merge_or_update(iterator hint, sorted_json_object&& source) |
940 | | { |
941 | | auto it = std::make_move_iterator(source.begin()); |
942 | | auto end = std::make_move_iterator(source.end()); |
943 | | for (; it != end; ++it) |
944 | | { |
945 | | iterator pos; |
946 | | if (hint != members_.end() && hint->key() <= (*it).key()) |
947 | | { |
948 | | pos = std::lower_bound(hint,members_.end(), (*it).key(), |
949 | | Comp()); |
950 | | } |
951 | | else |
952 | | { |
953 | | pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), |
954 | | Comp()); |
955 | | } |
956 | | if (pos == members_.end()) |
957 | | { |
958 | | members_.emplace_back(*it); |
959 | | hint = members_.begin() + (members_.size() - 1); |
960 | | } |
961 | | else |
962 | | { |
963 | | pos->value((*it).value()); |
964 | | hint = pos; |
965 | | } |
966 | | } |
967 | | } |
968 | | |
969 | | bool operator==(const sorted_json_object& rhs) const |
970 | | { |
971 | | return members_ == rhs.members_; |
972 | | } |
973 | | |
974 | | bool operator<(const sorted_json_object& rhs) const |
975 | | { |
976 | | return members_ < rhs.members_; |
977 | | } |
978 | | private: |
979 | | |
980 | | void flatten_and_destroy() noexcept |
981 | 17.3M | { |
982 | 17.3M | if (!members_.empty()) |
983 | 57.0k | { |
984 | 57.0k | json_array<Json> temp(get_allocator()); |
985 | | |
986 | 57.0k | for (auto& kv : members_) |
987 | 261k | { |
988 | 261k | switch (kv.value().storage_kind()) |
989 | 261k | { |
990 | 20.6k | case json_storage_kind::array: |
991 | 36.7k | case json_storage_kind::object: |
992 | 36.7k | if (!kv.value().empty()) |
993 | 16.3k | { |
994 | 16.3k | temp.emplace_back(std::move(kv.value())); |
995 | 16.3k | } |
996 | 36.7k | break; |
997 | 224k | default: |
998 | 224k | break; |
999 | 261k | } |
1000 | 261k | } |
1001 | 57.0k | } |
1002 | 17.3M | } jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy() Line | Count | Source | 981 | 17.3M | { | 982 | 17.3M | if (!members_.empty()) | 983 | 57.0k | { | 984 | 57.0k | json_array<Json> temp(get_allocator()); | 985 | | | 986 | 57.0k | for (auto& kv : members_) | 987 | 261k | { | 988 | 261k | switch (kv.value().storage_kind()) | 989 | 261k | { | 990 | 20.6k | case json_storage_kind::array: | 991 | 36.7k | case json_storage_kind::object: | 992 | 36.7k | if (!kv.value().empty()) | 993 | 16.3k | { | 994 | 16.3k | temp.emplace_back(std::move(kv.value())); | 995 | 16.3k | } | 996 | 36.7k | break; | 997 | 224k | default: | 998 | 224k | break; | 999 | 261k | } | 1000 | 261k | } | 1001 | 57.0k | } | 1002 | 17.3M | } |
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy() |
1003 | | }; |
1004 | | |
1005 | | // Preserve order |
1006 | | template <typename KeyT,typename Json,template <typename,typename> class SequenceContainer = std::vector> |
1007 | | class order_preserving_json_object : public allocator_holder<typename Json::allocator_type> |
1008 | | { |
1009 | | public: |
1010 | | using allocator_type = typename Json::allocator_type; |
1011 | | using char_type = typename Json::char_type; |
1012 | | using key_type = KeyT; |
1013 | | using string_view_type = typename Json::string_view_type; |
1014 | | using key_value_type = key_value<KeyT,Json>; |
1015 | | private: |
1016 | | struct MyHash |
1017 | | { |
1018 | | std::uintmax_t operator()(const key_type& s) const noexcept |
1019 | | { |
1020 | | const int p = 31; |
1021 | | const int m = static_cast<int>(1e9) + 9; |
1022 | | std::uintmax_t hash_value = 0; |
1023 | | std::uintmax_t p_pow = 1; |
1024 | | for (char_type c : s) { |
1025 | | hash_value = (hash_value + (c - 'a' + 1) * p_pow) % m; |
1026 | | p_pow = (p_pow * p) % m; |
1027 | | } |
1028 | | return hash_value; |
1029 | | } |
1030 | | }; |
1031 | | |
1032 | | using key_value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<key_value_type>; |
1033 | | using key_value_container_type = SequenceContainer<key_value_type,key_value_allocator_type>; |
1034 | | |
1035 | | key_value_container_type members_; |
1036 | | |
1037 | | struct Comp |
1038 | | { |
1039 | | const key_value_container_type& members_; |
1040 | | |
1041 | | Comp(const key_value_container_type& members_) |
1042 | | : members_(members_) |
1043 | | { |
1044 | | } |
1045 | | |
1046 | | bool operator() (std::size_t i, string_view_type k) const { return members_.at(i).key() < k; } |
1047 | | bool operator() (string_view_type k, std::size_t i) const { return k < members_.at(i).key(); } |
1048 | | }; |
1049 | | public: |
1050 | | using iterator = typename key_value_container_type::iterator; |
1051 | | using const_iterator = typename key_value_container_type::const_iterator; |
1052 | | |
1053 | | using allocator_holder<allocator_type>::get_allocator; |
1054 | | |
1055 | | order_preserving_json_object() |
1056 | 0 | { |
1057 | 0 | } |
1058 | | order_preserving_json_object(const allocator_type& alloc) |
1059 | | : allocator_holder<allocator_type>(alloc), |
1060 | | members_(key_value_allocator_type(alloc)) |
1061 | | { |
1062 | | } |
1063 | | |
1064 | | order_preserving_json_object(const order_preserving_json_object& val) |
1065 | | : allocator_holder<allocator_type>(val.get_allocator()), |
1066 | | members_(val.members_) |
1067 | | { |
1068 | | } |
1069 | | |
1070 | | order_preserving_json_object(order_preserving_json_object&& val,const allocator_type& alloc) |
1071 | | : allocator_holder<allocator_type>(alloc), |
1072 | | members_(std::move(val.members_),key_value_allocator_type(alloc)) |
1073 | | { |
1074 | | } |
1075 | | |
1076 | | order_preserving_json_object(order_preserving_json_object&& val) noexcept |
1077 | | : allocator_holder<allocator_type>(val.get_allocator()), |
1078 | | members_(std::move(val.members_)) |
1079 | | { |
1080 | | } |
1081 | | |
1082 | | order_preserving_json_object(const order_preserving_json_object& val, const allocator_type& alloc) |
1083 | | : allocator_holder<allocator_type>(alloc), |
1084 | | members_(val.members_,key_value_allocator_type(alloc)) |
1085 | | { |
1086 | | } |
1087 | | |
1088 | | template <typename InputIt> |
1089 | | order_preserving_json_object(InputIt first, InputIt last) |
1090 | | { |
1091 | | std::size_t count = std::distance(first,last); |
1092 | | members_.reserve(count); |
1093 | | std::unordered_set<key_type,MyHash> keys; |
1094 | | for (auto it = first; it != last; ++it) |
1095 | | { |
1096 | | auto kv = make_key_value<KeyT,Json>()(*it); |
1097 | | if (keys.find(kv.key()) == keys.end()) |
1098 | | { |
1099 | | keys.emplace(kv.key()); |
1100 | | members_.emplace_back(std::move(kv)); |
1101 | | } |
1102 | | } |
1103 | | } |
1104 | | |
1105 | | template <typename InputIt> |
1106 | | order_preserving_json_object(InputIt first, InputIt last, const allocator_type& alloc) |
1107 | | : allocator_holder<allocator_type>(alloc), |
1108 | | members_(key_value_allocator_type(alloc)) |
1109 | | { |
1110 | | std::unordered_set<key_type,MyHash> keys; |
1111 | | for (auto it = first; it != last; ++it) |
1112 | | { |
1113 | | auto kv = make_key_value<KeyT,Json>()(*it, alloc); |
1114 | | if (keys.find(kv.key()) == keys.end()) |
1115 | | { |
1116 | | keys.emplace(kv.key()); |
1117 | | members_.emplace_back(std::move(kv)); |
1118 | | } |
1119 | | } |
1120 | | } |
1121 | | |
1122 | | order_preserving_json_object(std::initializer_list<std::pair<std::basic_string<char_type>,Json>> init, |
1123 | | const allocator_type& alloc = allocator_type()) |
1124 | | : allocator_holder<allocator_type>(alloc), |
1125 | | members_(key_value_allocator_type(alloc)) |
1126 | | { |
1127 | | members_.reserve(init.size()); |
1128 | | for (auto& item : init) |
1129 | | { |
1130 | | insert_or_assign(item.first, item.second); |
1131 | | } |
1132 | | } |
1133 | | |
1134 | | ~order_preserving_json_object() noexcept |
1135 | 0 | { |
1136 | 0 | flatten_and_destroy(); |
1137 | 0 | } |
1138 | | |
1139 | | order_preserving_json_object& operator=(order_preserving_json_object&& val) |
1140 | | { |
1141 | | val.swap(*this); |
1142 | | return *this; |
1143 | | } |
1144 | | |
1145 | | order_preserving_json_object& operator=(const order_preserving_json_object& val) |
1146 | | { |
1147 | | members_ = val.members_; |
1148 | | return *this; |
1149 | | } |
1150 | | |
1151 | | void swap(order_preserving_json_object& other) noexcept |
1152 | | { |
1153 | | members_.swap(other.members_); |
1154 | | } |
1155 | | |
1156 | | bool empty() const |
1157 | 0 | { |
1158 | 0 | return members_.empty(); |
1159 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const |
1160 | | |
1161 | | iterator begin() |
1162 | 0 | { |
1163 | 0 | return members_.begin(); |
1164 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::begin() Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::begin() |
1165 | | |
1166 | | iterator end() |
1167 | 0 | { |
1168 | 0 | return members_.end(); |
1169 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::end() Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::end() |
1170 | | |
1171 | | const_iterator begin() const |
1172 | | { |
1173 | | return members_.begin(); |
1174 | | } |
1175 | | |
1176 | | const_iterator end() const |
1177 | | { |
1178 | | return members_.end(); |
1179 | | } |
1180 | | |
1181 | | std::size_t size() const {return members_.size();} |
1182 | | |
1183 | | std::size_t capacity() const {return members_.capacity();} |
1184 | | |
1185 | | void clear() |
1186 | 0 | { |
1187 | 0 | members_.clear(); |
1188 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::clear() Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::clear() |
1189 | | |
1190 | | void shrink_to_fit() |
1191 | | { |
1192 | | for (std::size_t i = 0; i < members_.size(); ++i) |
1193 | | { |
1194 | | members_[i].shrink_to_fit(); |
1195 | | } |
1196 | | members_.shrink_to_fit(); |
1197 | | } |
1198 | | |
1199 | 0 | void reserve(std::size_t n) {members_.reserve(n);}Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long) Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long) |
1200 | | |
1201 | | Json& at(std::size_t i) |
1202 | | { |
1203 | | if (i >= members_.size()) |
1204 | | { |
1205 | | JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript")); |
1206 | | } |
1207 | | return members_[i].value(); |
1208 | | } |
1209 | | |
1210 | | const Json& at(std::size_t i) const |
1211 | | { |
1212 | | if (i >= members_.size()) |
1213 | | { |
1214 | | JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript")); |
1215 | | } |
1216 | | return members_[i].value(); |
1217 | | } |
1218 | | |
1219 | | iterator find(const string_view_type& name) noexcept |
1220 | | { |
1221 | | bool found = false; |
1222 | | auto it = members_.begin(); |
1223 | | while (!found && it != members_.end()) |
1224 | | { |
1225 | | if ((*it).key() == name) |
1226 | | { |
1227 | | found = true; |
1228 | | } |
1229 | | else |
1230 | | { |
1231 | | ++it; |
1232 | | } |
1233 | | } |
1234 | | return it; |
1235 | | } |
1236 | | |
1237 | | const_iterator find(const string_view_type& name) const noexcept |
1238 | | { |
1239 | | bool found = false; |
1240 | | auto it = members_.begin(); |
1241 | | while (!found && it != members_.end()) |
1242 | | { |
1243 | | if ((*it).key() == name) |
1244 | | { |
1245 | | found = true; |
1246 | | } |
1247 | | else |
1248 | | { |
1249 | | ++it; |
1250 | | } |
1251 | | } |
1252 | | return it; |
1253 | | } |
1254 | | |
1255 | | iterator erase(const_iterator pos) |
1256 | | { |
1257 | | if (pos != members_.end()) |
1258 | | { |
1259 | | return members_.erase(pos); |
1260 | | } |
1261 | | else |
1262 | | { |
1263 | | return members_.end(); |
1264 | | } |
1265 | | } |
1266 | | |
1267 | | iterator erase(const_iterator first, const_iterator last) |
1268 | | { |
1269 | | std::size_t pos1 = first == members_.end() ? members_.size() : first - members_.begin(); |
1270 | | std::size_t pos2 = last == members_.end() ? members_.size() : last - members_.begin(); |
1271 | | |
1272 | | if (pos1 < members_.size() && pos2 <= members_.size()) |
1273 | | { |
1274 | | |
1275 | | return members_.erase(first,last); |
1276 | | } |
1277 | | else |
1278 | | { |
1279 | | return members_.end(); |
1280 | | } |
1281 | | } |
1282 | | |
1283 | | void erase(const string_view_type& name) |
1284 | | { |
1285 | | auto pos = find(name); |
1286 | | if (pos != members_.end()) |
1287 | | { |
1288 | | members_.erase(pos); |
1289 | | } |
1290 | | } |
1291 | | |
1292 | | static bool compare1(const index_key_value<Json>& item1, const index_key_value<Json>& item2) |
1293 | 0 | { |
1294 | 0 | int comp = item1.name.compare(item2.name); |
1295 | 0 | if (comp < 0) return true; |
1296 | 0 | if (comp == 0) return item1.index < item2.index; |
1297 | 0 |
|
1298 | 0 | return false; |
1299 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare1(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&) Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare1(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&) |
1300 | | |
1301 | | static bool compare2(const index_key_value<Json>& item1, const index_key_value<Json>& item2) |
1302 | 0 | { |
1303 | 0 | return item1.index < item2.index; |
1304 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare2(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&) Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare2(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&) |
1305 | | |
1306 | | void uninitialized_init(index_key_value<Json>* items, std::size_t length) |
1307 | 0 | { |
1308 | 0 | if (length > 0) |
1309 | 0 | { |
1310 | 0 | std::sort(items, items+length, compare1); |
1311 | 0 |
|
1312 | 0 | std::size_t count = 1; |
1313 | 0 | for (std::size_t i = 1; i < length; ++i) |
1314 | 0 | { |
1315 | 0 | while (i < length && items[i-1].name == items[i].name) |
1316 | 0 | { |
1317 | 0 | ++i; |
1318 | 0 | } |
1319 | 0 | if (i < length) |
1320 | 0 | { |
1321 | 0 | if (i != count) |
1322 | 0 | { |
1323 | 0 | items[count] = std::move(items[i]); |
1324 | 0 | } |
1325 | 0 | ++count; |
1326 | 0 | } |
1327 | 0 | } |
1328 | 0 |
|
1329 | 0 | std::sort(items, items+count, compare2); |
1330 | 0 |
|
1331 | 0 | members_.reserve(count); |
1332 | 0 |
|
1333 | 0 | for (std::size_t i = 0; i < count; ++i) |
1334 | 0 | { |
1335 | 0 | members_.emplace_back(std::move(items[i].name), std::move(items[i].value)); |
1336 | 0 | } |
1337 | 0 | } |
1338 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >*, unsigned long) Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > >*, unsigned long) |
1339 | | |
1340 | | template <typename InputIt> |
1341 | | void insert(InputIt first, InputIt last) |
1342 | | { |
1343 | | std::unordered_set<key_type,MyHash> keys; |
1344 | | for (auto it = first; it != last; ++it) |
1345 | | { |
1346 | | key_type key{(*it).first.c_str(), (*it).first.size(), get_allocator()}; |
1347 | | if (keys.find(key) == keys.end()) |
1348 | | { |
1349 | | keys.emplace(key.c_str(), key.size(), get_allocator()); |
1350 | | members_.emplace_back(std::move(key), (*it).second); |
1351 | | } |
1352 | | } |
1353 | | } |
1354 | | |
1355 | | template <typename InputIt> |
1356 | | void insert(sorted_unique_range_tag, InputIt first, InputIt last) |
1357 | | { |
1358 | | for (auto it = first; it != last; ++it) |
1359 | | { |
1360 | | members_.emplace_back(make_key_value<KeyT,Json>()(*it)); |
1361 | | } |
1362 | | } |
1363 | | |
1364 | | template <typename T,typename A=allocator_type> |
1365 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
1366 | | insert_or_assign(const string_view_type& name, T&& value) |
1367 | | { |
1368 | | auto it = find(name); |
1369 | | if (it == members_.end()) |
1370 | | { |
1371 | | members_.emplace_back(key_type(name.begin(), name.end()), std::forward<T>(value)); |
1372 | | auto pos = members_.begin() + (members_.size() - 1); |
1373 | | return std::make_pair(pos, true); |
1374 | | } |
1375 | | else |
1376 | | { |
1377 | | (*it).value(Json(std::forward<T>(value))); |
1378 | | return std::make_pair(it,false); |
1379 | | } |
1380 | | } |
1381 | | |
1382 | | template <typename T,typename A=allocator_type> |
1383 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
1384 | | insert_or_assign(const string_view_type& name, T&& value) |
1385 | | { |
1386 | | auto it = find(name); |
1387 | | if (it == members_.end()) |
1388 | | { |
1389 | | members_.emplace_back(key_type(name.begin(),name.end(),get_allocator()), std::forward<T>(value)); |
1390 | | auto pos = members_.begin() + (members_.size()-1); |
1391 | | return std::make_pair(pos,true); |
1392 | | } |
1393 | | else |
1394 | | { |
1395 | | (*it).value(Json(std::forward<T>(value),get_allocator())); |
1396 | | return std::make_pair(it,false); |
1397 | | } |
1398 | | } |
1399 | | |
1400 | | template <typename A=allocator_type,typename T> |
1401 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type |
1402 | | insert_or_assign(iterator hint, const string_view_type& key, T&& value) |
1403 | | { |
1404 | | if (hint == members_.end()) |
1405 | | { |
1406 | | auto result = insert_or_assign(key, std::forward<T>(value)); |
1407 | | return result.first; |
1408 | | } |
1409 | | else |
1410 | | { |
1411 | | auto it = find(hint, key); |
1412 | | if (it == members_.end()) |
1413 | | { |
1414 | | members_.emplace_back(key_type(key.begin(), key.end()), std::forward<T>(value)); |
1415 | | auto pos = members_.begin() + (members_.size() - 1); |
1416 | | return pos; |
1417 | | } |
1418 | | else |
1419 | | { |
1420 | | (*it).value(Json(std::forward<T>(value))); |
1421 | | return it; |
1422 | | } |
1423 | | } |
1424 | | } |
1425 | | |
1426 | | template <typename A=allocator_type,typename T> |
1427 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type |
1428 | | insert_or_assign(iterator hint, const string_view_type& key, T&& value) |
1429 | | { |
1430 | | if (hint == members_.end()) |
1431 | | { |
1432 | | auto result = insert_or_assign(key, std::forward<T>(value)); |
1433 | | return result.first; |
1434 | | } |
1435 | | else |
1436 | | { |
1437 | | auto it = find(hint, key); |
1438 | | if (it == members_.end()) |
1439 | | { |
1440 | | members_.emplace_back(key_type(key.begin(),key.end(),get_allocator()), std::forward<T>(value)); |
1441 | | auto pos = members_.begin() + (members_.size()-1); |
1442 | | return pos; |
1443 | | } |
1444 | | else |
1445 | | { |
1446 | | (*it).value(Json(std::forward<T>(value),get_allocator())); |
1447 | | return it; |
1448 | | } |
1449 | | } |
1450 | | } |
1451 | | |
1452 | | // merge |
1453 | | |
1454 | | void merge(const order_preserving_json_object& source) |
1455 | | { |
1456 | | for (auto it = source.begin(); it != source.end(); ++it) |
1457 | | { |
1458 | | try_emplace((*it).key(),(*it).value()); |
1459 | | } |
1460 | | } |
1461 | | |
1462 | | void merge(order_preserving_json_object&& source) |
1463 | | { |
1464 | | auto it = std::make_move_iterator(source.begin()); |
1465 | | auto end = std::make_move_iterator(source.end()); |
1466 | | for (; it != end; ++it) |
1467 | | { |
1468 | | auto pos = find((*it).key()); |
1469 | | if (pos == members_.end()) |
1470 | | { |
1471 | | try_emplace((*it).key(),std::move((*it).value())); |
1472 | | } |
1473 | | } |
1474 | | } |
1475 | | |
1476 | | void merge(iterator hint, const order_preserving_json_object& source) |
1477 | | { |
1478 | | std::size_t pos = hint - members_.begin(); |
1479 | | for (auto it = source.begin(); it != source.end(); ++it) |
1480 | | { |
1481 | | hint = try_emplace(hint, (*it).key(),(*it).value()); |
1482 | | std::size_t newpos = hint - members_.begin(); |
1483 | | if (newpos == pos) |
1484 | | { |
1485 | | ++hint; |
1486 | | pos = hint - members_.begin(); |
1487 | | } |
1488 | | else |
1489 | | { |
1490 | | hint = members_.begin() + pos; |
1491 | | } |
1492 | | } |
1493 | | } |
1494 | | |
1495 | | void merge(iterator hint, order_preserving_json_object&& source) |
1496 | | { |
1497 | | std::size_t pos = hint - members_.begin(); |
1498 | | |
1499 | | auto it = std::make_move_iterator(source.begin()); |
1500 | | auto end = std::make_move_iterator(source.end()); |
1501 | | for (; it != end; ++it) |
1502 | | { |
1503 | | hint = try_emplace(hint, (*it).key(), std::move((*it).value())); |
1504 | | std::size_t newpos = hint - members_.begin(); |
1505 | | if (newpos == pos) |
1506 | | { |
1507 | | ++hint; |
1508 | | pos = hint - members_.begin(); |
1509 | | } |
1510 | | else |
1511 | | { |
1512 | | hint = members_.begin() + pos; |
1513 | | } |
1514 | | } |
1515 | | } |
1516 | | |
1517 | | // merge_or_update |
1518 | | |
1519 | | void merge_or_update(const order_preserving_json_object& source) |
1520 | | { |
1521 | | for (auto it = source.begin(); it != source.end(); ++it) |
1522 | | { |
1523 | | insert_or_assign((*it).key(),(*it).value()); |
1524 | | } |
1525 | | } |
1526 | | |
1527 | | void merge_or_update(order_preserving_json_object&& source) |
1528 | | { |
1529 | | auto it = std::make_move_iterator(source.begin()); |
1530 | | auto end = std::make_move_iterator(source.end()); |
1531 | | for (; it != end; ++it) |
1532 | | { |
1533 | | auto pos = find((*it).key()); |
1534 | | if (pos == members_.end()) |
1535 | | { |
1536 | | insert_or_assign((*it).key(),std::move((*it).value())); |
1537 | | } |
1538 | | else |
1539 | | { |
1540 | | pos->value(std::move((*it).value())); |
1541 | | } |
1542 | | } |
1543 | | } |
1544 | | |
1545 | | void merge_or_update(iterator hint, const order_preserving_json_object& source) |
1546 | | { |
1547 | | std::size_t pos = hint - members_.begin(); |
1548 | | for (auto it = source.begin(); it != source.end(); ++it) |
1549 | | { |
1550 | | hint = insert_or_assign(hint, (*it).key(),(*it).value()); |
1551 | | std::size_t newpos = hint - members_.begin(); |
1552 | | if (newpos == pos) |
1553 | | { |
1554 | | ++hint; |
1555 | | pos = hint - members_.begin(); |
1556 | | } |
1557 | | else |
1558 | | { |
1559 | | hint = members_.begin() + pos; |
1560 | | } |
1561 | | } |
1562 | | } |
1563 | | |
1564 | | void merge_or_update(iterator hint, order_preserving_json_object&& source) |
1565 | | { |
1566 | | std::size_t pos = hint - members_.begin(); |
1567 | | auto it = std::make_move_iterator(source.begin()); |
1568 | | auto end = std::make_move_iterator(source.end()); |
1569 | | for (; it != end; ++it) |
1570 | | { |
1571 | | hint = insert_or_assign(hint, (*it).key(), std::move((*it).value())); |
1572 | | std::size_t newpos = hint - members_.begin(); |
1573 | | if (newpos == pos) |
1574 | | { |
1575 | | ++hint; |
1576 | | pos = hint - members_.begin(); |
1577 | | } |
1578 | | else |
1579 | | { |
1580 | | hint = members_.begin() + pos; |
1581 | | } |
1582 | | } |
1583 | | } |
1584 | | |
1585 | | // try_emplace |
1586 | | |
1587 | | template <typename A=allocator_type,typename... Args> |
1588 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
1589 | | try_emplace(const string_view_type& name, Args&&... args) |
1590 | | { |
1591 | | auto it = find(name); |
1592 | | if (it == members_.end()) |
1593 | | { |
1594 | | members_.emplace_back(key_type(name.begin(), name.end()), std::forward<Args>(args)...); |
1595 | | auto pos = members_.begin() + (members_.size()-1); |
1596 | | return std::make_pair(pos,true); |
1597 | | } |
1598 | | else |
1599 | | { |
1600 | | return std::make_pair(it,false); |
1601 | | } |
1602 | | } |
1603 | | |
1604 | | template <typename A=allocator_type,typename... Args> |
1605 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type |
1606 | | try_emplace(const string_view_type& key, Args&&... args) |
1607 | | { |
1608 | | auto it = find(key); |
1609 | | if (it == members_.end()) |
1610 | | { |
1611 | | members_.emplace_back(key_type(key.begin(),key.end(), get_allocator()), |
1612 | | std::forward<Args>(args)...); |
1613 | | auto pos = members_.begin() + members_.size(); |
1614 | | return std::make_pair(pos,true); |
1615 | | } |
1616 | | else |
1617 | | { |
1618 | | return std::make_pair(it,false); |
1619 | | } |
1620 | | } |
1621 | | |
1622 | | template <typename A=allocator_type,typename ... Args> |
1623 | | typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type |
1624 | | try_emplace(iterator hint, const string_view_type& key, Args&&... args) |
1625 | | { |
1626 | | if (hint == members_.end()) |
1627 | | { |
1628 | | auto result = try_emplace(key, std::forward<Args>(args)...); |
1629 | | return result.first; |
1630 | | } |
1631 | | else |
1632 | | { |
1633 | | auto it = find(hint, key); |
1634 | | if (it == members_.end()) |
1635 | | { |
1636 | | members_.emplace_back(key_type(key.begin(),key.end(), get_allocator()), |
1637 | | std::forward<Args>(args)...); |
1638 | | auto pos = members_.begin() + members_.size(); |
1639 | | return pos; |
1640 | | } |
1641 | | else |
1642 | | { |
1643 | | return it; |
1644 | | } |
1645 | | } |
1646 | | } |
1647 | | |
1648 | | template <typename A=allocator_type,typename ... Args> |
1649 | | typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type |
1650 | | try_emplace(iterator hint, const string_view_type& key, Args&&... args) |
1651 | | { |
1652 | | if (hint == members_.end()) |
1653 | | { |
1654 | | auto result = try_emplace(key, std::forward<Args>(args)...); |
1655 | | return result.first; |
1656 | | } |
1657 | | else |
1658 | | { |
1659 | | auto it = find(hint, key); |
1660 | | if (it == members_.end()) |
1661 | | { |
1662 | | members_.emplace_back(key_type(key.begin(),key.end(), get_allocator()), |
1663 | | std::forward<Args>(args)...); |
1664 | | auto pos = members_.begin() + members_.size(); |
1665 | | return pos; |
1666 | | } |
1667 | | else |
1668 | | { |
1669 | | return it; |
1670 | | } |
1671 | | } |
1672 | | } |
1673 | | |
1674 | | bool operator==(const order_preserving_json_object& rhs) const |
1675 | | { |
1676 | | return members_ == rhs.members_; |
1677 | | } |
1678 | | |
1679 | | bool operator<(const order_preserving_json_object& rhs) const |
1680 | | { |
1681 | | return members_ < rhs.members_; |
1682 | | } |
1683 | | private: |
1684 | | |
1685 | | iterator find(iterator hint, const string_view_type& name) noexcept |
1686 | | { |
1687 | | bool found = false; |
1688 | | auto it = hint; |
1689 | | while (!found && it != members_.end()) |
1690 | | { |
1691 | | if ((*it).key() == name) |
1692 | | { |
1693 | | found = true; |
1694 | | } |
1695 | | else |
1696 | | { |
1697 | | ++it; |
1698 | | } |
1699 | | } |
1700 | | return found ? it : find(name); |
1701 | | } |
1702 | | |
1703 | | void flatten_and_destroy() noexcept |
1704 | 0 | { |
1705 | 0 | if (!members_.empty()) |
1706 | 0 | { |
1707 | 0 | json_array<Json> temp(get_allocator()); |
1708 | 0 |
|
1709 | 0 | for (auto& kv : members_) |
1710 | 0 | { |
1711 | 0 | switch (kv.value().storage_kind()) |
1712 | 0 | { |
1713 | 0 | case json_storage_kind::array: |
1714 | 0 | case json_storage_kind::object: |
1715 | 0 | if (!kv.value().empty()) |
1716 | 0 | { |
1717 | 0 | temp.emplace_back(std::move(kv.value())); |
1718 | 0 | } |
1719 | 0 | break; |
1720 | 0 | default: |
1721 | 0 | break; |
1722 | 0 | } |
1723 | 0 | } |
1724 | 0 | } |
1725 | 0 | } Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy() Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy() |
1726 | | }; |
1727 | | |
1728 | | } // namespace jsoncons |
1729 | | |
1730 | | #endif // JSONCONS_JSON_OBJECT_HPP |