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,579 @@
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_JSONPATCH_JSONPATCH_HPP
8
+ #define JSONCONS_JSONPATCH_JSONPATCH_HPP
9
+
10
+ #include <string>
11
+ #include <vector>
12
+ #include <memory>
13
+ #include <algorithm> // std::min
14
+ #include <utility> // std::move
15
+ #include <jsoncons/json.hpp>
16
+ #include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
17
+ #include <jsoncons_ext/jsonpatch/jsonpatch_error.hpp>
18
+
19
+ namespace jsoncons { namespace jsonpatch {
20
+
21
+ namespace detail {
22
+
23
+ template <class CharT>
24
+ struct jsonpatch_names
25
+ {
26
+ static std::basic_string<CharT> test_name()
27
+ {
28
+ static std::basic_string<CharT> name{'t','e','s','t'};
29
+ return name;
30
+ }
31
+ static std::basic_string<CharT> add_name()
32
+ {
33
+ static std::basic_string<CharT> name{'a','d','d'};
34
+ return name;
35
+ }
36
+ static std::basic_string<CharT> remove_name()
37
+ {
38
+ static std::basic_string<CharT> name{'r','e','m','o','v','e'};
39
+ return name;
40
+ }
41
+ static std::basic_string<CharT> replace_name()
42
+ {
43
+ static std::basic_string<CharT> name{'r','e','p','l','a','c','e'};
44
+ return name;
45
+ }
46
+ static std::basic_string<CharT> move_name()
47
+ {
48
+ static std::basic_string<CharT> name{'m','o','v','e'};
49
+ return name;
50
+ }
51
+ static std::basic_string<CharT> copy_name()
52
+ {
53
+ static std::basic_string<CharT> name{'c','o','p','y'};
54
+ return name;
55
+ }
56
+ static std::basic_string<CharT> op_name()
57
+ {
58
+ static std::basic_string<CharT> name{'o','p'};
59
+ return name;
60
+ }
61
+ static std::basic_string<CharT> path_name()
62
+ {
63
+ static std::basic_string<CharT> name{'p','a','t','h'};
64
+ return name;
65
+ }
66
+ static std::basic_string<CharT> from_name()
67
+ {
68
+ static std::basic_string<CharT> name{'f','r','o','m'};
69
+ return name;
70
+ }
71
+ static std::basic_string<CharT> value_name()
72
+ {
73
+ static std::basic_string<CharT> name{'v','a','l','u','e'};
74
+ return name;
75
+ }
76
+ static std::basic_string<CharT> dash_name()
77
+ {
78
+ static std::basic_string<CharT> name{'-'};
79
+ return name;
80
+ }
81
+ };
82
+
83
+ template<class Json>
84
+ jsonpointer::basic_json_pointer<typename Json::char_type> definite_path(const Json& root, jsonpointer::basic_json_pointer<typename Json::char_type>& location)
85
+ {
86
+ using char_type = typename Json::char_type;
87
+ using string_type = std::basic_string<char_type>;
88
+
89
+ auto rit = location.rbegin();
90
+ if (rit == location.rend())
91
+ {
92
+ return location;
93
+ }
94
+
95
+ if (*rit != jsonpatch_names<char_type>::dash_name())
96
+ {
97
+ return location;
98
+ }
99
+
100
+ std::vector<string_type> tokens;
101
+ for (auto it = location.begin(); it != location.rbegin().base()-1; ++it)
102
+ {
103
+ tokens.push_back(*it);
104
+ }
105
+ jsonpointer::basic_json_pointer<char_type> pointer(tokens);
106
+
107
+ std::error_code ec;
108
+
109
+ Json val = jsonpointer::get(root, pointer, ec);
110
+ if (ec || !val.is_array())
111
+ {
112
+ return location;
113
+ }
114
+ string_type last_token;
115
+ jsoncons::detail::from_integer(val.size(), last_token);
116
+ tokens.emplace_back(std::move(last_token));
117
+
118
+ return jsonpointer::basic_json_pointer<char_type>(std::move(tokens));
119
+ }
120
+
121
+ enum class op_type {add,remove,replace};
122
+ enum class state_type {begin,abort,commit};
123
+
124
+ template <class Json>
125
+ struct operation_unwinder
126
+ {
127
+ using char_type = typename Json::char_type;
128
+ using string_type = std::basic_string<char_type>;
129
+ using json_pointer_type = jsonpointer::basic_json_pointer<char_type>;
130
+
131
+ struct entry
132
+ {
133
+ op_type op;
134
+ json_pointer_type path;
135
+ Json value;
136
+
137
+ entry(op_type op, const json_pointer_type& path, const Json& value)
138
+ : op(op), path(path), value(value)
139
+ {
140
+ }
141
+
142
+ entry(const entry&) = default;
143
+
144
+ entry(entry&&) = default;
145
+
146
+ entry& operator=(const entry&) = default;
147
+
148
+ entry& operator=(entry&&) = default;
149
+ };
150
+
151
+ Json& target;
152
+ state_type state;
153
+ std::vector<entry> stack;
154
+
155
+ operation_unwinder(Json& j)
156
+ : target(j), state(state_type::begin)
157
+ {
158
+ }
159
+
160
+ ~operation_unwinder() noexcept
161
+ {
162
+ std::error_code ec;
163
+ if (state != state_type::commit)
164
+ {
165
+ for (auto it = stack.rbegin(); it != stack.rend(); ++it)
166
+ {
167
+ if (it->op == op_type::add)
168
+ {
169
+ jsonpointer::add(target,it->path,it->value,ec);
170
+ if (ec)
171
+ {
172
+ //std::cout << "add: " << it->path << std::endl;
173
+ break;
174
+ }
175
+ }
176
+ else if (it->op == op_type::remove)
177
+ {
178
+ jsonpointer::remove(target,it->path,ec);
179
+ if (ec)
180
+ {
181
+ //std::cout << "remove: " << it->path << std::endl;
182
+ break;
183
+ }
184
+ }
185
+ else if (it->op == op_type::replace)
186
+ {
187
+ jsonpointer::replace(target,it->path,it->value,ec);
188
+ if (ec)
189
+ {
190
+ //std::cout << "replace: " << it->path << std::endl;
191
+ break;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ };
198
+
199
+ template <class Json>
200
+ Json from_diff(const Json& source, const Json& target, const typename Json::string_view_type& path)
201
+ {
202
+ using char_type = typename Json::char_type;
203
+
204
+ Json result = typename Json::array();
205
+
206
+ if (source == target)
207
+ {
208
+ return result;
209
+ }
210
+
211
+ if (source.is_array() && target.is_array())
212
+ {
213
+ std::size_t common = (std::min)(source.size(),target.size());
214
+ for (std::size_t i = 0; i < common; ++i)
215
+ {
216
+ std::basic_string<char_type> ss(path);
217
+ ss.push_back('/');
218
+ jsoncons::detail::from_integer(i,ss);
219
+ auto temp_diff = from_diff(source[i],target[i],ss);
220
+ result.insert(result.array_range().end(),temp_diff.array_range().begin(),temp_diff.array_range().end());
221
+ }
222
+ // Element in source, not in target - remove
223
+ for (std::size_t i = source.size(); i-- > target.size();)
224
+ {
225
+ std::basic_string<char_type> ss(path);
226
+ ss.push_back('/');
227
+ jsoncons::detail::from_integer(i,ss);
228
+ Json val(json_object_arg);
229
+ val.insert_or_assign(jsonpatch_names<char_type>::op_name(), jsonpatch_names<char_type>::remove_name());
230
+ val.insert_or_assign(jsonpatch_names<char_type>::path_name(), ss);
231
+ result.push_back(std::move(val));
232
+ }
233
+ // Element in target, not in source - add,
234
+ // Fix contributed by Alexander rog13
235
+ for (std::size_t i = source.size(); i < target.size(); ++i)
236
+ {
237
+ const auto& a = target[i];
238
+ std::basic_string<char_type> ss(path);
239
+ ss.push_back('/');
240
+ jsoncons::detail::from_integer(i,ss);
241
+ Json val(json_object_arg);
242
+ val.insert_or_assign(jsonpatch_names<char_type>::op_name(), jsonpatch_names<char_type>::add_name());
243
+ val.insert_or_assign(jsonpatch_names<char_type>::path_name(), ss);
244
+ val.insert_or_assign(jsonpatch_names<char_type>::value_name(), a);
245
+ result.push_back(std::move(val));
246
+ }
247
+ }
248
+ else if (source.is_object() && target.is_object())
249
+ {
250
+ for (const auto& a : source.object_range())
251
+ {
252
+ std::basic_string<char_type> ss(path);
253
+ ss.push_back('/');
254
+ jsonpointer::escape(a.key(),ss);
255
+ auto it = target.find(a.key());
256
+ if (it != target.object_range().end())
257
+ {
258
+ auto temp_diff = from_diff(a.value(),it->value(),ss);
259
+ result.insert(result.array_range().end(),temp_diff.array_range().begin(),temp_diff.array_range().end());
260
+ }
261
+ else
262
+ {
263
+ Json val(json_object_arg);
264
+ val.insert_or_assign(jsonpatch_names<char_type>::op_name(), jsonpatch_names<char_type>::remove_name());
265
+ val.insert_or_assign(jsonpatch_names<char_type>::path_name(), ss);
266
+ result.push_back(std::move(val));
267
+ }
268
+ }
269
+ for (const auto& a : target.object_range())
270
+ {
271
+ auto it = source.find(a.key());
272
+ if (it == source.object_range().end())
273
+ {
274
+ std::basic_string<char_type> ss(path);
275
+ ss.push_back('/');
276
+ jsonpointer::escape(a.key(),ss);
277
+ Json val(json_object_arg);
278
+ val.insert_or_assign(jsonpatch_names<char_type>::op_name(), jsonpatch_names<char_type>::add_name());
279
+ val.insert_or_assign(jsonpatch_names<char_type>::path_name(), ss);
280
+ val.insert_or_assign(jsonpatch_names<char_type>::value_name(), a.value());
281
+ result.push_back(std::move(val));
282
+ }
283
+ }
284
+ }
285
+ else
286
+ {
287
+ Json val(json_object_arg);
288
+ val.insert_or_assign(jsonpatch_names<char_type>::op_name(), jsonpatch_names<char_type>::replace_name());
289
+ val.insert_or_assign(jsonpatch_names<char_type>::path_name(), path);
290
+ val.insert_or_assign(jsonpatch_names<char_type>::value_name(), target);
291
+ result.push_back(std::move(val));
292
+ }
293
+
294
+ return result;
295
+ }
296
+ }
297
+
298
+ template <class Json>
299
+ void apply_patch(Json& target, const Json& patch, std::error_code& ec)
300
+ {
301
+ using char_type = typename Json::char_type;
302
+ using string_type = std::basic_string<char_type>;
303
+ using json_pointer_type = jsonpointer::basic_json_pointer<char_type>;
304
+
305
+ jsoncons::jsonpatch::detail::operation_unwinder<Json> unwinder(target);
306
+ std::error_code local_ec;
307
+
308
+ // Validate
309
+
310
+ for (const auto& operation : patch.array_range())
311
+ {
312
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::begin;
313
+
314
+ auto it_op = operation.find(detail::jsonpatch_names<char_type>::op_name());
315
+ if (it_op == operation.object_range().end())
316
+ {
317
+ ec = jsonpatch_errc::invalid_patch;
318
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
319
+ return;
320
+ }
321
+ string_type op = it_op->value().template as<string_type>();
322
+
323
+ auto it_path = operation.find(detail::jsonpatch_names<char_type>::path_name());
324
+ if (it_path == operation.object_range().end())
325
+ {
326
+ ec = jsonpatch_errc::invalid_patch;
327
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
328
+ return;
329
+ }
330
+ string_type path = it_path->value().template as<string_type>();
331
+ auto location = json_pointer_type::parse(path, local_ec);
332
+ if (local_ec)
333
+ {
334
+ ec = jsonpatch_errc::invalid_patch;
335
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
336
+ return;
337
+ }
338
+
339
+ if (op ==jsoncons::jsonpatch::detail::jsonpatch_names<char_type>::test_name())
340
+ {
341
+ Json val = jsonpointer::get(target,location,local_ec);
342
+ if (local_ec)
343
+ {
344
+ ec = jsonpatch_errc::test_failed;
345
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
346
+ return;
347
+ }
348
+ auto it_value = operation.find(detail::jsonpatch_names<char_type>::value_name());
349
+ if (it_value == operation.object_range().end())
350
+ {
351
+ ec = jsonpatch_errc::invalid_patch;
352
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
353
+ return;
354
+ }
355
+ if (val != it_value->value())
356
+ {
357
+ ec = jsonpatch_errc::test_failed;
358
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
359
+ return;
360
+ }
361
+ }
362
+ else if (op ==jsoncons::jsonpatch::detail::jsonpatch_names<char_type>::add_name())
363
+ {
364
+ auto it_value = operation.find(detail::jsonpatch_names<char_type>::value_name());
365
+ if (it_value == operation.object_range().end())
366
+ {
367
+ ec = jsonpatch_errc::invalid_patch;
368
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
369
+ return;
370
+ }
371
+ Json val = it_value->value();
372
+ auto npath = jsonpatch::detail::definite_path(target,location);
373
+
374
+ std::error_code insert_ec;
375
+ jsonpointer::add_if_absent(target,npath,val,insert_ec); // try insert without replace
376
+ if (insert_ec) // try a replace
377
+ {
378
+ std::error_code select_ec;
379
+ Json orig_val = jsonpointer::get(target,npath,select_ec);
380
+ if (select_ec) // shouldn't happen
381
+ {
382
+ ec = jsonpatch_errc::add_failed;
383
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
384
+ return;
385
+ }
386
+ std::error_code replace_ec;
387
+ jsonpointer::replace(target,npath,val,replace_ec);
388
+ if (replace_ec)
389
+ {
390
+ ec = jsonpatch_errc::add_failed;
391
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
392
+ return;
393
+ }
394
+ unwinder.stack.emplace_back(detail::op_type::replace,npath,orig_val);
395
+ }
396
+ else // insert without replace succeeded
397
+ {
398
+ unwinder.stack.emplace_back(detail::op_type::remove,npath,Json::null());
399
+ }
400
+ }
401
+ else if (op ==jsoncons::jsonpatch::detail::jsonpatch_names<char_type>::remove_name())
402
+ {
403
+ Json val = jsonpointer::get(target,location,local_ec);
404
+ if (local_ec)
405
+ {
406
+ ec = jsonpatch_errc::remove_failed;
407
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
408
+ return;
409
+ }
410
+ jsonpointer::remove(target,location,local_ec);
411
+ if (local_ec)
412
+ {
413
+ ec = jsonpatch_errc::remove_failed;
414
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
415
+ return;
416
+ }
417
+ unwinder.stack.emplace_back(detail::op_type::add, location, val);
418
+ }
419
+ else if (op ==jsoncons::jsonpatch::detail::jsonpatch_names<char_type>::replace_name())
420
+ {
421
+ Json val = jsonpointer::get(target,location,local_ec);
422
+ if (local_ec)
423
+ {
424
+ ec = jsonpatch_errc::replace_failed;
425
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
426
+ return;
427
+ }
428
+ auto it_value = operation.find(detail::jsonpatch_names<char_type>::value_name());
429
+ if (it_value == operation.object_range().end())
430
+ {
431
+ ec = jsonpatch_errc::invalid_patch;
432
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
433
+ return;
434
+ }
435
+ jsonpointer::replace(target, location, it_value->value(), local_ec);
436
+ if (local_ec)
437
+ {
438
+ ec = jsonpatch_errc::replace_failed;
439
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
440
+ return;
441
+ }
442
+ unwinder.stack.emplace_back(detail::op_type::replace,location,val);
443
+ }
444
+ else if (op ==jsoncons::jsonpatch::detail::jsonpatch_names<char_type>::move_name())
445
+ {
446
+ auto it_from = operation.find(detail::jsonpatch_names<char_type>::from_name());
447
+ if (it_from == operation.object_range().end())
448
+ {
449
+ ec = jsonpatch_errc::invalid_patch;
450
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
451
+ return;
452
+ }
453
+ string_type from = it_from->value().as_string();
454
+ auto from_pointer = json_pointer_type::parse(from, local_ec);
455
+ if (local_ec)
456
+ {
457
+ ec = jsonpatch_errc::move_failed;
458
+ unwinder.state = jsoncons::jsonpatch::detail::state_type::abort;
459
+ return;
460
+ }
461
+
462
+ Json val = jsonpointer::get(target, from_pointer, local_ec);
463
+ if (local_ec)
464
+ {
465
+ ec = jsonpatch_errc::move_failed;
466
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
467
+ return;
468
+ }
469
+ jsonpointer::remove(target, from_pointer, local_ec);
470
+ if (local_ec)
471
+ {
472
+ ec = jsonpatch_errc::move_failed;
473
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
474
+ return;
475
+ }
476
+ unwinder.stack.emplace_back(detail::op_type::add, from_pointer, val);
477
+ // add
478
+ std::error_code insert_ec;
479
+ auto npath = jsonpatch::detail::definite_path(target,location);
480
+ jsonpointer::add_if_absent(target,npath,val,insert_ec); // try insert without replace
481
+ if (insert_ec) // try a replace
482
+ {
483
+ std::error_code select_ec;
484
+ Json orig_val = jsonpointer::get(target,npath,select_ec);
485
+ if (select_ec) // shouldn't happen
486
+ {
487
+ ec = jsonpatch_errc::copy_failed;
488
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
489
+ return;
490
+ }
491
+ std::error_code replace_ec;
492
+ jsonpointer::replace(target, npath, val, replace_ec);
493
+ if (replace_ec)
494
+ {
495
+ ec = jsonpatch_errc::copy_failed;
496
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
497
+ return;
498
+ }
499
+ unwinder.stack.emplace_back(jsoncons::jsonpatch::detail::op_type::replace,npath,orig_val);
500
+ }
501
+ else
502
+ {
503
+ unwinder.stack.emplace_back(detail::op_type::remove,npath,Json::null());
504
+ }
505
+ }
506
+ else if (op ==jsoncons::jsonpatch::detail::jsonpatch_names<char_type>::copy_name())
507
+ {
508
+ auto it_from = operation.find(detail::jsonpatch_names<char_type>::from_name());
509
+ if (it_from == operation.object_range().end())
510
+ {
511
+ ec = jsonpatch_errc::invalid_patch;
512
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
513
+ return;
514
+ }
515
+ string_type from = it_from->value().as_string();
516
+ Json val = jsonpointer::get(target,from,local_ec);
517
+ if (local_ec)
518
+ {
519
+ ec = jsonpatch_errc::copy_failed;
520
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
521
+ return;
522
+ }
523
+ // add
524
+ auto npath = jsonpatch::detail::definite_path(target,location);
525
+ std::error_code insert_ec;
526
+ jsonpointer::add_if_absent(target,npath,val,insert_ec); // try insert without replace
527
+ if (insert_ec) // Failed, try a replace
528
+ {
529
+ std::error_code select_ec;
530
+ Json orig_val = jsonpointer::get(target,npath, select_ec);
531
+ if (select_ec) // shouldn't happen
532
+ {
533
+ ec = jsonpatch_errc::copy_failed;
534
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
535
+ return;
536
+ }
537
+ std::error_code replace_ec;
538
+ jsonpointer::replace(target, npath, val,replace_ec);
539
+ if (replace_ec)
540
+ {
541
+ ec = jsonpatch_errc::copy_failed;
542
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::abort;
543
+ return;
544
+ }
545
+ unwinder.stack.emplace_back(jsoncons::jsonpatch::detail::op_type::replace,npath,orig_val);
546
+ }
547
+ else
548
+ {
549
+ unwinder.stack.emplace_back(detail::op_type::remove,npath,Json::null());
550
+ }
551
+ }
552
+ }
553
+ if (unwinder.state ==jsoncons::jsonpatch::detail::state_type::begin)
554
+ {
555
+ unwinder.state =jsoncons::jsonpatch::detail::state_type::commit;
556
+ }
557
+ }
558
+
559
+ template <class Json>
560
+ Json from_diff(const Json& source, const Json& target)
561
+ {
562
+ std::basic_string<typename Json::char_type> path;
563
+ return jsoncons::jsonpatch::detail::from_diff(source, target, path);
564
+ }
565
+
566
+ template <class Json>
567
+ void apply_patch(Json& target, const Json& patch)
568
+ {
569
+ std::error_code ec;
570
+ apply_patch(target, patch, ec);
571
+ if (ec)
572
+ {
573
+ JSONCONS_THROW(jsonpatch_error(ec));
574
+ }
575
+ }
576
+
577
+ }}
578
+
579
+ #endif
@@ -0,0 +1,121 @@
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_JSONPATCH_JSONPATCH_ERROR_HPP
8
+ #define JSONCONS_JSONPATCH_JSONPATCH_ERROR_HPP
9
+
10
+ #include <jsoncons/json_exception.hpp>
11
+ #include <system_error>
12
+
13
+ namespace jsoncons { namespace jsonpatch {
14
+
15
+ enum class jsonpatch_errc
16
+ {
17
+ success = 0,
18
+ invalid_patch = 1,
19
+ test_failed,
20
+ add_failed,
21
+ remove_failed,
22
+ replace_failed,
23
+ move_failed,
24
+ copy_failed
25
+
26
+ };
27
+
28
+ class jsonpatch_error_category_impl
29
+ : public std::error_category
30
+ {
31
+ public:
32
+ const char* name() const noexcept override
33
+ {
34
+ return "jsoncons/jsonpatch";
35
+ }
36
+ std::string message(int ev) const override
37
+ {
38
+ switch (static_cast<jsonpatch_errc>(ev))
39
+ {
40
+ case jsonpatch_errc::invalid_patch:
41
+ return "Invalid JSON Patch document";
42
+ case jsonpatch_errc::test_failed:
43
+ return "JSON Patch test operation failed";
44
+ case jsonpatch_errc::add_failed:
45
+ return "JSON Patch add operation failed";
46
+ case jsonpatch_errc::remove_failed:
47
+ return "JSON Patch remove operation failed";
48
+ case jsonpatch_errc::replace_failed:
49
+ return "JSON Patch replace operation failed";
50
+ case jsonpatch_errc::move_failed:
51
+ return "JSON Patch move operation failed";
52
+ case jsonpatch_errc::copy_failed:
53
+ return "JSON Patch copy operation failed";
54
+ default:
55
+ return "Unknown JSON Patch error";
56
+ }
57
+ }
58
+ };
59
+
60
+ inline
61
+ const std::error_category& jsonpatch_error_category()
62
+ {
63
+ static jsonpatch_error_category_impl instance;
64
+ return instance;
65
+ }
66
+
67
+ inline
68
+ std::error_code make_error_code(jsonpatch_errc result)
69
+ {
70
+ return std::error_code(static_cast<int>(result),jsonpatch_error_category());
71
+ }
72
+
73
+ } // jsonpatch
74
+ } // jsoncons
75
+
76
+ namespace std {
77
+ template<>
78
+ struct is_error_code_enum<jsoncons::jsonpatch::jsonpatch_errc> : public true_type
79
+ {
80
+ };
81
+ }
82
+
83
+ namespace jsoncons { namespace jsonpatch {
84
+
85
+ // allow to disable exceptions
86
+ #if !defined(JSONCONS_NO_EXCEPTIONS)
87
+ #define JSONCONS_THROW(exception) throw exception
88
+ #define JSONCONS_RETHROW throw
89
+ #define JSONCONS_TRY try
90
+ #define JSONCONS_CATCH(exception) catch(exception)
91
+ #else
92
+ #define JSONCONS_THROW(exception) std::terminate()
93
+ #define JSONCONS_RETHROW std::terminate()
94
+ #define JSONCONS_TRY if (true)
95
+ #define JSONCONS_CATCH(exception) if (false)
96
+ #endif
97
+
98
+ class jsonpatch_error : public std::system_error, public virtual json_exception
99
+ {
100
+ public:
101
+ jsonpatch_error(const std::error_code& ec)
102
+ : std::system_error(ec)
103
+ {
104
+ }
105
+
106
+ jsonpatch_error(const jsonpatch_error& other) = default;
107
+
108
+ jsonpatch_error(jsonpatch_error&& other) = default;
109
+
110
+ jsonpatch_error& operator=(const jsonpatch_error& e) = default;
111
+ jsonpatch_error& operator=(jsonpatch_error&& e) = default;
112
+
113
+ const char* what() const noexcept override
114
+ {
115
+ return std::system_error::what();
116
+ }
117
+ };
118
+ } // jsonpatch
119
+ } // jsoncons
120
+
121
+ #endif