jsoncons 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/ext/jsoncons/extconf.rb +43 -0
  3. data/ext/jsoncons/jsoncons.cpp +161 -0
  4. data/ext/jsoncons/jsoncons.h +10 -0
  5. data/jsoncons.gemspec +44 -0
  6. data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
  7. data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
  8. data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
  9. data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
  10. data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
  11. data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
  12. data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
  13. data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
  14. data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
  15. data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
  16. data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
  17. data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
  18. data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
  19. data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
  20. data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
  21. data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
  22. data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
  23. data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
  24. data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
  25. data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
  26. data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
  27. data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
  28. data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
  29. data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
  30. data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
  31. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
  32. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
  33. data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
  34. data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
  35. data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
  36. data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
  37. data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
  38. data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
  39. data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
  40. data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
  41. data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
  42. data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
  43. data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
  44. data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
  45. data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
  46. data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
  47. data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
  48. data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
  49. data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
  50. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
  51. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
  52. data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
  53. data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
  54. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
  55. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
  56. data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
  57. data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
  58. data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
  59. data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
  60. data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
  61. data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
  62. data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
  63. data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
  64. data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
  65. data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
  66. data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
  67. data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
  68. data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
  69. data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
  70. data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
  71. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
  72. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
  73. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
  74. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
  75. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
  76. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
  77. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
  78. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
  79. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
  80. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
  81. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
  82. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
  83. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
  84. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
  85. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
  86. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
  87. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
  88. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
  89. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
  90. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
  91. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
  92. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
  93. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
  94. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
  95. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
  96. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
  97. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
  98. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
  99. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
  100. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
  101. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
  102. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
  103. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
  104. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
  105. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
  106. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
  107. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
  108. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
  109. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
  110. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
  111. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
  112. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
  113. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
  114. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
  115. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
  116. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
  117. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
  118. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
  119. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
  120. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
  121. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
  122. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
  123. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
  124. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
  125. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
  126. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
  127. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
  128. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
  129. data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
  130. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
  131. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
  132. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
  133. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
  134. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
  135. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
  136. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
  137. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
  138. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
  139. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
  140. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
  141. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
  142. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
  143. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
  144. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
  145. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
  146. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
  147. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
  148. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
  149. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
  150. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
  151. data/lib/jsoncons/version.rb +5 -0
  152. data/lib/jsoncons.rb +33 -0
  153. data/test/jsoncons_test.rb +108 -0
  154. data/test/test_helper.rb +7 -0
  155. 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