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