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.
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