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,1577 @@
|
|
|
1
|
+
// Copyright 2017 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_JSONPOINTER_JSONPOINTER_HPP
|
|
8
|
+
#define JSONCONS_JSONPOINTER_JSONPOINTER_HPP
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <iostream>
|
|
14
|
+
#include <iterator>
|
|
15
|
+
#include <utility> // std::move
|
|
16
|
+
#include <system_error> // system_error
|
|
17
|
+
#include <type_traits> // std::enable_if, std::true_type
|
|
18
|
+
#include <jsoncons/json.hpp>
|
|
19
|
+
#include <jsoncons_ext/jsonpointer/jsonpointer_error.hpp>
|
|
20
|
+
#include <jsoncons/detail/write_number.hpp>
|
|
21
|
+
|
|
22
|
+
namespace jsoncons { namespace jsonpointer {
|
|
23
|
+
|
|
24
|
+
namespace detail {
|
|
25
|
+
|
|
26
|
+
enum class pointer_state
|
|
27
|
+
{
|
|
28
|
+
start,
|
|
29
|
+
escaped,
|
|
30
|
+
delim
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
} // namespace detail
|
|
34
|
+
|
|
35
|
+
template <class CharT>
|
|
36
|
+
std::basic_string<CharT> escape_string(const std::basic_string<CharT>& s)
|
|
37
|
+
{
|
|
38
|
+
std::basic_string<CharT> result;
|
|
39
|
+
for (auto c : s)
|
|
40
|
+
{
|
|
41
|
+
switch (c)
|
|
42
|
+
{
|
|
43
|
+
case '~':
|
|
44
|
+
result.push_back('~');
|
|
45
|
+
result.push_back('0');
|
|
46
|
+
break;
|
|
47
|
+
case '/':
|
|
48
|
+
result.push_back('~');
|
|
49
|
+
result.push_back('1');
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
result.push_back(c);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// basic_json_pointer
|
|
60
|
+
|
|
61
|
+
template <class CharT>
|
|
62
|
+
class basic_json_pointer
|
|
63
|
+
{
|
|
64
|
+
public:
|
|
65
|
+
// Member types
|
|
66
|
+
using char_type = CharT;
|
|
67
|
+
using string_type = std::basic_string<char_type>;
|
|
68
|
+
using string_view_type = jsoncons::basic_string_view<char_type>;
|
|
69
|
+
using const_iterator = typename std::vector<string_type>::const_iterator;
|
|
70
|
+
using iterator = const_iterator;
|
|
71
|
+
using const_reverse_iterator = typename std::vector<string_type>::const_reverse_iterator;
|
|
72
|
+
using reverse_iterator = const_reverse_iterator;
|
|
73
|
+
private:
|
|
74
|
+
std::vector<string_type> tokens_;
|
|
75
|
+
public:
|
|
76
|
+
// Constructors
|
|
77
|
+
basic_json_pointer()
|
|
78
|
+
{
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
basic_json_pointer(const std::vector<string_type>& tokens)
|
|
82
|
+
: tokens_(tokens)
|
|
83
|
+
{
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
basic_json_pointer(std::vector<string_type>&& tokens)
|
|
87
|
+
: tokens_(std::move(tokens))
|
|
88
|
+
{
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
explicit basic_json_pointer(const string_view_type& s)
|
|
92
|
+
{
|
|
93
|
+
std::error_code ec;
|
|
94
|
+
auto jp = parse(s, ec);
|
|
95
|
+
if (ec)
|
|
96
|
+
{
|
|
97
|
+
throw jsonpointer_error(ec);
|
|
98
|
+
}
|
|
99
|
+
tokens_ = std::move(jp.tokens_);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
explicit basic_json_pointer(const string_view_type& s, std::error_code& ec)
|
|
103
|
+
{
|
|
104
|
+
auto jp = parse(s, ec);
|
|
105
|
+
if (!ec)
|
|
106
|
+
{
|
|
107
|
+
tokens_ = std::move(jp.tokens_);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
basic_json_pointer(const basic_json_pointer&) = default;
|
|
112
|
+
|
|
113
|
+
basic_json_pointer(basic_json_pointer&&) = default;
|
|
114
|
+
|
|
115
|
+
static basic_json_pointer parse(const string_view_type& input, std::error_code& ec)
|
|
116
|
+
{
|
|
117
|
+
std::vector<string_type> tokens;
|
|
118
|
+
if (input.empty() || (input[0] == '#' && input.size() == 1))
|
|
119
|
+
{
|
|
120
|
+
return basic_json_pointer<CharT>();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const char_type* p;
|
|
124
|
+
const char_type* pend;
|
|
125
|
+
string_type unescaped;
|
|
126
|
+
if (input[0] == '#')
|
|
127
|
+
{
|
|
128
|
+
unescaped = unescape_uri_string(input, ec);
|
|
129
|
+
p = unescaped.data() + 1;
|
|
130
|
+
pend = unescaped.data() + unescaped.size();
|
|
131
|
+
}
|
|
132
|
+
else
|
|
133
|
+
{
|
|
134
|
+
p = input.data();
|
|
135
|
+
pend = input.data() + input.size();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
auto state = jsonpointer::detail::pointer_state::start;
|
|
139
|
+
string_type buffer;
|
|
140
|
+
|
|
141
|
+
while (p < pend)
|
|
142
|
+
{
|
|
143
|
+
bool done = false;
|
|
144
|
+
while (p < pend && !done)
|
|
145
|
+
{
|
|
146
|
+
switch (state)
|
|
147
|
+
{
|
|
148
|
+
case jsonpointer::detail::pointer_state::start:
|
|
149
|
+
switch (*p)
|
|
150
|
+
{
|
|
151
|
+
case '/':
|
|
152
|
+
state = jsonpointer::detail::pointer_state::delim;
|
|
153
|
+
break;
|
|
154
|
+
default:
|
|
155
|
+
ec = jsonpointer_errc::expected_slash;
|
|
156
|
+
return basic_json_pointer();
|
|
157
|
+
};
|
|
158
|
+
break;
|
|
159
|
+
case jsonpointer::detail::pointer_state::delim:
|
|
160
|
+
switch (*p)
|
|
161
|
+
{
|
|
162
|
+
case '/':
|
|
163
|
+
done = true;
|
|
164
|
+
break;
|
|
165
|
+
case '~':
|
|
166
|
+
state = jsonpointer::detail::pointer_state::escaped;
|
|
167
|
+
break;
|
|
168
|
+
default:
|
|
169
|
+
buffer.push_back(*p);
|
|
170
|
+
break;
|
|
171
|
+
};
|
|
172
|
+
break;
|
|
173
|
+
case jsonpointer::detail::pointer_state::escaped:
|
|
174
|
+
switch (*p)
|
|
175
|
+
{
|
|
176
|
+
case '0':
|
|
177
|
+
buffer.push_back('~');
|
|
178
|
+
state = jsonpointer::detail::pointer_state::delim;
|
|
179
|
+
break;
|
|
180
|
+
case '1':
|
|
181
|
+
buffer.push_back('/');
|
|
182
|
+
state = jsonpointer::detail::pointer_state::delim;
|
|
183
|
+
break;
|
|
184
|
+
default:
|
|
185
|
+
ec = jsonpointer_errc::expected_0_or_1;
|
|
186
|
+
return basic_json_pointer();
|
|
187
|
+
};
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
++p;
|
|
191
|
+
}
|
|
192
|
+
tokens.push_back(buffer);
|
|
193
|
+
buffer.clear();
|
|
194
|
+
}
|
|
195
|
+
if (!buffer.empty())
|
|
196
|
+
{
|
|
197
|
+
tokens.push_back(buffer);
|
|
198
|
+
}
|
|
199
|
+
return basic_json_pointer(tokens);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static string_type escape_uri_string(const string_type& s)
|
|
203
|
+
{
|
|
204
|
+
string_type escaped;
|
|
205
|
+
for (auto ch : s)
|
|
206
|
+
{
|
|
207
|
+
switch (ch)
|
|
208
|
+
{
|
|
209
|
+
case '%':
|
|
210
|
+
escaped.append(string_type{'%','2','5'});
|
|
211
|
+
break;
|
|
212
|
+
case '^':
|
|
213
|
+
escaped.append(string_type{'%','5','E'});
|
|
214
|
+
break;
|
|
215
|
+
case '|':
|
|
216
|
+
escaped.append(string_type{'%','7','C'});
|
|
217
|
+
break;
|
|
218
|
+
case '\\':
|
|
219
|
+
escaped.append(string_type{'%','5','C'});
|
|
220
|
+
break;
|
|
221
|
+
case '\"':
|
|
222
|
+
escaped.append(string_type{'%','2','2'});
|
|
223
|
+
break;
|
|
224
|
+
case ' ':
|
|
225
|
+
escaped.append(string_type{'%','2','0'});
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
escaped.push_back(ch);
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return escaped;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static string_type unescape_uri_string(const string_view_type& s, std::error_code& ec)
|
|
237
|
+
{
|
|
238
|
+
if (s.size() < 3)
|
|
239
|
+
{
|
|
240
|
+
return string_type(s);
|
|
241
|
+
}
|
|
242
|
+
string_type unescaped;
|
|
243
|
+
std::size_t last = s.size() - 2;
|
|
244
|
+
std::size_t pos = 0;
|
|
245
|
+
while (pos < last)
|
|
246
|
+
{
|
|
247
|
+
if (s[pos] == '%')
|
|
248
|
+
{
|
|
249
|
+
uint8_t ch;
|
|
250
|
+
auto result = jsoncons::detail::to_integer_base16(s.data() + (pos+1), 2, ch);
|
|
251
|
+
if (!result)
|
|
252
|
+
{
|
|
253
|
+
ec = jsonpointer_errc::invalid_uri_escaped_data;
|
|
254
|
+
return string_type(s);
|
|
255
|
+
}
|
|
256
|
+
unescaped.push_back(ch);
|
|
257
|
+
pos += 3;
|
|
258
|
+
}
|
|
259
|
+
else
|
|
260
|
+
{
|
|
261
|
+
unescaped.push_back(s[pos]);
|
|
262
|
+
++pos;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
while (pos < s.size())
|
|
266
|
+
{
|
|
267
|
+
unescaped.push_back(s[pos]);
|
|
268
|
+
++pos;
|
|
269
|
+
}
|
|
270
|
+
return unescaped;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// operator=
|
|
274
|
+
basic_json_pointer& operator=(const basic_json_pointer&) = default;
|
|
275
|
+
|
|
276
|
+
basic_json_pointer& operator=(basic_json_pointer&&) = default;
|
|
277
|
+
|
|
278
|
+
// Modifiers
|
|
279
|
+
|
|
280
|
+
void clear()
|
|
281
|
+
{
|
|
282
|
+
tokens_.clear();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
basic_json_pointer& operator/=(const string_type& s)
|
|
286
|
+
{
|
|
287
|
+
tokens_.push_back(s);
|
|
288
|
+
return *this;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
template <class IntegerType>
|
|
292
|
+
typename std::enable_if<traits_extension::is_integer<IntegerType>::value, basic_json_pointer&>::type
|
|
293
|
+
operator/=(IntegerType val)
|
|
294
|
+
{
|
|
295
|
+
string_type s;
|
|
296
|
+
jsoncons::detail::from_integer(val, s);
|
|
297
|
+
tokens_.push_back(s);
|
|
298
|
+
|
|
299
|
+
return *this;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
basic_json_pointer& operator+=(const basic_json_pointer& p)
|
|
303
|
+
{
|
|
304
|
+
for (const auto& s : p.tokens_)
|
|
305
|
+
{
|
|
306
|
+
tokens_.push_back(s);
|
|
307
|
+
}
|
|
308
|
+
return *this;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Accessors
|
|
312
|
+
bool empty() const
|
|
313
|
+
{
|
|
314
|
+
return tokens_.empty();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
318
|
+
|
|
319
|
+
JSONCONS_DEPRECATED_MSG("Instead, use to_string()")
|
|
320
|
+
string_type string() const
|
|
321
|
+
{
|
|
322
|
+
return to_string();
|
|
323
|
+
}
|
|
324
|
+
#endif
|
|
325
|
+
string_type to_string() const
|
|
326
|
+
{
|
|
327
|
+
string_type buffer;
|
|
328
|
+
for (const auto& token : tokens_)
|
|
329
|
+
{
|
|
330
|
+
buffer.push_back('/');
|
|
331
|
+
for (auto c : token)
|
|
332
|
+
{
|
|
333
|
+
switch (c)
|
|
334
|
+
{
|
|
335
|
+
case '~':
|
|
336
|
+
buffer.push_back('~');
|
|
337
|
+
buffer.push_back('0');
|
|
338
|
+
break;
|
|
339
|
+
case '/':
|
|
340
|
+
buffer.push_back('~');
|
|
341
|
+
buffer.push_back('1');
|
|
342
|
+
break;
|
|
343
|
+
default:
|
|
344
|
+
buffer.push_back(c);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return buffer;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
string_type to_uri_fragment() const
|
|
353
|
+
{
|
|
354
|
+
string_type buffer{'#'};
|
|
355
|
+
for (const auto& token : tokens_)
|
|
356
|
+
{
|
|
357
|
+
buffer.push_back('/');
|
|
358
|
+
string_type s = escape_uri_string(token);
|
|
359
|
+
for (auto c : s)
|
|
360
|
+
{
|
|
361
|
+
switch (c)
|
|
362
|
+
{
|
|
363
|
+
case '~':
|
|
364
|
+
buffer.push_back('~');
|
|
365
|
+
buffer.push_back('0');
|
|
366
|
+
break;
|
|
367
|
+
case '/':
|
|
368
|
+
buffer.push_back('~');
|
|
369
|
+
buffer.push_back('1');
|
|
370
|
+
break;
|
|
371
|
+
default:
|
|
372
|
+
buffer.push_back(c);
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return buffer;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Iterators
|
|
381
|
+
iterator begin() const
|
|
382
|
+
{
|
|
383
|
+
return tokens_.begin();
|
|
384
|
+
}
|
|
385
|
+
iterator end() const
|
|
386
|
+
{
|
|
387
|
+
return tokens_.end();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
reverse_iterator rbegin() const
|
|
391
|
+
{
|
|
392
|
+
return tokens_.rbegin();
|
|
393
|
+
}
|
|
394
|
+
reverse_iterator rend() const
|
|
395
|
+
{
|
|
396
|
+
return tokens_.rend();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Non-member functions
|
|
400
|
+
friend basic_json_pointer<CharT> operator/(const basic_json_pointer<CharT>& lhs, const string_type& rhs)
|
|
401
|
+
{
|
|
402
|
+
basic_json_pointer<CharT> p(lhs);
|
|
403
|
+
p /= rhs;
|
|
404
|
+
return p;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
friend basic_json_pointer<CharT> operator+( const basic_json_pointer<CharT>& lhs, const basic_json_pointer<CharT>& rhs )
|
|
408
|
+
{
|
|
409
|
+
basic_json_pointer<CharT> p(lhs);
|
|
410
|
+
p += rhs;
|
|
411
|
+
return p;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
friend bool operator==( const basic_json_pointer& lhs, const basic_json_pointer& rhs )
|
|
415
|
+
{
|
|
416
|
+
return lhs.tokens_ == rhs.okens_;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
friend bool operator!=( const basic_json_pointer& lhs, const basic_json_pointer& rhs )
|
|
420
|
+
{
|
|
421
|
+
return lhs.tokens_ != rhs.tokens_;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
friend std::basic_ostream<CharT>&
|
|
425
|
+
operator<<( std::basic_ostream<CharT>& os, const basic_json_pointer<CharT>& p )
|
|
426
|
+
{
|
|
427
|
+
os << p.to_string();
|
|
428
|
+
return os;
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
template <class CharT,class IntegerType>
|
|
433
|
+
typename std::enable_if<traits_extension::is_integer<IntegerType>::value, basic_json_pointer<CharT>>::type
|
|
434
|
+
operator/(const basic_json_pointer<CharT>& lhs, IntegerType rhs)
|
|
435
|
+
{
|
|
436
|
+
basic_json_pointer<CharT> p(lhs);
|
|
437
|
+
p /= rhs;
|
|
438
|
+
return p;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
using json_pointer = basic_json_pointer<char>;
|
|
442
|
+
using wjson_pointer = basic_json_pointer<wchar_t>;
|
|
443
|
+
|
|
444
|
+
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
445
|
+
template<class CharT>
|
|
446
|
+
using basic_address = basic_json_pointer<CharT>;
|
|
447
|
+
template<class CharT>
|
|
448
|
+
using basic_json_ptr = basic_json_pointer<CharT>;
|
|
449
|
+
JSONCONS_DEPRECATED_MSG("Instead, use json_pointer") typedef json_pointer address;
|
|
450
|
+
JSONCONS_DEPRECATED_MSG("Instead, use json_pointer") typedef json_pointer json_ptr;
|
|
451
|
+
JSONCONS_DEPRECATED_MSG("Instead, use wjson_pointer") typedef json_pointer wjson_ptr;
|
|
452
|
+
#endif
|
|
453
|
+
|
|
454
|
+
namespace detail {
|
|
455
|
+
|
|
456
|
+
template <class Json>
|
|
457
|
+
const Json* resolve(const Json* current, const typename Json::string_view_type& buffer, std::error_code& ec)
|
|
458
|
+
{
|
|
459
|
+
if (current->is_array())
|
|
460
|
+
{
|
|
461
|
+
if (buffer.size() == 1 && buffer[0] == '-')
|
|
462
|
+
{
|
|
463
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
464
|
+
return current;
|
|
465
|
+
}
|
|
466
|
+
std::size_t index{0};
|
|
467
|
+
auto result = jsoncons::detail::to_integer_decimal(buffer.data(), buffer.length(), index);
|
|
468
|
+
if (!result)
|
|
469
|
+
{
|
|
470
|
+
ec = jsonpointer_errc::invalid_index;
|
|
471
|
+
return current;
|
|
472
|
+
}
|
|
473
|
+
if (index >= current->size())
|
|
474
|
+
{
|
|
475
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
476
|
+
return current;
|
|
477
|
+
}
|
|
478
|
+
current = std::addressof(current->at(index));
|
|
479
|
+
}
|
|
480
|
+
else if (current->is_object())
|
|
481
|
+
{
|
|
482
|
+
if (!current->contains(buffer))
|
|
483
|
+
{
|
|
484
|
+
ec = jsonpointer_errc::key_not_found;
|
|
485
|
+
return current;
|
|
486
|
+
}
|
|
487
|
+
current = std::addressof(current->at(buffer));
|
|
488
|
+
}
|
|
489
|
+
else
|
|
490
|
+
{
|
|
491
|
+
ec = jsonpointer_errc::expected_object_or_array;
|
|
492
|
+
return current;
|
|
493
|
+
}
|
|
494
|
+
return current;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
template <class Json>
|
|
498
|
+
Json* resolve(Json* current, const typename Json::string_view_type& buffer, bool create_if_missing, std::error_code& ec)
|
|
499
|
+
{
|
|
500
|
+
if (current->is_array())
|
|
501
|
+
{
|
|
502
|
+
if (buffer.size() == 1 && buffer[0] == '-')
|
|
503
|
+
{
|
|
504
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
505
|
+
return current;
|
|
506
|
+
}
|
|
507
|
+
std::size_t index{0};
|
|
508
|
+
auto result = jsoncons::detail::to_integer_decimal(buffer.data(), buffer.length(), index);
|
|
509
|
+
if (!result)
|
|
510
|
+
{
|
|
511
|
+
ec = jsonpointer_errc::invalid_index;
|
|
512
|
+
return current;
|
|
513
|
+
}
|
|
514
|
+
if (index >= current->size())
|
|
515
|
+
{
|
|
516
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
517
|
+
return current;
|
|
518
|
+
}
|
|
519
|
+
current = std::addressof(current->at(index));
|
|
520
|
+
}
|
|
521
|
+
else if (current->is_object())
|
|
522
|
+
{
|
|
523
|
+
if (!current->contains(buffer))
|
|
524
|
+
{
|
|
525
|
+
if (create_if_missing)
|
|
526
|
+
{
|
|
527
|
+
auto r = current->try_emplace(buffer, Json());
|
|
528
|
+
current = std::addressof(r.first->value());
|
|
529
|
+
}
|
|
530
|
+
else
|
|
531
|
+
{
|
|
532
|
+
ec = jsonpointer_errc::key_not_found;
|
|
533
|
+
return current;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
else
|
|
537
|
+
{
|
|
538
|
+
current = std::addressof(current->at(buffer));
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
else
|
|
542
|
+
{
|
|
543
|
+
ec = jsonpointer_errc::expected_object_or_array;
|
|
544
|
+
return current;
|
|
545
|
+
}
|
|
546
|
+
return current;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
} // namespace detail
|
|
550
|
+
|
|
551
|
+
// get
|
|
552
|
+
|
|
553
|
+
template<class Json>
|
|
554
|
+
Json& get(Json& root,
|
|
555
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
556
|
+
bool create_if_missing,
|
|
557
|
+
std::error_code& ec)
|
|
558
|
+
{
|
|
559
|
+
if (location.empty())
|
|
560
|
+
{
|
|
561
|
+
return root;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
Json* current = std::addressof(root);
|
|
565
|
+
auto it = location.begin();
|
|
566
|
+
auto end = location.end();
|
|
567
|
+
while (it != end)
|
|
568
|
+
{
|
|
569
|
+
current = jsoncons::jsonpointer::detail::resolve(current, *it, create_if_missing, ec);
|
|
570
|
+
if (ec)
|
|
571
|
+
return *current;
|
|
572
|
+
++it;
|
|
573
|
+
}
|
|
574
|
+
return *current;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
template<class Json, class StringSource>
|
|
578
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,Json&>::type
|
|
579
|
+
get(Json& root,
|
|
580
|
+
const StringSource& location_str,
|
|
581
|
+
bool create_if_missing,
|
|
582
|
+
std::error_code& ec)
|
|
583
|
+
{
|
|
584
|
+
auto jsonptr = basic_json_pointer<typename Json::char_type>::parse(location_str, ec);
|
|
585
|
+
if (ec)
|
|
586
|
+
{
|
|
587
|
+
return root;
|
|
588
|
+
}
|
|
589
|
+
return get(root, jsonptr, create_if_missing, ec);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
template<class Json>
|
|
593
|
+
const Json& get(const Json& root,
|
|
594
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
595
|
+
std::error_code& ec)
|
|
596
|
+
{
|
|
597
|
+
if (location.empty())
|
|
598
|
+
{
|
|
599
|
+
return root;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const Json* current = std::addressof(root);
|
|
603
|
+
auto it = location.begin();
|
|
604
|
+
auto end = location.end();
|
|
605
|
+
while (it != end)
|
|
606
|
+
{
|
|
607
|
+
current = jsoncons::jsonpointer::detail::resolve(current, *it, ec);
|
|
608
|
+
if (ec)
|
|
609
|
+
return *current;
|
|
610
|
+
++it;
|
|
611
|
+
}
|
|
612
|
+
return *current;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
template<class Json, class StringSource>
|
|
616
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,const Json&>::type
|
|
617
|
+
get(const Json& root,
|
|
618
|
+
const StringSource& location_str,
|
|
619
|
+
std::error_code& ec)
|
|
620
|
+
{
|
|
621
|
+
auto jsonptr = basic_json_pointer<typename Json::char_type>::parse(location_str, ec);
|
|
622
|
+
if (ec)
|
|
623
|
+
{
|
|
624
|
+
return root;
|
|
625
|
+
}
|
|
626
|
+
return get(root, jsonptr, ec);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
template<class Json>
|
|
630
|
+
Json& get(Json& root,
|
|
631
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
632
|
+
std::error_code& ec)
|
|
633
|
+
{
|
|
634
|
+
return get(root, location, false, ec);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
template<class Json, class StringSource>
|
|
638
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,Json&>::type
|
|
639
|
+
get(Json& root,
|
|
640
|
+
const StringSource& location_str,
|
|
641
|
+
std::error_code& ec)
|
|
642
|
+
{
|
|
643
|
+
return get(root, location_str, false, ec);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
template<class Json>
|
|
647
|
+
Json& get(Json& root,
|
|
648
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
649
|
+
bool create_if_missing = false)
|
|
650
|
+
{
|
|
651
|
+
std::error_code ec;
|
|
652
|
+
Json& j = get(root, location, create_if_missing, ec);
|
|
653
|
+
if (ec)
|
|
654
|
+
{
|
|
655
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
656
|
+
}
|
|
657
|
+
return j;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
template<class Json, class StringSource>
|
|
661
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,Json&>::type
|
|
662
|
+
get(Json& root,
|
|
663
|
+
const StringSource& location_str,
|
|
664
|
+
bool create_if_missing = false)
|
|
665
|
+
{
|
|
666
|
+
std::error_code ec;
|
|
667
|
+
Json& result = get(root, location_str, create_if_missing, ec);
|
|
668
|
+
if (ec)
|
|
669
|
+
{
|
|
670
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
671
|
+
}
|
|
672
|
+
return result;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
template<class Json>
|
|
676
|
+
const Json& get(const Json& root, const basic_json_pointer<typename Json::char_type>& location)
|
|
677
|
+
{
|
|
678
|
+
std::error_code ec;
|
|
679
|
+
const Json& j = get(root, location, ec);
|
|
680
|
+
if (ec)
|
|
681
|
+
{
|
|
682
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
683
|
+
}
|
|
684
|
+
return j;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
template<class Json, class StringSource>
|
|
688
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,const Json&>::type
|
|
689
|
+
get(const Json& root, const StringSource& location_str)
|
|
690
|
+
{
|
|
691
|
+
std::error_code ec;
|
|
692
|
+
const Json& j = get(root, location_str, ec);
|
|
693
|
+
if (ec)
|
|
694
|
+
{
|
|
695
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
696
|
+
}
|
|
697
|
+
return j;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// contains
|
|
701
|
+
|
|
702
|
+
template<class Json>
|
|
703
|
+
bool contains(const Json& root, const basic_json_pointer<typename Json::char_type>& location)
|
|
704
|
+
{
|
|
705
|
+
std::error_code ec;
|
|
706
|
+
get(root, location, ec);
|
|
707
|
+
return !ec ? true : false;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
template<class Json, class StringSource>
|
|
711
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,bool>::type
|
|
712
|
+
contains(const Json& root, const StringSource& location_str)
|
|
713
|
+
{
|
|
714
|
+
std::error_code ec;
|
|
715
|
+
get(root, location_str, ec);
|
|
716
|
+
return !ec ? true : false;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
template<class Json,class T>
|
|
720
|
+
void add(Json& root,
|
|
721
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
722
|
+
T&& value,
|
|
723
|
+
bool create_if_missing,
|
|
724
|
+
std::error_code& ec)
|
|
725
|
+
{
|
|
726
|
+
Json* current = std::addressof(root);
|
|
727
|
+
|
|
728
|
+
std::basic_string<typename Json::char_type> buffer;
|
|
729
|
+
auto it = location.begin();
|
|
730
|
+
auto end = location.end();
|
|
731
|
+
while (it != end)
|
|
732
|
+
{
|
|
733
|
+
buffer = *it;
|
|
734
|
+
++it;
|
|
735
|
+
if (it != end)
|
|
736
|
+
{
|
|
737
|
+
current = jsoncons::jsonpointer::detail::resolve(current, buffer, create_if_missing, ec);
|
|
738
|
+
if (ec)
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (current->is_array())
|
|
743
|
+
{
|
|
744
|
+
if (buffer.size() == 1 && buffer[0] == '-')
|
|
745
|
+
{
|
|
746
|
+
current->emplace_back(std::forward<T>(value));
|
|
747
|
+
current = std::addressof(current->at(current->size()-1));
|
|
748
|
+
}
|
|
749
|
+
else
|
|
750
|
+
{
|
|
751
|
+
std::size_t index{0};
|
|
752
|
+
auto result = jsoncons::detail::to_integer_decimal(buffer.data(), buffer.length(), index);
|
|
753
|
+
if (!result)
|
|
754
|
+
{
|
|
755
|
+
ec = jsonpointer_errc::invalid_index;
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (index > current->size())
|
|
759
|
+
{
|
|
760
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
if (index == current->size())
|
|
764
|
+
{
|
|
765
|
+
current->emplace_back(std::forward<T>(value));
|
|
766
|
+
current = std::addressof(current->at(current->size()-1));
|
|
767
|
+
}
|
|
768
|
+
else
|
|
769
|
+
{
|
|
770
|
+
auto it2 = current->insert(current->array_range().begin()+index,std::forward<T>(value));
|
|
771
|
+
current = std::addressof(*it2);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
else if (current->is_object())
|
|
776
|
+
{
|
|
777
|
+
auto r = current->insert_or_assign(buffer,std::forward<T>(value));
|
|
778
|
+
current = std::addressof(r.first->value());
|
|
779
|
+
}
|
|
780
|
+
else
|
|
781
|
+
{
|
|
782
|
+
ec = jsonpointer_errc::expected_object_or_array;
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// add
|
|
788
|
+
template<class Json, class StringSource, class T>
|
|
789
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
790
|
+
add(Json& root,
|
|
791
|
+
const StringSource& location_str,
|
|
792
|
+
T&& value,
|
|
793
|
+
bool create_if_missing,
|
|
794
|
+
std::error_code& ec)
|
|
795
|
+
{
|
|
796
|
+
auto jsonptr = basic_json_pointer<typename Json::char_type>::parse(location_str, ec);
|
|
797
|
+
if (ec)
|
|
798
|
+
{
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
add(root, jsonptr, std::forward<T>(value), create_if_missing, ec);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
template<class Json,class T>
|
|
805
|
+
void add(Json& root,
|
|
806
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
807
|
+
T&& value,
|
|
808
|
+
std::error_code& ec)
|
|
809
|
+
{
|
|
810
|
+
add(root, location, std::forward<T>(value), false, ec);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
template<class Json, class StringSource, class T>
|
|
814
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
815
|
+
add(Json& root,
|
|
816
|
+
const StringSource& location_str,
|
|
817
|
+
T&& value,
|
|
818
|
+
std::error_code& ec)
|
|
819
|
+
{
|
|
820
|
+
add(root, location_str, std::forward<T>(value), false, ec);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
template<class Json,class T>
|
|
824
|
+
void add(Json& root,
|
|
825
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
826
|
+
T&& value,
|
|
827
|
+
bool create_if_missing = false)
|
|
828
|
+
{
|
|
829
|
+
std::error_code ec;
|
|
830
|
+
add(root, location, std::forward<T>(value), create_if_missing, ec);
|
|
831
|
+
if (ec)
|
|
832
|
+
{
|
|
833
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
template<class Json, class StringSource, class T>
|
|
838
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
839
|
+
add(Json& root,
|
|
840
|
+
const StringSource& location_str,
|
|
841
|
+
T&& value,
|
|
842
|
+
bool create_if_missing = false)
|
|
843
|
+
{
|
|
844
|
+
std::error_code ec;
|
|
845
|
+
add(root, location_str, std::forward<T>(value), create_if_missing, ec);
|
|
846
|
+
if (ec)
|
|
847
|
+
{
|
|
848
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// add_if_absent
|
|
853
|
+
|
|
854
|
+
template<class Json, class T>
|
|
855
|
+
void add_if_absent(Json& root,
|
|
856
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
857
|
+
T&& value,
|
|
858
|
+
bool create_if_missing,
|
|
859
|
+
std::error_code& ec)
|
|
860
|
+
{
|
|
861
|
+
Json* current = std::addressof(root);
|
|
862
|
+
|
|
863
|
+
std::basic_string<typename Json::char_type> buffer;
|
|
864
|
+
auto it = location.begin();
|
|
865
|
+
auto end = location.end();
|
|
866
|
+
|
|
867
|
+
while (it != end)
|
|
868
|
+
{
|
|
869
|
+
buffer = *it;
|
|
870
|
+
++it;
|
|
871
|
+
if (it != end)
|
|
872
|
+
{
|
|
873
|
+
current = jsoncons::jsonpointer::detail::resolve(current, buffer, create_if_missing, ec);
|
|
874
|
+
if (ec)
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (current->is_array())
|
|
879
|
+
{
|
|
880
|
+
if (buffer.size() == 1 && buffer[0] == '-')
|
|
881
|
+
{
|
|
882
|
+
current->emplace_back(std::forward<T>(value));
|
|
883
|
+
current = std::addressof(current->at(current->size()-1));
|
|
884
|
+
}
|
|
885
|
+
else
|
|
886
|
+
{
|
|
887
|
+
std::size_t index{0};
|
|
888
|
+
auto result = jsoncons::detail::to_integer_decimal(buffer.data(), buffer.length(), index);
|
|
889
|
+
if (!result)
|
|
890
|
+
{
|
|
891
|
+
ec = jsonpointer_errc::invalid_index;
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
if (index > current->size())
|
|
895
|
+
{
|
|
896
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
if (index == current->size())
|
|
900
|
+
{
|
|
901
|
+
current->emplace_back(std::forward<T>(value));
|
|
902
|
+
current = std::addressof(current->at(current->size()-1));
|
|
903
|
+
}
|
|
904
|
+
else
|
|
905
|
+
{
|
|
906
|
+
auto it2 = current->insert(current->array_range().begin()+index,std::forward<T>(value));
|
|
907
|
+
current = std::addressof(*it2);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
else if (current->is_object())
|
|
912
|
+
{
|
|
913
|
+
if (current->contains(buffer))
|
|
914
|
+
{
|
|
915
|
+
ec = jsonpointer_errc::key_already_exists;
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
else
|
|
919
|
+
{
|
|
920
|
+
auto r = current->try_emplace(buffer,std::forward<T>(value));
|
|
921
|
+
current = std::addressof(r.first->value());
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
else
|
|
925
|
+
{
|
|
926
|
+
ec = jsonpointer_errc::expected_object_or_array;
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
template<class Json, class StringSource, class T>
|
|
932
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
933
|
+
add_if_absent(Json& root,
|
|
934
|
+
const StringSource& location_str,
|
|
935
|
+
T&& value,
|
|
936
|
+
bool create_if_missing,
|
|
937
|
+
std::error_code& ec)
|
|
938
|
+
{
|
|
939
|
+
auto jsonptr = basic_json_pointer<typename Json::char_type>::parse(location_str, ec);
|
|
940
|
+
if (ec)
|
|
941
|
+
{
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
add_if_absent(root, jsonptr, std::forward<T>(value), create_if_missing, ec);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
template<class Json, class StringSource, class T>
|
|
948
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
949
|
+
add_if_absent(Json& root,
|
|
950
|
+
const StringSource& location,
|
|
951
|
+
T&& value,
|
|
952
|
+
std::error_code& ec)
|
|
953
|
+
{
|
|
954
|
+
add_if_absent(root, location, std::forward<T>(value), false, ec);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
template<class Json, class StringSource, class T>
|
|
958
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
959
|
+
add_if_absent(Json& root,
|
|
960
|
+
const StringSource& location_str,
|
|
961
|
+
T&& value,
|
|
962
|
+
bool create_if_missing = false)
|
|
963
|
+
{
|
|
964
|
+
std::error_code ec;
|
|
965
|
+
add_if_absent(root, location_str, std::forward<T>(value), create_if_missing, ec);
|
|
966
|
+
if (ec)
|
|
967
|
+
{
|
|
968
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
template<class Json, class T>
|
|
973
|
+
void add_if_absent(Json& root,
|
|
974
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
975
|
+
T&& value,
|
|
976
|
+
std::error_code& ec)
|
|
977
|
+
{
|
|
978
|
+
add_if_absent(root, location, std::forward<T>(value), false, ec);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
template<class Json, class T>
|
|
982
|
+
void add_if_absent(Json& root,
|
|
983
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
984
|
+
T&& value,
|
|
985
|
+
bool create_if_missing = false)
|
|
986
|
+
{
|
|
987
|
+
std::error_code ec;
|
|
988
|
+
add_if_absent(root, location, std::forward<T>(value), create_if_missing, ec);
|
|
989
|
+
if (ec)
|
|
990
|
+
{
|
|
991
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// remove
|
|
996
|
+
|
|
997
|
+
template<class Json>
|
|
998
|
+
void remove(Json& root, const basic_json_pointer<typename Json::char_type>& location, std::error_code& ec)
|
|
999
|
+
{
|
|
1000
|
+
Json* current = std::addressof(root);
|
|
1001
|
+
|
|
1002
|
+
std::basic_string<typename Json::char_type> buffer;
|
|
1003
|
+
auto it = location.begin();
|
|
1004
|
+
auto end = location.end();
|
|
1005
|
+
|
|
1006
|
+
while (it != end)
|
|
1007
|
+
{
|
|
1008
|
+
buffer = *it;
|
|
1009
|
+
++it;
|
|
1010
|
+
if (it != end)
|
|
1011
|
+
{
|
|
1012
|
+
current = jsoncons::jsonpointer::detail::resolve(current, buffer, false, ec);
|
|
1013
|
+
if (ec)
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
if (current->is_array())
|
|
1018
|
+
{
|
|
1019
|
+
if (buffer.size() == 1 && buffer[0] == '-')
|
|
1020
|
+
{
|
|
1021
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
else
|
|
1025
|
+
{
|
|
1026
|
+
std::size_t index{0};
|
|
1027
|
+
auto result = jsoncons::detail::to_integer_decimal(buffer.data(), buffer.length(), index);
|
|
1028
|
+
if (!result)
|
|
1029
|
+
{
|
|
1030
|
+
ec = jsonpointer_errc::invalid_index;
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
if (index >= current->size())
|
|
1034
|
+
{
|
|
1035
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
current->erase(current->array_range().begin()+index);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
else if (current->is_object())
|
|
1042
|
+
{
|
|
1043
|
+
if (!current->contains(buffer))
|
|
1044
|
+
{
|
|
1045
|
+
ec = jsonpointer_errc::key_not_found;
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
else
|
|
1049
|
+
{
|
|
1050
|
+
current->erase(buffer);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
else
|
|
1054
|
+
{
|
|
1055
|
+
ec = jsonpointer_errc::expected_object_or_array;
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
template<class Json, class StringSource>
|
|
1061
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
1062
|
+
remove(Json& root, const StringSource& location_str, std::error_code& ec)
|
|
1063
|
+
{
|
|
1064
|
+
auto jsonptr = basic_json_pointer<typename Json::char_type>::parse(location_str, ec);
|
|
1065
|
+
if (ec)
|
|
1066
|
+
{
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
remove(root, jsonptr, ec);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
template<class Json, class StringSource>
|
|
1073
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
1074
|
+
remove(Json& root, const StringSource& location_str)
|
|
1075
|
+
{
|
|
1076
|
+
std::error_code ec;
|
|
1077
|
+
remove(root, location_str, ec);
|
|
1078
|
+
if (ec)
|
|
1079
|
+
{
|
|
1080
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
template<class Json>
|
|
1085
|
+
void remove(Json& root, const basic_json_pointer<typename Json::char_type>& location)
|
|
1086
|
+
{
|
|
1087
|
+
std::error_code ec;
|
|
1088
|
+
remove(root, location, ec);
|
|
1089
|
+
if (ec)
|
|
1090
|
+
{
|
|
1091
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// replace
|
|
1096
|
+
|
|
1097
|
+
template<class Json, class T>
|
|
1098
|
+
void replace(Json& root,
|
|
1099
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
1100
|
+
T&& value,
|
|
1101
|
+
bool create_if_missing,
|
|
1102
|
+
std::error_code& ec)
|
|
1103
|
+
{
|
|
1104
|
+
Json* current = std::addressof(root);
|
|
1105
|
+
|
|
1106
|
+
std::basic_string<typename Json::char_type> buffer;
|
|
1107
|
+
auto it = location.begin();
|
|
1108
|
+
auto end = location.end();
|
|
1109
|
+
|
|
1110
|
+
while (it != end)
|
|
1111
|
+
{
|
|
1112
|
+
buffer = *it;
|
|
1113
|
+
++it;
|
|
1114
|
+
if (it != end)
|
|
1115
|
+
{
|
|
1116
|
+
current = jsoncons::jsonpointer::detail::resolve(current, buffer, create_if_missing, ec);
|
|
1117
|
+
if (ec)
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
if (current->is_array())
|
|
1122
|
+
{
|
|
1123
|
+
if (buffer.size() == 1 && buffer[0] == '-')
|
|
1124
|
+
{
|
|
1125
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
else
|
|
1129
|
+
{
|
|
1130
|
+
std::size_t index{};
|
|
1131
|
+
auto result = jsoncons::detail::to_integer_decimal(buffer.data(), buffer.length(), index);
|
|
1132
|
+
if (!result)
|
|
1133
|
+
{
|
|
1134
|
+
ec = jsonpointer_errc::invalid_index;
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
if (index >= current->size())
|
|
1138
|
+
{
|
|
1139
|
+
ec = jsonpointer_errc::index_exceeds_array_size;
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
current->at(index) = std::forward<T>(value);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
else if (current->is_object())
|
|
1146
|
+
{
|
|
1147
|
+
if (!current->contains(buffer))
|
|
1148
|
+
{
|
|
1149
|
+
if (create_if_missing)
|
|
1150
|
+
{
|
|
1151
|
+
current->try_emplace(buffer,std::forward<T>(value));
|
|
1152
|
+
}
|
|
1153
|
+
else
|
|
1154
|
+
{
|
|
1155
|
+
ec = jsonpointer_errc::key_not_found;
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
else
|
|
1160
|
+
{
|
|
1161
|
+
auto r = current->insert_or_assign(buffer,std::forward<T>(value));
|
|
1162
|
+
current = std::addressof(r.first->value());
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
else
|
|
1166
|
+
{
|
|
1167
|
+
ec = jsonpointer_errc::expected_object_or_array;
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
template<class Json, class StringSource, class T>
|
|
1173
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
1174
|
+
replace(Json& root,
|
|
1175
|
+
const StringSource& location_str,
|
|
1176
|
+
T&& value,
|
|
1177
|
+
bool create_if_missing,
|
|
1178
|
+
std::error_code& ec)
|
|
1179
|
+
{
|
|
1180
|
+
auto jsonptr = basic_json_pointer<typename Json::char_type>::parse(location_str, ec);
|
|
1181
|
+
if (ec)
|
|
1182
|
+
{
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
replace(root, jsonptr, std::forward<T>(value), create_if_missing, ec);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
template<class Json, class StringSource, class T>
|
|
1189
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
1190
|
+
replace(Json& root,
|
|
1191
|
+
const StringSource& location_str,
|
|
1192
|
+
T&& value,
|
|
1193
|
+
std::error_code& ec)
|
|
1194
|
+
{
|
|
1195
|
+
replace(root, location_str, std::forward<T>(value), false, ec);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
template<class Json, class StringSource, class T>
|
|
1199
|
+
typename std::enable_if<std::is_convertible<StringSource,jsoncons::basic_string_view<typename Json::char_type>>::value,void>::type
|
|
1200
|
+
replace(Json& root,
|
|
1201
|
+
const StringSource& location_str,
|
|
1202
|
+
T&& value,
|
|
1203
|
+
bool create_if_missing = false)
|
|
1204
|
+
{
|
|
1205
|
+
std::error_code ec;
|
|
1206
|
+
replace(root, location_str, std::forward<T>(value), create_if_missing, ec);
|
|
1207
|
+
if (ec)
|
|
1208
|
+
{
|
|
1209
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
template<class Json, class T>
|
|
1214
|
+
void replace(Json& root,
|
|
1215
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
1216
|
+
T&& value,
|
|
1217
|
+
std::error_code& ec)
|
|
1218
|
+
{
|
|
1219
|
+
replace(root, location, std::forward<T>(value), false, ec);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
template<class Json, class T>
|
|
1223
|
+
void replace(Json& root,
|
|
1224
|
+
const basic_json_pointer<typename Json::char_type>& location,
|
|
1225
|
+
T&& value,
|
|
1226
|
+
bool create_if_missing = false)
|
|
1227
|
+
{
|
|
1228
|
+
std::error_code ec;
|
|
1229
|
+
replace(root, location, std::forward<T>(value), create_if_missing, ec);
|
|
1230
|
+
if (ec)
|
|
1231
|
+
{
|
|
1232
|
+
JSONCONS_THROW(jsonpointer_error(ec));
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
template <class String,class Result>
|
|
1237
|
+
typename std::enable_if<std::is_convertible<typename String::value_type,typename Result::value_type>::value>::type
|
|
1238
|
+
escape(const String& s, Result& result)
|
|
1239
|
+
{
|
|
1240
|
+
for (auto c : s)
|
|
1241
|
+
{
|
|
1242
|
+
if (c == '~')
|
|
1243
|
+
{
|
|
1244
|
+
result.push_back('~');
|
|
1245
|
+
result.push_back('0');
|
|
1246
|
+
}
|
|
1247
|
+
else if (c == '/')
|
|
1248
|
+
{
|
|
1249
|
+
result.push_back('~');
|
|
1250
|
+
result.push_back('1');
|
|
1251
|
+
}
|
|
1252
|
+
else
|
|
1253
|
+
{
|
|
1254
|
+
result.push_back(c);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
template <class CharT>
|
|
1260
|
+
std::basic_string<CharT> escape(const jsoncons::basic_string_view<CharT>& s)
|
|
1261
|
+
{
|
|
1262
|
+
std::basic_string<CharT> result;
|
|
1263
|
+
|
|
1264
|
+
for (auto c : s)
|
|
1265
|
+
{
|
|
1266
|
+
if (c == '~')
|
|
1267
|
+
{
|
|
1268
|
+
result.push_back('~');
|
|
1269
|
+
result.push_back('0');
|
|
1270
|
+
}
|
|
1271
|
+
else if (c == '/')
|
|
1272
|
+
{
|
|
1273
|
+
result.push_back('~');
|
|
1274
|
+
result.push_back('1');
|
|
1275
|
+
}
|
|
1276
|
+
else
|
|
1277
|
+
{
|
|
1278
|
+
result.push_back(c);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
return result;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// flatten
|
|
1285
|
+
|
|
1286
|
+
template<class Json>
|
|
1287
|
+
void flatten_(const std::basic_string<typename Json::char_type>& parent_key,
|
|
1288
|
+
const Json& parent_value,
|
|
1289
|
+
Json& result)
|
|
1290
|
+
{
|
|
1291
|
+
using char_type = typename Json::char_type;
|
|
1292
|
+
using string_type = std::basic_string<char_type>;
|
|
1293
|
+
|
|
1294
|
+
switch (parent_value.type())
|
|
1295
|
+
{
|
|
1296
|
+
case json_type::array_value:
|
|
1297
|
+
{
|
|
1298
|
+
if (parent_value.empty())
|
|
1299
|
+
{
|
|
1300
|
+
// Flatten empty array to null
|
|
1301
|
+
//result.try_emplace(parent_key, null_type{});
|
|
1302
|
+
//result[parent_key] = parent_value;
|
|
1303
|
+
result.try_emplace(parent_key, parent_value);
|
|
1304
|
+
}
|
|
1305
|
+
else
|
|
1306
|
+
{
|
|
1307
|
+
for (std::size_t i = 0; i < parent_value.size(); ++i)
|
|
1308
|
+
{
|
|
1309
|
+
string_type key(parent_key);
|
|
1310
|
+
key.push_back('/');
|
|
1311
|
+
jsoncons::detail::from_integer(i,key);
|
|
1312
|
+
flatten_(key, parent_value.at(i), result);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
case json_type::object_value:
|
|
1319
|
+
{
|
|
1320
|
+
if (parent_value.empty())
|
|
1321
|
+
{
|
|
1322
|
+
// Flatten empty object to null
|
|
1323
|
+
//result.try_emplace(parent_key, null_type{});
|
|
1324
|
+
//result[parent_key] = parent_value;
|
|
1325
|
+
result.try_emplace(parent_key, parent_value);
|
|
1326
|
+
}
|
|
1327
|
+
else
|
|
1328
|
+
{
|
|
1329
|
+
for (const auto& item : parent_value.object_range())
|
|
1330
|
+
{
|
|
1331
|
+
string_type key(parent_key);
|
|
1332
|
+
key.push_back('/');
|
|
1333
|
+
escape(jsoncons::basic_string_view<char_type>(item.key().data(),item.key().size()), key);
|
|
1334
|
+
flatten_(key, item.value(), result);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
break;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
default:
|
|
1341
|
+
{
|
|
1342
|
+
// add primitive parent_value with its reference string
|
|
1343
|
+
//result[parent_key] = parent_value;
|
|
1344
|
+
result.try_emplace(parent_key, parent_value);
|
|
1345
|
+
break;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
template<class Json>
|
|
1351
|
+
Json flatten(const Json& value)
|
|
1352
|
+
{
|
|
1353
|
+
Json result;
|
|
1354
|
+
std::basic_string<typename Json::char_type> parent_key;
|
|
1355
|
+
flatten_(parent_key, value, result);
|
|
1356
|
+
return result;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
// unflatten
|
|
1361
|
+
|
|
1362
|
+
enum class unflatten_options {none,assume_object = 1
|
|
1363
|
+
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
1364
|
+
,object = assume_object
|
|
1365
|
+
#endif
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1368
|
+
template<class Json>
|
|
1369
|
+
Json safe_unflatten (Json& value)
|
|
1370
|
+
{
|
|
1371
|
+
if (!value.is_object() || value.empty())
|
|
1372
|
+
{
|
|
1373
|
+
return value;
|
|
1374
|
+
}
|
|
1375
|
+
bool safe = true;
|
|
1376
|
+
std::size_t index = 0;
|
|
1377
|
+
for (const auto& item : value.object_range())
|
|
1378
|
+
{
|
|
1379
|
+
std::size_t n;
|
|
1380
|
+
auto r = jsoncons::detail::to_integer_decimal(item.key().data(),item.key().size(), n);
|
|
1381
|
+
if (!r || (index++ != n))
|
|
1382
|
+
{
|
|
1383
|
+
safe = false;
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
if (safe)
|
|
1389
|
+
{
|
|
1390
|
+
Json j(json_array_arg);
|
|
1391
|
+
j.reserve(value.size());
|
|
1392
|
+
for (auto& item : value.object_range())
|
|
1393
|
+
{
|
|
1394
|
+
j.emplace_back(std::move(item.value()));
|
|
1395
|
+
}
|
|
1396
|
+
Json a(json_array_arg);
|
|
1397
|
+
for (auto& item : j.array_range())
|
|
1398
|
+
{
|
|
1399
|
+
a.emplace_back(safe_unflatten (item));
|
|
1400
|
+
}
|
|
1401
|
+
return a;
|
|
1402
|
+
}
|
|
1403
|
+
else
|
|
1404
|
+
{
|
|
1405
|
+
Json o(json_object_arg);
|
|
1406
|
+
for (auto& item : value.object_range())
|
|
1407
|
+
{
|
|
1408
|
+
o.try_emplace(item.key(), safe_unflatten (item.value()));
|
|
1409
|
+
}
|
|
1410
|
+
return o;
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
template<class Json>
|
|
1415
|
+
jsoncons::optional<Json> try_unflatten_array(const Json& value)
|
|
1416
|
+
{
|
|
1417
|
+
using char_type = typename Json::char_type;
|
|
1418
|
+
|
|
1419
|
+
if (JSONCONS_UNLIKELY(!value.is_object()))
|
|
1420
|
+
{
|
|
1421
|
+
JSONCONS_THROW(jsonpointer_error(jsonpointer_errc::argument_to_unflatten_invalid));
|
|
1422
|
+
}
|
|
1423
|
+
Json result;
|
|
1424
|
+
|
|
1425
|
+
for (const auto& item: value.object_range())
|
|
1426
|
+
{
|
|
1427
|
+
Json* part = &result;
|
|
1428
|
+
basic_json_pointer<char_type> ptr(item.key());
|
|
1429
|
+
std::size_t index = 0;
|
|
1430
|
+
for (auto it = ptr.begin(); it != ptr.end(); )
|
|
1431
|
+
{
|
|
1432
|
+
auto s = *it;
|
|
1433
|
+
size_t n{0};
|
|
1434
|
+
auto r = jsoncons::detail::to_integer_decimal(s.data(), s.size(), n);
|
|
1435
|
+
if (r.ec == jsoncons::detail::to_integer_errc() && (index++ == n))
|
|
1436
|
+
{
|
|
1437
|
+
if (!part->is_array())
|
|
1438
|
+
{
|
|
1439
|
+
*part = Json(json_array_arg);
|
|
1440
|
+
}
|
|
1441
|
+
if (++it != ptr.end())
|
|
1442
|
+
{
|
|
1443
|
+
if (n+1 > part->size())
|
|
1444
|
+
{
|
|
1445
|
+
Json& ref = part->emplace_back();
|
|
1446
|
+
part = std::addressof(ref);
|
|
1447
|
+
}
|
|
1448
|
+
else
|
|
1449
|
+
{
|
|
1450
|
+
part = &part->at(n);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
else
|
|
1454
|
+
{
|
|
1455
|
+
Json& ref = part->emplace_back(item.value());
|
|
1456
|
+
part = std::addressof(ref);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
else if (part->is_object())
|
|
1460
|
+
{
|
|
1461
|
+
if (++it != ptr.end())
|
|
1462
|
+
{
|
|
1463
|
+
auto res = part->try_emplace(s,Json());
|
|
1464
|
+
part = &(res.first->value());
|
|
1465
|
+
}
|
|
1466
|
+
else
|
|
1467
|
+
{
|
|
1468
|
+
auto res = part->try_emplace(s, item.value());
|
|
1469
|
+
part = &(res.first->value());
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
else
|
|
1473
|
+
{
|
|
1474
|
+
return jsoncons::optional<Json>();
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
return result;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
template<class Json>
|
|
1483
|
+
Json unflatten_to_object(const Json& value, unflatten_options options = unflatten_options::none)
|
|
1484
|
+
{
|
|
1485
|
+
using char_type = typename Json::char_type;
|
|
1486
|
+
|
|
1487
|
+
if (JSONCONS_UNLIKELY(!value.is_object()))
|
|
1488
|
+
{
|
|
1489
|
+
JSONCONS_THROW(jsonpointer_error(jsonpointer_errc::argument_to_unflatten_invalid));
|
|
1490
|
+
}
|
|
1491
|
+
Json result;
|
|
1492
|
+
|
|
1493
|
+
for (const auto& item: value.object_range())
|
|
1494
|
+
{
|
|
1495
|
+
Json* part = &result;
|
|
1496
|
+
basic_json_pointer<char_type> ptr(item.key());
|
|
1497
|
+
for (auto it = ptr.begin(); it != ptr.end(); )
|
|
1498
|
+
{
|
|
1499
|
+
auto s = *it;
|
|
1500
|
+
if (++it != ptr.end())
|
|
1501
|
+
{
|
|
1502
|
+
auto res = part->try_emplace(s,Json());
|
|
1503
|
+
part = &(res.first->value());
|
|
1504
|
+
}
|
|
1505
|
+
else
|
|
1506
|
+
{
|
|
1507
|
+
auto res = part->try_emplace(s, item.value());
|
|
1508
|
+
part = &(res.first->value());
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
return options == unflatten_options::none ? safe_unflatten (result) : result;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
template<class Json>
|
|
1517
|
+
Json unflatten(const Json& value, unflatten_options options = unflatten_options::none)
|
|
1518
|
+
{
|
|
1519
|
+
if (options == unflatten_options::none)
|
|
1520
|
+
{
|
|
1521
|
+
jsoncons::optional<Json> j = try_unflatten_array(value);
|
|
1522
|
+
return j ? *j : unflatten_to_object(value,options);
|
|
1523
|
+
}
|
|
1524
|
+
else
|
|
1525
|
+
{
|
|
1526
|
+
return unflatten_to_object(value,options);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
1531
|
+
|
|
1532
|
+
template<class Json>
|
|
1533
|
+
JSONCONS_DEPRECATED_MSG("Instead, use add(Json&, const typename Json::string_view_type&, const Json&)")
|
|
1534
|
+
void insert_or_assign(Json& root, const std::basic_string<typename Json::char_type>& location, const Json& value)
|
|
1535
|
+
{
|
|
1536
|
+
add(root, location, value);
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
template<class Json>
|
|
1540
|
+
JSONCONS_DEPRECATED_MSG("Instead, use add(Json&, const typename Json::string_view_type&, const Json&, std::error_code&)")
|
|
1541
|
+
void insert_or_assign(Json& root, const std::basic_string<typename Json::char_type>& location, const Json& value, std::error_code& ec)
|
|
1542
|
+
{
|
|
1543
|
+
add(root, location, value, ec);
|
|
1544
|
+
}
|
|
1545
|
+
template<class Json, class T>
|
|
1546
|
+
void insert(Json& root,
|
|
1547
|
+
const std::basic_string<typename Json::char_type>& location,
|
|
1548
|
+
T&& value,
|
|
1549
|
+
bool create_if_missing,
|
|
1550
|
+
std::error_code& ec)
|
|
1551
|
+
{
|
|
1552
|
+
add_if_absent(root,location,std::forward<T>(value),create_if_missing,ec);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
template<class Json, class T>
|
|
1556
|
+
void insert(Json& root,
|
|
1557
|
+
const std::basic_string<typename Json::char_type>& location,
|
|
1558
|
+
T&& value,
|
|
1559
|
+
std::error_code& ec)
|
|
1560
|
+
{
|
|
1561
|
+
add_if_absent(root, location, std::forward<T>(value), ec);
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
template<class Json, class T>
|
|
1565
|
+
void insert(Json& root,
|
|
1566
|
+
const std::basic_string<typename Json::char_type>& location,
|
|
1567
|
+
T&& value,
|
|
1568
|
+
bool create_if_missing = false)
|
|
1569
|
+
{
|
|
1570
|
+
add_if_absent(root, location, std::forward<T>(value), create_if_missing);
|
|
1571
|
+
}
|
|
1572
|
+
#endif
|
|
1573
|
+
|
|
1574
|
+
} // namespace jsonpointer
|
|
1575
|
+
} // namespace jsoncons
|
|
1576
|
+
|
|
1577
|
+
#endif
|