1 | /* |
2 | __ _____ _____ _____ |
3 | __| | __| | | | JSON for Modern C++ |
4 | | | |__ | | | | | | version 3.7.0 |
5 | |_____|_____|_____|_|___| https://github.com/nlohmann/json |
6 | |
7 | Licensed under the MIT License <http://opensource.org/licenses/MIT>. |
8 | SPDX-License-Identifier: MIT |
9 | Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>. |
10 | |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy |
12 | of this software and associated documentation files (the "Software"), to deal |
13 | in the Software without restriction, including without limitation the rights |
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
15 | copies of the Software, and to permit persons to whom the Software is |
16 | furnished to do so, subject to the following conditions: |
17 | |
18 | The above copyright notice and this permission notice shall be included in all |
19 | copies or substantial portions of the Software. |
20 | |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
27 | SOFTWARE. |
28 | */ |
29 | |
30 | #ifndef INCLUDE_NLOHMANN_JSON_HPP_ |
31 | #define INCLUDE_NLOHMANN_JSON_HPP_ |
32 | |
33 | #define NLOHMANN_JSON_VERSION_MAJOR 3 |
34 | #define NLOHMANN_JSON_VERSION_MINOR 7 |
35 | #define NLOHMANN_JSON_VERSION_PATCH 0 |
36 | |
37 | #include <algorithm> // all_of, find, for_each |
38 | #include <cassert> // assert |
39 | #include <ciso646> // and, not, or |
40 | #include <cstddef> // nullptr_t, ptrdiff_t, size_t |
41 | #include <functional> // hash, less |
42 | #include <initializer_list> // initializer_list |
43 | #include <iosfwd> // istream, ostream |
44 | #include <iterator> // random_access_iterator_tag |
45 | #include <memory> // unique_ptr |
46 | #include <numeric> // accumulate |
47 | #include <string> // string, stoi, to_string |
48 | #include <utility> // declval, forward, move, pair, swap |
49 | #include <vector> // vector |
50 | |
51 | #include <nlohmann/adl_serializer.hpp> |
52 | #include <nlohmann/detail/conversions/from_json.hpp> |
53 | #include <nlohmann/detail/conversions/to_json.hpp> |
54 | #include <nlohmann/detail/exceptions.hpp> |
55 | #include <nlohmann/detail/input/binary_reader.hpp> |
56 | #include <nlohmann/detail/input/input_adapters.hpp> |
57 | #include <nlohmann/detail/input/lexer.hpp> |
58 | #include <nlohmann/detail/input/parser.hpp> |
59 | #include <nlohmann/detail/iterators/internal_iterator.hpp> |
60 | #include <nlohmann/detail/iterators/iter_impl.hpp> |
61 | #include <nlohmann/detail/iterators/iteration_proxy.hpp> |
62 | #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> |
63 | #include <nlohmann/detail/iterators/primitive_iterator.hpp> |
64 | #include <nlohmann/detail/json_pointer.hpp> |
65 | #include <nlohmann/detail/json_ref.hpp> |
66 | #include <nlohmann/detail/macro_scope.hpp> |
67 | #include <nlohmann/detail/meta/cpp_future.hpp> |
68 | #include <nlohmann/detail/meta/type_traits.hpp> |
69 | #include <nlohmann/detail/output/binary_writer.hpp> |
70 | #include <nlohmann/detail/output/output_adapters.hpp> |
71 | #include <nlohmann/detail/output/serializer.hpp> |
72 | #include <nlohmann/detail/value_t.hpp> |
73 | #include <nlohmann/json_fwd.hpp> |
74 | |
75 | /*! |
76 | @brief namespace for Niels Lohmann |
77 | @see https://github.com/nlohmann |
78 | @since version 1.0.0 |
79 | */ |
80 | namespace nlohmann |
81 | { |
82 | |
83 | /*! |
84 | @brief a class to store JSON values |
85 | |
86 | @tparam ObjectType type for JSON objects (`std::map` by default; will be used |
87 | in @ref object_t) |
88 | @tparam ArrayType type for JSON arrays (`std::vector` by default; will be used |
89 | in @ref array_t) |
90 | @tparam StringType type for JSON strings and object keys (`std::string` by |
91 | default; will be used in @ref string_t) |
92 | @tparam BooleanType type for JSON booleans (`bool` by default; will be used |
93 | in @ref boolean_t) |
94 | @tparam NumberIntegerType type for JSON integer numbers (`int64_t` by |
95 | default; will be used in @ref number_integer_t) |
96 | @tparam NumberUnsignedType type for JSON unsigned integer numbers (@c |
97 | `uint64_t` by default; will be used in @ref number_unsigned_t) |
98 | @tparam NumberFloatType type for JSON floating-point numbers (`double` by |
99 | default; will be used in @ref number_float_t) |
100 | @tparam AllocatorType type of the allocator to use (`std::allocator` by |
101 | default) |
102 | @tparam JSONSerializer the serializer to resolve internal calls to `to_json()` |
103 | and `from_json()` (@ref adl_serializer by default) |
104 | |
105 | @requirement The class satisfies the following concept requirements: |
106 | - Basic |
107 | - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible): |
108 | JSON values can be default constructed. The result will be a JSON null |
109 | value. |
110 | - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible): |
111 | A JSON value can be constructed from an rvalue argument. |
112 | - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible): |
113 | A JSON value can be copy-constructed from an lvalue expression. |
114 | - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): |
115 | A JSON value van be assigned from an rvalue argument. |
116 | - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable): |
117 | A JSON value can be copy-assigned from an lvalue expression. |
118 | - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible): |
119 | JSON values can be destructed. |
120 | - Layout |
121 | - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType): |
122 | JSON values have |
123 | [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout): |
124 | All non-static data members are private and standard layout types, the |
125 | class has no virtual functions or (virtual) base classes. |
126 | - Library-wide |
127 | - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): |
128 | JSON values can be compared with `==`, see @ref |
129 | operator==(const_reference,const_reference). |
130 | - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): |
131 | JSON values can be compared with `<`, see @ref |
132 | operator<(const_reference,const_reference). |
133 | - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): |
134 | Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of |
135 | other compatible types, using unqualified function call @ref swap(). |
136 | - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): |
137 | JSON values can be compared against `std::nullptr_t` objects which are used |
138 | to model the `null` value. |
139 | - Container |
140 | - [Container](https://en.cppreference.com/w/cpp/named_req/Container): |
141 | JSON values can be used like STL containers and provide iterator access. |
142 | - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer); |
143 | JSON values can be used like STL containers and provide reverse iterator |
144 | access. |
145 | |
146 | @invariant The member variables @a m_value and @a m_type have the following |
147 | relationship: |
148 | - If `m_type == value_t::object`, then `m_value.object != nullptr`. |
149 | - If `m_type == value_t::array`, then `m_value.array != nullptr`. |
150 | - If `m_type == value_t::string`, then `m_value.string != nullptr`. |
151 | The invariants are checked by member function assert_invariant(). |
152 | |
153 | @internal |
154 | @note ObjectType trick from http://stackoverflow.com/a/9860911 |
155 | @endinternal |
156 | |
157 | @see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange |
158 | Format](http://rfc7159.net/rfc7159) |
159 | |
160 | @since version 1.0.0 |
161 | |
162 | @nosubgrouping |
163 | */ |
164 | NLOHMANN_BASIC_JSON_TPL_DECLARATION |
165 | class basic_json |
166 | { |
167 | private: |
168 | template<detail::value_t> friend struct detail::external_constructor; |
169 | friend ::nlohmann::json_pointer<basic_json>; |
170 | friend ::nlohmann::detail::parser<basic_json>; |
171 | friend ::nlohmann::detail::serializer<basic_json>; |
172 | template<typename BasicJsonType> |
173 | friend class ::nlohmann::detail::iter_impl; |
174 | template<typename BasicJsonType, typename CharType> |
175 | friend class ::nlohmann::detail::binary_writer; |
176 | template<typename BasicJsonType, typename SAX> |
177 | friend class ::nlohmann::detail::binary_reader; |
178 | template<typename BasicJsonType> |
179 | friend class ::nlohmann::detail::json_sax_dom_parser; |
180 | template<typename BasicJsonType> |
181 | friend class ::nlohmann::detail::json_sax_dom_callback_parser; |
182 | |
183 | /// workaround type for MSVC |
184 | using basic_json_t = NLOHMANN_BASIC_JSON_TPL; |
185 | |
186 | // convenience aliases for types residing in namespace detail; |
187 | using lexer = ::nlohmann::detail::lexer<basic_json>; |
188 | using parser = ::nlohmann::detail::parser<basic_json>; |
189 | |
190 | using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; |
191 | template<typename BasicJsonType> |
192 | using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; |
193 | template<typename BasicJsonType> |
194 | using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; |
195 | template<typename Iterator> |
196 | using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; |
197 | template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; |
198 | |
199 | template<typename CharType> |
200 | using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; |
201 | |
202 | using binary_reader = ::nlohmann::detail::binary_reader<basic_json>; |
203 | template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; |
204 | |
205 | using serializer = ::nlohmann::detail::serializer<basic_json>; |
206 | |
207 | public: |
208 | using value_t = detail::value_t; |
209 | /// JSON Pointer, see @ref nlohmann::json_pointer |
210 | using json_pointer = ::nlohmann::json_pointer<basic_json>; |
211 | template<typename T, typename SFINAE> |
212 | using json_serializer = JSONSerializer<T, SFINAE>; |
213 | /// how to treat decoding errors |
214 | using error_handler_t = detail::error_handler_t; |
215 | /// helper type for initializer lists of basic_json values |
216 | using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; |
217 | |
218 | using input_format_t = detail::input_format_t; |
219 | /// SAX interface type, see @ref nlohmann::json_sax |
220 | using json_sax_t = json_sax<basic_json>; |
221 | |
222 | //////////////// |
223 | // exceptions // |
224 | //////////////// |
225 | |
226 | /// @name exceptions |
227 | /// Classes to implement user-defined exceptions. |
228 | /// @{ |
229 | |
230 | /// @copydoc detail::exception |
231 | using exception = detail::exception; |
232 | /// @copydoc detail::parse_error |
233 | using parse_error = detail::parse_error; |
234 | /// @copydoc detail::invalid_iterator |
235 | using invalid_iterator = detail::invalid_iterator; |
236 | /// @copydoc detail::type_error |
237 | using type_error = detail::type_error; |
238 | /// @copydoc detail::out_of_range |
239 | using out_of_range = detail::out_of_range; |
240 | /// @copydoc detail::other_error |
241 | using other_error = detail::other_error; |
242 | |
243 | /// @} |
244 | |
245 | |
246 | ///////////////////// |
247 | // container types // |
248 | ///////////////////// |
249 | |
250 | /// @name container types |
251 | /// The canonic container types to use @ref basic_json like any other STL |
252 | /// container. |
253 | /// @{ |
254 | |
255 | /// the type of elements in a basic_json container |
256 | using value_type = basic_json; |
257 | |
258 | /// the type of an element reference |
259 | using reference = value_type&; |
260 | /// the type of an element const reference |
261 | using const_reference = const value_type&; |
262 | |
263 | /// a type to represent differences between iterators |
264 | using difference_type = std::ptrdiff_t; |
265 | /// a type to represent container sizes |
266 | using size_type = std::size_t; |
267 | |
268 | /// the allocator type |
269 | using allocator_type = AllocatorType<basic_json>; |
270 | |
271 | /// the type of an element pointer |
272 | using pointer = typename std::allocator_traits<allocator_type>::pointer; |
273 | /// the type of an element const pointer |
274 | using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; |
275 | |
276 | /// an iterator for a basic_json container |
277 | using iterator = iter_impl<basic_json>; |
278 | /// a const iterator for a basic_json container |
279 | using const_iterator = iter_impl<const basic_json>; |
280 | /// a reverse iterator for a basic_json container |
281 | using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; |
282 | /// a const reverse iterator for a basic_json container |
283 | using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; |
284 | |
285 | /// @} |
286 | |
287 | |
288 | /*! |
289 | @brief returns the allocator associated with the container |
290 | */ |
291 | static allocator_type get_allocator() |
292 | { |
293 | return allocator_type(); |
294 | } |
295 | |
296 | /*! |
297 | @brief returns version information on the library |
298 | |
299 | This function returns a JSON object with information about the library, |
300 | including the version number and information on the platform and compiler. |
301 | |
302 | @return JSON object holding version information |
303 | key | description |
304 | ----------- | --------------- |
305 | `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). |
306 | `copyright` | The copyright line for the library as string. |
307 | `name` | The name of the library as string. |
308 | `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. |
309 | `url` | The URL of the project as string. |
310 | `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). |
311 | |
312 | @liveexample{The following code shows an example output of the `meta()` |
313 | function.,meta} |
314 | |
315 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
316 | changes to any JSON value. |
317 | |
318 | @complexity Constant. |
319 | |
320 | @since 2.1.0 |
321 | */ |
322 | JSON_HEDLEY_WARN_UNUSED_RESULT |
323 | static basic_json meta() |
324 | { |
325 | basic_json result; |
326 | |
327 | result["copyright" ] = "(C) 2013-2017 Niels Lohmann" ; |
328 | result["name" ] = "JSON for Modern C++" ; |
329 | result["url" ] = "https://github.com/nlohmann/json" ; |
330 | result["version" ]["string" ] = |
331 | std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + |
332 | std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + |
333 | std::to_string(NLOHMANN_JSON_VERSION_PATCH); |
334 | result["version" ]["major" ] = NLOHMANN_JSON_VERSION_MAJOR; |
335 | result["version" ]["minor" ] = NLOHMANN_JSON_VERSION_MINOR; |
336 | result["version" ]["patch" ] = NLOHMANN_JSON_VERSION_PATCH; |
337 | |
338 | #ifdef _WIN32 |
339 | result["platform" ] = "win32" ; |
340 | #elif defined __linux__ |
341 | result["platform" ] = "linux" ; |
342 | #elif defined __APPLE__ |
343 | result["platform" ] = "apple" ; |
344 | #elif defined __unix__ |
345 | result["platform" ] = "unix" ; |
346 | #else |
347 | result["platform" ] = "unknown" ; |
348 | #endif |
349 | |
350 | #if defined(__ICC) || defined(__INTEL_COMPILER) |
351 | result["compiler" ] = {{"family" , "icc" }, {"version" , __INTEL_COMPILER}}; |
352 | #elif defined(__clang__) |
353 | result["compiler" ] = {{"family" , "clang" }, {"version" , __clang_version__}}; |
354 | #elif defined(__GNUC__) || defined(__GNUG__) |
355 | result["compiler" ] = {{"family" , "gcc" }, {"version" , std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; |
356 | #elif defined(__HP_cc) || defined(__HP_aCC) |
357 | result["compiler" ] = "hp" |
358 | #elif defined(__IBMCPP__) |
359 | result["compiler" ] = {{"family" , "ilecpp" }, {"version" , __IBMCPP__}}; |
360 | #elif defined(_MSC_VER) |
361 | result["compiler" ] = {{"family" , "msvc" }, {"version" , _MSC_VER}}; |
362 | #elif defined(__PGI) |
363 | result["compiler" ] = {{"family" , "pgcpp" }, {"version" , __PGI}}; |
364 | #elif defined(__SUNPRO_CC) |
365 | result["compiler" ] = {{"family" , "sunpro" }, {"version" , __SUNPRO_CC}}; |
366 | #else |
367 | result["compiler" ] = {{"family" , "unknown" }, {"version" , "unknown" }}; |
368 | #endif |
369 | |
370 | #ifdef __cplusplus |
371 | result["compiler" ]["c++" ] = std::to_string(__cplusplus); |
372 | #else |
373 | result["compiler" ]["c++" ] = "unknown" ; |
374 | #endif |
375 | return result; |
376 | } |
377 | |
378 | |
379 | /////////////////////////// |
380 | // JSON value data types // |
381 | /////////////////////////// |
382 | |
383 | /// @name JSON value data types |
384 | /// The data types to store a JSON value. These types are derived from |
385 | /// the template arguments passed to class @ref basic_json. |
386 | /// @{ |
387 | |
388 | #if defined(JSON_HAS_CPP_14) |
389 | // Use transparent comparator if possible, combined with perfect forwarding |
390 | // on find() and count() calls prevents unnecessary string construction. |
391 | using object_comparator_t = std::less<>; |
392 | #else |
393 | using object_comparator_t = std::less<StringType>; |
394 | #endif |
395 | |
396 | /*! |
397 | @brief a type for an object |
398 | |
399 | [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: |
400 | > An object is an unordered collection of zero or more name/value pairs, |
401 | > where a name is a string and a value is a string, number, boolean, null, |
402 | > object, or array. |
403 | |
404 | To store objects in C++, a type is defined by the template parameters |
405 | described below. |
406 | |
407 | @tparam ObjectType the container to store objects (e.g., `std::map` or |
408 | `std::unordered_map`) |
409 | @tparam StringType the type of the keys or names (e.g., `std::string`). |
410 | The comparison function `std::less<StringType>` is used to order elements |
411 | inside the container. |
412 | @tparam AllocatorType the allocator to use for objects (e.g., |
413 | `std::allocator`) |
414 | |
415 | #### Default type |
416 | |
417 | With the default values for @a ObjectType (`std::map`), @a StringType |
418 | (`std::string`), and @a AllocatorType (`std::allocator`), the default |
419 | value for @a object_t is: |
420 | |
421 | @code {.cpp} |
422 | std::map< |
423 | std::string, // key_type |
424 | basic_json, // value_type |
425 | std::less<std::string>, // key_compare |
426 | std::allocator<std::pair<const std::string, basic_json>> // allocator_type |
427 | > |
428 | @endcode |
429 | |
430 | #### Behavior |
431 | |
432 | The choice of @a object_t influences the behavior of the JSON class. With |
433 | the default type, objects have the following behavior: |
434 | |
435 | - When all names are unique, objects will be interoperable in the sense |
436 | that all software implementations receiving that object will agree on |
437 | the name-value mappings. |
438 | - When the names within an object are not unique, it is unspecified which |
439 | one of the values for a given key will be chosen. For instance, |
440 | `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or |
441 | `{"key": 2}`. |
442 | - Internally, name/value pairs are stored in lexicographical order of the |
443 | names. Objects will also be serialized (see @ref dump) in this order. |
444 | For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored |
445 | and serialized as `{"a": 2, "b": 1}`. |
446 | - When comparing objects, the order of the name/value pairs is irrelevant. |
447 | This makes objects interoperable in the sense that they will not be |
448 | affected by these differences. For instance, `{"b": 1, "a": 2}` and |
449 | `{"a": 2, "b": 1}` will be treated as equal. |
450 | |
451 | #### Limits |
452 | |
453 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: |
454 | > An implementation may set limits on the maximum depth of nesting. |
455 | |
456 | In this class, the object's limit of nesting is not explicitly constrained. |
457 | However, a maximum depth of nesting may be introduced by the compiler or |
458 | runtime environment. A theoretical limit can be queried by calling the |
459 | @ref max_size function of a JSON object. |
460 | |
461 | #### Storage |
462 | |
463 | Objects are stored as pointers in a @ref basic_json type. That is, for any |
464 | access to object values, a pointer of type `object_t*` must be |
465 | dereferenced. |
466 | |
467 | @sa @ref array_t -- type for an array value |
468 | |
469 | @since version 1.0.0 |
470 | |
471 | @note The order name/value pairs are added to the object is *not* |
472 | preserved by the library. Therefore, iterating an object may return |
473 | name/value pairs in a different order than they were originally stored. In |
474 | fact, keys will be traversed in alphabetical order as `std::map` with |
475 | `std::less` is used by default. Please note this behavior conforms to [RFC |
476 | 7159](http://rfc7159.net/rfc7159), because any order implements the |
477 | specified "unordered" nature of JSON objects. |
478 | */ |
479 | using object_t = ObjectType<StringType, |
480 | basic_json, |
481 | object_comparator_t, |
482 | AllocatorType<std::pair<const StringType, |
483 | basic_json>>>; |
484 | |
485 | /*! |
486 | @brief a type for an array |
487 | |
488 | [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: |
489 | > An array is an ordered sequence of zero or more values. |
490 | |
491 | To store objects in C++, a type is defined by the template parameters |
492 | explained below. |
493 | |
494 | @tparam ArrayType container type to store arrays (e.g., `std::vector` or |
495 | `std::list`) |
496 | @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) |
497 | |
498 | #### Default type |
499 | |
500 | With the default values for @a ArrayType (`std::vector`) and @a |
501 | AllocatorType (`std::allocator`), the default value for @a array_t is: |
502 | |
503 | @code {.cpp} |
504 | std::vector< |
505 | basic_json, // value_type |
506 | std::allocator<basic_json> // allocator_type |
507 | > |
508 | @endcode |
509 | |
510 | #### Limits |
511 | |
512 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: |
513 | > An implementation may set limits on the maximum depth of nesting. |
514 | |
515 | In this class, the array's limit of nesting is not explicitly constrained. |
516 | However, a maximum depth of nesting may be introduced by the compiler or |
517 | runtime environment. A theoretical limit can be queried by calling the |
518 | @ref max_size function of a JSON array. |
519 | |
520 | #### Storage |
521 | |
522 | Arrays are stored as pointers in a @ref basic_json type. That is, for any |
523 | access to array values, a pointer of type `array_t*` must be dereferenced. |
524 | |
525 | @sa @ref object_t -- type for an object value |
526 | |
527 | @since version 1.0.0 |
528 | */ |
529 | using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; |
530 | |
531 | /*! |
532 | @brief a type for a string |
533 | |
534 | [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: |
535 | > A string is a sequence of zero or more Unicode characters. |
536 | |
537 | To store objects in C++, a type is defined by the template parameter |
538 | described below. Unicode values are split by the JSON class into |
539 | byte-sized characters during deserialization. |
540 | |
541 | @tparam StringType the container to store strings (e.g., `std::string`). |
542 | Note this container is used for keys/names in objects, see @ref object_t. |
543 | |
544 | #### Default type |
545 | |
546 | With the default values for @a StringType (`std::string`), the default |
547 | value for @a string_t is: |
548 | |
549 | @code {.cpp} |
550 | std::string |
551 | @endcode |
552 | |
553 | #### Encoding |
554 | |
555 | Strings are stored in UTF-8 encoding. Therefore, functions like |
556 | `std::string::size()` or `std::string::length()` return the number of |
557 | bytes in the string rather than the number of characters or glyphs. |
558 | |
559 | #### String comparison |
560 | |
561 | [RFC 7159](http://rfc7159.net/rfc7159) states: |
562 | > Software implementations are typically required to test names of object |
563 | > members for equality. Implementations that transform the textual |
564 | > representation into sequences of Unicode code units and then perform the |
565 | > comparison numerically, code unit by code unit, are interoperable in the |
566 | > sense that implementations will agree in all cases on equality or |
567 | > inequality of two strings. For example, implementations that compare |
568 | > strings with escaped characters unconverted may incorrectly find that |
569 | > `"a\\b"` and `"a\u005Cb"` are not equal. |
570 | |
571 | This implementation is interoperable as it does compare strings code unit |
572 | by code unit. |
573 | |
574 | #### Storage |
575 | |
576 | String values are stored as pointers in a @ref basic_json type. That is, |
577 | for any access to string values, a pointer of type `string_t*` must be |
578 | dereferenced. |
579 | |
580 | @since version 1.0.0 |
581 | */ |
582 | using string_t = StringType; |
583 | |
584 | /*! |
585 | @brief a type for a boolean |
586 | |
587 | [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a |
588 | type which differentiates the two literals `true` and `false`. |
589 | |
590 | To store objects in C++, a type is defined by the template parameter @a |
591 | BooleanType which chooses the type to use. |
592 | |
593 | #### Default type |
594 | |
595 | With the default values for @a BooleanType (`bool`), the default value for |
596 | @a boolean_t is: |
597 | |
598 | @code {.cpp} |
599 | bool |
600 | @endcode |
601 | |
602 | #### Storage |
603 | |
604 | Boolean values are stored directly inside a @ref basic_json type. |
605 | |
606 | @since version 1.0.0 |
607 | */ |
608 | using boolean_t = BooleanType; |
609 | |
610 | /*! |
611 | @brief a type for a number (integer) |
612 | |
613 | [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: |
614 | > The representation of numbers is similar to that used in most |
615 | > programming languages. A number is represented in base 10 using decimal |
616 | > digits. It contains an integer component that may be prefixed with an |
617 | > optional minus sign, which may be followed by a fraction part and/or an |
618 | > exponent part. Leading zeros are not allowed. (...) Numeric values that |
619 | > cannot be represented in the grammar below (such as Infinity and NaN) |
620 | > are not permitted. |
621 | |
622 | This description includes both integer and floating-point numbers. |
623 | However, C++ allows more precise storage if it is known whether the number |
624 | is a signed integer, an unsigned integer or a floating-point number. |
625 | Therefore, three different types, @ref number_integer_t, @ref |
626 | number_unsigned_t and @ref number_float_t are used. |
627 | |
628 | To store integer numbers in C++, a type is defined by the template |
629 | parameter @a NumberIntegerType which chooses the type to use. |
630 | |
631 | #### Default type |
632 | |
633 | With the default values for @a NumberIntegerType (`int64_t`), the default |
634 | value for @a number_integer_t is: |
635 | |
636 | @code {.cpp} |
637 | int64_t |
638 | @endcode |
639 | |
640 | #### Default behavior |
641 | |
642 | - The restrictions about leading zeros is not enforced in C++. Instead, |
643 | leading zeros in integer literals lead to an interpretation as octal |
644 | number. Internally, the value will be stored as decimal number. For |
645 | instance, the C++ integer literal `010` will be serialized to `8`. |
646 | During deserialization, leading zeros yield an error. |
647 | - Not-a-number (NaN) values will be serialized to `null`. |
648 | |
649 | #### Limits |
650 | |
651 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: |
652 | > An implementation may set limits on the range and precision of numbers. |
653 | |
654 | When the default type is used, the maximal integer number that can be |
655 | stored is `9223372036854775807` (INT64_MAX) and the minimal integer number |
656 | that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers |
657 | that are out of range will yield over/underflow when used in a |
658 | constructor. During deserialization, too large or small integer numbers |
659 | will be automatically be stored as @ref number_unsigned_t or @ref |
660 | number_float_t. |
661 | |
662 | [RFC 7159](http://rfc7159.net/rfc7159) further states: |
663 | > Note that when such software is used, numbers that are integers and are |
664 | > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense |
665 | > that implementations will agree exactly on their numeric values. |
666 | |
667 | As this range is a subrange of the exactly supported range [INT64_MIN, |
668 | INT64_MAX], this class's integer type is interoperable. |
669 | |
670 | #### Storage |
671 | |
672 | Integer number values are stored directly inside a @ref basic_json type. |
673 | |
674 | @sa @ref number_float_t -- type for number values (floating-point) |
675 | |
676 | @sa @ref number_unsigned_t -- type for number values (unsigned integer) |
677 | |
678 | @since version 1.0.0 |
679 | */ |
680 | using number_integer_t = NumberIntegerType; |
681 | |
682 | /*! |
683 | @brief a type for a number (unsigned) |
684 | |
685 | [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: |
686 | > The representation of numbers is similar to that used in most |
687 | > programming languages. A number is represented in base 10 using decimal |
688 | > digits. It contains an integer component that may be prefixed with an |
689 | > optional minus sign, which may be followed by a fraction part and/or an |
690 | > exponent part. Leading zeros are not allowed. (...) Numeric values that |
691 | > cannot be represented in the grammar below (such as Infinity and NaN) |
692 | > are not permitted. |
693 | |
694 | This description includes both integer and floating-point numbers. |
695 | However, C++ allows more precise storage if it is known whether the number |
696 | is a signed integer, an unsigned integer or a floating-point number. |
697 | Therefore, three different types, @ref number_integer_t, @ref |
698 | number_unsigned_t and @ref number_float_t are used. |
699 | |
700 | To store unsigned integer numbers in C++, a type is defined by the |
701 | template parameter @a NumberUnsignedType which chooses the type to use. |
702 | |
703 | #### Default type |
704 | |
705 | With the default values for @a NumberUnsignedType (`uint64_t`), the |
706 | default value for @a number_unsigned_t is: |
707 | |
708 | @code {.cpp} |
709 | uint64_t |
710 | @endcode |
711 | |
712 | #### Default behavior |
713 | |
714 | - The restrictions about leading zeros is not enforced in C++. Instead, |
715 | leading zeros in integer literals lead to an interpretation as octal |
716 | number. Internally, the value will be stored as decimal number. For |
717 | instance, the C++ integer literal `010` will be serialized to `8`. |
718 | During deserialization, leading zeros yield an error. |
719 | - Not-a-number (NaN) values will be serialized to `null`. |
720 | |
721 | #### Limits |
722 | |
723 | [RFC 7159](http://rfc7159.net/rfc7159) specifies: |
724 | > An implementation may set limits on the range and precision of numbers. |
725 | |
726 | When the default type is used, the maximal integer number that can be |
727 | stored is `18446744073709551615` (UINT64_MAX) and the minimal integer |
728 | number that can be stored is `0`. Integer numbers that are out of range |
729 | will yield over/underflow when used in a constructor. During |
730 | deserialization, too large or small integer numbers will be automatically |
731 | be stored as @ref number_integer_t or @ref number_float_t. |
732 | |
733 | [RFC 7159](http://rfc7159.net/rfc7159) further states: |
734 | > Note that when such software is used, numbers that are integers and are |
735 | > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense |
736 | > that implementations will agree exactly on their numeric values. |
737 | |
738 | As this range is a subrange (when considered in conjunction with the |
739 | number_integer_t type) of the exactly supported range [0, UINT64_MAX], |
740 | this class's integer type is interoperable. |
741 | |
742 | #### Storage |
743 | |
744 | Integer number values are stored directly inside a @ref basic_json type. |
745 | |
746 | @sa @ref number_float_t -- type for number values (floating-point) |
747 | @sa @ref number_integer_t -- type for number values (integer) |
748 | |
749 | @since version 2.0.0 |
750 | */ |
751 | using number_unsigned_t = NumberUnsignedType; |
752 | |
753 | /*! |
754 | @brief a type for a number (floating-point) |
755 | |
756 | [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: |
757 | > The representation of numbers is similar to that used in most |
758 | > programming languages. A number is represented in base 10 using decimal |
759 | > digits. It contains an integer component that may be prefixed with an |
760 | > optional minus sign, which may be followed by a fraction part and/or an |
761 | > exponent part. Leading zeros are not allowed. (...) Numeric values that |
762 | > cannot be represented in the grammar below (such as Infinity and NaN) |
763 | > are not permitted. |
764 | |
765 | This description includes both integer and floating-point numbers. |
766 | However, C++ allows more precise storage if it is known whether the number |
767 | is a signed integer, an unsigned integer or a floating-point number. |
768 | Therefore, three different types, @ref number_integer_t, @ref |
769 | number_unsigned_t and @ref number_float_t are used. |
770 | |
771 | To store floating-point numbers in C++, a type is defined by the template |
772 | parameter @a NumberFloatType which chooses the type to use. |
773 | |
774 | #### Default type |
775 | |
776 | With the default values for @a NumberFloatType (`double`), the default |
777 | value for @a number_float_t is: |
778 | |
779 | @code {.cpp} |
780 | double |
781 | @endcode |
782 | |
783 | #### Default behavior |
784 | |
785 | - The restrictions about leading zeros is not enforced in C++. Instead, |
786 | leading zeros in floating-point literals will be ignored. Internally, |
787 | the value will be stored as decimal number. For instance, the C++ |
788 | floating-point literal `01.2` will be serialized to `1.2`. During |
789 | deserialization, leading zeros yield an error. |
790 | - Not-a-number (NaN) values will be serialized to `null`. |
791 | |
792 | #### Limits |
793 | |
794 | [RFC 7159](http://rfc7159.net/rfc7159) states: |
795 | > This specification allows implementations to set limits on the range and |
796 | > precision of numbers accepted. Since software that implements IEEE |
797 | > 754-2008 binary64 (double precision) numbers is generally available and |
798 | > widely used, good interoperability can be achieved by implementations |
799 | > that expect no more precision or range than these provide, in the sense |
800 | > that implementations will approximate JSON numbers within the expected |
801 | > precision. |
802 | |
803 | This implementation does exactly follow this approach, as it uses double |
804 | precision floating-point numbers. Note values smaller than |
805 | `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` |
806 | will be stored as NaN internally and be serialized to `null`. |
807 | |
808 | #### Storage |
809 | |
810 | Floating-point number values are stored directly inside a @ref basic_json |
811 | type. |
812 | |
813 | @sa @ref number_integer_t -- type for number values (integer) |
814 | |
815 | @sa @ref number_unsigned_t -- type for number values (unsigned integer) |
816 | |
817 | @since version 1.0.0 |
818 | */ |
819 | using number_float_t = NumberFloatType; |
820 | |
821 | /// @} |
822 | |
823 | private: |
824 | |
825 | /// helper for exception-safe object creation |
826 | template<typename T, typename... Args> |
827 | JSON_HEDLEY_RETURNS_NON_NULL |
828 | static T* create(Args&& ... args) |
829 | { |
830 | AllocatorType<T> alloc; |
831 | using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; |
832 | |
833 | auto deleter = [&](T * object) |
834 | { |
835 | AllocatorTraits::deallocate(alloc, object, 1); |
836 | }; |
837 | std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter); |
838 | AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...); |
839 | assert(object != nullptr); |
840 | return object.release(); |
841 | } |
842 | |
843 | //////////////////////// |
844 | // JSON value storage // |
845 | //////////////////////// |
846 | |
847 | /*! |
848 | @brief a JSON value |
849 | |
850 | The actual storage for a JSON value of the @ref basic_json class. This |
851 | union combines the different storage types for the JSON value types |
852 | defined in @ref value_t. |
853 | |
854 | JSON type | value_t type | used type |
855 | --------- | --------------- | ------------------------ |
856 | object | object | pointer to @ref object_t |
857 | array | array | pointer to @ref array_t |
858 | string | string | pointer to @ref string_t |
859 | boolean | boolean | @ref boolean_t |
860 | number | number_integer | @ref number_integer_t |
861 | number | number_unsigned | @ref number_unsigned_t |
862 | number | number_float | @ref number_float_t |
863 | null | null | *no value is stored* |
864 | |
865 | @note Variable-length types (objects, arrays, and strings) are stored as |
866 | pointers. The size of the union should not exceed 64 bits if the default |
867 | value types are used. |
868 | |
869 | @since version 1.0.0 |
870 | */ |
871 | union json_value |
872 | { |
873 | /// object (stored with pointer to save storage) |
874 | object_t* object; |
875 | /// array (stored with pointer to save storage) |
876 | array_t* array; |
877 | /// string (stored with pointer to save storage) |
878 | string_t* string; |
879 | /// boolean |
880 | boolean_t boolean; |
881 | /// number (integer) |
882 | number_integer_t number_integer; |
883 | /// number (unsigned integer) |
884 | number_unsigned_t number_unsigned; |
885 | /// number (floating-point) |
886 | number_float_t number_float; |
887 | |
888 | /// default constructor (for null values) |
889 | json_value() = default; |
890 | /// constructor for booleans |
891 | json_value(boolean_t v) noexcept : boolean(v) {} |
892 | /// constructor for numbers (integer) |
893 | json_value(number_integer_t v) noexcept : number_integer(v) {} |
894 | /// constructor for numbers (unsigned) |
895 | json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} |
896 | /// constructor for numbers (floating-point) |
897 | json_value(number_float_t v) noexcept : number_float(v) {} |
898 | /// constructor for empty values of a given type |
899 | json_value(value_t t) |
900 | { |
901 | switch (t) |
902 | { |
903 | case value_t::object: |
904 | { |
905 | object = create<object_t>(); |
906 | break; |
907 | } |
908 | |
909 | case value_t::array: |
910 | { |
911 | array = create<array_t>(); |
912 | break; |
913 | } |
914 | |
915 | case value_t::string: |
916 | { |
917 | string = create<string_t>("" ); |
918 | break; |
919 | } |
920 | |
921 | case value_t::boolean: |
922 | { |
923 | boolean = boolean_t(false); |
924 | break; |
925 | } |
926 | |
927 | case value_t::number_integer: |
928 | { |
929 | number_integer = number_integer_t(0); |
930 | break; |
931 | } |
932 | |
933 | case value_t::number_unsigned: |
934 | { |
935 | number_unsigned = number_unsigned_t(0); |
936 | break; |
937 | } |
938 | |
939 | case value_t::number_float: |
940 | { |
941 | number_float = number_float_t(0.0); |
942 | break; |
943 | } |
944 | |
945 | case value_t::null: |
946 | { |
947 | object = nullptr; // silence warning, see #821 |
948 | break; |
949 | } |
950 | |
951 | default: |
952 | { |
953 | object = nullptr; // silence warning, see #821 |
954 | if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) |
955 | { |
956 | JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.0" )); // LCOV_EXCL_LINE |
957 | } |
958 | break; |
959 | } |
960 | } |
961 | } |
962 | |
963 | /// constructor for strings |
964 | json_value(const string_t& value) |
965 | { |
966 | string = create<string_t>(value); |
967 | } |
968 | |
969 | /// constructor for rvalue strings |
970 | json_value(string_t&& value) |
971 | { |
972 | string = create<string_t>(std::move(value)); |
973 | } |
974 | |
975 | /// constructor for objects |
976 | json_value(const object_t& value) |
977 | { |
978 | object = create<object_t>(value); |
979 | } |
980 | |
981 | /// constructor for rvalue objects |
982 | json_value(object_t&& value) |
983 | { |
984 | object = create<object_t>(std::move(value)); |
985 | } |
986 | |
987 | /// constructor for arrays |
988 | json_value(const array_t& value) |
989 | { |
990 | array = create<array_t>(value); |
991 | } |
992 | |
993 | /// constructor for rvalue arrays |
994 | json_value(array_t&& value) |
995 | { |
996 | array = create<array_t>(std::move(value)); |
997 | } |
998 | |
999 | void destroy(value_t t) noexcept |
1000 | { |
1001 | switch (t) |
1002 | { |
1003 | case value_t::object: |
1004 | { |
1005 | AllocatorType<object_t> alloc; |
1006 | std::allocator_traits<decltype(alloc)>::destroy(alloc, object); |
1007 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); |
1008 | break; |
1009 | } |
1010 | |
1011 | case value_t::array: |
1012 | { |
1013 | AllocatorType<array_t> alloc; |
1014 | std::allocator_traits<decltype(alloc)>::destroy(alloc, array); |
1015 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); |
1016 | break; |
1017 | } |
1018 | |
1019 | case value_t::string: |
1020 | { |
1021 | AllocatorType<string_t> alloc; |
1022 | std::allocator_traits<decltype(alloc)>::destroy(alloc, string); |
1023 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); |
1024 | break; |
1025 | } |
1026 | |
1027 | default: |
1028 | { |
1029 | break; |
1030 | } |
1031 | } |
1032 | } |
1033 | }; |
1034 | |
1035 | /*! |
1036 | @brief checks the class invariants |
1037 | |
1038 | This function asserts the class invariants. It needs to be called at the |
1039 | end of every constructor to make sure that created objects respect the |
1040 | invariant. Furthermore, it has to be called each time the type of a JSON |
1041 | value is changed, because the invariant expresses a relationship between |
1042 | @a m_type and @a m_value. |
1043 | */ |
1044 | void assert_invariant() const noexcept |
1045 | { |
1046 | assert(m_type != value_t::object or m_value.object != nullptr); |
1047 | assert(m_type != value_t::array or m_value.array != nullptr); |
1048 | assert(m_type != value_t::string or m_value.string != nullptr); |
1049 | } |
1050 | |
1051 | public: |
1052 | ////////////////////////// |
1053 | // JSON parser callback // |
1054 | ////////////////////////// |
1055 | |
1056 | /*! |
1057 | @brief parser event types |
1058 | |
1059 | The parser callback distinguishes the following events: |
1060 | - `object_start`: the parser read `{` and started to process a JSON object |
1061 | - `key`: the parser read a key of a value in an object |
1062 | - `object_end`: the parser read `}` and finished processing a JSON object |
1063 | - `array_start`: the parser read `[` and started to process a JSON array |
1064 | - `array_end`: the parser read `]` and finished processing a JSON array |
1065 | - `value`: the parser finished reading a JSON value |
1066 | |
1067 | @image html callback_events.png "Example when certain parse events are triggered" |
1068 | |
1069 | @sa @ref parser_callback_t for more information and examples |
1070 | */ |
1071 | using parse_event_t = typename parser::parse_event_t; |
1072 | |
1073 | /*! |
1074 | @brief per-element parser callback type |
1075 | |
1076 | With a parser callback function, the result of parsing a JSON text can be |
1077 | influenced. When passed to @ref parse, it is called on certain events |
1078 | (passed as @ref parse_event_t via parameter @a event) with a set recursion |
1079 | depth @a depth and context JSON value @a parsed. The return value of the |
1080 | callback function is a boolean indicating whether the element that emitted |
1081 | the callback shall be kept or not. |
1082 | |
1083 | We distinguish six scenarios (determined by the event type) in which the |
1084 | callback function can be called. The following table describes the values |
1085 | of the parameters @a depth, @a event, and @a parsed. |
1086 | |
1087 | parameter @a event | description | parameter @a depth | parameter @a parsed |
1088 | ------------------ | ----------- | ------------------ | ------------------- |
1089 | parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded |
1090 | parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key |
1091 | parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object |
1092 | parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded |
1093 | parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array |
1094 | parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value |
1095 | |
1096 | @image html callback_events.png "Example when certain parse events are triggered" |
1097 | |
1098 | Discarding a value (i.e., returning `false`) has different effects |
1099 | depending on the context in which function was called: |
1100 | |
1101 | - Discarded values in structured types are skipped. That is, the parser |
1102 | will behave as if the discarded value was never read. |
1103 | - In case a value outside a structured type is skipped, it is replaced |
1104 | with `null`. This case happens if the top-level element is skipped. |
1105 | |
1106 | @param[in] depth the depth of the recursion during parsing |
1107 | |
1108 | @param[in] event an event of type parse_event_t indicating the context in |
1109 | the callback function has been called |
1110 | |
1111 | @param[in,out] parsed the current intermediate parse result; note that |
1112 | writing to this value has no effect for parse_event_t::key events |
1113 | |
1114 | @return Whether the JSON value which called the function during parsing |
1115 | should be kept (`true`) or not (`false`). In the latter case, it is either |
1116 | skipped completely or replaced by an empty discarded object. |
1117 | |
1118 | @sa @ref parse for examples |
1119 | |
1120 | @since version 1.0.0 |
1121 | */ |
1122 | using parser_callback_t = typename parser::parser_callback_t; |
1123 | |
1124 | ////////////////// |
1125 | // constructors // |
1126 | ////////////////// |
1127 | |
1128 | /// @name constructors and destructors |
1129 | /// Constructors of class @ref basic_json, copy/move constructor, copy |
1130 | /// assignment, static functions creating objects, and the destructor. |
1131 | /// @{ |
1132 | |
1133 | /*! |
1134 | @brief create an empty value with a given type |
1135 | |
1136 | Create an empty JSON value with a given type. The value will be default |
1137 | initialized with an empty value which depends on the type: |
1138 | |
1139 | Value type | initial value |
1140 | ----------- | ------------- |
1141 | null | `null` |
1142 | boolean | `false` |
1143 | string | `""` |
1144 | number | `0` |
1145 | object | `{}` |
1146 | array | `[]` |
1147 | |
1148 | @param[in] v the type of the value to create |
1149 | |
1150 | @complexity Constant. |
1151 | |
1152 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1153 | changes to any JSON value. |
1154 | |
1155 | @liveexample{The following code shows the constructor for different @ref |
1156 | value_t values,basic_json__value_t} |
1157 | |
1158 | @sa @ref clear() -- restores the postcondition of this constructor |
1159 | |
1160 | @since version 1.0.0 |
1161 | */ |
1162 | basic_json(const value_t v) |
1163 | : m_type(v), m_value(v) |
1164 | { |
1165 | assert_invariant(); |
1166 | } |
1167 | |
1168 | /*! |
1169 | @brief create a null object |
1170 | |
1171 | Create a `null` JSON value. It either takes a null pointer as parameter |
1172 | (explicitly creating `null`) or no parameter (implicitly creating `null`). |
1173 | The passed null pointer itself is not read -- it is only used to choose |
1174 | the right constructor. |
1175 | |
1176 | @complexity Constant. |
1177 | |
1178 | @exceptionsafety No-throw guarantee: this constructor never throws |
1179 | exceptions. |
1180 | |
1181 | @liveexample{The following code shows the constructor with and without a |
1182 | null pointer parameter.,basic_json__nullptr_t} |
1183 | |
1184 | @since version 1.0.0 |
1185 | */ |
1186 | basic_json(std::nullptr_t = nullptr) noexcept |
1187 | : basic_json(value_t::null) |
1188 | { |
1189 | assert_invariant(); |
1190 | } |
1191 | |
1192 | /*! |
1193 | @brief create a JSON value |
1194 | |
1195 | This is a "catch all" constructor for all compatible JSON types; that is, |
1196 | types for which a `to_json()` method exists. The constructor forwards the |
1197 | parameter @a val to that method (to `json_serializer<U>::to_json` method |
1198 | with `U = uncvref_t<CompatibleType>`, to be exact). |
1199 | |
1200 | Template type @a CompatibleType includes, but is not limited to, the |
1201 | following types: |
1202 | - **arrays**: @ref array_t and all kinds of compatible containers such as |
1203 | `std::vector`, `std::deque`, `std::list`, `std::forward_list`, |
1204 | `std::array`, `std::valarray`, `std::set`, `std::unordered_set`, |
1205 | `std::multiset`, and `std::unordered_multiset` with a `value_type` from |
1206 | which a @ref basic_json value can be constructed. |
1207 | - **objects**: @ref object_t and all kinds of compatible associative |
1208 | containers such as `std::map`, `std::unordered_map`, `std::multimap`, |
1209 | and `std::unordered_multimap` with a `key_type` compatible to |
1210 | @ref string_t and a `value_type` from which a @ref basic_json value can |
1211 | be constructed. |
1212 | - **strings**: @ref string_t, string literals, and all compatible string |
1213 | containers can be used. |
1214 | - **numbers**: @ref number_integer_t, @ref number_unsigned_t, |
1215 | @ref number_float_t, and all convertible number types such as `int`, |
1216 | `size_t`, `int64_t`, `float` or `double` can be used. |
1217 | - **boolean**: @ref boolean_t / `bool` can be used. |
1218 | |
1219 | See the examples below. |
1220 | |
1221 | @tparam CompatibleType a type such that: |
1222 | - @a CompatibleType is not derived from `std::istream`, |
1223 | - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move |
1224 | constructors), |
1225 | - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments) |
1226 | - @a CompatibleType is not a @ref basic_json nested type (e.g., |
1227 | @ref json_pointer, @ref iterator, etc ...) |
1228 | - @ref @ref json_serializer<U> has a |
1229 | `to_json(basic_json_t&, CompatibleType&&)` method |
1230 | |
1231 | @tparam U = `uncvref_t<CompatibleType>` |
1232 | |
1233 | @param[in] val the value to be forwarded to the respective constructor |
1234 | |
1235 | @complexity Usually linear in the size of the passed @a val, also |
1236 | depending on the implementation of the called `to_json()` |
1237 | method. |
1238 | |
1239 | @exceptionsafety Depends on the called constructor. For types directly |
1240 | supported by the library (i.e., all types for which no `to_json()` function |
1241 | was provided), strong guarantee holds: if an exception is thrown, there are |
1242 | no changes to any JSON value. |
1243 | |
1244 | @liveexample{The following code shows the constructor with several |
1245 | compatible types.,basic_json__CompatibleType} |
1246 | |
1247 | @since version 2.1.0 |
1248 | */ |
1249 | template <typename CompatibleType, |
1250 | typename U = detail::uncvref_t<CompatibleType>, |
1251 | detail::enable_if_t< |
1252 | not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0> |
1253 | basic_json(CompatibleType && val) noexcept(noexcept( |
1254 | JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), |
1255 | std::forward<CompatibleType>(val)))) |
1256 | { |
1257 | JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); |
1258 | assert_invariant(); |
1259 | } |
1260 | |
1261 | /*! |
1262 | @brief create a JSON value from an existing one |
1263 | |
1264 | This is a constructor for existing @ref basic_json types. |
1265 | It does not hijack copy/move constructors, since the parameter has different |
1266 | template arguments than the current ones. |
1267 | |
1268 | The constructor tries to convert the internal @ref m_value of the parameter. |
1269 | |
1270 | @tparam BasicJsonType a type such that: |
1271 | - @a BasicJsonType is a @ref basic_json type. |
1272 | - @a BasicJsonType has different template arguments than @ref basic_json_t. |
1273 | |
1274 | @param[in] val the @ref basic_json value to be converted. |
1275 | |
1276 | @complexity Usually linear in the size of the passed @a val, also |
1277 | depending on the implementation of the called `to_json()` |
1278 | method. |
1279 | |
1280 | @exceptionsafety Depends on the called constructor. For types directly |
1281 | supported by the library (i.e., all types for which no `to_json()` function |
1282 | was provided), strong guarantee holds: if an exception is thrown, there are |
1283 | no changes to any JSON value. |
1284 | |
1285 | @since version 3.2.0 |
1286 | */ |
1287 | template <typename BasicJsonType, |
1288 | detail::enable_if_t< |
1289 | detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0> |
1290 | basic_json(const BasicJsonType& val) |
1291 | { |
1292 | using other_boolean_t = typename BasicJsonType::boolean_t; |
1293 | using other_number_float_t = typename BasicJsonType::number_float_t; |
1294 | using other_number_integer_t = typename BasicJsonType::number_integer_t; |
1295 | using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; |
1296 | using other_string_t = typename BasicJsonType::string_t; |
1297 | using other_object_t = typename BasicJsonType::object_t; |
1298 | using other_array_t = typename BasicJsonType::array_t; |
1299 | |
1300 | switch (val.type()) |
1301 | { |
1302 | case value_t::boolean: |
1303 | JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); |
1304 | break; |
1305 | case value_t::number_float: |
1306 | JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); |
1307 | break; |
1308 | case value_t::number_integer: |
1309 | JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); |
1310 | break; |
1311 | case value_t::number_unsigned: |
1312 | JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); |
1313 | break; |
1314 | case value_t::string: |
1315 | JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); |
1316 | break; |
1317 | case value_t::object: |
1318 | JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); |
1319 | break; |
1320 | case value_t::array: |
1321 | JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); |
1322 | break; |
1323 | case value_t::null: |
1324 | *this = nullptr; |
1325 | break; |
1326 | case value_t::discarded: |
1327 | m_type = value_t::discarded; |
1328 | break; |
1329 | default: // LCOV_EXCL_LINE |
1330 | assert(false); // LCOV_EXCL_LINE |
1331 | } |
1332 | assert_invariant(); |
1333 | } |
1334 | |
1335 | /*! |
1336 | @brief create a container (array or object) from an initializer list |
1337 | |
1338 | Creates a JSON value of type array or object from the passed initializer |
1339 | list @a init. In case @a type_deduction is `true` (default), the type of |
1340 | the JSON value to be created is deducted from the initializer list @a init |
1341 | according to the following rules: |
1342 | |
1343 | 1. If the list is empty, an empty JSON object value `{}` is created. |
1344 | 2. If the list consists of pairs whose first element is a string, a JSON |
1345 | object value is created where the first elements of the pairs are |
1346 | treated as keys and the second elements are as values. |
1347 | 3. In all other cases, an array is created. |
1348 | |
1349 | The rules aim to create the best fit between a C++ initializer list and |
1350 | JSON values. The rationale is as follows: |
1351 | |
1352 | 1. The empty initializer list is written as `{}` which is exactly an empty |
1353 | JSON object. |
1354 | 2. C++ has no way of describing mapped types other than to list a list of |
1355 | pairs. As JSON requires that keys must be of type string, rule 2 is the |
1356 | weakest constraint one can pose on initializer lists to interpret them |
1357 | as an object. |
1358 | 3. In all other cases, the initializer list could not be interpreted as |
1359 | JSON object type, so interpreting it as JSON array type is safe. |
1360 | |
1361 | With the rules described above, the following JSON values cannot be |
1362 | expressed by an initializer list: |
1363 | |
1364 | - the empty array (`[]`): use @ref array(initializer_list_t) |
1365 | with an empty initializer list in this case |
1366 | - arrays whose elements satisfy rule 2: use @ref |
1367 | array(initializer_list_t) with the same initializer list |
1368 | in this case |
1369 | |
1370 | @note When used without parentheses around an empty initializer list, @ref |
1371 | basic_json() is called instead of this function, yielding the JSON null |
1372 | value. |
1373 | |
1374 | @param[in] init initializer list with JSON values |
1375 | |
1376 | @param[in] type_deduction internal parameter; when set to `true`, the type |
1377 | of the JSON value is deducted from the initializer list @a init; when set |
1378 | to `false`, the type provided via @a manual_type is forced. This mode is |
1379 | used by the functions @ref array(initializer_list_t) and |
1380 | @ref object(initializer_list_t). |
1381 | |
1382 | @param[in] manual_type internal parameter; when @a type_deduction is set |
1383 | to `false`, the created JSON value will use the provided type (only @ref |
1384 | value_t::array and @ref value_t::object are valid); when @a type_deduction |
1385 | is set to `true`, this parameter has no effect |
1386 | |
1387 | @throw type_error.301 if @a type_deduction is `false`, @a manual_type is |
1388 | `value_t::object`, but @a init contains an element which is not a pair |
1389 | whose first element is a string. In this case, the constructor could not |
1390 | create an object. If @a type_deduction would have be `true`, an array |
1391 | would have been created. See @ref object(initializer_list_t) |
1392 | for an example. |
1393 | |
1394 | @complexity Linear in the size of the initializer list @a init. |
1395 | |
1396 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1397 | changes to any JSON value. |
1398 | |
1399 | @liveexample{The example below shows how JSON values are created from |
1400 | initializer lists.,basic_json__list_init_t} |
1401 | |
1402 | @sa @ref array(initializer_list_t) -- create a JSON array |
1403 | value from an initializer list |
1404 | @sa @ref object(initializer_list_t) -- create a JSON object |
1405 | value from an initializer list |
1406 | |
1407 | @since version 1.0.0 |
1408 | */ |
1409 | basic_json(initializer_list_t init, |
1410 | bool type_deduction = true, |
1411 | value_t manual_type = value_t::array) |
1412 | { |
1413 | // check if each element is an array with two elements whose first |
1414 | // element is a string |
1415 | bool is_an_object = std::all_of(init.begin(), init.end(), |
1416 | [](const detail::json_ref<basic_json>& element_ref) |
1417 | { |
1418 | return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string(); |
1419 | }); |
1420 | |
1421 | // adjust type if type deduction is not wanted |
1422 | if (not type_deduction) |
1423 | { |
1424 | // if array is wanted, do not create an object though possible |
1425 | if (manual_type == value_t::array) |
1426 | { |
1427 | is_an_object = false; |
1428 | } |
1429 | |
1430 | // if object is wanted but impossible, throw an exception |
1431 | if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object and not is_an_object)) |
1432 | { |
1433 | JSON_THROW(type_error::create(301, "cannot create object from initializer list" )); |
1434 | } |
1435 | } |
1436 | |
1437 | if (is_an_object) |
1438 | { |
1439 | // the initializer list is a list of pairs -> create object |
1440 | m_type = value_t::object; |
1441 | m_value = value_t::object; |
1442 | |
1443 | std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref) |
1444 | { |
1445 | auto element = element_ref.moved_or_copied(); |
1446 | m_value.object->emplace( |
1447 | std::move(*((*element.m_value.array)[0].m_value.string)), |
1448 | std::move((*element.m_value.array)[1])); |
1449 | }); |
1450 | } |
1451 | else |
1452 | { |
1453 | // the initializer list describes an array -> create array |
1454 | m_type = value_t::array; |
1455 | m_value.array = create<array_t>(init.begin(), init.end()); |
1456 | } |
1457 | |
1458 | assert_invariant(); |
1459 | } |
1460 | |
1461 | /*! |
1462 | @brief explicitly create an array from an initializer list |
1463 | |
1464 | Creates a JSON array value from a given initializer list. That is, given a |
1465 | list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the |
1466 | initializer list is empty, the empty array `[]` is created. |
1467 | |
1468 | @note This function is only needed to express two edge cases that cannot |
1469 | be realized with the initializer list constructor (@ref |
1470 | basic_json(initializer_list_t, bool, value_t)). These cases |
1471 | are: |
1472 | 1. creating an array whose elements are all pairs whose first element is a |
1473 | string -- in this case, the initializer list constructor would create an |
1474 | object, taking the first elements as keys |
1475 | 2. creating an empty array -- passing the empty initializer list to the |
1476 | initializer list constructor yields an empty object |
1477 | |
1478 | @param[in] init initializer list with JSON values to create an array from |
1479 | (optional) |
1480 | |
1481 | @return JSON array value |
1482 | |
1483 | @complexity Linear in the size of @a init. |
1484 | |
1485 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1486 | changes to any JSON value. |
1487 | |
1488 | @liveexample{The following code shows an example for the `array` |
1489 | function.,array} |
1490 | |
1491 | @sa @ref basic_json(initializer_list_t, bool, value_t) -- |
1492 | create a JSON value from an initializer list |
1493 | @sa @ref object(initializer_list_t) -- create a JSON object |
1494 | value from an initializer list |
1495 | |
1496 | @since version 1.0.0 |
1497 | */ |
1498 | JSON_HEDLEY_WARN_UNUSED_RESULT |
1499 | static basic_json array(initializer_list_t init = {}) |
1500 | { |
1501 | return basic_json(init, false, value_t::array); |
1502 | } |
1503 | |
1504 | /*! |
1505 | @brief explicitly create an object from an initializer list |
1506 | |
1507 | Creates a JSON object value from a given initializer list. The initializer |
1508 | lists elements must be pairs, and their first elements must be strings. If |
1509 | the initializer list is empty, the empty object `{}` is created. |
1510 | |
1511 | @note This function is only added for symmetry reasons. In contrast to the |
1512 | related function @ref array(initializer_list_t), there are |
1513 | no cases which can only be expressed by this function. That is, any |
1514 | initializer list @a init can also be passed to the initializer list |
1515 | constructor @ref basic_json(initializer_list_t, bool, value_t). |
1516 | |
1517 | @param[in] init initializer list to create an object from (optional) |
1518 | |
1519 | @return JSON object value |
1520 | |
1521 | @throw type_error.301 if @a init is not a list of pairs whose first |
1522 | elements are strings. In this case, no object can be created. When such a |
1523 | value is passed to @ref basic_json(initializer_list_t, bool, value_t), |
1524 | an array would have been created from the passed initializer list @a init. |
1525 | See example below. |
1526 | |
1527 | @complexity Linear in the size of @a init. |
1528 | |
1529 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1530 | changes to any JSON value. |
1531 | |
1532 | @liveexample{The following code shows an example for the `object` |
1533 | function.,object} |
1534 | |
1535 | @sa @ref basic_json(initializer_list_t, bool, value_t) -- |
1536 | create a JSON value from an initializer list |
1537 | @sa @ref array(initializer_list_t) -- create a JSON array |
1538 | value from an initializer list |
1539 | |
1540 | @since version 1.0.0 |
1541 | */ |
1542 | JSON_HEDLEY_WARN_UNUSED_RESULT |
1543 | static basic_json object(initializer_list_t init = {}) |
1544 | { |
1545 | return basic_json(init, false, value_t::object); |
1546 | } |
1547 | |
1548 | /*! |
1549 | @brief construct an array with count copies of given value |
1550 | |
1551 | Constructs a JSON array value by creating @a cnt copies of a passed value. |
1552 | In case @a cnt is `0`, an empty array is created. |
1553 | |
1554 | @param[in] cnt the number of JSON copies of @a val to create |
1555 | @param[in] val the JSON value to copy |
1556 | |
1557 | @post `std::distance(begin(),end()) == cnt` holds. |
1558 | |
1559 | @complexity Linear in @a cnt. |
1560 | |
1561 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1562 | changes to any JSON value. |
1563 | |
1564 | @liveexample{The following code shows examples for the @ref |
1565 | basic_json(size_type\, const basic_json&) |
1566 | constructor.,basic_json__size_type_basic_json} |
1567 | |
1568 | @since version 1.0.0 |
1569 | */ |
1570 | basic_json(size_type cnt, const basic_json& val) |
1571 | : m_type(value_t::array) |
1572 | { |
1573 | m_value.array = create<array_t>(cnt, val); |
1574 | assert_invariant(); |
1575 | } |
1576 | |
1577 | /*! |
1578 | @brief construct a JSON container given an iterator range |
1579 | |
1580 | Constructs the JSON value with the contents of the range `[first, last)`. |
1581 | The semantics depends on the different types a JSON value can have: |
1582 | - In case of a null type, invalid_iterator.206 is thrown. |
1583 | - In case of other primitive types (number, boolean, or string), @a first |
1584 | must be `begin()` and @a last must be `end()`. In this case, the value is |
1585 | copied. Otherwise, invalid_iterator.204 is thrown. |
1586 | - In case of structured types (array, object), the constructor behaves as |
1587 | similar versions for `std::vector` or `std::map`; that is, a JSON array |
1588 | or object is constructed from the values in the range. |
1589 | |
1590 | @tparam InputIT an input iterator type (@ref iterator or @ref |
1591 | const_iterator) |
1592 | |
1593 | @param[in] first begin of the range to copy from (included) |
1594 | @param[in] last end of the range to copy from (excluded) |
1595 | |
1596 | @pre Iterators @a first and @a last must be initialized. **This |
1597 | precondition is enforced with an assertion (see warning).** If |
1598 | assertions are switched off, a violation of this precondition yields |
1599 | undefined behavior. |
1600 | |
1601 | @pre Range `[first, last)` is valid. Usually, this precondition cannot be |
1602 | checked efficiently. Only certain edge cases are detected; see the |
1603 | description of the exceptions below. A violation of this precondition |
1604 | yields undefined behavior. |
1605 | |
1606 | @warning A precondition is enforced with a runtime assertion that will |
1607 | result in calling `std::abort` if this precondition is not met. |
1608 | Assertions can be disabled by defining `NDEBUG` at compile time. |
1609 | See https://en.cppreference.com/w/cpp/error/assert for more |
1610 | information. |
1611 | |
1612 | @throw invalid_iterator.201 if iterators @a first and @a last are not |
1613 | compatible (i.e., do not belong to the same JSON value). In this case, |
1614 | the range `[first, last)` is undefined. |
1615 | @throw invalid_iterator.204 if iterators @a first and @a last belong to a |
1616 | primitive type (number, boolean, or string), but @a first does not point |
1617 | to the first element any more. In this case, the range `[first, last)` is |
1618 | undefined. See example code below. |
1619 | @throw invalid_iterator.206 if iterators @a first and @a last belong to a |
1620 | null value. In this case, the range `[first, last)` is undefined. |
1621 | |
1622 | @complexity Linear in distance between @a first and @a last. |
1623 | |
1624 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1625 | changes to any JSON value. |
1626 | |
1627 | @liveexample{The example below shows several ways to create JSON values by |
1628 | specifying a subrange with iterators.,basic_json__InputIt_InputIt} |
1629 | |
1630 | @since version 1.0.0 |
1631 | */ |
1632 | template<class InputIT, typename std::enable_if< |
1633 | std::is_same<InputIT, typename basic_json_t::iterator>::value or |
1634 | std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0> |
1635 | basic_json(InputIT first, InputIT last) |
1636 | { |
1637 | assert(first.m_object != nullptr); |
1638 | assert(last.m_object != nullptr); |
1639 | |
1640 | // make sure iterator fits the current value |
1641 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) |
1642 | { |
1643 | JSON_THROW(invalid_iterator::create(201, "iterators are not compatible" )); |
1644 | } |
1645 | |
1646 | // copy type from first iterator |
1647 | m_type = first.m_object->m_type; |
1648 | |
1649 | // check if iterator range is complete for primitive values |
1650 | switch (m_type) |
1651 | { |
1652 | case value_t::boolean: |
1653 | case value_t::number_float: |
1654 | case value_t::number_integer: |
1655 | case value_t::number_unsigned: |
1656 | case value_t::string: |
1657 | { |
1658 | if (JSON_HEDLEY_UNLIKELY(not first.m_it.primitive_iterator.is_begin() |
1659 | or not last.m_it.primitive_iterator.is_end())) |
1660 | { |
1661 | JSON_THROW(invalid_iterator::create(204, "iterators out of range" )); |
1662 | } |
1663 | break; |
1664 | } |
1665 | |
1666 | default: |
1667 | break; |
1668 | } |
1669 | |
1670 | switch (m_type) |
1671 | { |
1672 | case value_t::number_integer: |
1673 | { |
1674 | m_value.number_integer = first.m_object->m_value.number_integer; |
1675 | break; |
1676 | } |
1677 | |
1678 | case value_t::number_unsigned: |
1679 | { |
1680 | m_value.number_unsigned = first.m_object->m_value.number_unsigned; |
1681 | break; |
1682 | } |
1683 | |
1684 | case value_t::number_float: |
1685 | { |
1686 | m_value.number_float = first.m_object->m_value.number_float; |
1687 | break; |
1688 | } |
1689 | |
1690 | case value_t::boolean: |
1691 | { |
1692 | m_value.boolean = first.m_object->m_value.boolean; |
1693 | break; |
1694 | } |
1695 | |
1696 | case value_t::string: |
1697 | { |
1698 | m_value = *first.m_object->m_value.string; |
1699 | break; |
1700 | } |
1701 | |
1702 | case value_t::object: |
1703 | { |
1704 | m_value.object = create<object_t>(first.m_it.object_iterator, |
1705 | last.m_it.object_iterator); |
1706 | break; |
1707 | } |
1708 | |
1709 | case value_t::array: |
1710 | { |
1711 | m_value.array = create<array_t>(first.m_it.array_iterator, |
1712 | last.m_it.array_iterator); |
1713 | break; |
1714 | } |
1715 | |
1716 | default: |
1717 | JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + |
1718 | std::string(first.m_object->type_name()))); |
1719 | } |
1720 | |
1721 | assert_invariant(); |
1722 | } |
1723 | |
1724 | |
1725 | /////////////////////////////////////// |
1726 | // other constructors and destructor // |
1727 | /////////////////////////////////////// |
1728 | |
1729 | /// @private |
1730 | basic_json(const detail::json_ref<basic_json>& ref) |
1731 | : basic_json(ref.moved_or_copied()) |
1732 | {} |
1733 | |
1734 | /*! |
1735 | @brief copy constructor |
1736 | |
1737 | Creates a copy of a given JSON value. |
1738 | |
1739 | @param[in] other the JSON value to copy |
1740 | |
1741 | @post `*this == other` |
1742 | |
1743 | @complexity Linear in the size of @a other. |
1744 | |
1745 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1746 | changes to any JSON value. |
1747 | |
1748 | @requirement This function helps `basic_json` satisfying the |
1749 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
1750 | requirements: |
1751 | - The complexity is linear. |
1752 | - As postcondition, it holds: `other == basic_json(other)`. |
1753 | |
1754 | @liveexample{The following code shows an example for the copy |
1755 | constructor.,basic_json__basic_json} |
1756 | |
1757 | @since version 1.0.0 |
1758 | */ |
1759 | basic_json(const basic_json& other) |
1760 | : m_type(other.m_type) |
1761 | { |
1762 | // check of passed value is valid |
1763 | other.assert_invariant(); |
1764 | |
1765 | switch (m_type) |
1766 | { |
1767 | case value_t::object: |
1768 | { |
1769 | m_value = *other.m_value.object; |
1770 | break; |
1771 | } |
1772 | |
1773 | case value_t::array: |
1774 | { |
1775 | m_value = *other.m_value.array; |
1776 | break; |
1777 | } |
1778 | |
1779 | case value_t::string: |
1780 | { |
1781 | m_value = *other.m_value.string; |
1782 | break; |
1783 | } |
1784 | |
1785 | case value_t::boolean: |
1786 | { |
1787 | m_value = other.m_value.boolean; |
1788 | break; |
1789 | } |
1790 | |
1791 | case value_t::number_integer: |
1792 | { |
1793 | m_value = other.m_value.number_integer; |
1794 | break; |
1795 | } |
1796 | |
1797 | case value_t::number_unsigned: |
1798 | { |
1799 | m_value = other.m_value.number_unsigned; |
1800 | break; |
1801 | } |
1802 | |
1803 | case value_t::number_float: |
1804 | { |
1805 | m_value = other.m_value.number_float; |
1806 | break; |
1807 | } |
1808 | |
1809 | default: |
1810 | break; |
1811 | } |
1812 | |
1813 | assert_invariant(); |
1814 | } |
1815 | |
1816 | /*! |
1817 | @brief move constructor |
1818 | |
1819 | Move constructor. Constructs a JSON value with the contents of the given |
1820 | value @a other using move semantics. It "steals" the resources from @a |
1821 | other and leaves it as JSON null value. |
1822 | |
1823 | @param[in,out] other value to move to this object |
1824 | |
1825 | @post `*this` has the same value as @a other before the call. |
1826 | @post @a other is a JSON null value. |
1827 | |
1828 | @complexity Constant. |
1829 | |
1830 | @exceptionsafety No-throw guarantee: this constructor never throws |
1831 | exceptions. |
1832 | |
1833 | @requirement This function helps `basic_json` satisfying the |
1834 | [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible) |
1835 | requirements. |
1836 | |
1837 | @liveexample{The code below shows the move constructor explicitly called |
1838 | via std::move.,basic_json__moveconstructor} |
1839 | |
1840 | @since version 1.0.0 |
1841 | */ |
1842 | basic_json(basic_json&& other) noexcept |
1843 | : m_type(std::move(other.m_type)), |
1844 | m_value(std::move(other.m_value)) |
1845 | { |
1846 | // check that passed value is valid |
1847 | other.assert_invariant(); |
1848 | |
1849 | // invalidate payload |
1850 | other.m_type = value_t::null; |
1851 | other.m_value = {}; |
1852 | |
1853 | assert_invariant(); |
1854 | } |
1855 | |
1856 | /*! |
1857 | @brief copy assignment |
1858 | |
1859 | Copy assignment operator. Copies a JSON value via the "copy and swap" |
1860 | strategy: It is expressed in terms of the copy constructor, destructor, |
1861 | and the `swap()` member function. |
1862 | |
1863 | @param[in] other value to copy from |
1864 | |
1865 | @complexity Linear. |
1866 | |
1867 | @requirement This function helps `basic_json` satisfying the |
1868 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
1869 | requirements: |
1870 | - The complexity is linear. |
1871 | |
1872 | @liveexample{The code below shows and example for the copy assignment. It |
1873 | creates a copy of value `a` which is then swapped with `b`. Finally\, the |
1874 | copy of `a` (which is the null value after the swap) is |
1875 | destroyed.,basic_json__copyassignment} |
1876 | |
1877 | @since version 1.0.0 |
1878 | */ |
1879 | basic_json& operator=(basic_json other) noexcept ( |
1880 | std::is_nothrow_move_constructible<value_t>::value and |
1881 | std::is_nothrow_move_assignable<value_t>::value and |
1882 | std::is_nothrow_move_constructible<json_value>::value and |
1883 | std::is_nothrow_move_assignable<json_value>::value |
1884 | ) |
1885 | { |
1886 | // check that passed value is valid |
1887 | other.assert_invariant(); |
1888 | |
1889 | using std::swap; |
1890 | swap(m_type, other.m_type); |
1891 | swap(m_value, other.m_value); |
1892 | |
1893 | assert_invariant(); |
1894 | return *this; |
1895 | } |
1896 | |
1897 | /*! |
1898 | @brief destructor |
1899 | |
1900 | Destroys the JSON value and frees all allocated memory. |
1901 | |
1902 | @complexity Linear. |
1903 | |
1904 | @requirement This function helps `basic_json` satisfying the |
1905 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
1906 | requirements: |
1907 | - The complexity is linear. |
1908 | - All stored elements are destroyed and all memory is freed. |
1909 | |
1910 | @since version 1.0.0 |
1911 | */ |
1912 | ~basic_json() noexcept |
1913 | { |
1914 | assert_invariant(); |
1915 | m_value.destroy(m_type); |
1916 | } |
1917 | |
1918 | /// @} |
1919 | |
1920 | public: |
1921 | /////////////////////// |
1922 | // object inspection // |
1923 | /////////////////////// |
1924 | |
1925 | /// @name object inspection |
1926 | /// Functions to inspect the type of a JSON value. |
1927 | /// @{ |
1928 | |
1929 | /*! |
1930 | @brief serialization |
1931 | |
1932 | Serialization function for JSON values. The function tries to mimic |
1933 | Python's `json.dumps()` function, and currently supports its @a indent |
1934 | and @a ensure_ascii parameters. |
1935 | |
1936 | @param[in] indent If indent is nonnegative, then array elements and object |
1937 | members will be pretty-printed with that indent level. An indent level of |
1938 | `0` will only insert newlines. `-1` (the default) selects the most compact |
1939 | representation. |
1940 | @param[in] indent_char The character to use for indentation if @a indent is |
1941 | greater than `0`. The default is ` ` (space). |
1942 | @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters |
1943 | in the output are escaped with `\uXXXX` sequences, and the result consists |
1944 | of ASCII characters only. |
1945 | @param[in] error_handler how to react on decoding errors; there are three |
1946 | possible values: `strict` (throws and exception in case a decoding error |
1947 | occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD), |
1948 | and `ignore` (ignore invalid UTF-8 sequences during serialization). |
1949 | |
1950 | @return string containing the serialization of the JSON value |
1951 | |
1952 | @throw type_error.316 if a string stored inside the JSON value is not |
1953 | UTF-8 encoded |
1954 | |
1955 | @complexity Linear. |
1956 | |
1957 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
1958 | changes in the JSON value. |
1959 | |
1960 | @liveexample{The following example shows the effect of different @a indent\, |
1961 | @a indent_char\, and @a ensure_ascii parameters to the result of the |
1962 | serialization.,dump} |
1963 | |
1964 | @see https://docs.python.org/2/library/json.html#json.dump |
1965 | |
1966 | @since version 1.0.0; indentation character @a indent_char, option |
1967 | @a ensure_ascii and exceptions added in version 3.0.0; error |
1968 | handlers added in version 3.4.0. |
1969 | */ |
1970 | string_t dump(const int indent = -1, |
1971 | const char indent_char = ' ', |
1972 | const bool ensure_ascii = false, |
1973 | const error_handler_t error_handler = error_handler_t::strict) const |
1974 | { |
1975 | string_t result; |
1976 | serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler); |
1977 | |
1978 | if (indent >= 0) |
1979 | { |
1980 | s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); |
1981 | } |
1982 | else |
1983 | { |
1984 | s.dump(*this, false, ensure_ascii, 0); |
1985 | } |
1986 | |
1987 | return result; |
1988 | } |
1989 | |
1990 | /*! |
1991 | @brief return the type of the JSON value (explicit) |
1992 | |
1993 | Return the type of the JSON value as a value from the @ref value_t |
1994 | enumeration. |
1995 | |
1996 | @return the type of the JSON value |
1997 | Value type | return value |
1998 | ------------------------- | ------------------------- |
1999 | null | value_t::null |
2000 | boolean | value_t::boolean |
2001 | string | value_t::string |
2002 | number (integer) | value_t::number_integer |
2003 | number (unsigned integer) | value_t::number_unsigned |
2004 | number (floating-point) | value_t::number_float |
2005 | object | value_t::object |
2006 | array | value_t::array |
2007 | discarded | value_t::discarded |
2008 | |
2009 | @complexity Constant. |
2010 | |
2011 | @exceptionsafety No-throw guarantee: this member function never throws |
2012 | exceptions. |
2013 | |
2014 | @liveexample{The following code exemplifies `type()` for all JSON |
2015 | types.,type} |
2016 | |
2017 | @sa @ref operator value_t() -- return the type of the JSON value (implicit) |
2018 | @sa @ref type_name() -- return the type as string |
2019 | |
2020 | @since version 1.0.0 |
2021 | */ |
2022 | constexpr value_t type() const noexcept |
2023 | { |
2024 | return m_type; |
2025 | } |
2026 | |
2027 | /*! |
2028 | @brief return whether type is primitive |
2029 | |
2030 | This function returns true if and only if the JSON type is primitive |
2031 | (string, number, boolean, or null). |
2032 | |
2033 | @return `true` if type is primitive (string, number, boolean, or null), |
2034 | `false` otherwise. |
2035 | |
2036 | @complexity Constant. |
2037 | |
2038 | @exceptionsafety No-throw guarantee: this member function never throws |
2039 | exceptions. |
2040 | |
2041 | @liveexample{The following code exemplifies `is_primitive()` for all JSON |
2042 | types.,is_primitive} |
2043 | |
2044 | @sa @ref is_structured() -- returns whether JSON value is structured |
2045 | @sa @ref is_null() -- returns whether JSON value is `null` |
2046 | @sa @ref is_string() -- returns whether JSON value is a string |
2047 | @sa @ref is_boolean() -- returns whether JSON value is a boolean |
2048 | @sa @ref is_number() -- returns whether JSON value is a number |
2049 | |
2050 | @since version 1.0.0 |
2051 | */ |
2052 | constexpr bool is_primitive() const noexcept |
2053 | { |
2054 | return is_null() or is_string() or is_boolean() or is_number(); |
2055 | } |
2056 | |
2057 | /*! |
2058 | @brief return whether type is structured |
2059 | |
2060 | This function returns true if and only if the JSON type is structured |
2061 | (array or object). |
2062 | |
2063 | @return `true` if type is structured (array or object), `false` otherwise. |
2064 | |
2065 | @complexity Constant. |
2066 | |
2067 | @exceptionsafety No-throw guarantee: this member function never throws |
2068 | exceptions. |
2069 | |
2070 | @liveexample{The following code exemplifies `is_structured()` for all JSON |
2071 | types.,is_structured} |
2072 | |
2073 | @sa @ref is_primitive() -- returns whether value is primitive |
2074 | @sa @ref is_array() -- returns whether value is an array |
2075 | @sa @ref is_object() -- returns whether value is an object |
2076 | |
2077 | @since version 1.0.0 |
2078 | */ |
2079 | constexpr bool is_structured() const noexcept |
2080 | { |
2081 | return is_array() or is_object(); |
2082 | } |
2083 | |
2084 | /*! |
2085 | @brief return whether value is null |
2086 | |
2087 | This function returns true if and only if the JSON value is null. |
2088 | |
2089 | @return `true` if type is null, `false` otherwise. |
2090 | |
2091 | @complexity Constant. |
2092 | |
2093 | @exceptionsafety No-throw guarantee: this member function never throws |
2094 | exceptions. |
2095 | |
2096 | @liveexample{The following code exemplifies `is_null()` for all JSON |
2097 | types.,is_null} |
2098 | |
2099 | @since version 1.0.0 |
2100 | */ |
2101 | constexpr bool is_null() const noexcept |
2102 | { |
2103 | return m_type == value_t::null; |
2104 | } |
2105 | |
2106 | /*! |
2107 | @brief return whether value is a boolean |
2108 | |
2109 | This function returns true if and only if the JSON value is a boolean. |
2110 | |
2111 | @return `true` if type is boolean, `false` otherwise. |
2112 | |
2113 | @complexity Constant. |
2114 | |
2115 | @exceptionsafety No-throw guarantee: this member function never throws |
2116 | exceptions. |
2117 | |
2118 | @liveexample{The following code exemplifies `is_boolean()` for all JSON |
2119 | types.,is_boolean} |
2120 | |
2121 | @since version 1.0.0 |
2122 | */ |
2123 | constexpr bool is_boolean() const noexcept |
2124 | { |
2125 | return m_type == value_t::boolean; |
2126 | } |
2127 | |
2128 | /*! |
2129 | @brief return whether value is a number |
2130 | |
2131 | This function returns true if and only if the JSON value is a number. This |
2132 | includes both integer (signed and unsigned) and floating-point values. |
2133 | |
2134 | @return `true` if type is number (regardless whether integer, unsigned |
2135 | integer or floating-type), `false` otherwise. |
2136 | |
2137 | @complexity Constant. |
2138 | |
2139 | @exceptionsafety No-throw guarantee: this member function never throws |
2140 | exceptions. |
2141 | |
2142 | @liveexample{The following code exemplifies `is_number()` for all JSON |
2143 | types.,is_number} |
2144 | |
2145 | @sa @ref is_number_integer() -- check if value is an integer or unsigned |
2146 | integer number |
2147 | @sa @ref is_number_unsigned() -- check if value is an unsigned integer |
2148 | number |
2149 | @sa @ref is_number_float() -- check if value is a floating-point number |
2150 | |
2151 | @since version 1.0.0 |
2152 | */ |
2153 | constexpr bool is_number() const noexcept |
2154 | { |
2155 | return is_number_integer() or is_number_float(); |
2156 | } |
2157 | |
2158 | /*! |
2159 | @brief return whether value is an integer number |
2160 | |
2161 | This function returns true if and only if the JSON value is a signed or |
2162 | unsigned integer number. This excludes floating-point values. |
2163 | |
2164 | @return `true` if type is an integer or unsigned integer number, `false` |
2165 | otherwise. |
2166 | |
2167 | @complexity Constant. |
2168 | |
2169 | @exceptionsafety No-throw guarantee: this member function never throws |
2170 | exceptions. |
2171 | |
2172 | @liveexample{The following code exemplifies `is_number_integer()` for all |
2173 | JSON types.,is_number_integer} |
2174 | |
2175 | @sa @ref is_number() -- check if value is a number |
2176 | @sa @ref is_number_unsigned() -- check if value is an unsigned integer |
2177 | number |
2178 | @sa @ref is_number_float() -- check if value is a floating-point number |
2179 | |
2180 | @since version 1.0.0 |
2181 | */ |
2182 | constexpr bool is_number_integer() const noexcept |
2183 | { |
2184 | return m_type == value_t::number_integer or m_type == value_t::number_unsigned; |
2185 | } |
2186 | |
2187 | /*! |
2188 | @brief return whether value is an unsigned integer number |
2189 | |
2190 | This function returns true if and only if the JSON value is an unsigned |
2191 | integer number. This excludes floating-point and signed integer values. |
2192 | |
2193 | @return `true` if type is an unsigned integer number, `false` otherwise. |
2194 | |
2195 | @complexity Constant. |
2196 | |
2197 | @exceptionsafety No-throw guarantee: this member function never throws |
2198 | exceptions. |
2199 | |
2200 | @liveexample{The following code exemplifies `is_number_unsigned()` for all |
2201 | JSON types.,is_number_unsigned} |
2202 | |
2203 | @sa @ref is_number() -- check if value is a number |
2204 | @sa @ref is_number_integer() -- check if value is an integer or unsigned |
2205 | integer number |
2206 | @sa @ref is_number_float() -- check if value is a floating-point number |
2207 | |
2208 | @since version 2.0.0 |
2209 | */ |
2210 | constexpr bool is_number_unsigned() const noexcept |
2211 | { |
2212 | return m_type == value_t::number_unsigned; |
2213 | } |
2214 | |
2215 | /*! |
2216 | @brief return whether value is a floating-point number |
2217 | |
2218 | This function returns true if and only if the JSON value is a |
2219 | floating-point number. This excludes signed and unsigned integer values. |
2220 | |
2221 | @return `true` if type is a floating-point number, `false` otherwise. |
2222 | |
2223 | @complexity Constant. |
2224 | |
2225 | @exceptionsafety No-throw guarantee: this member function never throws |
2226 | exceptions. |
2227 | |
2228 | @liveexample{The following code exemplifies `is_number_float()` for all |
2229 | JSON types.,is_number_float} |
2230 | |
2231 | @sa @ref is_number() -- check if value is number |
2232 | @sa @ref is_number_integer() -- check if value is an integer number |
2233 | @sa @ref is_number_unsigned() -- check if value is an unsigned integer |
2234 | number |
2235 | |
2236 | @since version 1.0.0 |
2237 | */ |
2238 | constexpr bool is_number_float() const noexcept |
2239 | { |
2240 | return m_type == value_t::number_float; |
2241 | } |
2242 | |
2243 | /*! |
2244 | @brief return whether value is an object |
2245 | |
2246 | This function returns true if and only if the JSON value is an object. |
2247 | |
2248 | @return `true` if type is object, `false` otherwise. |
2249 | |
2250 | @complexity Constant. |
2251 | |
2252 | @exceptionsafety No-throw guarantee: this member function never throws |
2253 | exceptions. |
2254 | |
2255 | @liveexample{The following code exemplifies `is_object()` for all JSON |
2256 | types.,is_object} |
2257 | |
2258 | @since version 1.0.0 |
2259 | */ |
2260 | constexpr bool is_object() const noexcept |
2261 | { |
2262 | return m_type == value_t::object; |
2263 | } |
2264 | |
2265 | /*! |
2266 | @brief return whether value is an array |
2267 | |
2268 | This function returns true if and only if the JSON value is an array. |
2269 | |
2270 | @return `true` if type is array, `false` otherwise. |
2271 | |
2272 | @complexity Constant. |
2273 | |
2274 | @exceptionsafety No-throw guarantee: this member function never throws |
2275 | exceptions. |
2276 | |
2277 | @liveexample{The following code exemplifies `is_array()` for all JSON |
2278 | types.,is_array} |
2279 | |
2280 | @since version 1.0.0 |
2281 | */ |
2282 | constexpr bool is_array() const noexcept |
2283 | { |
2284 | return m_type == value_t::array; |
2285 | } |
2286 | |
2287 | /*! |
2288 | @brief return whether value is a string |
2289 | |
2290 | This function returns true if and only if the JSON value is a string. |
2291 | |
2292 | @return `true` if type is string, `false` otherwise. |
2293 | |
2294 | @complexity Constant. |
2295 | |
2296 | @exceptionsafety No-throw guarantee: this member function never throws |
2297 | exceptions. |
2298 | |
2299 | @liveexample{The following code exemplifies `is_string()` for all JSON |
2300 | types.,is_string} |
2301 | |
2302 | @since version 1.0.0 |
2303 | */ |
2304 | constexpr bool is_string() const noexcept |
2305 | { |
2306 | return m_type == value_t::string; |
2307 | } |
2308 | |
2309 | /*! |
2310 | @brief return whether value is discarded |
2311 | |
2312 | This function returns true if and only if the JSON value was discarded |
2313 | during parsing with a callback function (see @ref parser_callback_t). |
2314 | |
2315 | @note This function will always be `false` for JSON values after parsing. |
2316 | That is, discarded values can only occur during parsing, but will be |
2317 | removed when inside a structured value or replaced by null in other cases. |
2318 | |
2319 | @return `true` if type is discarded, `false` otherwise. |
2320 | |
2321 | @complexity Constant. |
2322 | |
2323 | @exceptionsafety No-throw guarantee: this member function never throws |
2324 | exceptions. |
2325 | |
2326 | @liveexample{The following code exemplifies `is_discarded()` for all JSON |
2327 | types.,is_discarded} |
2328 | |
2329 | @since version 1.0.0 |
2330 | */ |
2331 | constexpr bool is_discarded() const noexcept |
2332 | { |
2333 | return m_type == value_t::discarded; |
2334 | } |
2335 | |
2336 | /*! |
2337 | @brief return the type of the JSON value (implicit) |
2338 | |
2339 | Implicitly return the type of the JSON value as a value from the @ref |
2340 | value_t enumeration. |
2341 | |
2342 | @return the type of the JSON value |
2343 | |
2344 | @complexity Constant. |
2345 | |
2346 | @exceptionsafety No-throw guarantee: this member function never throws |
2347 | exceptions. |
2348 | |
2349 | @liveexample{The following code exemplifies the @ref value_t operator for |
2350 | all JSON types.,operator__value_t} |
2351 | |
2352 | @sa @ref type() -- return the type of the JSON value (explicit) |
2353 | @sa @ref type_name() -- return the type as string |
2354 | |
2355 | @since version 1.0.0 |
2356 | */ |
2357 | constexpr operator value_t() const noexcept |
2358 | { |
2359 | return m_type; |
2360 | } |
2361 | |
2362 | /// @} |
2363 | |
2364 | private: |
2365 | ////////////////// |
2366 | // value access // |
2367 | ////////////////// |
2368 | |
2369 | /// get a boolean (explicit) |
2370 | boolean_t get_impl(boolean_t* /*unused*/) const |
2371 | { |
2372 | if (JSON_HEDLEY_LIKELY(is_boolean())) |
2373 | { |
2374 | return m_value.boolean; |
2375 | } |
2376 | |
2377 | JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); |
2378 | } |
2379 | |
2380 | /// get a pointer to the value (object) |
2381 | object_t* get_impl_ptr(object_t* /*unused*/) noexcept |
2382 | { |
2383 | return is_object() ? m_value.object : nullptr; |
2384 | } |
2385 | |
2386 | /// get a pointer to the value (object) |
2387 | constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept |
2388 | { |
2389 | return is_object() ? m_value.object : nullptr; |
2390 | } |
2391 | |
2392 | /// get a pointer to the value (array) |
2393 | array_t* get_impl_ptr(array_t* /*unused*/) noexcept |
2394 | { |
2395 | return is_array() ? m_value.array : nullptr; |
2396 | } |
2397 | |
2398 | /// get a pointer to the value (array) |
2399 | constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept |
2400 | { |
2401 | return is_array() ? m_value.array : nullptr; |
2402 | } |
2403 | |
2404 | /// get a pointer to the value (string) |
2405 | string_t* get_impl_ptr(string_t* /*unused*/) noexcept |
2406 | { |
2407 | return is_string() ? m_value.string : nullptr; |
2408 | } |
2409 | |
2410 | /// get a pointer to the value (string) |
2411 | constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept |
2412 | { |
2413 | return is_string() ? m_value.string : nullptr; |
2414 | } |
2415 | |
2416 | /// get a pointer to the value (boolean) |
2417 | boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept |
2418 | { |
2419 | return is_boolean() ? &m_value.boolean : nullptr; |
2420 | } |
2421 | |
2422 | /// get a pointer to the value (boolean) |
2423 | constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept |
2424 | { |
2425 | return is_boolean() ? &m_value.boolean : nullptr; |
2426 | } |
2427 | |
2428 | /// get a pointer to the value (integer number) |
2429 | number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept |
2430 | { |
2431 | return is_number_integer() ? &m_value.number_integer : nullptr; |
2432 | } |
2433 | |
2434 | /// get a pointer to the value (integer number) |
2435 | constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept |
2436 | { |
2437 | return is_number_integer() ? &m_value.number_integer : nullptr; |
2438 | } |
2439 | |
2440 | /// get a pointer to the value (unsigned number) |
2441 | number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept |
2442 | { |
2443 | return is_number_unsigned() ? &m_value.number_unsigned : nullptr; |
2444 | } |
2445 | |
2446 | /// get a pointer to the value (unsigned number) |
2447 | constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept |
2448 | { |
2449 | return is_number_unsigned() ? &m_value.number_unsigned : nullptr; |
2450 | } |
2451 | |
2452 | /// get a pointer to the value (floating-point number) |
2453 | number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept |
2454 | { |
2455 | return is_number_float() ? &m_value.number_float : nullptr; |
2456 | } |
2457 | |
2458 | /// get a pointer to the value (floating-point number) |
2459 | constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept |
2460 | { |
2461 | return is_number_float() ? &m_value.number_float : nullptr; |
2462 | } |
2463 | |
2464 | /*! |
2465 | @brief helper function to implement get_ref() |
2466 | |
2467 | This function helps to implement get_ref() without code duplication for |
2468 | const and non-const overloads |
2469 | |
2470 | @tparam ThisType will be deduced as `basic_json` or `const basic_json` |
2471 | |
2472 | @throw type_error.303 if ReferenceType does not match underlying value |
2473 | type of the current JSON |
2474 | */ |
2475 | template<typename ReferenceType, typename ThisType> |
2476 | static ReferenceType get_ref_impl(ThisType& obj) |
2477 | { |
2478 | // delegate the call to get_ptr<>() |
2479 | auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); |
2480 | |
2481 | if (JSON_HEDLEY_LIKELY(ptr != nullptr)) |
2482 | { |
2483 | return *ptr; |
2484 | } |
2485 | |
2486 | JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); |
2487 | } |
2488 | |
2489 | public: |
2490 | /// @name value access |
2491 | /// Direct access to the stored value of a JSON value. |
2492 | /// @{ |
2493 | |
2494 | /*! |
2495 | @brief get special-case overload |
2496 | |
2497 | This overloads avoids a lot of template boilerplate, it can be seen as the |
2498 | identity method |
2499 | |
2500 | @tparam BasicJsonType == @ref basic_json |
2501 | |
2502 | @return a copy of *this |
2503 | |
2504 | @complexity Constant. |
2505 | |
2506 | @since version 2.1.0 |
2507 | */ |
2508 | template<typename BasicJsonType, detail::enable_if_t< |
2509 | std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value, |
2510 | int> = 0> |
2511 | basic_json get() const |
2512 | { |
2513 | return *this; |
2514 | } |
2515 | |
2516 | /*! |
2517 | @brief get special-case overload |
2518 | |
2519 | This overloads converts the current @ref basic_json in a different |
2520 | @ref basic_json type |
2521 | |
2522 | @tparam BasicJsonType == @ref basic_json |
2523 | |
2524 | @return a copy of *this, converted into @tparam BasicJsonType |
2525 | |
2526 | @complexity Depending on the implementation of the called `from_json()` |
2527 | method. |
2528 | |
2529 | @since version 3.2.0 |
2530 | */ |
2531 | template<typename BasicJsonType, detail::enable_if_t< |
2532 | not std::is_same<BasicJsonType, basic_json>::value and |
2533 | detail::is_basic_json<BasicJsonType>::value, int> = 0> |
2534 | BasicJsonType get() const |
2535 | { |
2536 | return *this; |
2537 | } |
2538 | |
2539 | /*! |
2540 | @brief get a value (explicit) |
2541 | |
2542 | Explicit type conversion between the JSON value and a compatible value |
2543 | which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) |
2544 | and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). |
2545 | The value is converted by calling the @ref json_serializer<ValueType> |
2546 | `from_json()` method. |
2547 | |
2548 | The function is equivalent to executing |
2549 | @code {.cpp} |
2550 | ValueType ret; |
2551 | JSONSerializer<ValueType>::from_json(*this, ret); |
2552 | return ret; |
2553 | @endcode |
2554 | |
2555 | This overloads is chosen if: |
2556 | - @a ValueType is not @ref basic_json, |
2557 | - @ref json_serializer<ValueType> has a `from_json()` method of the form |
2558 | `void from_json(const basic_json&, ValueType&)`, and |
2559 | - @ref json_serializer<ValueType> does not have a `from_json()` method of |
2560 | the form `ValueType from_json(const basic_json&)` |
2561 | |
2562 | @tparam ValueTypeCV the provided value type |
2563 | @tparam ValueType the returned value type |
2564 | |
2565 | @return copy of the JSON value, converted to @a ValueType |
2566 | |
2567 | @throw what @ref json_serializer<ValueType> `from_json()` method throws |
2568 | |
2569 | @liveexample{The example below shows several conversions from JSON values |
2570 | to other types. There a few things to note: (1) Floating-point numbers can |
2571 | be converted to integers\, (2) A JSON array can be converted to a standard |
2572 | `std::vector<short>`\, (3) A JSON object can be converted to C++ |
2573 | associative containers such as `std::unordered_map<std::string\, |
2574 | json>`.,get__ValueType_const} |
2575 | |
2576 | @since version 2.1.0 |
2577 | */ |
2578 | template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>, |
2579 | detail::enable_if_t < |
2580 | not detail::is_basic_json<ValueType>::value and |
2581 | detail::has_from_json<basic_json_t, ValueType>::value and |
2582 | not detail::has_non_default_from_json<basic_json_t, ValueType>::value, |
2583 | int> = 0> |
2584 | ValueType get() const noexcept(noexcept( |
2585 | JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) |
2586 | { |
2587 | // we cannot static_assert on ValueTypeCV being non-const, because |
2588 | // there is support for get<const basic_json_t>(), which is why we |
2589 | // still need the uncvref |
2590 | static_assert(not std::is_reference<ValueTypeCV>::value, |
2591 | "get() cannot be used with reference types, you might want to use get_ref()" ); |
2592 | static_assert(std::is_default_constructible<ValueType>::value, |
2593 | "types must be DefaultConstructible when used with get()" ); |
2594 | |
2595 | ValueType ret; |
2596 | JSONSerializer<ValueType>::from_json(*this, ret); |
2597 | return ret; |
2598 | } |
2599 | |
2600 | /*! |
2601 | @brief get a value (explicit); special case |
2602 | |
2603 | Explicit type conversion between the JSON value and a compatible value |
2604 | which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) |
2605 | and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). |
2606 | The value is converted by calling the @ref json_serializer<ValueType> |
2607 | `from_json()` method. |
2608 | |
2609 | The function is equivalent to executing |
2610 | @code {.cpp} |
2611 | return JSONSerializer<ValueTypeCV>::from_json(*this); |
2612 | @endcode |
2613 | |
2614 | This overloads is chosen if: |
2615 | - @a ValueType is not @ref basic_json and |
2616 | - @ref json_serializer<ValueType> has a `from_json()` method of the form |
2617 | `ValueType from_json(const basic_json&)` |
2618 | |
2619 | @note If @ref json_serializer<ValueType> has both overloads of |
2620 | `from_json()`, this one is chosen. |
2621 | |
2622 | @tparam ValueTypeCV the provided value type |
2623 | @tparam ValueType the returned value type |
2624 | |
2625 | @return copy of the JSON value, converted to @a ValueType |
2626 | |
2627 | @throw what @ref json_serializer<ValueType> `from_json()` method throws |
2628 | |
2629 | @since version 2.1.0 |
2630 | */ |
2631 | template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>, |
2632 | detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and |
2633 | detail::has_non_default_from_json<basic_json_t, ValueType>::value, |
2634 | int> = 0> |
2635 | ValueType get() const noexcept(noexcept( |
2636 | JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>()))) |
2637 | { |
2638 | static_assert(not std::is_reference<ValueTypeCV>::value, |
2639 | "get() cannot be used with reference types, you might want to use get_ref()" ); |
2640 | return JSONSerializer<ValueTypeCV>::from_json(*this); |
2641 | } |
2642 | |
2643 | /*! |
2644 | @brief get a value (explicit) |
2645 | |
2646 | Explicit type conversion between the JSON value and a compatible value. |
2647 | The value is filled into the input parameter by calling the @ref json_serializer<ValueType> |
2648 | `from_json()` method. |
2649 | |
2650 | The function is equivalent to executing |
2651 | @code {.cpp} |
2652 | ValueType v; |
2653 | JSONSerializer<ValueType>::from_json(*this, v); |
2654 | @endcode |
2655 | |
2656 | This overloads is chosen if: |
2657 | - @a ValueType is not @ref basic_json, |
2658 | - @ref json_serializer<ValueType> has a `from_json()` method of the form |
2659 | `void from_json(const basic_json&, ValueType&)`, and |
2660 | |
2661 | @tparam ValueType the input parameter type. |
2662 | |
2663 | @return the input parameter, allowing chaining calls. |
2664 | |
2665 | @throw what @ref json_serializer<ValueType> `from_json()` method throws |
2666 | |
2667 | @liveexample{The example below shows several conversions from JSON values |
2668 | to other types. There a few things to note: (1) Floating-point numbers can |
2669 | be converted to integers\, (2) A JSON array can be converted to a standard |
2670 | `std::vector<short>`\, (3) A JSON object can be converted to C++ |
2671 | associative containers such as `std::unordered_map<std::string\, |
2672 | json>`.,get_to} |
2673 | |
2674 | @since version 3.3.0 |
2675 | */ |
2676 | template<typename ValueType, |
2677 | detail::enable_if_t < |
2678 | not detail::is_basic_json<ValueType>::value and |
2679 | detail::has_from_json<basic_json_t, ValueType>::value, |
2680 | int> = 0> |
2681 | ValueType & get_to(ValueType& v) const noexcept(noexcept( |
2682 | JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) |
2683 | { |
2684 | JSONSerializer<ValueType>::from_json(*this, v); |
2685 | return v; |
2686 | } |
2687 | |
2688 | template < |
2689 | typename T, std::size_t N, |
2690 | typename Array = T (&)[N], |
2691 | detail::enable_if_t < |
2692 | detail::has_from_json<basic_json_t, Array>::value, int > = 0 > |
2693 | Array get_to(T (&v)[N]) const |
2694 | noexcept(noexcept(JSONSerializer<Array>::from_json( |
2695 | std::declval<const basic_json_t&>(), v))) |
2696 | { |
2697 | JSONSerializer<Array>::from_json(*this, v); |
2698 | return v; |
2699 | } |
2700 | |
2701 | |
2702 | /*! |
2703 | @brief get a pointer value (implicit) |
2704 | |
2705 | Implicit pointer access to the internally stored JSON value. No copies are |
2706 | made. |
2707 | |
2708 | @warning Writing data to the pointee of the result yields an undefined |
2709 | state. |
2710 | |
2711 | @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref |
2712 | object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, |
2713 | @ref number_unsigned_t, or @ref number_float_t. Enforced by a static |
2714 | assertion. |
2715 | |
2716 | @return pointer to the internally stored JSON value if the requested |
2717 | pointer type @a PointerType fits to the JSON value; `nullptr` otherwise |
2718 | |
2719 | @complexity Constant. |
2720 | |
2721 | @liveexample{The example below shows how pointers to internal values of a |
2722 | JSON value can be requested. Note that no type conversions are made and a |
2723 | `nullptr` is returned if the value and the requested pointer type does not |
2724 | match.,get_ptr} |
2725 | |
2726 | @since version 1.0.0 |
2727 | */ |
2728 | template<typename PointerType, typename std::enable_if< |
2729 | std::is_pointer<PointerType>::value, int>::type = 0> |
2730 | auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) |
2731 | { |
2732 | // delegate the call to get_impl_ptr<>() |
2733 | return get_impl_ptr(static_cast<PointerType>(nullptr)); |
2734 | } |
2735 | |
2736 | /*! |
2737 | @brief get a pointer value (implicit) |
2738 | @copydoc get_ptr() |
2739 | */ |
2740 | template<typename PointerType, typename std::enable_if< |
2741 | std::is_pointer<PointerType>::value and |
2742 | std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0> |
2743 | constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) |
2744 | { |
2745 | // delegate the call to get_impl_ptr<>() const |
2746 | return get_impl_ptr(static_cast<PointerType>(nullptr)); |
2747 | } |
2748 | |
2749 | /*! |
2750 | @brief get a pointer value (explicit) |
2751 | |
2752 | Explicit pointer access to the internally stored JSON value. No copies are |
2753 | made. |
2754 | |
2755 | @warning The pointer becomes invalid if the underlying JSON object |
2756 | changes. |
2757 | |
2758 | @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref |
2759 | object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, |
2760 | @ref number_unsigned_t, or @ref number_float_t. |
2761 | |
2762 | @return pointer to the internally stored JSON value if the requested |
2763 | pointer type @a PointerType fits to the JSON value; `nullptr` otherwise |
2764 | |
2765 | @complexity Constant. |
2766 | |
2767 | @liveexample{The example below shows how pointers to internal values of a |
2768 | JSON value can be requested. Note that no type conversions are made and a |
2769 | `nullptr` is returned if the value and the requested pointer type does not |
2770 | match.,get__PointerType} |
2771 | |
2772 | @sa @ref get_ptr() for explicit pointer-member access |
2773 | |
2774 | @since version 1.0.0 |
2775 | */ |
2776 | template<typename PointerType, typename std::enable_if< |
2777 | std::is_pointer<PointerType>::value, int>::type = 0> |
2778 | auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) |
2779 | { |
2780 | // delegate the call to get_ptr |
2781 | return get_ptr<PointerType>(); |
2782 | } |
2783 | |
2784 | /*! |
2785 | @brief get a pointer value (explicit) |
2786 | @copydoc get() |
2787 | */ |
2788 | template<typename PointerType, typename std::enable_if< |
2789 | std::is_pointer<PointerType>::value, int>::type = 0> |
2790 | constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) |
2791 | { |
2792 | // delegate the call to get_ptr |
2793 | return get_ptr<PointerType>(); |
2794 | } |
2795 | |
2796 | /*! |
2797 | @brief get a reference value (implicit) |
2798 | |
2799 | Implicit reference access to the internally stored JSON value. No copies |
2800 | are made. |
2801 | |
2802 | @warning Writing data to the referee of the result yields an undefined |
2803 | state. |
2804 | |
2805 | @tparam ReferenceType reference type; must be a reference to @ref array_t, |
2806 | @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or |
2807 | @ref number_float_t. Enforced by static assertion. |
2808 | |
2809 | @return reference to the internally stored JSON value if the requested |
2810 | reference type @a ReferenceType fits to the JSON value; throws |
2811 | type_error.303 otherwise |
2812 | |
2813 | @throw type_error.303 in case passed type @a ReferenceType is incompatible |
2814 | with the stored JSON value; see example below |
2815 | |
2816 | @complexity Constant. |
2817 | |
2818 | @liveexample{The example shows several calls to `get_ref()`.,get_ref} |
2819 | |
2820 | @since version 1.1.0 |
2821 | */ |
2822 | template<typename ReferenceType, typename std::enable_if< |
2823 | std::is_reference<ReferenceType>::value, int>::type = 0> |
2824 | ReferenceType get_ref() |
2825 | { |
2826 | // delegate call to get_ref_impl |
2827 | return get_ref_impl<ReferenceType>(*this); |
2828 | } |
2829 | |
2830 | /*! |
2831 | @brief get a reference value (implicit) |
2832 | @copydoc get_ref() |
2833 | */ |
2834 | template<typename ReferenceType, typename std::enable_if< |
2835 | std::is_reference<ReferenceType>::value and |
2836 | std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0> |
2837 | ReferenceType get_ref() const |
2838 | { |
2839 | // delegate call to get_ref_impl |
2840 | return get_ref_impl<ReferenceType>(*this); |
2841 | } |
2842 | |
2843 | /*! |
2844 | @brief get a value (implicit) |
2845 | |
2846 | Implicit type conversion between the JSON value and a compatible value. |
2847 | The call is realized by calling @ref get() const. |
2848 | |
2849 | @tparam ValueType non-pointer type compatible to the JSON value, for |
2850 | instance `int` for JSON integer numbers, `bool` for JSON booleans, or |
2851 | `std::vector` types for JSON arrays. The character type of @ref string_t |
2852 | as well as an initializer list of this type is excluded to avoid |
2853 | ambiguities as these types implicitly convert to `std::string`. |
2854 | |
2855 | @return copy of the JSON value, converted to type @a ValueType |
2856 | |
2857 | @throw type_error.302 in case passed type @a ValueType is incompatible |
2858 | to the JSON value type (e.g., the JSON value is of type boolean, but a |
2859 | string is requested); see example below |
2860 | |
2861 | @complexity Linear in the size of the JSON value. |
2862 | |
2863 | @liveexample{The example below shows several conversions from JSON values |
2864 | to other types. There a few things to note: (1) Floating-point numbers can |
2865 | be converted to integers\, (2) A JSON array can be converted to a standard |
2866 | `std::vector<short>`\, (3) A JSON object can be converted to C++ |
2867 | associative containers such as `std::unordered_map<std::string\, |
2868 | json>`.,operator__ValueType} |
2869 | |
2870 | @since version 1.0.0 |
2871 | */ |
2872 | template < typename ValueType, typename std::enable_if < |
2873 | not std::is_pointer<ValueType>::value and |
2874 | not std::is_same<ValueType, detail::json_ref<basic_json>>::value and |
2875 | not std::is_same<ValueType, typename string_t::value_type>::value and |
2876 | not detail::is_basic_json<ValueType>::value |
2877 | |
2878 | #ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015 |
2879 | and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value |
2880 | #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914)) |
2881 | and not std::is_same<ValueType, typename std::string_view>::value |
2882 | #endif |
2883 | #endif |
2884 | and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value |
2885 | , int >::type = 0 > |
2886 | operator ValueType() const |
2887 | { |
2888 | // delegate the call to get<>() const |
2889 | return get<ValueType>(); |
2890 | } |
2891 | |
2892 | /// @} |
2893 | |
2894 | |
2895 | //////////////////// |
2896 | // element access // |
2897 | //////////////////// |
2898 | |
2899 | /// @name element access |
2900 | /// Access to the JSON value. |
2901 | /// @{ |
2902 | |
2903 | /*! |
2904 | @brief access specified array element with bounds checking |
2905 | |
2906 | Returns a reference to the element at specified location @a idx, with |
2907 | bounds checking. |
2908 | |
2909 | @param[in] idx index of the element to access |
2910 | |
2911 | @return reference to the element at index @a idx |
2912 | |
2913 | @throw type_error.304 if the JSON value is not an array; in this case, |
2914 | calling `at` with an index makes no sense. See example below. |
2915 | @throw out_of_range.401 if the index @a idx is out of range of the array; |
2916 | that is, `idx >= size()`. See example below. |
2917 | |
2918 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
2919 | changes in the JSON value. |
2920 | |
2921 | @complexity Constant. |
2922 | |
2923 | @since version 1.0.0 |
2924 | |
2925 | @liveexample{The example below shows how array elements can be read and |
2926 | written using `at()`. It also demonstrates the different exceptions that |
2927 | can be thrown.,at__size_type} |
2928 | */ |
2929 | reference at(size_type idx) |
2930 | { |
2931 | // at only works for arrays |
2932 | if (JSON_HEDLEY_LIKELY(is_array())) |
2933 | { |
2934 | JSON_TRY |
2935 | { |
2936 | return m_value.array->at(idx); |
2937 | } |
2938 | JSON_CATCH (std::out_of_range&) |
2939 | { |
2940 | // create better exception explanation |
2941 | JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range" )); |
2942 | } |
2943 | } |
2944 | else |
2945 | { |
2946 | JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); |
2947 | } |
2948 | } |
2949 | |
2950 | /*! |
2951 | @brief access specified array element with bounds checking |
2952 | |
2953 | Returns a const reference to the element at specified location @a idx, |
2954 | with bounds checking. |
2955 | |
2956 | @param[in] idx index of the element to access |
2957 | |
2958 | @return const reference to the element at index @a idx |
2959 | |
2960 | @throw type_error.304 if the JSON value is not an array; in this case, |
2961 | calling `at` with an index makes no sense. See example below. |
2962 | @throw out_of_range.401 if the index @a idx is out of range of the array; |
2963 | that is, `idx >= size()`. See example below. |
2964 | |
2965 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
2966 | changes in the JSON value. |
2967 | |
2968 | @complexity Constant. |
2969 | |
2970 | @since version 1.0.0 |
2971 | |
2972 | @liveexample{The example below shows how array elements can be read using |
2973 | `at()`. It also demonstrates the different exceptions that can be thrown., |
2974 | at__size_type_const} |
2975 | */ |
2976 | const_reference at(size_type idx) const |
2977 | { |
2978 | // at only works for arrays |
2979 | if (JSON_HEDLEY_LIKELY(is_array())) |
2980 | { |
2981 | JSON_TRY |
2982 | { |
2983 | return m_value.array->at(idx); |
2984 | } |
2985 | JSON_CATCH (std::out_of_range&) |
2986 | { |
2987 | // create better exception explanation |
2988 | JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range" )); |
2989 | } |
2990 | } |
2991 | else |
2992 | { |
2993 | JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); |
2994 | } |
2995 | } |
2996 | |
2997 | /*! |
2998 | @brief access specified object element with bounds checking |
2999 | |
3000 | Returns a reference to the element at with specified key @a key, with |
3001 | bounds checking. |
3002 | |
3003 | @param[in] key key of the element to access |
3004 | |
3005 | @return reference to the element at key @a key |
3006 | |
3007 | @throw type_error.304 if the JSON value is not an object; in this case, |
3008 | calling `at` with a key makes no sense. See example below. |
3009 | @throw out_of_range.403 if the key @a key is is not stored in the object; |
3010 | that is, `find(key) == end()`. See example below. |
3011 | |
3012 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
3013 | changes in the JSON value. |
3014 | |
3015 | @complexity Logarithmic in the size of the container. |
3016 | |
3017 | @sa @ref operator[](const typename object_t::key_type&) for unchecked |
3018 | access by reference |
3019 | @sa @ref value() for access by value with a default value |
3020 | |
3021 | @since version 1.0.0 |
3022 | |
3023 | @liveexample{The example below shows how object elements can be read and |
3024 | written using `at()`. It also demonstrates the different exceptions that |
3025 | can be thrown.,at__object_t_key_type} |
3026 | */ |
3027 | reference at(const typename object_t::key_type& key) |
3028 | { |
3029 | // at only works for objects |
3030 | if (JSON_HEDLEY_LIKELY(is_object())) |
3031 | { |
3032 | JSON_TRY |
3033 | { |
3034 | return m_value.object->at(key); |
3035 | } |
3036 | JSON_CATCH (std::out_of_range&) |
3037 | { |
3038 | // create better exception explanation |
3039 | JSON_THROW(out_of_range::create(403, "key '" + key + "' not found" )); |
3040 | } |
3041 | } |
3042 | else |
3043 | { |
3044 | JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); |
3045 | } |
3046 | } |
3047 | |
3048 | /*! |
3049 | @brief access specified object element with bounds checking |
3050 | |
3051 | Returns a const reference to the element at with specified key @a key, |
3052 | with bounds checking. |
3053 | |
3054 | @param[in] key key of the element to access |
3055 | |
3056 | @return const reference to the element at key @a key |
3057 | |
3058 | @throw type_error.304 if the JSON value is not an object; in this case, |
3059 | calling `at` with a key makes no sense. See example below. |
3060 | @throw out_of_range.403 if the key @a key is is not stored in the object; |
3061 | that is, `find(key) == end()`. See example below. |
3062 | |
3063 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
3064 | changes in the JSON value. |
3065 | |
3066 | @complexity Logarithmic in the size of the container. |
3067 | |
3068 | @sa @ref operator[](const typename object_t::key_type&) for unchecked |
3069 | access by reference |
3070 | @sa @ref value() for access by value with a default value |
3071 | |
3072 | @since version 1.0.0 |
3073 | |
3074 | @liveexample{The example below shows how object elements can be read using |
3075 | `at()`. It also demonstrates the different exceptions that can be thrown., |
3076 | at__object_t_key_type_const} |
3077 | */ |
3078 | const_reference at(const typename object_t::key_type& key) const |
3079 | { |
3080 | // at only works for objects |
3081 | if (JSON_HEDLEY_LIKELY(is_object())) |
3082 | { |
3083 | JSON_TRY |
3084 | { |
3085 | return m_value.object->at(key); |
3086 | } |
3087 | JSON_CATCH (std::out_of_range&) |
3088 | { |
3089 | // create better exception explanation |
3090 | JSON_THROW(out_of_range::create(403, "key '" + key + "' not found" )); |
3091 | } |
3092 | } |
3093 | else |
3094 | { |
3095 | JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); |
3096 | } |
3097 | } |
3098 | |
3099 | /*! |
3100 | @brief access specified array element |
3101 | |
3102 | Returns a reference to the element at specified location @a idx. |
3103 | |
3104 | @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), |
3105 | then the array is silently filled up with `null` values to make `idx` a |
3106 | valid reference to the last stored element. |
3107 | |
3108 | @param[in] idx index of the element to access |
3109 | |
3110 | @return reference to the element at index @a idx |
3111 | |
3112 | @throw type_error.305 if the JSON value is not an array or null; in that |
3113 | cases, using the [] operator with an index makes no sense. |
3114 | |
3115 | @complexity Constant if @a idx is in the range of the array. Otherwise |
3116 | linear in `idx - size()`. |
3117 | |
3118 | @liveexample{The example below shows how array elements can be read and |
3119 | written using `[]` operator. Note the addition of `null` |
3120 | values.,operatorarray__size_type} |
3121 | |
3122 | @since version 1.0.0 |
3123 | */ |
3124 | reference operator[](size_type idx) |
3125 | { |
3126 | // implicitly convert null value to an empty array |
3127 | if (is_null()) |
3128 | { |
3129 | m_type = value_t::array; |
3130 | m_value.array = create<array_t>(); |
3131 | assert_invariant(); |
3132 | } |
3133 | |
3134 | // operator[] only works for arrays |
3135 | if (JSON_HEDLEY_LIKELY(is_array())) |
3136 | { |
3137 | // fill up array with null values if given idx is outside range |
3138 | if (idx >= m_value.array->size()) |
3139 | { |
3140 | m_value.array->insert(m_value.array->end(), |
3141 | idx - m_value.array->size() + 1, |
3142 | basic_json()); |
3143 | } |
3144 | |
3145 | return m_value.array->operator[](idx); |
3146 | } |
3147 | |
3148 | JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); |
3149 | } |
3150 | |
3151 | /*! |
3152 | @brief access specified array element |
3153 | |
3154 | Returns a const reference to the element at specified location @a idx. |
3155 | |
3156 | @param[in] idx index of the element to access |
3157 | |
3158 | @return const reference to the element at index @a idx |
3159 | |
3160 | @throw type_error.305 if the JSON value is not an array; in that case, |
3161 | using the [] operator with an index makes no sense. |
3162 | |
3163 | @complexity Constant. |
3164 | |
3165 | @liveexample{The example below shows how array elements can be read using |
3166 | the `[]` operator.,operatorarray__size_type_const} |
3167 | |
3168 | @since version 1.0.0 |
3169 | */ |
3170 | const_reference operator[](size_type idx) const |
3171 | { |
3172 | // const operator[] only works for arrays |
3173 | if (JSON_HEDLEY_LIKELY(is_array())) |
3174 | { |
3175 | return m_value.array->operator[](idx); |
3176 | } |
3177 | |
3178 | JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); |
3179 | } |
3180 | |
3181 | /*! |
3182 | @brief access specified object element |
3183 | |
3184 | Returns a reference to the element at with specified key @a key. |
3185 | |
3186 | @note If @a key is not found in the object, then it is silently added to |
3187 | the object and filled with a `null` value to make `key` a valid reference. |
3188 | In case the value was `null` before, it is converted to an object. |
3189 | |
3190 | @param[in] key key of the element to access |
3191 | |
3192 | @return reference to the element at key @a key |
3193 | |
3194 | @throw type_error.305 if the JSON value is not an object or null; in that |
3195 | cases, using the [] operator with a key makes no sense. |
3196 | |
3197 | @complexity Logarithmic in the size of the container. |
3198 | |
3199 | @liveexample{The example below shows how object elements can be read and |
3200 | written using the `[]` operator.,operatorarray__key_type} |
3201 | |
3202 | @sa @ref at(const typename object_t::key_type&) for access by reference |
3203 | with range checking |
3204 | @sa @ref value() for access by value with a default value |
3205 | |
3206 | @since version 1.0.0 |
3207 | */ |
3208 | reference operator[](const typename object_t::key_type& key) |
3209 | { |
3210 | // implicitly convert null value to an empty object |
3211 | if (is_null()) |
3212 | { |
3213 | m_type = value_t::object; |
3214 | m_value.object = create<object_t>(); |
3215 | assert_invariant(); |
3216 | } |
3217 | |
3218 | // operator[] only works for objects |
3219 | if (JSON_HEDLEY_LIKELY(is_object())) |
3220 | { |
3221 | return m_value.object->operator[](key); |
3222 | } |
3223 | |
3224 | JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); |
3225 | } |
3226 | |
3227 | /*! |
3228 | @brief read-only access specified object element |
3229 | |
3230 | Returns a const reference to the element at with specified key @a key. No |
3231 | bounds checking is performed. |
3232 | |
3233 | @warning If the element with key @a key does not exist, the behavior is |
3234 | undefined. |
3235 | |
3236 | @param[in] key key of the element to access |
3237 | |
3238 | @return const reference to the element at key @a key |
3239 | |
3240 | @pre The element with key @a key must exist. **This precondition is |
3241 | enforced with an assertion.** |
3242 | |
3243 | @throw type_error.305 if the JSON value is not an object; in that case, |
3244 | using the [] operator with a key makes no sense. |
3245 | |
3246 | @complexity Logarithmic in the size of the container. |
3247 | |
3248 | @liveexample{The example below shows how object elements can be read using |
3249 | the `[]` operator.,operatorarray__key_type_const} |
3250 | |
3251 | @sa @ref at(const typename object_t::key_type&) for access by reference |
3252 | with range checking |
3253 | @sa @ref value() for access by value with a default value |
3254 | |
3255 | @since version 1.0.0 |
3256 | */ |
3257 | const_reference operator[](const typename object_t::key_type& key) const |
3258 | { |
3259 | // const operator[] only works for objects |
3260 | if (JSON_HEDLEY_LIKELY(is_object())) |
3261 | { |
3262 | assert(m_value.object->find(key) != m_value.object->end()); |
3263 | return m_value.object->find(key)->second; |
3264 | } |
3265 | |
3266 | JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); |
3267 | } |
3268 | |
3269 | /*! |
3270 | @brief access specified object element |
3271 | |
3272 | Returns a reference to the element at with specified key @a key. |
3273 | |
3274 | @note If @a key is not found in the object, then it is silently added to |
3275 | the object and filled with a `null` value to make `key` a valid reference. |
3276 | In case the value was `null` before, it is converted to an object. |
3277 | |
3278 | @param[in] key key of the element to access |
3279 | |
3280 | @return reference to the element at key @a key |
3281 | |
3282 | @throw type_error.305 if the JSON value is not an object or null; in that |
3283 | cases, using the [] operator with a key makes no sense. |
3284 | |
3285 | @complexity Logarithmic in the size of the container. |
3286 | |
3287 | @liveexample{The example below shows how object elements can be read and |
3288 | written using the `[]` operator.,operatorarray__key_type} |
3289 | |
3290 | @sa @ref at(const typename object_t::key_type&) for access by reference |
3291 | with range checking |
3292 | @sa @ref value() for access by value with a default value |
3293 | |
3294 | @since version 1.1.0 |
3295 | */ |
3296 | template<typename T> |
3297 | JSON_HEDLEY_NON_NULL(2) |
3298 | reference operator[](T* key) |
3299 | { |
3300 | // implicitly convert null to object |
3301 | if (is_null()) |
3302 | { |
3303 | m_type = value_t::object; |
3304 | m_value = value_t::object; |
3305 | assert_invariant(); |
3306 | } |
3307 | |
3308 | // at only works for objects |
3309 | if (JSON_HEDLEY_LIKELY(is_object())) |
3310 | { |
3311 | return m_value.object->operator[](key); |
3312 | } |
3313 | |
3314 | JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); |
3315 | } |
3316 | |
3317 | /*! |
3318 | @brief read-only access specified object element |
3319 | |
3320 | Returns a const reference to the element at with specified key @a key. No |
3321 | bounds checking is performed. |
3322 | |
3323 | @warning If the element with key @a key does not exist, the behavior is |
3324 | undefined. |
3325 | |
3326 | @param[in] key key of the element to access |
3327 | |
3328 | @return const reference to the element at key @a key |
3329 | |
3330 | @pre The element with key @a key must exist. **This precondition is |
3331 | enforced with an assertion.** |
3332 | |
3333 | @throw type_error.305 if the JSON value is not an object; in that case, |
3334 | using the [] operator with a key makes no sense. |
3335 | |
3336 | @complexity Logarithmic in the size of the container. |
3337 | |
3338 | @liveexample{The example below shows how object elements can be read using |
3339 | the `[]` operator.,operatorarray__key_type_const} |
3340 | |
3341 | @sa @ref at(const typename object_t::key_type&) for access by reference |
3342 | with range checking |
3343 | @sa @ref value() for access by value with a default value |
3344 | |
3345 | @since version 1.1.0 |
3346 | */ |
3347 | template<typename T> |
3348 | JSON_HEDLEY_NON_NULL(2) |
3349 | const_reference operator[](T* key) const |
3350 | { |
3351 | // at only works for objects |
3352 | if (JSON_HEDLEY_LIKELY(is_object())) |
3353 | { |
3354 | assert(m_value.object->find(key) != m_value.object->end()); |
3355 | return m_value.object->find(key)->second; |
3356 | } |
3357 | |
3358 | JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); |
3359 | } |
3360 | |
3361 | /*! |
3362 | @brief access specified object element with default value |
3363 | |
3364 | Returns either a copy of an object's element at the specified key @a key |
3365 | or a given default value if no element with key @a key exists. |
3366 | |
3367 | The function is basically equivalent to executing |
3368 | @code {.cpp} |
3369 | try { |
3370 | return at(key); |
3371 | } catch(out_of_range) { |
3372 | return default_value; |
3373 | } |
3374 | @endcode |
3375 | |
3376 | @note Unlike @ref at(const typename object_t::key_type&), this function |
3377 | does not throw if the given key @a key was not found. |
3378 | |
3379 | @note Unlike @ref operator[](const typename object_t::key_type& key), this |
3380 | function does not implicitly add an element to the position defined by @a |
3381 | key. This function is furthermore also applicable to const objects. |
3382 | |
3383 | @param[in] key key of the element to access |
3384 | @param[in] default_value the value to return if @a key is not found |
3385 | |
3386 | @tparam ValueType type compatible to JSON values, for instance `int` for |
3387 | JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for |
3388 | JSON arrays. Note the type of the expected value at @a key and the default |
3389 | value @a default_value must be compatible. |
3390 | |
3391 | @return copy of the element at key @a key or @a default_value if @a key |
3392 | is not found |
3393 | |
3394 | @throw type_error.302 if @a default_value does not match the type of the |
3395 | value at @a key |
3396 | @throw type_error.306 if the JSON value is not an object; in that case, |
3397 | using `value()` with a key makes no sense. |
3398 | |
3399 | @complexity Logarithmic in the size of the container. |
3400 | |
3401 | @liveexample{The example below shows how object elements can be queried |
3402 | with a default value.,basic_json__value} |
3403 | |
3404 | @sa @ref at(const typename object_t::key_type&) for access by reference |
3405 | with range checking |
3406 | @sa @ref operator[](const typename object_t::key_type&) for unchecked |
3407 | access by reference |
3408 | |
3409 | @since version 1.0.0 |
3410 | */ |
3411 | template<class ValueType, typename std::enable_if< |
3412 | std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0> |
3413 | ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const |
3414 | { |
3415 | // at only works for objects |
3416 | if (JSON_HEDLEY_LIKELY(is_object())) |
3417 | { |
3418 | // if key is found, return value and given default value otherwise |
3419 | const auto it = find(key); |
3420 | if (it != end()) |
3421 | { |
3422 | return *it; |
3423 | } |
3424 | |
3425 | return default_value; |
3426 | } |
3427 | |
3428 | JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); |
3429 | } |
3430 | |
3431 | /*! |
3432 | @brief overload for a default value of type const char* |
3433 | @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const |
3434 | */ |
3435 | string_t value(const typename object_t::key_type& key, const char* default_value) const |
3436 | { |
3437 | return value(key, string_t(default_value)); |
3438 | } |
3439 | |
3440 | /*! |
3441 | @brief access specified object element via JSON Pointer with default value |
3442 | |
3443 | Returns either a copy of an object's element at the specified key @a key |
3444 | or a given default value if no element with key @a key exists. |
3445 | |
3446 | The function is basically equivalent to executing |
3447 | @code {.cpp} |
3448 | try { |
3449 | return at(ptr); |
3450 | } catch(out_of_range) { |
3451 | return default_value; |
3452 | } |
3453 | @endcode |
3454 | |
3455 | @note Unlike @ref at(const json_pointer&), this function does not throw |
3456 | if the given key @a key was not found. |
3457 | |
3458 | @param[in] ptr a JSON pointer to the element to access |
3459 | @param[in] default_value the value to return if @a ptr found no value |
3460 | |
3461 | @tparam ValueType type compatible to JSON values, for instance `int` for |
3462 | JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for |
3463 | JSON arrays. Note the type of the expected value at @a key and the default |
3464 | value @a default_value must be compatible. |
3465 | |
3466 | @return copy of the element at key @a key or @a default_value if @a key |
3467 | is not found |
3468 | |
3469 | @throw type_error.302 if @a default_value does not match the type of the |
3470 | value at @a ptr |
3471 | @throw type_error.306 if the JSON value is not an object; in that case, |
3472 | using `value()` with a key makes no sense. |
3473 | |
3474 | @complexity Logarithmic in the size of the container. |
3475 | |
3476 | @liveexample{The example below shows how object elements can be queried |
3477 | with a default value.,basic_json__value_ptr} |
3478 | |
3479 | @sa @ref operator[](const json_pointer&) for unchecked access by reference |
3480 | |
3481 | @since version 2.0.2 |
3482 | */ |
3483 | template<class ValueType, typename std::enable_if< |
3484 | std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0> |
3485 | ValueType value(const json_pointer& ptr, const ValueType& default_value) const |
3486 | { |
3487 | // at only works for objects |
3488 | if (JSON_HEDLEY_LIKELY(is_object())) |
3489 | { |
3490 | // if pointer resolves a value, return it or use default value |
3491 | JSON_TRY |
3492 | { |
3493 | return ptr.get_checked(this); |
3494 | } |
3495 | JSON_INTERNAL_CATCH (out_of_range&) |
3496 | { |
3497 | return default_value; |
3498 | } |
3499 | } |
3500 | |
3501 | JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); |
3502 | } |
3503 | |
3504 | /*! |
3505 | @brief overload for a default value of type const char* |
3506 | @copydoc basic_json::value(const json_pointer&, ValueType) const |
3507 | */ |
3508 | JSON_HEDLEY_NON_NULL(3) |
3509 | string_t value(const json_pointer& ptr, const char* default_value) const |
3510 | { |
3511 | return value(ptr, string_t(default_value)); |
3512 | } |
3513 | |
3514 | /*! |
3515 | @brief access the first element |
3516 | |
3517 | Returns a reference to the first element in the container. For a JSON |
3518 | container `c`, the expression `c.front()` is equivalent to `*c.begin()`. |
3519 | |
3520 | @return In case of a structured type (array or object), a reference to the |
3521 | first element is returned. In case of number, string, or boolean values, a |
3522 | reference to the value is returned. |
3523 | |
3524 | @complexity Constant. |
3525 | |
3526 | @pre The JSON value must not be `null` (would throw `std::out_of_range`) |
3527 | or an empty array or object (undefined behavior, **guarded by |
3528 | assertions**). |
3529 | @post The JSON value remains unchanged. |
3530 | |
3531 | @throw invalid_iterator.214 when called on `null` value |
3532 | |
3533 | @liveexample{The following code shows an example for `front()`.,front} |
3534 | |
3535 | @sa @ref back() -- access the last element |
3536 | |
3537 | @since version 1.0.0 |
3538 | */ |
3539 | reference front() |
3540 | { |
3541 | return *begin(); |
3542 | } |
3543 | |
3544 | /*! |
3545 | @copydoc basic_json::front() |
3546 | */ |
3547 | const_reference front() const |
3548 | { |
3549 | return *cbegin(); |
3550 | } |
3551 | |
3552 | /*! |
3553 | @brief access the last element |
3554 | |
3555 | Returns a reference to the last element in the container. For a JSON |
3556 | container `c`, the expression `c.back()` is equivalent to |
3557 | @code {.cpp} |
3558 | auto tmp = c.end(); |
3559 | --tmp; |
3560 | return *tmp; |
3561 | @endcode |
3562 | |
3563 | @return In case of a structured type (array or object), a reference to the |
3564 | last element is returned. In case of number, string, or boolean values, a |
3565 | reference to the value is returned. |
3566 | |
3567 | @complexity Constant. |
3568 | |
3569 | @pre The JSON value must not be `null` (would throw `std::out_of_range`) |
3570 | or an empty array or object (undefined behavior, **guarded by |
3571 | assertions**). |
3572 | @post The JSON value remains unchanged. |
3573 | |
3574 | @throw invalid_iterator.214 when called on a `null` value. See example |
3575 | below. |
3576 | |
3577 | @liveexample{The following code shows an example for `back()`.,back} |
3578 | |
3579 | @sa @ref front() -- access the first element |
3580 | |
3581 | @since version 1.0.0 |
3582 | */ |
3583 | reference back() |
3584 | { |
3585 | auto tmp = end(); |
3586 | --tmp; |
3587 | return *tmp; |
3588 | } |
3589 | |
3590 | /*! |
3591 | @copydoc basic_json::back() |
3592 | */ |
3593 | const_reference back() const |
3594 | { |
3595 | auto tmp = cend(); |
3596 | --tmp; |
3597 | return *tmp; |
3598 | } |
3599 | |
3600 | /*! |
3601 | @brief remove element given an iterator |
3602 | |
3603 | Removes the element specified by iterator @a pos. The iterator @a pos must |
3604 | be valid and dereferenceable. Thus the `end()` iterator (which is valid, |
3605 | but is not dereferenceable) cannot be used as a value for @a pos. |
3606 | |
3607 | If called on a primitive type other than `null`, the resulting JSON value |
3608 | will be `null`. |
3609 | |
3610 | @param[in] pos iterator to the element to remove |
3611 | @return Iterator following the last removed element. If the iterator @a |
3612 | pos refers to the last element, the `end()` iterator is returned. |
3613 | |
3614 | @tparam IteratorType an @ref iterator or @ref const_iterator |
3615 | |
3616 | @post Invalidates iterators and references at or after the point of the |
3617 | erase, including the `end()` iterator. |
3618 | |
3619 | @throw type_error.307 if called on a `null` value; example: `"cannot use |
3620 | erase() with null"` |
3621 | @throw invalid_iterator.202 if called on an iterator which does not belong |
3622 | to the current JSON value; example: `"iterator does not fit current |
3623 | value"` |
3624 | @throw invalid_iterator.205 if called on a primitive type with invalid |
3625 | iterator (i.e., any iterator which is not `begin()`); example: `"iterator |
3626 | out of range"` |
3627 | |
3628 | @complexity The complexity depends on the type: |
3629 | - objects: amortized constant |
3630 | - arrays: linear in distance between @a pos and the end of the container |
3631 | - strings: linear in the length of the string |
3632 | - other types: constant |
3633 | |
3634 | @liveexample{The example shows the result of `erase()` for different JSON |
3635 | types.,erase__IteratorType} |
3636 | |
3637 | @sa @ref erase(IteratorType, IteratorType) -- removes the elements in |
3638 | the given range |
3639 | @sa @ref erase(const typename object_t::key_type&) -- removes the element |
3640 | from an object at the given key |
3641 | @sa @ref erase(const size_type) -- removes the element from an array at |
3642 | the given index |
3643 | |
3644 | @since version 1.0.0 |
3645 | */ |
3646 | template<class IteratorType, typename std::enable_if< |
3647 | std::is_same<IteratorType, typename basic_json_t::iterator>::value or |
3648 | std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type |
3649 | = 0> |
3650 | IteratorType erase(IteratorType pos) |
3651 | { |
3652 | // make sure iterator fits the current value |
3653 | if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) |
3654 | { |
3655 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value" )); |
3656 | } |
3657 | |
3658 | IteratorType result = end(); |
3659 | |
3660 | switch (m_type) |
3661 | { |
3662 | case value_t::boolean: |
3663 | case value_t::number_float: |
3664 | case value_t::number_integer: |
3665 | case value_t::number_unsigned: |
3666 | case value_t::string: |
3667 | { |
3668 | if (JSON_HEDLEY_UNLIKELY(not pos.m_it.primitive_iterator.is_begin())) |
3669 | { |
3670 | JSON_THROW(invalid_iterator::create(205, "iterator out of range" )); |
3671 | } |
3672 | |
3673 | if (is_string()) |
3674 | { |
3675 | AllocatorType<string_t> alloc; |
3676 | std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string); |
3677 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1); |
3678 | m_value.string = nullptr; |
3679 | } |
3680 | |
3681 | m_type = value_t::null; |
3682 | assert_invariant(); |
3683 | break; |
3684 | } |
3685 | |
3686 | case value_t::object: |
3687 | { |
3688 | result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); |
3689 | break; |
3690 | } |
3691 | |
3692 | case value_t::array: |
3693 | { |
3694 | result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); |
3695 | break; |
3696 | } |
3697 | |
3698 | default: |
3699 | JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); |
3700 | } |
3701 | |
3702 | return result; |
3703 | } |
3704 | |
3705 | /*! |
3706 | @brief remove elements given an iterator range |
3707 | |
3708 | Removes the element specified by the range `[first; last)`. The iterator |
3709 | @a first does not need to be dereferenceable if `first == last`: erasing |
3710 | an empty range is a no-op. |
3711 | |
3712 | If called on a primitive type other than `null`, the resulting JSON value |
3713 | will be `null`. |
3714 | |
3715 | @param[in] first iterator to the beginning of the range to remove |
3716 | @param[in] last iterator past the end of the range to remove |
3717 | @return Iterator following the last removed element. If the iterator @a |
3718 | second refers to the last element, the `end()` iterator is returned. |
3719 | |
3720 | @tparam IteratorType an @ref iterator or @ref const_iterator |
3721 | |
3722 | @post Invalidates iterators and references at or after the point of the |
3723 | erase, including the `end()` iterator. |
3724 | |
3725 | @throw type_error.307 if called on a `null` value; example: `"cannot use |
3726 | erase() with null"` |
3727 | @throw invalid_iterator.203 if called on iterators which does not belong |
3728 | to the current JSON value; example: `"iterators do not fit current value"` |
3729 | @throw invalid_iterator.204 if called on a primitive type with invalid |
3730 | iterators (i.e., if `first != begin()` and `last != end()`); example: |
3731 | `"iterators out of range"` |
3732 | |
3733 | @complexity The complexity depends on the type: |
3734 | - objects: `log(size()) + std::distance(first, last)` |
3735 | - arrays: linear in the distance between @a first and @a last, plus linear |
3736 | in the distance between @a last and end of the container |
3737 | - strings: linear in the length of the string |
3738 | - other types: constant |
3739 | |
3740 | @liveexample{The example shows the result of `erase()` for different JSON |
3741 | types.,erase__IteratorType_IteratorType} |
3742 | |
3743 | @sa @ref erase(IteratorType) -- removes the element at a given position |
3744 | @sa @ref erase(const typename object_t::key_type&) -- removes the element |
3745 | from an object at the given key |
3746 | @sa @ref erase(const size_type) -- removes the element from an array at |
3747 | the given index |
3748 | |
3749 | @since version 1.0.0 |
3750 | */ |
3751 | template<class IteratorType, typename std::enable_if< |
3752 | std::is_same<IteratorType, typename basic_json_t::iterator>::value or |
3753 | std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type |
3754 | = 0> |
3755 | IteratorType erase(IteratorType first, IteratorType last) |
3756 | { |
3757 | // make sure iterator fits the current value |
3758 | if (JSON_HEDLEY_UNLIKELY(this != first.m_object or this != last.m_object)) |
3759 | { |
3760 | JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value" )); |
3761 | } |
3762 | |
3763 | IteratorType result = end(); |
3764 | |
3765 | switch (m_type) |
3766 | { |
3767 | case value_t::boolean: |
3768 | case value_t::number_float: |
3769 | case value_t::number_integer: |
3770 | case value_t::number_unsigned: |
3771 | case value_t::string: |
3772 | { |
3773 | if (JSON_HEDLEY_LIKELY(not first.m_it.primitive_iterator.is_begin() |
3774 | or not last.m_it.primitive_iterator.is_end())) |
3775 | { |
3776 | JSON_THROW(invalid_iterator::create(204, "iterators out of range" )); |
3777 | } |
3778 | |
3779 | if (is_string()) |
3780 | { |
3781 | AllocatorType<string_t> alloc; |
3782 | std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string); |
3783 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1); |
3784 | m_value.string = nullptr; |
3785 | } |
3786 | |
3787 | m_type = value_t::null; |
3788 | assert_invariant(); |
3789 | break; |
3790 | } |
3791 | |
3792 | case value_t::object: |
3793 | { |
3794 | result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, |
3795 | last.m_it.object_iterator); |
3796 | break; |
3797 | } |
3798 | |
3799 | case value_t::array: |
3800 | { |
3801 | result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, |
3802 | last.m_it.array_iterator); |
3803 | break; |
3804 | } |
3805 | |
3806 | default: |
3807 | JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); |
3808 | } |
3809 | |
3810 | return result; |
3811 | } |
3812 | |
3813 | /*! |
3814 | @brief remove element from a JSON object given a key |
3815 | |
3816 | Removes elements from a JSON object with the key value @a key. |
3817 | |
3818 | @param[in] key value of the elements to remove |
3819 | |
3820 | @return Number of elements removed. If @a ObjectType is the default |
3821 | `std::map` type, the return value will always be `0` (@a key was not |
3822 | found) or `1` (@a key was found). |
3823 | |
3824 | @post References and iterators to the erased elements are invalidated. |
3825 | Other references and iterators are not affected. |
3826 | |
3827 | @throw type_error.307 when called on a type other than JSON object; |
3828 | example: `"cannot use erase() with null"` |
3829 | |
3830 | @complexity `log(size()) + count(key)` |
3831 | |
3832 | @liveexample{The example shows the effect of `erase()`.,erase__key_type} |
3833 | |
3834 | @sa @ref erase(IteratorType) -- removes the element at a given position |
3835 | @sa @ref erase(IteratorType, IteratorType) -- removes the elements in |
3836 | the given range |
3837 | @sa @ref erase(const size_type) -- removes the element from an array at |
3838 | the given index |
3839 | |
3840 | @since version 1.0.0 |
3841 | */ |
3842 | size_type erase(const typename object_t::key_type& key) |
3843 | { |
3844 | // this erase only works for objects |
3845 | if (JSON_HEDLEY_LIKELY(is_object())) |
3846 | { |
3847 | return m_value.object->erase(key); |
3848 | } |
3849 | |
3850 | JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); |
3851 | } |
3852 | |
3853 | /*! |
3854 | @brief remove element from a JSON array given an index |
3855 | |
3856 | Removes element from a JSON array at the index @a idx. |
3857 | |
3858 | @param[in] idx index of the element to remove |
3859 | |
3860 | @throw type_error.307 when called on a type other than JSON object; |
3861 | example: `"cannot use erase() with null"` |
3862 | @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 |
3863 | is out of range"` |
3864 | |
3865 | @complexity Linear in distance between @a idx and the end of the container. |
3866 | |
3867 | @liveexample{The example shows the effect of `erase()`.,erase__size_type} |
3868 | |
3869 | @sa @ref erase(IteratorType) -- removes the element at a given position |
3870 | @sa @ref erase(IteratorType, IteratorType) -- removes the elements in |
3871 | the given range |
3872 | @sa @ref erase(const typename object_t::key_type&) -- removes the element |
3873 | from an object at the given key |
3874 | |
3875 | @since version 1.0.0 |
3876 | */ |
3877 | void erase(const size_type idx) |
3878 | { |
3879 | // this erase only works for arrays |
3880 | if (JSON_HEDLEY_LIKELY(is_array())) |
3881 | { |
3882 | if (JSON_HEDLEY_UNLIKELY(idx >= size())) |
3883 | { |
3884 | JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range" )); |
3885 | } |
3886 | |
3887 | m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx)); |
3888 | } |
3889 | else |
3890 | { |
3891 | JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); |
3892 | } |
3893 | } |
3894 | |
3895 | /// @} |
3896 | |
3897 | |
3898 | //////////// |
3899 | // lookup // |
3900 | //////////// |
3901 | |
3902 | /// @name lookup |
3903 | /// @{ |
3904 | |
3905 | /*! |
3906 | @brief find an element in a JSON object |
3907 | |
3908 | Finds an element in a JSON object with key equivalent to @a key. If the |
3909 | element is not found or the JSON value is not an object, end() is |
3910 | returned. |
3911 | |
3912 | @note This method always returns @ref end() when executed on a JSON type |
3913 | that is not an object. |
3914 | |
3915 | @param[in] key key value of the element to search for. |
3916 | |
3917 | @return Iterator to an element with key equivalent to @a key. If no such |
3918 | element is found or the JSON value is not an object, past-the-end (see |
3919 | @ref end()) iterator is returned. |
3920 | |
3921 | @complexity Logarithmic in the size of the JSON object. |
3922 | |
3923 | @liveexample{The example shows how `find()` is used.,find__key_type} |
3924 | |
3925 | @sa @ref contains(KeyT&&) const -- checks whether a key exists |
3926 | |
3927 | @since version 1.0.0 |
3928 | */ |
3929 | template<typename KeyT> |
3930 | iterator find(KeyT&& key) |
3931 | { |
3932 | auto result = end(); |
3933 | |
3934 | if (is_object()) |
3935 | { |
3936 | result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key)); |
3937 | } |
3938 | |
3939 | return result; |
3940 | } |
3941 | |
3942 | /*! |
3943 | @brief find an element in a JSON object |
3944 | @copydoc find(KeyT&&) |
3945 | */ |
3946 | template<typename KeyT> |
3947 | const_iterator find(KeyT&& key) const |
3948 | { |
3949 | auto result = cend(); |
3950 | |
3951 | if (is_object()) |
3952 | { |
3953 | result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key)); |
3954 | } |
3955 | |
3956 | return result; |
3957 | } |
3958 | |
3959 | /*! |
3960 | @brief returns the number of occurrences of a key in a JSON object |
3961 | |
3962 | Returns the number of elements with key @a key. If ObjectType is the |
3963 | default `std::map` type, the return value will always be `0` (@a key was |
3964 | not found) or `1` (@a key was found). |
3965 | |
3966 | @note This method always returns `0` when executed on a JSON type that is |
3967 | not an object. |
3968 | |
3969 | @param[in] key key value of the element to count |
3970 | |
3971 | @return Number of elements with key @a key. If the JSON value is not an |
3972 | object, the return value will be `0`. |
3973 | |
3974 | @complexity Logarithmic in the size of the JSON object. |
3975 | |
3976 | @liveexample{The example shows how `count()` is used.,count} |
3977 | |
3978 | @since version 1.0.0 |
3979 | */ |
3980 | template<typename KeyT> |
3981 | size_type count(KeyT&& key) const |
3982 | { |
3983 | // return 0 for all nonobject types |
3984 | return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0; |
3985 | } |
3986 | |
3987 | /*! |
3988 | @brief check the existence of an element in a JSON object |
3989 | |
3990 | Check whether an element exists in a JSON object with key equivalent to |
3991 | @a key. If the element is not found or the JSON value is not an object, |
3992 | false is returned. |
3993 | |
3994 | @note This method always returns false when executed on a JSON type |
3995 | that is not an object. |
3996 | |
3997 | @param[in] key key value to check its existence. |
3998 | |
3999 | @return true if an element with specified @a key exists. If no such |
4000 | element with such key is found or the JSON value is not an object, |
4001 | false is returned. |
4002 | |
4003 | @complexity Logarithmic in the size of the JSON object. |
4004 | |
4005 | @liveexample{The following code shows an example for `contains()`.,contains} |
4006 | |
4007 | @sa @ref find(KeyT&&) -- returns an iterator to an object element |
4008 | @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer |
4009 | |
4010 | @since version 3.6.0 |
4011 | */ |
4012 | template<typename KeyT, typename std::enable_if< |
4013 | not std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int>::type = 0> |
4014 | bool contains(KeyT && key) const |
4015 | { |
4016 | return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end(); |
4017 | } |
4018 | |
4019 | /*! |
4020 | @brief check the existence of an element in a JSON object given a JSON pointer |
4021 | |
4022 | Check whether the given JSON pointer @a ptr can be resolved in the current |
4023 | JSON value. |
4024 | |
4025 | @note This method can be executed on any JSON value type. |
4026 | |
4027 | @param[in] ptr JSON pointer to check its existence. |
4028 | |
4029 | @return true if the JSON pointer can be resolved to a stored value, false |
4030 | otherwise. |
4031 | |
4032 | @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`. |
4033 | |
4034 | @throw parse_error.106 if an array index begins with '0' |
4035 | @throw parse_error.109 if an array index was not a number |
4036 | |
4037 | @complexity Logarithmic in the size of the JSON object. |
4038 | |
4039 | @liveexample{The following code shows an example for `contains()`.,contains_json_pointer} |
4040 | |
4041 | @sa @ref contains(KeyT &&) const -- checks the existence of a key |
4042 | |
4043 | @since version 3.7.0 |
4044 | */ |
4045 | bool contains(const json_pointer& ptr) const |
4046 | { |
4047 | return ptr.contains(this); |
4048 | } |
4049 | |
4050 | /// @} |
4051 | |
4052 | |
4053 | /////////////// |
4054 | // iterators // |
4055 | /////////////// |
4056 | |
4057 | /// @name iterators |
4058 | /// @{ |
4059 | |
4060 | /*! |
4061 | @brief returns an iterator to the first element |
4062 | |
4063 | Returns an iterator to the first element. |
4064 | |
4065 | @image html range-begin-end.svg "Illustration from cppreference.com" |
4066 | |
4067 | @return iterator to the first element |
4068 | |
4069 | @complexity Constant. |
4070 | |
4071 | @requirement This function helps `basic_json` satisfying the |
4072 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4073 | requirements: |
4074 | - The complexity is constant. |
4075 | |
4076 | @liveexample{The following code shows an example for `begin()`.,begin} |
4077 | |
4078 | @sa @ref cbegin() -- returns a const iterator to the beginning |
4079 | @sa @ref end() -- returns an iterator to the end |
4080 | @sa @ref cend() -- returns a const iterator to the end |
4081 | |
4082 | @since version 1.0.0 |
4083 | */ |
4084 | iterator begin() noexcept |
4085 | { |
4086 | iterator result(this); |
4087 | result.set_begin(); |
4088 | return result; |
4089 | } |
4090 | |
4091 | /*! |
4092 | @copydoc basic_json::cbegin() |
4093 | */ |
4094 | const_iterator begin() const noexcept |
4095 | { |
4096 | return cbegin(); |
4097 | } |
4098 | |
4099 | /*! |
4100 | @brief returns a const iterator to the first element |
4101 | |
4102 | Returns a const iterator to the first element. |
4103 | |
4104 | @image html range-begin-end.svg "Illustration from cppreference.com" |
4105 | |
4106 | @return const iterator to the first element |
4107 | |
4108 | @complexity Constant. |
4109 | |
4110 | @requirement This function helps `basic_json` satisfying the |
4111 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4112 | requirements: |
4113 | - The complexity is constant. |
4114 | - Has the semantics of `const_cast<const basic_json&>(*this).begin()`. |
4115 | |
4116 | @liveexample{The following code shows an example for `cbegin()`.,cbegin} |
4117 | |
4118 | @sa @ref begin() -- returns an iterator to the beginning |
4119 | @sa @ref end() -- returns an iterator to the end |
4120 | @sa @ref cend() -- returns a const iterator to the end |
4121 | |
4122 | @since version 1.0.0 |
4123 | */ |
4124 | const_iterator cbegin() const noexcept |
4125 | { |
4126 | const_iterator result(this); |
4127 | result.set_begin(); |
4128 | return result; |
4129 | } |
4130 | |
4131 | /*! |
4132 | @brief returns an iterator to one past the last element |
4133 | |
4134 | Returns an iterator to one past the last element. |
4135 | |
4136 | @image html range-begin-end.svg "Illustration from cppreference.com" |
4137 | |
4138 | @return iterator one past the last element |
4139 | |
4140 | @complexity Constant. |
4141 | |
4142 | @requirement This function helps `basic_json` satisfying the |
4143 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4144 | requirements: |
4145 | - The complexity is constant. |
4146 | |
4147 | @liveexample{The following code shows an example for `end()`.,end} |
4148 | |
4149 | @sa @ref cend() -- returns a const iterator to the end |
4150 | @sa @ref begin() -- returns an iterator to the beginning |
4151 | @sa @ref cbegin() -- returns a const iterator to the beginning |
4152 | |
4153 | @since version 1.0.0 |
4154 | */ |
4155 | iterator end() noexcept |
4156 | { |
4157 | iterator result(this); |
4158 | result.set_end(); |
4159 | return result; |
4160 | } |
4161 | |
4162 | /*! |
4163 | @copydoc basic_json::cend() |
4164 | */ |
4165 | const_iterator end() const noexcept |
4166 | { |
4167 | return cend(); |
4168 | } |
4169 | |
4170 | /*! |
4171 | @brief returns a const iterator to one past the last element |
4172 | |
4173 | Returns a const iterator to one past the last element. |
4174 | |
4175 | @image html range-begin-end.svg "Illustration from cppreference.com" |
4176 | |
4177 | @return const iterator one past the last element |
4178 | |
4179 | @complexity Constant. |
4180 | |
4181 | @requirement This function helps `basic_json` satisfying the |
4182 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4183 | requirements: |
4184 | - The complexity is constant. |
4185 | - Has the semantics of `const_cast<const basic_json&>(*this).end()`. |
4186 | |
4187 | @liveexample{The following code shows an example for `cend()`.,cend} |
4188 | |
4189 | @sa @ref end() -- returns an iterator to the end |
4190 | @sa @ref begin() -- returns an iterator to the beginning |
4191 | @sa @ref cbegin() -- returns a const iterator to the beginning |
4192 | |
4193 | @since version 1.0.0 |
4194 | */ |
4195 | const_iterator cend() const noexcept |
4196 | { |
4197 | const_iterator result(this); |
4198 | result.set_end(); |
4199 | return result; |
4200 | } |
4201 | |
4202 | /*! |
4203 | @brief returns an iterator to the reverse-beginning |
4204 | |
4205 | Returns an iterator to the reverse-beginning; that is, the last element. |
4206 | |
4207 | @image html range-rbegin-rend.svg "Illustration from cppreference.com" |
4208 | |
4209 | @complexity Constant. |
4210 | |
4211 | @requirement This function helps `basic_json` satisfying the |
4212 | [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) |
4213 | requirements: |
4214 | - The complexity is constant. |
4215 | - Has the semantics of `reverse_iterator(end())`. |
4216 | |
4217 | @liveexample{The following code shows an example for `rbegin()`.,rbegin} |
4218 | |
4219 | @sa @ref crbegin() -- returns a const reverse iterator to the beginning |
4220 | @sa @ref rend() -- returns a reverse iterator to the end |
4221 | @sa @ref crend() -- returns a const reverse iterator to the end |
4222 | |
4223 | @since version 1.0.0 |
4224 | */ |
4225 | reverse_iterator rbegin() noexcept |
4226 | { |
4227 | return reverse_iterator(end()); |
4228 | } |
4229 | |
4230 | /*! |
4231 | @copydoc basic_json::crbegin() |
4232 | */ |
4233 | const_reverse_iterator rbegin() const noexcept |
4234 | { |
4235 | return crbegin(); |
4236 | } |
4237 | |
4238 | /*! |
4239 | @brief returns an iterator to the reverse-end |
4240 | |
4241 | Returns an iterator to the reverse-end; that is, one before the first |
4242 | element. |
4243 | |
4244 | @image html range-rbegin-rend.svg "Illustration from cppreference.com" |
4245 | |
4246 | @complexity Constant. |
4247 | |
4248 | @requirement This function helps `basic_json` satisfying the |
4249 | [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) |
4250 | requirements: |
4251 | - The complexity is constant. |
4252 | - Has the semantics of `reverse_iterator(begin())`. |
4253 | |
4254 | @liveexample{The following code shows an example for `rend()`.,rend} |
4255 | |
4256 | @sa @ref crend() -- returns a const reverse iterator to the end |
4257 | @sa @ref rbegin() -- returns a reverse iterator to the beginning |
4258 | @sa @ref crbegin() -- returns a const reverse iterator to the beginning |
4259 | |
4260 | @since version 1.0.0 |
4261 | */ |
4262 | reverse_iterator rend() noexcept |
4263 | { |
4264 | return reverse_iterator(begin()); |
4265 | } |
4266 | |
4267 | /*! |
4268 | @copydoc basic_json::crend() |
4269 | */ |
4270 | const_reverse_iterator rend() const noexcept |
4271 | { |
4272 | return crend(); |
4273 | } |
4274 | |
4275 | /*! |
4276 | @brief returns a const reverse iterator to the last element |
4277 | |
4278 | Returns a const iterator to the reverse-beginning; that is, the last |
4279 | element. |
4280 | |
4281 | @image html range-rbegin-rend.svg "Illustration from cppreference.com" |
4282 | |
4283 | @complexity Constant. |
4284 | |
4285 | @requirement This function helps `basic_json` satisfying the |
4286 | [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) |
4287 | requirements: |
4288 | - The complexity is constant. |
4289 | - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`. |
4290 | |
4291 | @liveexample{The following code shows an example for `crbegin()`.,crbegin} |
4292 | |
4293 | @sa @ref rbegin() -- returns a reverse iterator to the beginning |
4294 | @sa @ref rend() -- returns a reverse iterator to the end |
4295 | @sa @ref crend() -- returns a const reverse iterator to the end |
4296 | |
4297 | @since version 1.0.0 |
4298 | */ |
4299 | const_reverse_iterator crbegin() const noexcept |
4300 | { |
4301 | return const_reverse_iterator(cend()); |
4302 | } |
4303 | |
4304 | /*! |
4305 | @brief returns a const reverse iterator to one before the first |
4306 | |
4307 | Returns a const reverse iterator to the reverse-end; that is, one before |
4308 | the first element. |
4309 | |
4310 | @image html range-rbegin-rend.svg "Illustration from cppreference.com" |
4311 | |
4312 | @complexity Constant. |
4313 | |
4314 | @requirement This function helps `basic_json` satisfying the |
4315 | [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) |
4316 | requirements: |
4317 | - The complexity is constant. |
4318 | - Has the semantics of `const_cast<const basic_json&>(*this).rend()`. |
4319 | |
4320 | @liveexample{The following code shows an example for `crend()`.,crend} |
4321 | |
4322 | @sa @ref rend() -- returns a reverse iterator to the end |
4323 | @sa @ref rbegin() -- returns a reverse iterator to the beginning |
4324 | @sa @ref crbegin() -- returns a const reverse iterator to the beginning |
4325 | |
4326 | @since version 1.0.0 |
4327 | */ |
4328 | const_reverse_iterator crend() const noexcept |
4329 | { |
4330 | return const_reverse_iterator(cbegin()); |
4331 | } |
4332 | |
4333 | public: |
4334 | /*! |
4335 | @brief wrapper to access iterator member functions in range-based for |
4336 | |
4337 | This function allows to access @ref iterator::key() and @ref |
4338 | iterator::value() during range-based for loops. In these loops, a |
4339 | reference to the JSON values is returned, so there is no access to the |
4340 | underlying iterator. |
4341 | |
4342 | For loop without iterator_wrapper: |
4343 | |
4344 | @code{cpp} |
4345 | for (auto it = j_object.begin(); it != j_object.end(); ++it) |
4346 | { |
4347 | std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; |
4348 | } |
4349 | @endcode |
4350 | |
4351 | Range-based for loop without iterator proxy: |
4352 | |
4353 | @code{cpp} |
4354 | for (auto it : j_object) |
4355 | { |
4356 | // "it" is of type json::reference and has no key() member |
4357 | std::cout << "value: " << it << '\n'; |
4358 | } |
4359 | @endcode |
4360 | |
4361 | Range-based for loop with iterator proxy: |
4362 | |
4363 | @code{cpp} |
4364 | for (auto it : json::iterator_wrapper(j_object)) |
4365 | { |
4366 | std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; |
4367 | } |
4368 | @endcode |
4369 | |
4370 | @note When iterating over an array, `key()` will return the index of the |
4371 | element as string (see example). |
4372 | |
4373 | @param[in] ref reference to a JSON value |
4374 | @return iteration proxy object wrapping @a ref with an interface to use in |
4375 | range-based for loops |
4376 | |
4377 | @liveexample{The following code shows how the wrapper is used,iterator_wrapper} |
4378 | |
4379 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
4380 | changes in the JSON value. |
4381 | |
4382 | @complexity Constant. |
4383 | |
4384 | @note The name of this function is not yet final and may change in the |
4385 | future. |
4386 | |
4387 | @deprecated This stream operator is deprecated and will be removed in |
4388 | future 4.0.0 of the library. Please use @ref items() instead; |
4389 | that is, replace `json::iterator_wrapper(j)` with `j.items()`. |
4390 | */ |
4391 | JSON_HEDLEY_DEPRECATED(3.1.0) |
4392 | static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept |
4393 | { |
4394 | return ref.items(); |
4395 | } |
4396 | |
4397 | /*! |
4398 | @copydoc iterator_wrapper(reference) |
4399 | */ |
4400 | JSON_HEDLEY_DEPRECATED(3.1.0) |
4401 | static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept |
4402 | { |
4403 | return ref.items(); |
4404 | } |
4405 | |
4406 | /*! |
4407 | @brief helper to access iterator member functions in range-based for |
4408 | |
4409 | This function allows to access @ref iterator::key() and @ref |
4410 | iterator::value() during range-based for loops. In these loops, a |
4411 | reference to the JSON values is returned, so there is no access to the |
4412 | underlying iterator. |
4413 | |
4414 | For loop without `items()` function: |
4415 | |
4416 | @code{cpp} |
4417 | for (auto it = j_object.begin(); it != j_object.end(); ++it) |
4418 | { |
4419 | std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; |
4420 | } |
4421 | @endcode |
4422 | |
4423 | Range-based for loop without `items()` function: |
4424 | |
4425 | @code{cpp} |
4426 | for (auto it : j_object) |
4427 | { |
4428 | // "it" is of type json::reference and has no key() member |
4429 | std::cout << "value: " << it << '\n'; |
4430 | } |
4431 | @endcode |
4432 | |
4433 | Range-based for loop with `items()` function: |
4434 | |
4435 | @code{cpp} |
4436 | for (auto& el : j_object.items()) |
4437 | { |
4438 | std::cout << "key: " << el.key() << ", value:" << el.value() << '\n'; |
4439 | } |
4440 | @endcode |
4441 | |
4442 | The `items()` function also allows to use |
4443 | [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding) |
4444 | (C++17): |
4445 | |
4446 | @code{cpp} |
4447 | for (auto& [key, val] : j_object.items()) |
4448 | { |
4449 | std::cout << "key: " << key << ", value:" << val << '\n'; |
4450 | } |
4451 | @endcode |
4452 | |
4453 | @note When iterating over an array, `key()` will return the index of the |
4454 | element as string (see example). For primitive types (e.g., numbers), |
4455 | `key()` returns an empty string. |
4456 | |
4457 | @return iteration proxy object wrapping @a ref with an interface to use in |
4458 | range-based for loops |
4459 | |
4460 | @liveexample{The following code shows how the function is used.,items} |
4461 | |
4462 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
4463 | changes in the JSON value. |
4464 | |
4465 | @complexity Constant. |
4466 | |
4467 | @since version 3.1.0, structured bindings support since 3.5.0. |
4468 | */ |
4469 | iteration_proxy<iterator> items() noexcept |
4470 | { |
4471 | return iteration_proxy<iterator>(*this); |
4472 | } |
4473 | |
4474 | /*! |
4475 | @copydoc items() |
4476 | */ |
4477 | iteration_proxy<const_iterator> items() const noexcept |
4478 | { |
4479 | return iteration_proxy<const_iterator>(*this); |
4480 | } |
4481 | |
4482 | /// @} |
4483 | |
4484 | |
4485 | ////////////// |
4486 | // capacity // |
4487 | ////////////// |
4488 | |
4489 | /// @name capacity |
4490 | /// @{ |
4491 | |
4492 | /*! |
4493 | @brief checks whether the container is empty. |
4494 | |
4495 | Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). |
4496 | |
4497 | @return The return value depends on the different types and is |
4498 | defined as follows: |
4499 | Value type | return value |
4500 | ----------- | ------------- |
4501 | null | `true` |
4502 | boolean | `false` |
4503 | string | `false` |
4504 | number | `false` |
4505 | object | result of function `object_t::empty()` |
4506 | array | result of function `array_t::empty()` |
4507 | |
4508 | @liveexample{The following code uses `empty()` to check if a JSON |
4509 | object contains any elements.,empty} |
4510 | |
4511 | @complexity Constant, as long as @ref array_t and @ref object_t satisfy |
4512 | the Container concept; that is, their `empty()` functions have constant |
4513 | complexity. |
4514 | |
4515 | @iterators No changes. |
4516 | |
4517 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
4518 | |
4519 | @note This function does not return whether a string stored as JSON value |
4520 | is empty - it returns whether the JSON container itself is empty which is |
4521 | false in the case of a string. |
4522 | |
4523 | @requirement This function helps `basic_json` satisfying the |
4524 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4525 | requirements: |
4526 | - The complexity is constant. |
4527 | - Has the semantics of `begin() == end()`. |
4528 | |
4529 | @sa @ref size() -- returns the number of elements |
4530 | |
4531 | @since version 1.0.0 |
4532 | */ |
4533 | bool empty() const noexcept |
4534 | { |
4535 | switch (m_type) |
4536 | { |
4537 | case value_t::null: |
4538 | { |
4539 | // null values are empty |
4540 | return true; |
4541 | } |
4542 | |
4543 | case value_t::array: |
4544 | { |
4545 | // delegate call to array_t::empty() |
4546 | return m_value.array->empty(); |
4547 | } |
4548 | |
4549 | case value_t::object: |
4550 | { |
4551 | // delegate call to object_t::empty() |
4552 | return m_value.object->empty(); |
4553 | } |
4554 | |
4555 | default: |
4556 | { |
4557 | // all other types are nonempty |
4558 | return false; |
4559 | } |
4560 | } |
4561 | } |
4562 | |
4563 | /*! |
4564 | @brief returns the number of elements |
4565 | |
4566 | Returns the number of elements in a JSON value. |
4567 | |
4568 | @return The return value depends on the different types and is |
4569 | defined as follows: |
4570 | Value type | return value |
4571 | ----------- | ------------- |
4572 | null | `0` |
4573 | boolean | `1` |
4574 | string | `1` |
4575 | number | `1` |
4576 | object | result of function object_t::size() |
4577 | array | result of function array_t::size() |
4578 | |
4579 | @liveexample{The following code calls `size()` on the different value |
4580 | types.,size} |
4581 | |
4582 | @complexity Constant, as long as @ref array_t and @ref object_t satisfy |
4583 | the Container concept; that is, their size() functions have constant |
4584 | complexity. |
4585 | |
4586 | @iterators No changes. |
4587 | |
4588 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
4589 | |
4590 | @note This function does not return the length of a string stored as JSON |
4591 | value - it returns the number of elements in the JSON value which is 1 in |
4592 | the case of a string. |
4593 | |
4594 | @requirement This function helps `basic_json` satisfying the |
4595 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4596 | requirements: |
4597 | - The complexity is constant. |
4598 | - Has the semantics of `std::distance(begin(), end())`. |
4599 | |
4600 | @sa @ref empty() -- checks whether the container is empty |
4601 | @sa @ref max_size() -- returns the maximal number of elements |
4602 | |
4603 | @since version 1.0.0 |
4604 | */ |
4605 | size_type size() const noexcept |
4606 | { |
4607 | switch (m_type) |
4608 | { |
4609 | case value_t::null: |
4610 | { |
4611 | // null values are empty |
4612 | return 0; |
4613 | } |
4614 | |
4615 | case value_t::array: |
4616 | { |
4617 | // delegate call to array_t::size() |
4618 | return m_value.array->size(); |
4619 | } |
4620 | |
4621 | case value_t::object: |
4622 | { |
4623 | // delegate call to object_t::size() |
4624 | return m_value.object->size(); |
4625 | } |
4626 | |
4627 | default: |
4628 | { |
4629 | // all other types have size 1 |
4630 | return 1; |
4631 | } |
4632 | } |
4633 | } |
4634 | |
4635 | /*! |
4636 | @brief returns the maximum possible number of elements |
4637 | |
4638 | Returns the maximum number of elements a JSON value is able to hold due to |
4639 | system or library implementation limitations, i.e. `std::distance(begin(), |
4640 | end())` for the JSON value. |
4641 | |
4642 | @return The return value depends on the different types and is |
4643 | defined as follows: |
4644 | Value type | return value |
4645 | ----------- | ------------- |
4646 | null | `0` (same as `size()`) |
4647 | boolean | `1` (same as `size()`) |
4648 | string | `1` (same as `size()`) |
4649 | number | `1` (same as `size()`) |
4650 | object | result of function `object_t::max_size()` |
4651 | array | result of function `array_t::max_size()` |
4652 | |
4653 | @liveexample{The following code calls `max_size()` on the different value |
4654 | types. Note the output is implementation specific.,max_size} |
4655 | |
4656 | @complexity Constant, as long as @ref array_t and @ref object_t satisfy |
4657 | the Container concept; that is, their `max_size()` functions have constant |
4658 | complexity. |
4659 | |
4660 | @iterators No changes. |
4661 | |
4662 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
4663 | |
4664 | @requirement This function helps `basic_json` satisfying the |
4665 | [Container](https://en.cppreference.com/w/cpp/named_req/Container) |
4666 | requirements: |
4667 | - The complexity is constant. |
4668 | - Has the semantics of returning `b.size()` where `b` is the largest |
4669 | possible JSON value. |
4670 | |
4671 | @sa @ref size() -- returns the number of elements |
4672 | |
4673 | @since version 1.0.0 |
4674 | */ |
4675 | size_type max_size() const noexcept |
4676 | { |
4677 | switch (m_type) |
4678 | { |
4679 | case value_t::array: |
4680 | { |
4681 | // delegate call to array_t::max_size() |
4682 | return m_value.array->max_size(); |
4683 | } |
4684 | |
4685 | case value_t::object: |
4686 | { |
4687 | // delegate call to object_t::max_size() |
4688 | return m_value.object->max_size(); |
4689 | } |
4690 | |
4691 | default: |
4692 | { |
4693 | // all other types have max_size() == size() |
4694 | return size(); |
4695 | } |
4696 | } |
4697 | } |
4698 | |
4699 | /// @} |
4700 | |
4701 | |
4702 | /////////////// |
4703 | // modifiers // |
4704 | /////////////// |
4705 | |
4706 | /// @name modifiers |
4707 | /// @{ |
4708 | |
4709 | /*! |
4710 | @brief clears the contents |
4711 | |
4712 | Clears the content of a JSON value and resets it to the default value as |
4713 | if @ref basic_json(value_t) would have been called with the current value |
4714 | type from @ref type(): |
4715 | |
4716 | Value type | initial value |
4717 | ----------- | ------------- |
4718 | null | `null` |
4719 | boolean | `false` |
4720 | string | `""` |
4721 | number | `0` |
4722 | object | `{}` |
4723 | array | `[]` |
4724 | |
4725 | @post Has the same effect as calling |
4726 | @code {.cpp} |
4727 | *this = basic_json(type()); |
4728 | @endcode |
4729 | |
4730 | @liveexample{The example below shows the effect of `clear()` to different |
4731 | JSON types.,clear} |
4732 | |
4733 | @complexity Linear in the size of the JSON value. |
4734 | |
4735 | @iterators All iterators, pointers and references related to this container |
4736 | are invalidated. |
4737 | |
4738 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
4739 | |
4740 | @sa @ref basic_json(value_t) -- constructor that creates an object with the |
4741 | same value than calling `clear()` |
4742 | |
4743 | @since version 1.0.0 |
4744 | */ |
4745 | void clear() noexcept |
4746 | { |
4747 | switch (m_type) |
4748 | { |
4749 | case value_t::number_integer: |
4750 | { |
4751 | m_value.number_integer = 0; |
4752 | break; |
4753 | } |
4754 | |
4755 | case value_t::number_unsigned: |
4756 | { |
4757 | m_value.number_unsigned = 0; |
4758 | break; |
4759 | } |
4760 | |
4761 | case value_t::number_float: |
4762 | { |
4763 | m_value.number_float = 0.0; |
4764 | break; |
4765 | } |
4766 | |
4767 | case value_t::boolean: |
4768 | { |
4769 | m_value.boolean = false; |
4770 | break; |
4771 | } |
4772 | |
4773 | case value_t::string: |
4774 | { |
4775 | m_value.string->clear(); |
4776 | break; |
4777 | } |
4778 | |
4779 | case value_t::array: |
4780 | { |
4781 | m_value.array->clear(); |
4782 | break; |
4783 | } |
4784 | |
4785 | case value_t::object: |
4786 | { |
4787 | m_value.object->clear(); |
4788 | break; |
4789 | } |
4790 | |
4791 | default: |
4792 | break; |
4793 | } |
4794 | } |
4795 | |
4796 | /*! |
4797 | @brief add an object to an array |
4798 | |
4799 | Appends the given element @a val to the end of the JSON value. If the |
4800 | function is called on a JSON null value, an empty array is created before |
4801 | appending @a val. |
4802 | |
4803 | @param[in] val the value to add to the JSON array |
4804 | |
4805 | @throw type_error.308 when called on a type other than JSON array or |
4806 | null; example: `"cannot use push_back() with number"` |
4807 | |
4808 | @complexity Amortized constant. |
4809 | |
4810 | @liveexample{The example shows how `push_back()` and `+=` can be used to |
4811 | add elements to a JSON array. Note how the `null` value was silently |
4812 | converted to a JSON array.,push_back} |
4813 | |
4814 | @since version 1.0.0 |
4815 | */ |
4816 | void push_back(basic_json&& val) |
4817 | { |
4818 | // push_back only works for null objects or arrays |
4819 | if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array()))) |
4820 | { |
4821 | JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); |
4822 | } |
4823 | |
4824 | // transform null object into an array |
4825 | if (is_null()) |
4826 | { |
4827 | m_type = value_t::array; |
4828 | m_value = value_t::array; |
4829 | assert_invariant(); |
4830 | } |
4831 | |
4832 | // add element to array (move semantics) |
4833 | m_value.array->push_back(std::move(val)); |
4834 | // invalidate object: mark it null so we do not call the destructor |
4835 | // cppcheck-suppress accessMoved |
4836 | val.m_type = value_t::null; |
4837 | } |
4838 | |
4839 | /*! |
4840 | @brief add an object to an array |
4841 | @copydoc push_back(basic_json&&) |
4842 | */ |
4843 | reference operator+=(basic_json&& val) |
4844 | { |
4845 | push_back(std::move(val)); |
4846 | return *this; |
4847 | } |
4848 | |
4849 | /*! |
4850 | @brief add an object to an array |
4851 | @copydoc push_back(basic_json&&) |
4852 | */ |
4853 | void push_back(const basic_json& val) |
4854 | { |
4855 | // push_back only works for null objects or arrays |
4856 | if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array()))) |
4857 | { |
4858 | JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); |
4859 | } |
4860 | |
4861 | // transform null object into an array |
4862 | if (is_null()) |
4863 | { |
4864 | m_type = value_t::array; |
4865 | m_value = value_t::array; |
4866 | assert_invariant(); |
4867 | } |
4868 | |
4869 | // add element to array |
4870 | m_value.array->push_back(val); |
4871 | } |
4872 | |
4873 | /*! |
4874 | @brief add an object to an array |
4875 | @copydoc push_back(basic_json&&) |
4876 | */ |
4877 | reference operator+=(const basic_json& val) |
4878 | { |
4879 | push_back(val); |
4880 | return *this; |
4881 | } |
4882 | |
4883 | /*! |
4884 | @brief add an object to an object |
4885 | |
4886 | Inserts the given element @a val to the JSON object. If the function is |
4887 | called on a JSON null value, an empty object is created before inserting |
4888 | @a val. |
4889 | |
4890 | @param[in] val the value to add to the JSON object |
4891 | |
4892 | @throw type_error.308 when called on a type other than JSON object or |
4893 | null; example: `"cannot use push_back() with number"` |
4894 | |
4895 | @complexity Logarithmic in the size of the container, O(log(`size()`)). |
4896 | |
4897 | @liveexample{The example shows how `push_back()` and `+=` can be used to |
4898 | add elements to a JSON object. Note how the `null` value was silently |
4899 | converted to a JSON object.,push_back__object_t__value} |
4900 | |
4901 | @since version 1.0.0 |
4902 | */ |
4903 | void push_back(const typename object_t::value_type& val) |
4904 | { |
4905 | // push_back only works for null objects or objects |
4906 | if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object()))) |
4907 | { |
4908 | JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); |
4909 | } |
4910 | |
4911 | // transform null object into an object |
4912 | if (is_null()) |
4913 | { |
4914 | m_type = value_t::object; |
4915 | m_value = value_t::object; |
4916 | assert_invariant(); |
4917 | } |
4918 | |
4919 | // add element to array |
4920 | m_value.object->insert(val); |
4921 | } |
4922 | |
4923 | /*! |
4924 | @brief add an object to an object |
4925 | @copydoc push_back(const typename object_t::value_type&) |
4926 | */ |
4927 | reference operator+=(const typename object_t::value_type& val) |
4928 | { |
4929 | push_back(val); |
4930 | return *this; |
4931 | } |
4932 | |
4933 | /*! |
4934 | @brief add an object to an object |
4935 | |
4936 | This function allows to use `push_back` with an initializer list. In case |
4937 | |
4938 | 1. the current value is an object, |
4939 | 2. the initializer list @a init contains only two elements, and |
4940 | 3. the first element of @a init is a string, |
4941 | |
4942 | @a init is converted into an object element and added using |
4943 | @ref push_back(const typename object_t::value_type&). Otherwise, @a init |
4944 | is converted to a JSON value and added using @ref push_back(basic_json&&). |
4945 | |
4946 | @param[in] init an initializer list |
4947 | |
4948 | @complexity Linear in the size of the initializer list @a init. |
4949 | |
4950 | @note This function is required to resolve an ambiguous overload error, |
4951 | because pairs like `{"key", "value"}` can be both interpreted as |
4952 | `object_t::value_type` or `std::initializer_list<basic_json>`, see |
4953 | https://github.com/nlohmann/json/issues/235 for more information. |
4954 | |
4955 | @liveexample{The example shows how initializer lists are treated as |
4956 | objects when possible.,push_back__initializer_list} |
4957 | */ |
4958 | void push_back(initializer_list_t init) |
4959 | { |
4960 | if (is_object() and init.size() == 2 and (*init.begin())->is_string()) |
4961 | { |
4962 | basic_json&& key = init.begin()->moved_or_copied(); |
4963 | push_back(typename object_t::value_type( |
4964 | std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); |
4965 | } |
4966 | else |
4967 | { |
4968 | push_back(basic_json(init)); |
4969 | } |
4970 | } |
4971 | |
4972 | /*! |
4973 | @brief add an object to an object |
4974 | @copydoc push_back(initializer_list_t) |
4975 | */ |
4976 | reference operator+=(initializer_list_t init) |
4977 | { |
4978 | push_back(init); |
4979 | return *this; |
4980 | } |
4981 | |
4982 | /*! |
4983 | @brief add an object to an array |
4984 | |
4985 | Creates a JSON value from the passed parameters @a args to the end of the |
4986 | JSON value. If the function is called on a JSON null value, an empty array |
4987 | is created before appending the value created from @a args. |
4988 | |
4989 | @param[in] args arguments to forward to a constructor of @ref basic_json |
4990 | @tparam Args compatible types to create a @ref basic_json object |
4991 | |
4992 | @return reference to the inserted element |
4993 | |
4994 | @throw type_error.311 when called on a type other than JSON array or |
4995 | null; example: `"cannot use emplace_back() with number"` |
4996 | |
4997 | @complexity Amortized constant. |
4998 | |
4999 | @liveexample{The example shows how `push_back()` can be used to add |
5000 | elements to a JSON array. Note how the `null` value was silently converted |
5001 | to a JSON array.,emplace_back} |
5002 | |
5003 | @since version 2.0.8, returns reference since 3.7.0 |
5004 | */ |
5005 | template<class... Args> |
5006 | reference emplace_back(Args&& ... args) |
5007 | { |
5008 | // emplace_back only works for null objects or arrays |
5009 | if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array()))) |
5010 | { |
5011 | JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); |
5012 | } |
5013 | |
5014 | // transform null object into an array |
5015 | if (is_null()) |
5016 | { |
5017 | m_type = value_t::array; |
5018 | m_value = value_t::array; |
5019 | assert_invariant(); |
5020 | } |
5021 | |
5022 | // add element to array (perfect forwarding) |
5023 | #ifdef JSON_HAS_CPP_17 |
5024 | return m_value.array->emplace_back(std::forward<Args>(args)...); |
5025 | #else |
5026 | m_value.array->emplace_back(std::forward<Args>(args)...); |
5027 | return m_value.array->back(); |
5028 | #endif |
5029 | } |
5030 | |
5031 | /*! |
5032 | @brief add an object to an object if key does not exist |
5033 | |
5034 | Inserts a new element into a JSON object constructed in-place with the |
5035 | given @a args if there is no element with the key in the container. If the |
5036 | function is called on a JSON null value, an empty object is created before |
5037 | appending the value created from @a args. |
5038 | |
5039 | @param[in] args arguments to forward to a constructor of @ref basic_json |
5040 | @tparam Args compatible types to create a @ref basic_json object |
5041 | |
5042 | @return a pair consisting of an iterator to the inserted element, or the |
5043 | already-existing element if no insertion happened, and a bool |
5044 | denoting whether the insertion took place. |
5045 | |
5046 | @throw type_error.311 when called on a type other than JSON object or |
5047 | null; example: `"cannot use emplace() with number"` |
5048 | |
5049 | @complexity Logarithmic in the size of the container, O(log(`size()`)). |
5050 | |
5051 | @liveexample{The example shows how `emplace()` can be used to add elements |
5052 | to a JSON object. Note how the `null` value was silently converted to a |
5053 | JSON object. Further note how no value is added if there was already one |
5054 | value stored with the same key.,emplace} |
5055 | |
5056 | @since version 2.0.8 |
5057 | */ |
5058 | template<class... Args> |
5059 | std::pair<iterator, bool> emplace(Args&& ... args) |
5060 | { |
5061 | // emplace only works for null objects or arrays |
5062 | if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object()))) |
5063 | { |
5064 | JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); |
5065 | } |
5066 | |
5067 | // transform null object into an object |
5068 | if (is_null()) |
5069 | { |
5070 | m_type = value_t::object; |
5071 | m_value = value_t::object; |
5072 | assert_invariant(); |
5073 | } |
5074 | |
5075 | // add element to array (perfect forwarding) |
5076 | auto res = m_value.object->emplace(std::forward<Args>(args)...); |
5077 | // create result iterator and set iterator to the result of emplace |
5078 | auto it = begin(); |
5079 | it.m_it.object_iterator = res.first; |
5080 | |
5081 | // return pair of iterator and boolean |
5082 | return {it, res.second}; |
5083 | } |
5084 | |
5085 | /// Helper for insertion of an iterator |
5086 | /// @note: This uses std::distance to support GCC 4.8, |
5087 | /// see https://github.com/nlohmann/json/pull/1257 |
5088 | template<typename... Args> |
5089 | iterator insert_iterator(const_iterator pos, Args&& ... args) |
5090 | { |
5091 | iterator result(this); |
5092 | assert(m_value.array != nullptr); |
5093 | |
5094 | auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); |
5095 | m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...); |
5096 | result.m_it.array_iterator = m_value.array->begin() + insert_pos; |
5097 | |
5098 | // This could have been written as: |
5099 | // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); |
5100 | // but the return value of insert is missing in GCC 4.8, so it is written this way instead. |
5101 | |
5102 | return result; |
5103 | } |
5104 | |
5105 | /*! |
5106 | @brief inserts element |
5107 | |
5108 | Inserts element @a val before iterator @a pos. |
5109 | |
5110 | @param[in] pos iterator before which the content will be inserted; may be |
5111 | the end() iterator |
5112 | @param[in] val element to insert |
5113 | @return iterator pointing to the inserted @a val. |
5114 | |
5115 | @throw type_error.309 if called on JSON values other than arrays; |
5116 | example: `"cannot use insert() with string"` |
5117 | @throw invalid_iterator.202 if @a pos is not an iterator of *this; |
5118 | example: `"iterator does not fit current value"` |
5119 | |
5120 | @complexity Constant plus linear in the distance between @a pos and end of |
5121 | the container. |
5122 | |
5123 | @liveexample{The example shows how `insert()` is used.,insert} |
5124 | |
5125 | @since version 1.0.0 |
5126 | */ |
5127 | iterator insert(const_iterator pos, const basic_json& val) |
5128 | { |
5129 | // insert only works for arrays |
5130 | if (JSON_HEDLEY_LIKELY(is_array())) |
5131 | { |
5132 | // check if iterator pos fits to this JSON value |
5133 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) |
5134 | { |
5135 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value" )); |
5136 | } |
5137 | |
5138 | // insert to array and return iterator |
5139 | return insert_iterator(pos, val); |
5140 | } |
5141 | |
5142 | JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); |
5143 | } |
5144 | |
5145 | /*! |
5146 | @brief inserts element |
5147 | @copydoc insert(const_iterator, const basic_json&) |
5148 | */ |
5149 | iterator insert(const_iterator pos, basic_json&& val) |
5150 | { |
5151 | return insert(pos, val); |
5152 | } |
5153 | |
5154 | /*! |
5155 | @brief inserts elements |
5156 | |
5157 | Inserts @a cnt copies of @a val before iterator @a pos. |
5158 | |
5159 | @param[in] pos iterator before which the content will be inserted; may be |
5160 | the end() iterator |
5161 | @param[in] cnt number of copies of @a val to insert |
5162 | @param[in] val element to insert |
5163 | @return iterator pointing to the first element inserted, or @a pos if |
5164 | `cnt==0` |
5165 | |
5166 | @throw type_error.309 if called on JSON values other than arrays; example: |
5167 | `"cannot use insert() with string"` |
5168 | @throw invalid_iterator.202 if @a pos is not an iterator of *this; |
5169 | example: `"iterator does not fit current value"` |
5170 | |
5171 | @complexity Linear in @a cnt plus linear in the distance between @a pos |
5172 | and end of the container. |
5173 | |
5174 | @liveexample{The example shows how `insert()` is used.,insert__count} |
5175 | |
5176 | @since version 1.0.0 |
5177 | */ |
5178 | iterator insert(const_iterator pos, size_type cnt, const basic_json& val) |
5179 | { |
5180 | // insert only works for arrays |
5181 | if (JSON_HEDLEY_LIKELY(is_array())) |
5182 | { |
5183 | // check if iterator pos fits to this JSON value |
5184 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) |
5185 | { |
5186 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value" )); |
5187 | } |
5188 | |
5189 | // insert to array and return iterator |
5190 | return insert_iterator(pos, cnt, val); |
5191 | } |
5192 | |
5193 | JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); |
5194 | } |
5195 | |
5196 | /*! |
5197 | @brief inserts elements |
5198 | |
5199 | Inserts elements from range `[first, last)` before iterator @a pos. |
5200 | |
5201 | @param[in] pos iterator before which the content will be inserted; may be |
5202 | the end() iterator |
5203 | @param[in] first begin of the range of elements to insert |
5204 | @param[in] last end of the range of elements to insert |
5205 | |
5206 | @throw type_error.309 if called on JSON values other than arrays; example: |
5207 | `"cannot use insert() with string"` |
5208 | @throw invalid_iterator.202 if @a pos is not an iterator of *this; |
5209 | example: `"iterator does not fit current value"` |
5210 | @throw invalid_iterator.210 if @a first and @a last do not belong to the |
5211 | same JSON value; example: `"iterators do not fit"` |
5212 | @throw invalid_iterator.211 if @a first or @a last are iterators into |
5213 | container for which insert is called; example: `"passed iterators may not |
5214 | belong to container"` |
5215 | |
5216 | @return iterator pointing to the first element inserted, or @a pos if |
5217 | `first==last` |
5218 | |
5219 | @complexity Linear in `std::distance(first, last)` plus linear in the |
5220 | distance between @a pos and end of the container. |
5221 | |
5222 | @liveexample{The example shows how `insert()` is used.,insert__range} |
5223 | |
5224 | @since version 1.0.0 |
5225 | */ |
5226 | iterator insert(const_iterator pos, const_iterator first, const_iterator last) |
5227 | { |
5228 | // insert only works for arrays |
5229 | if (JSON_HEDLEY_UNLIKELY(not is_array())) |
5230 | { |
5231 | JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); |
5232 | } |
5233 | |
5234 | // check if iterator pos fits to this JSON value |
5235 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) |
5236 | { |
5237 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value" )); |
5238 | } |
5239 | |
5240 | // check if range iterators belong to the same JSON object |
5241 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) |
5242 | { |
5243 | JSON_THROW(invalid_iterator::create(210, "iterators do not fit" )); |
5244 | } |
5245 | |
5246 | if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) |
5247 | { |
5248 | JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container" )); |
5249 | } |
5250 | |
5251 | // insert to array and return iterator |
5252 | return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); |
5253 | } |
5254 | |
5255 | /*! |
5256 | @brief inserts elements |
5257 | |
5258 | Inserts elements from initializer list @a ilist before iterator @a pos. |
5259 | |
5260 | @param[in] pos iterator before which the content will be inserted; may be |
5261 | the end() iterator |
5262 | @param[in] ilist initializer list to insert the values from |
5263 | |
5264 | @throw type_error.309 if called on JSON values other than arrays; example: |
5265 | `"cannot use insert() with string"` |
5266 | @throw invalid_iterator.202 if @a pos is not an iterator of *this; |
5267 | example: `"iterator does not fit current value"` |
5268 | |
5269 | @return iterator pointing to the first element inserted, or @a pos if |
5270 | `ilist` is empty |
5271 | |
5272 | @complexity Linear in `ilist.size()` plus linear in the distance between |
5273 | @a pos and end of the container. |
5274 | |
5275 | @liveexample{The example shows how `insert()` is used.,insert__ilist} |
5276 | |
5277 | @since version 1.0.0 |
5278 | */ |
5279 | iterator insert(const_iterator pos, initializer_list_t ilist) |
5280 | { |
5281 | // insert only works for arrays |
5282 | if (JSON_HEDLEY_UNLIKELY(not is_array())) |
5283 | { |
5284 | JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); |
5285 | } |
5286 | |
5287 | // check if iterator pos fits to this JSON value |
5288 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) |
5289 | { |
5290 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value" )); |
5291 | } |
5292 | |
5293 | // insert to array and return iterator |
5294 | return insert_iterator(pos, ilist.begin(), ilist.end()); |
5295 | } |
5296 | |
5297 | /*! |
5298 | @brief inserts elements |
5299 | |
5300 | Inserts elements from range `[first, last)`. |
5301 | |
5302 | @param[in] first begin of the range of elements to insert |
5303 | @param[in] last end of the range of elements to insert |
5304 | |
5305 | @throw type_error.309 if called on JSON values other than objects; example: |
5306 | `"cannot use insert() with string"` |
5307 | @throw invalid_iterator.202 if iterator @a first or @a last does does not |
5308 | point to an object; example: `"iterators first and last must point to |
5309 | objects"` |
5310 | @throw invalid_iterator.210 if @a first and @a last do not belong to the |
5311 | same JSON value; example: `"iterators do not fit"` |
5312 | |
5313 | @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number |
5314 | of elements to insert. |
5315 | |
5316 | @liveexample{The example shows how `insert()` is used.,insert__range_object} |
5317 | |
5318 | @since version 3.0.0 |
5319 | */ |
5320 | void insert(const_iterator first, const_iterator last) |
5321 | { |
5322 | // insert only works for objects |
5323 | if (JSON_HEDLEY_UNLIKELY(not is_object())) |
5324 | { |
5325 | JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); |
5326 | } |
5327 | |
5328 | // check if range iterators belong to the same JSON object |
5329 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) |
5330 | { |
5331 | JSON_THROW(invalid_iterator::create(210, "iterators do not fit" )); |
5332 | } |
5333 | |
5334 | // passed iterators must belong to objects |
5335 | if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object())) |
5336 | { |
5337 | JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects" )); |
5338 | } |
5339 | |
5340 | m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); |
5341 | } |
5342 | |
5343 | /*! |
5344 | @brief updates a JSON object from another object, overwriting existing keys |
5345 | |
5346 | Inserts all values from JSON object @a j and overwrites existing keys. |
5347 | |
5348 | @param[in] j JSON object to read values from |
5349 | |
5350 | @throw type_error.312 if called on JSON values other than objects; example: |
5351 | `"cannot use update() with string"` |
5352 | |
5353 | @complexity O(N*log(size() + N)), where N is the number of elements to |
5354 | insert. |
5355 | |
5356 | @liveexample{The example shows how `update()` is used.,update} |
5357 | |
5358 | @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update |
5359 | |
5360 | @since version 3.0.0 |
5361 | */ |
5362 | void update(const_reference j) |
5363 | { |
5364 | // implicitly convert null value to an empty object |
5365 | if (is_null()) |
5366 | { |
5367 | m_type = value_t::object; |
5368 | m_value.object = create<object_t>(); |
5369 | assert_invariant(); |
5370 | } |
5371 | |
5372 | if (JSON_HEDLEY_UNLIKELY(not is_object())) |
5373 | { |
5374 | JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); |
5375 | } |
5376 | if (JSON_HEDLEY_UNLIKELY(not j.is_object())) |
5377 | { |
5378 | JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); |
5379 | } |
5380 | |
5381 | for (auto it = j.cbegin(); it != j.cend(); ++it) |
5382 | { |
5383 | m_value.object->operator[](it.key()) = it.value(); |
5384 | } |
5385 | } |
5386 | |
5387 | /*! |
5388 | @brief updates a JSON object from another object, overwriting existing keys |
5389 | |
5390 | Inserts all values from from range `[first, last)` and overwrites existing |
5391 | keys. |
5392 | |
5393 | @param[in] first begin of the range of elements to insert |
5394 | @param[in] last end of the range of elements to insert |
5395 | |
5396 | @throw type_error.312 if called on JSON values other than objects; example: |
5397 | `"cannot use update() with string"` |
5398 | @throw invalid_iterator.202 if iterator @a first or @a last does does not |
5399 | point to an object; example: `"iterators first and last must point to |
5400 | objects"` |
5401 | @throw invalid_iterator.210 if @a first and @a last do not belong to the |
5402 | same JSON value; example: `"iterators do not fit"` |
5403 | |
5404 | @complexity O(N*log(size() + N)), where N is the number of elements to |
5405 | insert. |
5406 | |
5407 | @liveexample{The example shows how `update()` is used__range.,update} |
5408 | |
5409 | @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update |
5410 | |
5411 | @since version 3.0.0 |
5412 | */ |
5413 | void update(const_iterator first, const_iterator last) |
5414 | { |
5415 | // implicitly convert null value to an empty object |
5416 | if (is_null()) |
5417 | { |
5418 | m_type = value_t::object; |
5419 | m_value.object = create<object_t>(); |
5420 | assert_invariant(); |
5421 | } |
5422 | |
5423 | if (JSON_HEDLEY_UNLIKELY(not is_object())) |
5424 | { |
5425 | JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); |
5426 | } |
5427 | |
5428 | // check if range iterators belong to the same JSON object |
5429 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) |
5430 | { |
5431 | JSON_THROW(invalid_iterator::create(210, "iterators do not fit" )); |
5432 | } |
5433 | |
5434 | // passed iterators must belong to objects |
5435 | if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object() |
5436 | or not last.m_object->is_object())) |
5437 | { |
5438 | JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects" )); |
5439 | } |
5440 | |
5441 | for (auto it = first; it != last; ++it) |
5442 | { |
5443 | m_value.object->operator[](it.key()) = it.value(); |
5444 | } |
5445 | } |
5446 | |
5447 | /*! |
5448 | @brief exchanges the values |
5449 | |
5450 | Exchanges the contents of the JSON value with those of @a other. Does not |
5451 | invoke any move, copy, or swap operations on individual elements. All |
5452 | iterators and references remain valid. The past-the-end iterator is |
5453 | invalidated. |
5454 | |
5455 | @param[in,out] other JSON value to exchange the contents with |
5456 | |
5457 | @complexity Constant. |
5458 | |
5459 | @liveexample{The example below shows how JSON values can be swapped with |
5460 | `swap()`.,swap__reference} |
5461 | |
5462 | @since version 1.0.0 |
5463 | */ |
5464 | void swap(reference other) noexcept ( |
5465 | std::is_nothrow_move_constructible<value_t>::value and |
5466 | std::is_nothrow_move_assignable<value_t>::value and |
5467 | std::is_nothrow_move_constructible<json_value>::value and |
5468 | std::is_nothrow_move_assignable<json_value>::value |
5469 | ) |
5470 | { |
5471 | std::swap(m_type, other.m_type); |
5472 | std::swap(m_value, other.m_value); |
5473 | assert_invariant(); |
5474 | } |
5475 | |
5476 | /*! |
5477 | @brief exchanges the values |
5478 | |
5479 | Exchanges the contents of a JSON array with those of @a other. Does not |
5480 | invoke any move, copy, or swap operations on individual elements. All |
5481 | iterators and references remain valid. The past-the-end iterator is |
5482 | invalidated. |
5483 | |
5484 | @param[in,out] other array to exchange the contents with |
5485 | |
5486 | @throw type_error.310 when JSON value is not an array; example: `"cannot |
5487 | use swap() with string"` |
5488 | |
5489 | @complexity Constant. |
5490 | |
5491 | @liveexample{The example below shows how arrays can be swapped with |
5492 | `swap()`.,swap__array_t} |
5493 | |
5494 | @since version 1.0.0 |
5495 | */ |
5496 | void swap(array_t& other) |
5497 | { |
5498 | // swap only works for arrays |
5499 | if (JSON_HEDLEY_LIKELY(is_array())) |
5500 | { |
5501 | std::swap(*(m_value.array), other); |
5502 | } |
5503 | else |
5504 | { |
5505 | JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); |
5506 | } |
5507 | } |
5508 | |
5509 | /*! |
5510 | @brief exchanges the values |
5511 | |
5512 | Exchanges the contents of a JSON object with those of @a other. Does not |
5513 | invoke any move, copy, or swap operations on individual elements. All |
5514 | iterators and references remain valid. The past-the-end iterator is |
5515 | invalidated. |
5516 | |
5517 | @param[in,out] other object to exchange the contents with |
5518 | |
5519 | @throw type_error.310 when JSON value is not an object; example: |
5520 | `"cannot use swap() with string"` |
5521 | |
5522 | @complexity Constant. |
5523 | |
5524 | @liveexample{The example below shows how objects can be swapped with |
5525 | `swap()`.,swap__object_t} |
5526 | |
5527 | @since version 1.0.0 |
5528 | */ |
5529 | void swap(object_t& other) |
5530 | { |
5531 | // swap only works for objects |
5532 | if (JSON_HEDLEY_LIKELY(is_object())) |
5533 | { |
5534 | std::swap(*(m_value.object), other); |
5535 | } |
5536 | else |
5537 | { |
5538 | JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); |
5539 | } |
5540 | } |
5541 | |
5542 | /*! |
5543 | @brief exchanges the values |
5544 | |
5545 | Exchanges the contents of a JSON string with those of @a other. Does not |
5546 | invoke any move, copy, or swap operations on individual elements. All |
5547 | iterators and references remain valid. The past-the-end iterator is |
5548 | invalidated. |
5549 | |
5550 | @param[in,out] other string to exchange the contents with |
5551 | |
5552 | @throw type_error.310 when JSON value is not a string; example: `"cannot |
5553 | use swap() with boolean"` |
5554 | |
5555 | @complexity Constant. |
5556 | |
5557 | @liveexample{The example below shows how strings can be swapped with |
5558 | `swap()`.,swap__string_t} |
5559 | |
5560 | @since version 1.0.0 |
5561 | */ |
5562 | void swap(string_t& other) |
5563 | { |
5564 | // swap only works for strings |
5565 | if (JSON_HEDLEY_LIKELY(is_string())) |
5566 | { |
5567 | std::swap(*(m_value.string), other); |
5568 | } |
5569 | else |
5570 | { |
5571 | JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); |
5572 | } |
5573 | } |
5574 | |
5575 | /// @} |
5576 | |
5577 | public: |
5578 | ////////////////////////////////////////// |
5579 | // lexicographical comparison operators // |
5580 | ////////////////////////////////////////// |
5581 | |
5582 | /// @name lexicographical comparison operators |
5583 | /// @{ |
5584 | |
5585 | /*! |
5586 | @brief comparison: equal |
5587 | |
5588 | Compares two JSON values for equality according to the following rules: |
5589 | - Two JSON values are equal if (1) they are from the same type and (2) |
5590 | their stored values are the same according to their respective |
5591 | `operator==`. |
5592 | - Integer and floating-point numbers are automatically converted before |
5593 | comparison. Note than two NaN values are always treated as unequal. |
5594 | - Two JSON null values are equal. |
5595 | |
5596 | @note Floating-point inside JSON values numbers are compared with |
5597 | `json::number_float_t::operator==` which is `double::operator==` by |
5598 | default. To compare floating-point while respecting an epsilon, an alternative |
5599 | [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39) |
5600 | could be used, for instance |
5601 | @code {.cpp} |
5602 | template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type> |
5603 | inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept |
5604 | { |
5605 | return std::abs(a - b) <= epsilon; |
5606 | } |
5607 | @endcode |
5608 | |
5609 | @note NaN values never compare equal to themselves or to other NaN values. |
5610 | |
5611 | @param[in] lhs first JSON value to consider |
5612 | @param[in] rhs second JSON value to consider |
5613 | @return whether the values @a lhs and @a rhs are equal |
5614 | |
5615 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
5616 | |
5617 | @complexity Linear. |
5618 | |
5619 | @liveexample{The example demonstrates comparing several JSON |
5620 | types.,operator__equal} |
5621 | |
5622 | @since version 1.0.0 |
5623 | */ |
5624 | friend bool operator==(const_reference lhs, const_reference rhs) noexcept |
5625 | { |
5626 | const auto lhs_type = lhs.type(); |
5627 | const auto rhs_type = rhs.type(); |
5628 | |
5629 | if (lhs_type == rhs_type) |
5630 | { |
5631 | switch (lhs_type) |
5632 | { |
5633 | case value_t::array: |
5634 | return *lhs.m_value.array == *rhs.m_value.array; |
5635 | |
5636 | case value_t::object: |
5637 | return *lhs.m_value.object == *rhs.m_value.object; |
5638 | |
5639 | case value_t::null: |
5640 | return true; |
5641 | |
5642 | case value_t::string: |
5643 | return *lhs.m_value.string == *rhs.m_value.string; |
5644 | |
5645 | case value_t::boolean: |
5646 | return lhs.m_value.boolean == rhs.m_value.boolean; |
5647 | |
5648 | case value_t::number_integer: |
5649 | return lhs.m_value.number_integer == rhs.m_value.number_integer; |
5650 | |
5651 | case value_t::number_unsigned: |
5652 | return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; |
5653 | |
5654 | case value_t::number_float: |
5655 | return lhs.m_value.number_float == rhs.m_value.number_float; |
5656 | |
5657 | default: |
5658 | return false; |
5659 | } |
5660 | } |
5661 | else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) |
5662 | { |
5663 | return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float; |
5664 | } |
5665 | else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) |
5666 | { |
5667 | return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer); |
5668 | } |
5669 | else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) |
5670 | { |
5671 | return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float; |
5672 | } |
5673 | else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) |
5674 | { |
5675 | return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned); |
5676 | } |
5677 | else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) |
5678 | { |
5679 | return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; |
5680 | } |
5681 | else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) |
5682 | { |
5683 | return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned); |
5684 | } |
5685 | |
5686 | return false; |
5687 | } |
5688 | |
5689 | /*! |
5690 | @brief comparison: equal |
5691 | @copydoc operator==(const_reference, const_reference) |
5692 | */ |
5693 | template<typename ScalarType, typename std::enable_if< |
5694 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5695 | friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept |
5696 | { |
5697 | return lhs == basic_json(rhs); |
5698 | } |
5699 | |
5700 | /*! |
5701 | @brief comparison: equal |
5702 | @copydoc operator==(const_reference, const_reference) |
5703 | */ |
5704 | template<typename ScalarType, typename std::enable_if< |
5705 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5706 | friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept |
5707 | { |
5708 | return basic_json(lhs) == rhs; |
5709 | } |
5710 | |
5711 | /*! |
5712 | @brief comparison: not equal |
5713 | |
5714 | Compares two JSON values for inequality by calculating `not (lhs == rhs)`. |
5715 | |
5716 | @param[in] lhs first JSON value to consider |
5717 | @param[in] rhs second JSON value to consider |
5718 | @return whether the values @a lhs and @a rhs are not equal |
5719 | |
5720 | @complexity Linear. |
5721 | |
5722 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
5723 | |
5724 | @liveexample{The example demonstrates comparing several JSON |
5725 | types.,operator__notequal} |
5726 | |
5727 | @since version 1.0.0 |
5728 | */ |
5729 | friend bool operator!=(const_reference lhs, const_reference rhs) noexcept |
5730 | { |
5731 | return not (lhs == rhs); |
5732 | } |
5733 | |
5734 | /*! |
5735 | @brief comparison: not equal |
5736 | @copydoc operator!=(const_reference, const_reference) |
5737 | */ |
5738 | template<typename ScalarType, typename std::enable_if< |
5739 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5740 | friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept |
5741 | { |
5742 | return lhs != basic_json(rhs); |
5743 | } |
5744 | |
5745 | /*! |
5746 | @brief comparison: not equal |
5747 | @copydoc operator!=(const_reference, const_reference) |
5748 | */ |
5749 | template<typename ScalarType, typename std::enable_if< |
5750 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5751 | friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept |
5752 | { |
5753 | return basic_json(lhs) != rhs; |
5754 | } |
5755 | |
5756 | /*! |
5757 | @brief comparison: less than |
5758 | |
5759 | Compares whether one JSON value @a lhs is less than another JSON value @a |
5760 | rhs according to the following rules: |
5761 | - If @a lhs and @a rhs have the same type, the values are compared using |
5762 | the default `<` operator. |
5763 | - Integer and floating-point numbers are automatically converted before |
5764 | comparison |
5765 | - In case @a lhs and @a rhs have different types, the values are ignored |
5766 | and the order of the types is considered, see |
5767 | @ref operator<(const value_t, const value_t). |
5768 | |
5769 | @param[in] lhs first JSON value to consider |
5770 | @param[in] rhs second JSON value to consider |
5771 | @return whether @a lhs is less than @a rhs |
5772 | |
5773 | @complexity Linear. |
5774 | |
5775 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
5776 | |
5777 | @liveexample{The example demonstrates comparing several JSON |
5778 | types.,operator__less} |
5779 | |
5780 | @since version 1.0.0 |
5781 | */ |
5782 | friend bool operator<(const_reference lhs, const_reference rhs) noexcept |
5783 | { |
5784 | const auto lhs_type = lhs.type(); |
5785 | const auto rhs_type = rhs.type(); |
5786 | |
5787 | if (lhs_type == rhs_type) |
5788 | { |
5789 | switch (lhs_type) |
5790 | { |
5791 | case value_t::array: |
5792 | // note parentheses are necessary, see |
5793 | // https://github.com/nlohmann/json/issues/1530 |
5794 | return (*lhs.m_value.array) < (*rhs.m_value.array); |
5795 | |
5796 | case value_t::object: |
5797 | return (*lhs.m_value.object) < (*rhs.m_value.object); |
5798 | |
5799 | case value_t::null: |
5800 | return false; |
5801 | |
5802 | case value_t::string: |
5803 | return (*lhs.m_value.string) < (*rhs.m_value.string); |
5804 | |
5805 | case value_t::boolean: |
5806 | return (lhs.m_value.boolean) < (rhs.m_value.boolean); |
5807 | |
5808 | case value_t::number_integer: |
5809 | return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); |
5810 | |
5811 | case value_t::number_unsigned: |
5812 | return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); |
5813 | |
5814 | case value_t::number_float: |
5815 | return (lhs.m_value.number_float) < (rhs.m_value.number_float); |
5816 | |
5817 | default: |
5818 | return false; |
5819 | } |
5820 | } |
5821 | else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) |
5822 | { |
5823 | return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float; |
5824 | } |
5825 | else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) |
5826 | { |
5827 | return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer); |
5828 | } |
5829 | else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) |
5830 | { |
5831 | return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float; |
5832 | } |
5833 | else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) |
5834 | { |
5835 | return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned); |
5836 | } |
5837 | else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) |
5838 | { |
5839 | return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned); |
5840 | } |
5841 | else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) |
5842 | { |
5843 | return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; |
5844 | } |
5845 | |
5846 | // We only reach this line if we cannot compare values. In that case, |
5847 | // we compare types. Note we have to call the operator explicitly, |
5848 | // because MSVC has problems otherwise. |
5849 | return operator<(lhs_type, rhs_type); |
5850 | } |
5851 | |
5852 | /*! |
5853 | @brief comparison: less than |
5854 | @copydoc operator<(const_reference, const_reference) |
5855 | */ |
5856 | template<typename ScalarType, typename std::enable_if< |
5857 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5858 | friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept |
5859 | { |
5860 | return lhs < basic_json(rhs); |
5861 | } |
5862 | |
5863 | /*! |
5864 | @brief comparison: less than |
5865 | @copydoc operator<(const_reference, const_reference) |
5866 | */ |
5867 | template<typename ScalarType, typename std::enable_if< |
5868 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5869 | friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept |
5870 | { |
5871 | return basic_json(lhs) < rhs; |
5872 | } |
5873 | |
5874 | /*! |
5875 | @brief comparison: less than or equal |
5876 | |
5877 | Compares whether one JSON value @a lhs is less than or equal to another |
5878 | JSON value by calculating `not (rhs < lhs)`. |
5879 | |
5880 | @param[in] lhs first JSON value to consider |
5881 | @param[in] rhs second JSON value to consider |
5882 | @return whether @a lhs is less than or equal to @a rhs |
5883 | |
5884 | @complexity Linear. |
5885 | |
5886 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
5887 | |
5888 | @liveexample{The example demonstrates comparing several JSON |
5889 | types.,operator__greater} |
5890 | |
5891 | @since version 1.0.0 |
5892 | */ |
5893 | friend bool operator<=(const_reference lhs, const_reference rhs) noexcept |
5894 | { |
5895 | return not (rhs < lhs); |
5896 | } |
5897 | |
5898 | /*! |
5899 | @brief comparison: less than or equal |
5900 | @copydoc operator<=(const_reference, const_reference) |
5901 | */ |
5902 | template<typename ScalarType, typename std::enable_if< |
5903 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5904 | friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept |
5905 | { |
5906 | return lhs <= basic_json(rhs); |
5907 | } |
5908 | |
5909 | /*! |
5910 | @brief comparison: less than or equal |
5911 | @copydoc operator<=(const_reference, const_reference) |
5912 | */ |
5913 | template<typename ScalarType, typename std::enable_if< |
5914 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5915 | friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept |
5916 | { |
5917 | return basic_json(lhs) <= rhs; |
5918 | } |
5919 | |
5920 | /*! |
5921 | @brief comparison: greater than |
5922 | |
5923 | Compares whether one JSON value @a lhs is greater than another |
5924 | JSON value by calculating `not (lhs <= rhs)`. |
5925 | |
5926 | @param[in] lhs first JSON value to consider |
5927 | @param[in] rhs second JSON value to consider |
5928 | @return whether @a lhs is greater than to @a rhs |
5929 | |
5930 | @complexity Linear. |
5931 | |
5932 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
5933 | |
5934 | @liveexample{The example demonstrates comparing several JSON |
5935 | types.,operator__lessequal} |
5936 | |
5937 | @since version 1.0.0 |
5938 | */ |
5939 | friend bool operator>(const_reference lhs, const_reference rhs) noexcept |
5940 | { |
5941 | return not (lhs <= rhs); |
5942 | } |
5943 | |
5944 | /*! |
5945 | @brief comparison: greater than |
5946 | @copydoc operator>(const_reference, const_reference) |
5947 | */ |
5948 | template<typename ScalarType, typename std::enable_if< |
5949 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5950 | friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept |
5951 | { |
5952 | return lhs > basic_json(rhs); |
5953 | } |
5954 | |
5955 | /*! |
5956 | @brief comparison: greater than |
5957 | @copydoc operator>(const_reference, const_reference) |
5958 | */ |
5959 | template<typename ScalarType, typename std::enable_if< |
5960 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5961 | friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept |
5962 | { |
5963 | return basic_json(lhs) > rhs; |
5964 | } |
5965 | |
5966 | /*! |
5967 | @brief comparison: greater than or equal |
5968 | |
5969 | Compares whether one JSON value @a lhs is greater than or equal to another |
5970 | JSON value by calculating `not (lhs < rhs)`. |
5971 | |
5972 | @param[in] lhs first JSON value to consider |
5973 | @param[in] rhs second JSON value to consider |
5974 | @return whether @a lhs is greater than or equal to @a rhs |
5975 | |
5976 | @complexity Linear. |
5977 | |
5978 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
5979 | |
5980 | @liveexample{The example demonstrates comparing several JSON |
5981 | types.,operator__greaterequal} |
5982 | |
5983 | @since version 1.0.0 |
5984 | */ |
5985 | friend bool operator>=(const_reference lhs, const_reference rhs) noexcept |
5986 | { |
5987 | return not (lhs < rhs); |
5988 | } |
5989 | |
5990 | /*! |
5991 | @brief comparison: greater than or equal |
5992 | @copydoc operator>=(const_reference, const_reference) |
5993 | */ |
5994 | template<typename ScalarType, typename std::enable_if< |
5995 | std::is_scalar<ScalarType>::value, int>::type = 0> |
5996 | friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept |
5997 | { |
5998 | return lhs >= basic_json(rhs); |
5999 | } |
6000 | |
6001 | /*! |
6002 | @brief comparison: greater than or equal |
6003 | @copydoc operator>=(const_reference, const_reference) |
6004 | */ |
6005 | template<typename ScalarType, typename std::enable_if< |
6006 | std::is_scalar<ScalarType>::value, int>::type = 0> |
6007 | friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept |
6008 | { |
6009 | return basic_json(lhs) >= rhs; |
6010 | } |
6011 | |
6012 | /// @} |
6013 | |
6014 | /////////////////// |
6015 | // serialization // |
6016 | /////////////////// |
6017 | |
6018 | /// @name serialization |
6019 | /// @{ |
6020 | |
6021 | /*! |
6022 | @brief serialize to stream |
6023 | |
6024 | Serialize the given JSON value @a j to the output stream @a o. The JSON |
6025 | value will be serialized using the @ref dump member function. |
6026 | |
6027 | - The indentation of the output can be controlled with the member variable |
6028 | `width` of the output stream @a o. For instance, using the manipulator |
6029 | `std::setw(4)` on @a o sets the indentation level to `4` and the |
6030 | serialization result is the same as calling `dump(4)`. |
6031 | |
6032 | - The indentation character can be controlled with the member variable |
6033 | `fill` of the output stream @a o. For instance, the manipulator |
6034 | `std::setfill('\\t')` sets indentation to use a tab character rather than |
6035 | the default space character. |
6036 | |
6037 | @param[in,out] o stream to serialize to |
6038 | @param[in] j JSON value to serialize |
6039 | |
6040 | @return the stream @a o |
6041 | |
6042 | @throw type_error.316 if a string stored inside the JSON value is not |
6043 | UTF-8 encoded |
6044 | |
6045 | @complexity Linear. |
6046 | |
6047 | @liveexample{The example below shows the serialization with different |
6048 | parameters to `width` to adjust the indentation level.,operator_serialize} |
6049 | |
6050 | @since version 1.0.0; indentation character added in version 3.0.0 |
6051 | */ |
6052 | friend std::ostream& operator<<(std::ostream& o, const basic_json& j) |
6053 | { |
6054 | // read width member and use it as indentation parameter if nonzero |
6055 | const bool pretty_print = o.width() > 0; |
6056 | const auto indentation = pretty_print ? o.width() : 0; |
6057 | |
6058 | // reset width to 0 for subsequent calls to this stream |
6059 | o.width(0); |
6060 | |
6061 | // do the actual serialization |
6062 | serializer s(detail::output_adapter<char>(o), o.fill()); |
6063 | s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); |
6064 | return o; |
6065 | } |
6066 | |
6067 | /*! |
6068 | @brief serialize to stream |
6069 | @deprecated This stream operator is deprecated and will be removed in |
6070 | future 4.0.0 of the library. Please use |
6071 | @ref operator<<(std::ostream&, const basic_json&) |
6072 | instead; that is, replace calls like `j >> o;` with `o << j;`. |
6073 | @since version 1.0.0; deprecated since version 3.0.0 |
6074 | */ |
6075 | JSON_HEDLEY_DEPRECATED(3.0.0) |
6076 | friend std::ostream& operator>>(const basic_json& j, std::ostream& o) |
6077 | { |
6078 | return o << j; |
6079 | } |
6080 | |
6081 | /// @} |
6082 | |
6083 | |
6084 | ///////////////////// |
6085 | // deserialization // |
6086 | ///////////////////// |
6087 | |
6088 | /// @name deserialization |
6089 | /// @{ |
6090 | |
6091 | /*! |
6092 | @brief deserialize from a compatible input |
6093 | |
6094 | This function reads from a compatible input. Examples are: |
6095 | - an array of 1-byte values |
6096 | - strings with character/literal type with size of 1 byte |
6097 | - input streams |
6098 | - container with contiguous storage of 1-byte values. Compatible container |
6099 | types include `std::vector`, `std::string`, `std::array`, |
6100 | `std::valarray`, and `std::initializer_list`. Furthermore, C-style |
6101 | arrays can be used with `std::begin()`/`std::end()`. User-defined |
6102 | containers can be used as long as they implement random-access iterators |
6103 | and a contiguous storage. |
6104 | |
6105 | @pre Each element of the container has a size of 1 byte. Violating this |
6106 | precondition yields undefined behavior. **This precondition is enforced |
6107 | with a static assertion.** |
6108 | |
6109 | @pre The container storage is contiguous. Violating this precondition |
6110 | yields undefined behavior. **This precondition is enforced with an |
6111 | assertion.** |
6112 | |
6113 | @warning There is no way to enforce all preconditions at compile-time. If |
6114 | the function is called with a noncompliant container and with |
6115 | assertions switched off, the behavior is undefined and will most |
6116 | likely yield segmentation violation. |
6117 | |
6118 | @param[in] i input to read from |
6119 | @param[in] cb a parser callback function of type @ref parser_callback_t |
6120 | which is used to control the deserialization by filtering unwanted values |
6121 | (optional) |
6122 | @param[in] allow_exceptions whether to throw exceptions in case of a |
6123 | parse error (optional, true by default) |
6124 | |
6125 | @return deserialized JSON value; in case of a parse error and |
6126 | @a allow_exceptions set to `false`, the return value will be |
6127 | value_t::discarded. |
6128 | |
6129 | @throw parse_error.101 if a parse error occurs; example: `""unexpected end |
6130 | of input; expected string literal""` |
6131 | @throw parse_error.102 if to_unicode fails or surrogate error |
6132 | @throw parse_error.103 if to_unicode fails |
6133 | |
6134 | @complexity Linear in the length of the input. The parser is a predictive |
6135 | LL(1) parser. The complexity can be higher if the parser callback function |
6136 | @a cb has a super-linear complexity. |
6137 | |
6138 | @note A UTF-8 byte order mark is silently ignored. |
6139 | |
6140 | @liveexample{The example below demonstrates the `parse()` function reading |
6141 | from an array.,parse__array__parser_callback_t} |
6142 | |
6143 | @liveexample{The example below demonstrates the `parse()` function with |
6144 | and without callback function.,parse__string__parser_callback_t} |
6145 | |
6146 | @liveexample{The example below demonstrates the `parse()` function with |
6147 | and without callback function.,parse__istream__parser_callback_t} |
6148 | |
6149 | @liveexample{The example below demonstrates the `parse()` function reading |
6150 | from a contiguous container.,parse__contiguouscontainer__parser_callback_t} |
6151 | |
6152 | @since version 2.0.3 (contiguous containers) |
6153 | */ |
6154 | JSON_HEDLEY_WARN_UNUSED_RESULT |
6155 | static basic_json parse(detail::input_adapter&& i, |
6156 | const parser_callback_t cb = nullptr, |
6157 | const bool allow_exceptions = true) |
6158 | { |
6159 | basic_json result; |
6160 | parser(i, cb, allow_exceptions).parse(true, result); |
6161 | return result; |
6162 | } |
6163 | |
6164 | static bool accept(detail::input_adapter&& i) |
6165 | { |
6166 | return parser(i).accept(true); |
6167 | } |
6168 | |
6169 | /*! |
6170 | @brief generate SAX events |
6171 | |
6172 | The SAX event lister must follow the interface of @ref json_sax. |
6173 | |
6174 | This function reads from a compatible input. Examples are: |
6175 | - an array of 1-byte values |
6176 | - strings with character/literal type with size of 1 byte |
6177 | - input streams |
6178 | - container with contiguous storage of 1-byte values. Compatible container |
6179 | types include `std::vector`, `std::string`, `std::array`, |
6180 | `std::valarray`, and `std::initializer_list`. Furthermore, C-style |
6181 | arrays can be used with `std::begin()`/`std::end()`. User-defined |
6182 | containers can be used as long as they implement random-access iterators |
6183 | and a contiguous storage. |
6184 | |
6185 | @pre Each element of the container has a size of 1 byte. Violating this |
6186 | precondition yields undefined behavior. **This precondition is enforced |
6187 | with a static assertion.** |
6188 | |
6189 | @pre The container storage is contiguous. Violating this precondition |
6190 | yields undefined behavior. **This precondition is enforced with an |
6191 | assertion.** |
6192 | |
6193 | @warning There is no way to enforce all preconditions at compile-time. If |
6194 | the function is called with a noncompliant container and with |
6195 | assertions switched off, the behavior is undefined and will most |
6196 | likely yield segmentation violation. |
6197 | |
6198 | @param[in] i input to read from |
6199 | @param[in,out] sax SAX event listener |
6200 | @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON) |
6201 | @param[in] strict whether the input has to be consumed completely |
6202 | |
6203 | @return return value of the last processed SAX event |
6204 | |
6205 | @throw parse_error.101 if a parse error occurs; example: `""unexpected end |
6206 | of input; expected string literal""` |
6207 | @throw parse_error.102 if to_unicode fails or surrogate error |
6208 | @throw parse_error.103 if to_unicode fails |
6209 | |
6210 | @complexity Linear in the length of the input. The parser is a predictive |
6211 | LL(1) parser. The complexity can be higher if the SAX consumer @a sax has |
6212 | a super-linear complexity. |
6213 | |
6214 | @note A UTF-8 byte order mark is silently ignored. |
6215 | |
6216 | @liveexample{The example below demonstrates the `sax_parse()` function |
6217 | reading from string and processing the events with a user-defined SAX |
6218 | event consumer.,sax_parse} |
6219 | |
6220 | @since version 3.2.0 |
6221 | */ |
6222 | template <typename SAX> |
6223 | JSON_HEDLEY_NON_NULL(2) |
6224 | static bool sax_parse(detail::input_adapter&& i, SAX* sax, |
6225 | input_format_t format = input_format_t::json, |
6226 | const bool strict = true) |
6227 | { |
6228 | assert(sax); |
6229 | return format == input_format_t::json |
6230 | ? parser(std::move(i)).sax_parse(sax, strict) |
6231 | : detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict); |
6232 | } |
6233 | |
6234 | /*! |
6235 | @brief deserialize from an iterator range with contiguous storage |
6236 | |
6237 | This function reads from an iterator range of a container with contiguous |
6238 | storage of 1-byte values. Compatible container types include |
6239 | `std::vector`, `std::string`, `std::array`, `std::valarray`, and |
6240 | `std::initializer_list`. Furthermore, C-style arrays can be used with |
6241 | `std::begin()`/`std::end()`. User-defined containers can be used as long |
6242 | as they implement random-access iterators and a contiguous storage. |
6243 | |
6244 | @pre The iterator range is contiguous. Violating this precondition yields |
6245 | undefined behavior. **This precondition is enforced with an assertion.** |
6246 | @pre Each element in the range has a size of 1 byte. Violating this |
6247 | precondition yields undefined behavior. **This precondition is enforced |
6248 | with a static assertion.** |
6249 | |
6250 | @warning There is no way to enforce all preconditions at compile-time. If |
6251 | the function is called with noncompliant iterators and with |
6252 | assertions switched off, the behavior is undefined and will most |
6253 | likely yield segmentation violation. |
6254 | |
6255 | @tparam IteratorType iterator of container with contiguous storage |
6256 | @param[in] first begin of the range to parse (included) |
6257 | @param[in] last end of the range to parse (excluded) |
6258 | @param[in] cb a parser callback function of type @ref parser_callback_t |
6259 | which is used to control the deserialization by filtering unwanted values |
6260 | (optional) |
6261 | @param[in] allow_exceptions whether to throw exceptions in case of a |
6262 | parse error (optional, true by default) |
6263 | |
6264 | @return deserialized JSON value; in case of a parse error and |
6265 | @a allow_exceptions set to `false`, the return value will be |
6266 | value_t::discarded. |
6267 | |
6268 | @throw parse_error.101 in case of an unexpected token |
6269 | @throw parse_error.102 if to_unicode fails or surrogate error |
6270 | @throw parse_error.103 if to_unicode fails |
6271 | |
6272 | @complexity Linear in the length of the input. The parser is a predictive |
6273 | LL(1) parser. The complexity can be higher if the parser callback function |
6274 | @a cb has a super-linear complexity. |
6275 | |
6276 | @note A UTF-8 byte order mark is silently ignored. |
6277 | |
6278 | @liveexample{The example below demonstrates the `parse()` function reading |
6279 | from an iterator range.,parse__iteratortype__parser_callback_t} |
6280 | |
6281 | @since version 2.0.3 |
6282 | */ |
6283 | template<class IteratorType, typename std::enable_if< |
6284 | std::is_base_of< |
6285 | std::random_access_iterator_tag, |
6286 | typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0> |
6287 | static basic_json parse(IteratorType first, IteratorType last, |
6288 | const parser_callback_t cb = nullptr, |
6289 | const bool allow_exceptions = true) |
6290 | { |
6291 | basic_json result; |
6292 | parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result); |
6293 | return result; |
6294 | } |
6295 | |
6296 | template<class IteratorType, typename std::enable_if< |
6297 | std::is_base_of< |
6298 | std::random_access_iterator_tag, |
6299 | typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0> |
6300 | static bool accept(IteratorType first, IteratorType last) |
6301 | { |
6302 | return parser(detail::input_adapter(first, last)).accept(true); |
6303 | } |
6304 | |
6305 | template<class IteratorType, class SAX, typename std::enable_if< |
6306 | std::is_base_of< |
6307 | std::random_access_iterator_tag, |
6308 | typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0> |
6309 | JSON_HEDLEY_NON_NULL(3) |
6310 | static bool sax_parse(IteratorType first, IteratorType last, SAX* sax) |
6311 | { |
6312 | return parser(detail::input_adapter(first, last)).sax_parse(sax); |
6313 | } |
6314 | |
6315 | /*! |
6316 | @brief deserialize from stream |
6317 | @deprecated This stream operator is deprecated and will be removed in |
6318 | version 4.0.0 of the library. Please use |
6319 | @ref operator>>(std::istream&, basic_json&) |
6320 | instead; that is, replace calls like `j << i;` with `i >> j;`. |
6321 | @since version 1.0.0; deprecated since version 3.0.0 |
6322 | */ |
6323 | JSON_HEDLEY_DEPRECATED(3.0.0) |
6324 | friend std::istream& operator<<(basic_json& j, std::istream& i) |
6325 | { |
6326 | return operator>>(i, j); |
6327 | } |
6328 | |
6329 | /*! |
6330 | @brief deserialize from stream |
6331 | |
6332 | Deserializes an input stream to a JSON value. |
6333 | |
6334 | @param[in,out] i input stream to read a serialized JSON value from |
6335 | @param[in,out] j JSON value to write the deserialized input to |
6336 | |
6337 | @throw parse_error.101 in case of an unexpected token |
6338 | @throw parse_error.102 if to_unicode fails or surrogate error |
6339 | @throw parse_error.103 if to_unicode fails |
6340 | |
6341 | @complexity Linear in the length of the input. The parser is a predictive |
6342 | LL(1) parser. |
6343 | |
6344 | @note A UTF-8 byte order mark is silently ignored. |
6345 | |
6346 | @liveexample{The example below shows how a JSON value is constructed by |
6347 | reading a serialization from a stream.,operator_deserialize} |
6348 | |
6349 | @sa parse(std::istream&, const parser_callback_t) for a variant with a |
6350 | parser callback function to filter values while parsing |
6351 | |
6352 | @since version 1.0.0 |
6353 | */ |
6354 | friend std::istream& operator>>(std::istream& i, basic_json& j) |
6355 | { |
6356 | parser(detail::input_adapter(i)).parse(false, j); |
6357 | return i; |
6358 | } |
6359 | |
6360 | /// @} |
6361 | |
6362 | /////////////////////////// |
6363 | // convenience functions // |
6364 | /////////////////////////// |
6365 | |
6366 | /*! |
6367 | @brief return the type as string |
6368 | |
6369 | Returns the type name as string to be used in error messages - usually to |
6370 | indicate that a function was called on a wrong JSON type. |
6371 | |
6372 | @return a string representation of a the @a m_type member: |
6373 | Value type | return value |
6374 | ----------- | ------------- |
6375 | null | `"null"` |
6376 | boolean | `"boolean"` |
6377 | string | `"string"` |
6378 | number | `"number"` (for all number types) |
6379 | object | `"object"` |
6380 | array | `"array"` |
6381 | discarded | `"discarded"` |
6382 | |
6383 | @exceptionsafety No-throw guarantee: this function never throws exceptions. |
6384 | |
6385 | @complexity Constant. |
6386 | |
6387 | @liveexample{The following code exemplifies `type_name()` for all JSON |
6388 | types.,type_name} |
6389 | |
6390 | @sa @ref type() -- return the type of the JSON value |
6391 | @sa @ref operator value_t() -- return the type of the JSON value (implicit) |
6392 | |
6393 | @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` |
6394 | since 3.0.0 |
6395 | */ |
6396 | JSON_HEDLEY_RETURNS_NON_NULL |
6397 | const char* type_name() const noexcept |
6398 | { |
6399 | { |
6400 | switch (m_type) |
6401 | { |
6402 | case value_t::null: |
6403 | return "null" ; |
6404 | case value_t::object: |
6405 | return "object" ; |
6406 | case value_t::array: |
6407 | return "array" ; |
6408 | case value_t::string: |
6409 | return "string" ; |
6410 | case value_t::boolean: |
6411 | return "boolean" ; |
6412 | case value_t::discarded: |
6413 | return "discarded" ; |
6414 | default: |
6415 | return "number" ; |
6416 | } |
6417 | } |
6418 | } |
6419 | |
6420 | |
6421 | private: |
6422 | ////////////////////// |
6423 | // member variables // |
6424 | ////////////////////// |
6425 | |
6426 | /// the type of the current element |
6427 | value_t m_type = value_t::null; |
6428 | |
6429 | /// the value of the current element |
6430 | json_value m_value = {}; |
6431 | |
6432 | ////////////////////////////////////////// |
6433 | // binary serialization/deserialization // |
6434 | ////////////////////////////////////////// |
6435 | |
6436 | /// @name binary serialization/deserialization support |
6437 | /// @{ |
6438 | |
6439 | public: |
6440 | /*! |
6441 | @brief create a CBOR serialization of a given JSON value |
6442 | |
6443 | Serializes a given JSON value @a j to a byte vector using the CBOR (Concise |
6444 | Binary Object Representation) serialization format. CBOR is a binary |
6445 | serialization format which aims to be more compact than JSON itself, yet |
6446 | more efficient to parse. |
6447 | |
6448 | The library uses the following mapping from JSON values types to |
6449 | CBOR types according to the CBOR specification (RFC 7049): |
6450 | |
6451 | JSON value type | value/range | CBOR type | first byte |
6452 | --------------- | ------------------------------------------ | ---------------------------------- | --------------- |
6453 | null | `null` | Null | 0xF6 |
6454 | boolean | `true` | True | 0xF5 |
6455 | boolean | `false` | False | 0xF4 |
6456 | number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B |
6457 | number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A |
6458 | number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 |
6459 | number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 |
6460 | number_integer | -24..-1 | Negative integer | 0x20..0x37 |
6461 | number_integer | 0..23 | Integer | 0x00..0x17 |
6462 | number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 |
6463 | number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 |
6464 | number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A |
6465 | number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B |
6466 | number_unsigned | 0..23 | Integer | 0x00..0x17 |
6467 | number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 |
6468 | number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 |
6469 | number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A |
6470 | number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B |
6471 | number_float | *any value* | Double-Precision Float | 0xFB |
6472 | string | *length*: 0..23 | UTF-8 string | 0x60..0x77 |
6473 | string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 |
6474 | string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 |
6475 | string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A |
6476 | string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B |
6477 | array | *size*: 0..23 | array | 0x80..0x97 |
6478 | array | *size*: 23..255 | array (1 byte follow) | 0x98 |
6479 | array | *size*: 256..65535 | array (2 bytes follow) | 0x99 |
6480 | array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A |
6481 | array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B |
6482 | object | *size*: 0..23 | map | 0xA0..0xB7 |
6483 | object | *size*: 23..255 | map (1 byte follow) | 0xB8 |
6484 | object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 |
6485 | object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA |
6486 | object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB |
6487 | |
6488 | @note The mapping is **complete** in the sense that any JSON value type |
6489 | can be converted to a CBOR value. |
6490 | |
6491 | @note If NaN or Infinity are stored inside a JSON number, they are |
6492 | serialized properly. This behavior differs from the @ref dump() |
6493 | function which serializes NaN or Infinity to `null`. |
6494 | |
6495 | @note The following CBOR types are not used in the conversion: |
6496 | - byte strings (0x40..0x5F) |
6497 | - UTF-8 strings terminated by "break" (0x7F) |
6498 | - arrays terminated by "break" (0x9F) |
6499 | - maps terminated by "break" (0xBF) |
6500 | - date/time (0xC0..0xC1) |
6501 | - bignum (0xC2..0xC3) |
6502 | - decimal fraction (0xC4) |
6503 | - bigfloat (0xC5) |
6504 | - tagged items (0xC6..0xD4, 0xD8..0xDB) |
6505 | - expected conversions (0xD5..0xD7) |
6506 | - simple values (0xE0..0xF3, 0xF8) |
6507 | - undefined (0xF7) |
6508 | - half and single-precision floats (0xF9-0xFA) |
6509 | - break (0xFF) |
6510 | |
6511 | @param[in] j JSON value to serialize |
6512 | @return MessagePack serialization as byte vector |
6513 | |
6514 | @complexity Linear in the size of the JSON value @a j. |
6515 | |
6516 | @liveexample{The example shows the serialization of a JSON value to a byte |
6517 | vector in CBOR format.,to_cbor} |
6518 | |
6519 | @sa http://cbor.io |
6520 | @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the |
6521 | analogous deserialization |
6522 | @sa @ref to_msgpack(const basic_json&) for the related MessagePack format |
6523 | @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the |
6524 | related UBJSON format |
6525 | |
6526 | @since version 2.0.9 |
6527 | */ |
6528 | static std::vector<uint8_t> to_cbor(const basic_json& j) |
6529 | { |
6530 | std::vector<uint8_t> result; |
6531 | to_cbor(j, result); |
6532 | return result; |
6533 | } |
6534 | |
6535 | static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o) |
6536 | { |
6537 | binary_writer<uint8_t>(o).write_cbor(j); |
6538 | } |
6539 | |
6540 | static void to_cbor(const basic_json& j, detail::output_adapter<char> o) |
6541 | { |
6542 | binary_writer<char>(o).write_cbor(j); |
6543 | } |
6544 | |
6545 | /*! |
6546 | @brief create a MessagePack serialization of a given JSON value |
6547 | |
6548 | Serializes a given JSON value @a j to a byte vector using the MessagePack |
6549 | serialization format. MessagePack is a binary serialization format which |
6550 | aims to be more compact than JSON itself, yet more efficient to parse. |
6551 | |
6552 | The library uses the following mapping from JSON values types to |
6553 | MessagePack types according to the MessagePack specification: |
6554 | |
6555 | JSON value type | value/range | MessagePack type | first byte |
6556 | --------------- | --------------------------------- | ---------------- | ---------- |
6557 | null | `null` | nil | 0xC0 |
6558 | boolean | `true` | true | 0xC3 |
6559 | boolean | `false` | false | 0xC2 |
6560 | number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 |
6561 | number_integer | -2147483648..-32769 | int32 | 0xD2 |
6562 | number_integer | -32768..-129 | int16 | 0xD1 |
6563 | number_integer | -128..-33 | int8 | 0xD0 |
6564 | number_integer | -32..-1 | negative fixint | 0xE0..0xFF |
6565 | number_integer | 0..127 | positive fixint | 0x00..0x7F |
6566 | number_integer | 128..255 | uint 8 | 0xCC |
6567 | number_integer | 256..65535 | uint 16 | 0xCD |
6568 | number_integer | 65536..4294967295 | uint 32 | 0xCE |
6569 | number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF |
6570 | number_unsigned | 0..127 | positive fixint | 0x00..0x7F |
6571 | number_unsigned | 128..255 | uint 8 | 0xCC |
6572 | number_unsigned | 256..65535 | uint 16 | 0xCD |
6573 | number_unsigned | 65536..4294967295 | uint 32 | 0xCE |
6574 | number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF |
6575 | number_float | *any value* | float 64 | 0xCB |
6576 | string | *length*: 0..31 | fixstr | 0xA0..0xBF |
6577 | string | *length*: 32..255 | str 8 | 0xD9 |
6578 | string | *length*: 256..65535 | str 16 | 0xDA |
6579 | string | *length*: 65536..4294967295 | str 32 | 0xDB |
6580 | array | *size*: 0..15 | fixarray | 0x90..0x9F |
6581 | array | *size*: 16..65535 | array 16 | 0xDC |
6582 | array | *size*: 65536..4294967295 | array 32 | 0xDD |
6583 | object | *size*: 0..15 | fix map | 0x80..0x8F |
6584 | object | *size*: 16..65535 | map 16 | 0xDE |
6585 | object | *size*: 65536..4294967295 | map 32 | 0xDF |
6586 | |
6587 | @note The mapping is **complete** in the sense that any JSON value type |
6588 | can be converted to a MessagePack value. |
6589 | |
6590 | @note The following values can **not** be converted to a MessagePack value: |
6591 | - strings with more than 4294967295 bytes |
6592 | - arrays with more than 4294967295 elements |
6593 | - objects with more than 4294967295 elements |
6594 | |
6595 | @note The following MessagePack types are not used in the conversion: |
6596 | - bin 8 - bin 32 (0xC4..0xC6) |
6597 | - ext 8 - ext 32 (0xC7..0xC9) |
6598 | - float 32 (0xCA) |
6599 | - fixext 1 - fixext 16 (0xD4..0xD8) |
6600 | |
6601 | @note Any MessagePack output created @ref to_msgpack can be successfully |
6602 | parsed by @ref from_msgpack. |
6603 | |
6604 | @note If NaN or Infinity are stored inside a JSON number, they are |
6605 | serialized properly. This behavior differs from the @ref dump() |
6606 | function which serializes NaN or Infinity to `null`. |
6607 | |
6608 | @param[in] j JSON value to serialize |
6609 | @return MessagePack serialization as byte vector |
6610 | |
6611 | @complexity Linear in the size of the JSON value @a j. |
6612 | |
6613 | @liveexample{The example shows the serialization of a JSON value to a byte |
6614 | vector in MessagePack format.,to_msgpack} |
6615 | |
6616 | @sa http://msgpack.org |
6617 | @sa @ref from_msgpack for the analogous deserialization |
6618 | @sa @ref to_cbor(const basic_json& for the related CBOR format |
6619 | @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the |
6620 | related UBJSON format |
6621 | |
6622 | @since version 2.0.9 |
6623 | */ |
6624 | static std::vector<uint8_t> to_msgpack(const basic_json& j) |
6625 | { |
6626 | std::vector<uint8_t> result; |
6627 | to_msgpack(j, result); |
6628 | return result; |
6629 | } |
6630 | |
6631 | static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o) |
6632 | { |
6633 | binary_writer<uint8_t>(o).write_msgpack(j); |
6634 | } |
6635 | |
6636 | static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) |
6637 | { |
6638 | binary_writer<char>(o).write_msgpack(j); |
6639 | } |
6640 | |
6641 | /*! |
6642 | @brief create a UBJSON serialization of a given JSON value |
6643 | |
6644 | Serializes a given JSON value @a j to a byte vector using the UBJSON |
6645 | (Universal Binary JSON) serialization format. UBJSON aims to be more compact |
6646 | than JSON itself, yet more efficient to parse. |
6647 | |
6648 | The library uses the following mapping from JSON values types to |
6649 | UBJSON types according to the UBJSON specification: |
6650 | |
6651 | JSON value type | value/range | UBJSON type | marker |
6652 | --------------- | --------------------------------- | ----------- | ------ |
6653 | null | `null` | null | `Z` |
6654 | boolean | `true` | true | `T` |
6655 | boolean | `false` | false | `F` |
6656 | number_integer | -9223372036854775808..-2147483649 | int64 | `L` |
6657 | number_integer | -2147483648..-32769 | int32 | `l` |
6658 | number_integer | -32768..-129 | int16 | `I` |
6659 | number_integer | -128..127 | int8 | `i` |
6660 | number_integer | 128..255 | uint8 | `U` |
6661 | number_integer | 256..32767 | int16 | `I` |
6662 | number_integer | 32768..2147483647 | int32 | `l` |
6663 | number_integer | 2147483648..9223372036854775807 | int64 | `L` |
6664 | number_unsigned | 0..127 | int8 | `i` |
6665 | number_unsigned | 128..255 | uint8 | `U` |
6666 | number_unsigned | 256..32767 | int16 | `I` |
6667 | number_unsigned | 32768..2147483647 | int32 | `l` |
6668 | number_unsigned | 2147483648..9223372036854775807 | int64 | `L` |
6669 | number_float | *any value* | float64 | `D` |
6670 | string | *with shortest length indicator* | string | `S` |
6671 | array | *see notes on optimized format* | array | `[` |
6672 | object | *see notes on optimized format* | map | `{` |
6673 | |
6674 | @note The mapping is **complete** in the sense that any JSON value type |
6675 | can be converted to a UBJSON value. |
6676 | |
6677 | @note The following values can **not** be converted to a UBJSON value: |
6678 | - strings with more than 9223372036854775807 bytes (theoretical) |
6679 | - unsigned integer numbers above 9223372036854775807 |
6680 | |
6681 | @note The following markers are not used in the conversion: |
6682 | - `Z`: no-op values are not created. |
6683 | - `C`: single-byte strings are serialized with `S` markers. |
6684 | |
6685 | @note Any UBJSON output created @ref to_ubjson can be successfully parsed |
6686 | by @ref from_ubjson. |
6687 | |
6688 | @note If NaN or Infinity are stored inside a JSON number, they are |
6689 | serialized properly. This behavior differs from the @ref dump() |
6690 | function which serializes NaN or Infinity to `null`. |
6691 | |
6692 | @note The optimized formats for containers are supported: Parameter |
6693 | @a use_size adds size information to the beginning of a container and |
6694 | removes the closing marker. Parameter @a use_type further checks |
6695 | whether all elements of a container have the same type and adds the |
6696 | type marker to the beginning of the container. The @a use_type |
6697 | parameter must only be used together with @a use_size = true. Note |
6698 | that @a use_size = true alone may result in larger representations - |
6699 | the benefit of this parameter is that the receiving side is |
6700 | immediately informed on the number of elements of the container. |
6701 | |
6702 | @param[in] j JSON value to serialize |
6703 | @param[in] use_size whether to add size annotations to container types |
6704 | @param[in] use_type whether to add type annotations to container types |
6705 | (must be combined with @a use_size = true) |
6706 | @return UBJSON serialization as byte vector |
6707 | |
6708 | @complexity Linear in the size of the JSON value @a j. |
6709 | |
6710 | @liveexample{The example shows the serialization of a JSON value to a byte |
6711 | vector in UBJSON format.,to_ubjson} |
6712 | |
6713 | @sa http://ubjson.org |
6714 | @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the |
6715 | analogous deserialization |
6716 | @sa @ref to_cbor(const basic_json& for the related CBOR format |
6717 | @sa @ref to_msgpack(const basic_json&) for the related MessagePack format |
6718 | |
6719 | @since version 3.1.0 |
6720 | */ |
6721 | static std::vector<uint8_t> to_ubjson(const basic_json& j, |
6722 | const bool use_size = false, |
6723 | const bool use_type = false) |
6724 | { |
6725 | std::vector<uint8_t> result; |
6726 | to_ubjson(j, result, use_size, use_type); |
6727 | return result; |
6728 | } |
6729 | |
6730 | static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o, |
6731 | const bool use_size = false, const bool use_type = false) |
6732 | { |
6733 | binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type); |
6734 | } |
6735 | |
6736 | static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, |
6737 | const bool use_size = false, const bool use_type = false) |
6738 | { |
6739 | binary_writer<char>(o).write_ubjson(j, use_size, use_type); |
6740 | } |
6741 | |
6742 | |
6743 | /*! |
6744 | @brief Serializes the given JSON object `j` to BSON and returns a vector |
6745 | containing the corresponding BSON-representation. |
6746 | |
6747 | BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are |
6748 | stored as a single entity (a so-called document). |
6749 | |
6750 | The library uses the following mapping from JSON values types to BSON types: |
6751 | |
6752 | JSON value type | value/range | BSON type | marker |
6753 | --------------- | --------------------------------- | ----------- | ------ |
6754 | null | `null` | null | 0x0A |
6755 | boolean | `true`, `false` | boolean | 0x08 |
6756 | number_integer | -9223372036854775808..-2147483649 | int64 | 0x12 |
6757 | number_integer | -2147483648..2147483647 | int32 | 0x10 |
6758 | number_integer | 2147483648..9223372036854775807 | int64 | 0x12 |
6759 | number_unsigned | 0..2147483647 | int32 | 0x10 |
6760 | number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12 |
6761 | number_unsigned | 9223372036854775808..18446744073709551615| -- | -- |
6762 | number_float | *any value* | double | 0x01 |
6763 | string | *any value* | string | 0x02 |
6764 | array | *any value* | document | 0x04 |
6765 | object | *any value* | document | 0x03 |
6766 | |
6767 | @warning The mapping is **incomplete**, since only JSON-objects (and things |
6768 | contained therein) can be serialized to BSON. |
6769 | Also, integers larger than 9223372036854775807 cannot be serialized to BSON, |
6770 | and the keys may not contain U+0000, since they are serialized a |
6771 | zero-terminated c-strings. |
6772 | |
6773 | @throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807` |
6774 | @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) |
6775 | @throw type_error.317 if `!j.is_object()` |
6776 | |
6777 | @pre The input `j` is required to be an object: `j.is_object() == true`. |
6778 | |
6779 | @note Any BSON output created via @ref to_bson can be successfully parsed |
6780 | by @ref from_bson. |
6781 | |
6782 | @param[in] j JSON value to serialize |
6783 | @return BSON serialization as byte vector |
6784 | |
6785 | @complexity Linear in the size of the JSON value @a j. |
6786 | |
6787 | @liveexample{The example shows the serialization of a JSON value to a byte |
6788 | vector in BSON format.,to_bson} |
6789 | |
6790 | @sa http://bsonspec.org/spec.html |
6791 | @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the |
6792 | analogous deserialization |
6793 | @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the |
6794 | related UBJSON format |
6795 | @sa @ref to_cbor(const basic_json&) for the related CBOR format |
6796 | @sa @ref to_msgpack(const basic_json&) for the related MessagePack format |
6797 | */ |
6798 | static std::vector<uint8_t> to_bson(const basic_json& j) |
6799 | { |
6800 | std::vector<uint8_t> result; |
6801 | to_bson(j, result); |
6802 | return result; |
6803 | } |
6804 | |
6805 | /*! |
6806 | @brief Serializes the given JSON object `j` to BSON and forwards the |
6807 | corresponding BSON-representation to the given output_adapter `o`. |
6808 | @param j The JSON object to convert to BSON. |
6809 | @param o The output adapter that receives the binary BSON representation. |
6810 | @pre The input `j` shall be an object: `j.is_object() == true` |
6811 | @sa @ref to_bson(const basic_json&) |
6812 | */ |
6813 | static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o) |
6814 | { |
6815 | binary_writer<uint8_t>(o).write_bson(j); |
6816 | } |
6817 | |
6818 | /*! |
6819 | @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>) |
6820 | */ |
6821 | static void to_bson(const basic_json& j, detail::output_adapter<char> o) |
6822 | { |
6823 | binary_writer<char>(o).write_bson(j); |
6824 | } |
6825 | |
6826 | |
6827 | /*! |
6828 | @brief create a JSON value from an input in CBOR format |
6829 | |
6830 | Deserializes a given input @a i to a JSON value using the CBOR (Concise |
6831 | Binary Object Representation) serialization format. |
6832 | |
6833 | The library maps CBOR types to JSON value types as follows: |
6834 | |
6835 | CBOR type | JSON value type | first byte |
6836 | ---------------------- | --------------- | ---------- |
6837 | Integer | number_unsigned | 0x00..0x17 |
6838 | Unsigned integer | number_unsigned | 0x18 |
6839 | Unsigned integer | number_unsigned | 0x19 |
6840 | Unsigned integer | number_unsigned | 0x1A |
6841 | Unsigned integer | number_unsigned | 0x1B |
6842 | Negative integer | number_integer | 0x20..0x37 |
6843 | Negative integer | number_integer | 0x38 |
6844 | Negative integer | number_integer | 0x39 |
6845 | Negative integer | number_integer | 0x3A |
6846 | Negative integer | number_integer | 0x3B |
6847 | Negative integer | number_integer | 0x40..0x57 |
6848 | UTF-8 string | string | 0x60..0x77 |
6849 | UTF-8 string | string | 0x78 |
6850 | UTF-8 string | string | 0x79 |
6851 | UTF-8 string | string | 0x7A |
6852 | UTF-8 string | string | 0x7B |
6853 | UTF-8 string | string | 0x7F |
6854 | array | array | 0x80..0x97 |
6855 | array | array | 0x98 |
6856 | array | array | 0x99 |
6857 | array | array | 0x9A |
6858 | array | array | 0x9B |
6859 | array | array | 0x9F |
6860 | map | object | 0xA0..0xB7 |
6861 | map | object | 0xB8 |
6862 | map | object | 0xB9 |
6863 | map | object | 0xBA |
6864 | map | object | 0xBB |
6865 | map | object | 0xBF |
6866 | False | `false` | 0xF4 |
6867 | True | `true` | 0xF5 |
6868 | Null | `null` | 0xF6 |
6869 | Half-Precision Float | number_float | 0xF9 |
6870 | Single-Precision Float | number_float | 0xFA |
6871 | Double-Precision Float | number_float | 0xFB |
6872 | |
6873 | @warning The mapping is **incomplete** in the sense that not all CBOR |
6874 | types can be converted to a JSON value. The following CBOR types |
6875 | are not supported and will yield parse errors (parse_error.112): |
6876 | - byte strings (0x40..0x5F) |
6877 | - date/time (0xC0..0xC1) |
6878 | - bignum (0xC2..0xC3) |
6879 | - decimal fraction (0xC4) |
6880 | - bigfloat (0xC5) |
6881 | - tagged items (0xC6..0xD4, 0xD8..0xDB) |
6882 | - expected conversions (0xD5..0xD7) |
6883 | - simple values (0xE0..0xF3, 0xF8) |
6884 | - undefined (0xF7) |
6885 | |
6886 | @warning CBOR allows map keys of any type, whereas JSON only allows |
6887 | strings as keys in object values. Therefore, CBOR maps with keys |
6888 | other than UTF-8 strings are rejected (parse_error.113). |
6889 | |
6890 | @note Any CBOR output created @ref to_cbor can be successfully parsed by |
6891 | @ref from_cbor. |
6892 | |
6893 | @param[in] i an input in CBOR format convertible to an input adapter |
6894 | @param[in] strict whether to expect the input to be consumed until EOF |
6895 | (true by default) |
6896 | @param[in] allow_exceptions whether to throw exceptions in case of a |
6897 | parse error (optional, true by default) |
6898 | |
6899 | @return deserialized JSON value; in case of a parse error and |
6900 | @a allow_exceptions set to `false`, the return value will be |
6901 | value_t::discarded. |
6902 | |
6903 | @throw parse_error.110 if the given input ends prematurely or the end of |
6904 | file was not reached when @a strict was set to true |
6905 | @throw parse_error.112 if unsupported features from CBOR were |
6906 | used in the given input @a v or if the input is not valid CBOR |
6907 | @throw parse_error.113 if a string was expected as map key, but not found |
6908 | |
6909 | @complexity Linear in the size of the input @a i. |
6910 | |
6911 | @liveexample{The example shows the deserialization of a byte vector in CBOR |
6912 | format to a JSON value.,from_cbor} |
6913 | |
6914 | @sa http://cbor.io |
6915 | @sa @ref to_cbor(const basic_json&) for the analogous serialization |
6916 | @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the |
6917 | related MessagePack format |
6918 | @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the |
6919 | related UBJSON format |
6920 | |
6921 | @since version 2.0.9; parameter @a start_index since 2.1.1; changed to |
6922 | consume input adapters, removed start_index parameter, and added |
6923 | @a strict parameter since 3.0.0; added @a allow_exceptions parameter |
6924 | since 3.2.0 |
6925 | */ |
6926 | JSON_HEDLEY_WARN_UNUSED_RESULT |
6927 | static basic_json from_cbor(detail::input_adapter&& i, |
6928 | const bool strict = true, |
6929 | const bool allow_exceptions = true) |
6930 | { |
6931 | basic_json result; |
6932 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
6933 | const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict); |
6934 | return res ? result : basic_json(value_t::discarded); |
6935 | } |
6936 | |
6937 | /*! |
6938 | @copydoc from_cbor(detail::input_adapter&&, const bool, const bool) |
6939 | */ |
6940 | template<typename A1, typename A2, |
6941 | detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> |
6942 | JSON_HEDLEY_WARN_UNUSED_RESULT |
6943 | static basic_json from_cbor(A1 && a1, A2 && a2, |
6944 | const bool strict = true, |
6945 | const bool allow_exceptions = true) |
6946 | { |
6947 | basic_json result; |
6948 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
6949 | const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict); |
6950 | return res ? result : basic_json(value_t::discarded); |
6951 | } |
6952 | |
6953 | /*! |
6954 | @brief create a JSON value from an input in MessagePack format |
6955 | |
6956 | Deserializes a given input @a i to a JSON value using the MessagePack |
6957 | serialization format. |
6958 | |
6959 | The library maps MessagePack types to JSON value types as follows: |
6960 | |
6961 | MessagePack type | JSON value type | first byte |
6962 | ---------------- | --------------- | ---------- |
6963 | positive fixint | number_unsigned | 0x00..0x7F |
6964 | fixmap | object | 0x80..0x8F |
6965 | fixarray | array | 0x90..0x9F |
6966 | fixstr | string | 0xA0..0xBF |
6967 | nil | `null` | 0xC0 |
6968 | false | `false` | 0xC2 |
6969 | true | `true` | 0xC3 |
6970 | float 32 | number_float | 0xCA |
6971 | float 64 | number_float | 0xCB |
6972 | uint 8 | number_unsigned | 0xCC |
6973 | uint 16 | number_unsigned | 0xCD |
6974 | uint 32 | number_unsigned | 0xCE |
6975 | uint 64 | number_unsigned | 0xCF |
6976 | int 8 | number_integer | 0xD0 |
6977 | int 16 | number_integer | 0xD1 |
6978 | int 32 | number_integer | 0xD2 |
6979 | int 64 | number_integer | 0xD3 |
6980 | str 8 | string | 0xD9 |
6981 | str 16 | string | 0xDA |
6982 | str 32 | string | 0xDB |
6983 | array 16 | array | 0xDC |
6984 | array 32 | array | 0xDD |
6985 | map 16 | object | 0xDE |
6986 | map 32 | object | 0xDF |
6987 | negative fixint | number_integer | 0xE0-0xFF |
6988 | |
6989 | @warning The mapping is **incomplete** in the sense that not all |
6990 | MessagePack types can be converted to a JSON value. The following |
6991 | MessagePack types are not supported and will yield parse errors: |
6992 | - bin 8 - bin 32 (0xC4..0xC6) |
6993 | - ext 8 - ext 32 (0xC7..0xC9) |
6994 | - fixext 1 - fixext 16 (0xD4..0xD8) |
6995 | |
6996 | @note Any MessagePack output created @ref to_msgpack can be successfully |
6997 | parsed by @ref from_msgpack. |
6998 | |
6999 | @param[in] i an input in MessagePack format convertible to an input |
7000 | adapter |
7001 | @param[in] strict whether to expect the input to be consumed until EOF |
7002 | (true by default) |
7003 | @param[in] allow_exceptions whether to throw exceptions in case of a |
7004 | parse error (optional, true by default) |
7005 | |
7006 | @return deserialized JSON value; in case of a parse error and |
7007 | @a allow_exceptions set to `false`, the return value will be |
7008 | value_t::discarded. |
7009 | |
7010 | @throw parse_error.110 if the given input ends prematurely or the end of |
7011 | file was not reached when @a strict was set to true |
7012 | @throw parse_error.112 if unsupported features from MessagePack were |
7013 | used in the given input @a i or if the input is not valid MessagePack |
7014 | @throw parse_error.113 if a string was expected as map key, but not found |
7015 | |
7016 | @complexity Linear in the size of the input @a i. |
7017 | |
7018 | @liveexample{The example shows the deserialization of a byte vector in |
7019 | MessagePack format to a JSON value.,from_msgpack} |
7020 | |
7021 | @sa http://msgpack.org |
7022 | @sa @ref to_msgpack(const basic_json&) for the analogous serialization |
7023 | @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the |
7024 | related CBOR format |
7025 | @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for |
7026 | the related UBJSON format |
7027 | @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for |
7028 | the related BSON format |
7029 | |
7030 | @since version 2.0.9; parameter @a start_index since 2.1.1; changed to |
7031 | consume input adapters, removed start_index parameter, and added |
7032 | @a strict parameter since 3.0.0; added @a allow_exceptions parameter |
7033 | since 3.2.0 |
7034 | */ |
7035 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7036 | static basic_json from_msgpack(detail::input_adapter&& i, |
7037 | const bool strict = true, |
7038 | const bool allow_exceptions = true) |
7039 | { |
7040 | basic_json result; |
7041 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
7042 | const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict); |
7043 | return res ? result : basic_json(value_t::discarded); |
7044 | } |
7045 | |
7046 | /*! |
7047 | @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool) |
7048 | */ |
7049 | template<typename A1, typename A2, |
7050 | detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> |
7051 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7052 | static basic_json from_msgpack(A1 && a1, A2 && a2, |
7053 | const bool strict = true, |
7054 | const bool allow_exceptions = true) |
7055 | { |
7056 | basic_json result; |
7057 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
7058 | const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict); |
7059 | return res ? result : basic_json(value_t::discarded); |
7060 | } |
7061 | |
7062 | /*! |
7063 | @brief create a JSON value from an input in UBJSON format |
7064 | |
7065 | Deserializes a given input @a i to a JSON value using the UBJSON (Universal |
7066 | Binary JSON) serialization format. |
7067 | |
7068 | The library maps UBJSON types to JSON value types as follows: |
7069 | |
7070 | UBJSON type | JSON value type | marker |
7071 | ----------- | --------------------------------------- | ------ |
7072 | no-op | *no value, next value is read* | `N` |
7073 | null | `null` | `Z` |
7074 | false | `false` | `F` |
7075 | true | `true` | `T` |
7076 | float32 | number_float | `d` |
7077 | float64 | number_float | `D` |
7078 | uint8 | number_unsigned | `U` |
7079 | int8 | number_integer | `i` |
7080 | int16 | number_integer | `I` |
7081 | int32 | number_integer | `l` |
7082 | int64 | number_integer | `L` |
7083 | string | string | `S` |
7084 | char | string | `C` |
7085 | array | array (optimized values are supported) | `[` |
7086 | object | object (optimized values are supported) | `{` |
7087 | |
7088 | @note The mapping is **complete** in the sense that any UBJSON value can |
7089 | be converted to a JSON value. |
7090 | |
7091 | @param[in] i an input in UBJSON format convertible to an input adapter |
7092 | @param[in] strict whether to expect the input to be consumed until EOF |
7093 | (true by default) |
7094 | @param[in] allow_exceptions whether to throw exceptions in case of a |
7095 | parse error (optional, true by default) |
7096 | |
7097 | @return deserialized JSON value; in case of a parse error and |
7098 | @a allow_exceptions set to `false`, the return value will be |
7099 | value_t::discarded. |
7100 | |
7101 | @throw parse_error.110 if the given input ends prematurely or the end of |
7102 | file was not reached when @a strict was set to true |
7103 | @throw parse_error.112 if a parse error occurs |
7104 | @throw parse_error.113 if a string could not be parsed successfully |
7105 | |
7106 | @complexity Linear in the size of the input @a i. |
7107 | |
7108 | @liveexample{The example shows the deserialization of a byte vector in |
7109 | UBJSON format to a JSON value.,from_ubjson} |
7110 | |
7111 | @sa http://ubjson.org |
7112 | @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the |
7113 | analogous serialization |
7114 | @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the |
7115 | related CBOR format |
7116 | @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for |
7117 | the related MessagePack format |
7118 | @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for |
7119 | the related BSON format |
7120 | |
7121 | @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 |
7122 | */ |
7123 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7124 | static basic_json from_ubjson(detail::input_adapter&& i, |
7125 | const bool strict = true, |
7126 | const bool allow_exceptions = true) |
7127 | { |
7128 | basic_json result; |
7129 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
7130 | const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict); |
7131 | return res ? result : basic_json(value_t::discarded); |
7132 | } |
7133 | |
7134 | /*! |
7135 | @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool) |
7136 | */ |
7137 | template<typename A1, typename A2, |
7138 | detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> |
7139 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7140 | static basic_json from_ubjson(A1 && a1, A2 && a2, |
7141 | const bool strict = true, |
7142 | const bool allow_exceptions = true) |
7143 | { |
7144 | basic_json result; |
7145 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
7146 | const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict); |
7147 | return res ? result : basic_json(value_t::discarded); |
7148 | } |
7149 | |
7150 | /*! |
7151 | @brief Create a JSON value from an input in BSON format |
7152 | |
7153 | Deserializes a given input @a i to a JSON value using the BSON (Binary JSON) |
7154 | serialization format. |
7155 | |
7156 | The library maps BSON record types to JSON value types as follows: |
7157 | |
7158 | BSON type | BSON marker byte | JSON value type |
7159 | --------------- | ---------------- | --------------------------- |
7160 | double | 0x01 | number_float |
7161 | string | 0x02 | string |
7162 | document | 0x03 | object |
7163 | array | 0x04 | array |
7164 | binary | 0x05 | still unsupported |
7165 | undefined | 0x06 | still unsupported |
7166 | ObjectId | 0x07 | still unsupported |
7167 | boolean | 0x08 | boolean |
7168 | UTC Date-Time | 0x09 | still unsupported |
7169 | null | 0x0A | null |
7170 | Regular Expr. | 0x0B | still unsupported |
7171 | DB Pointer | 0x0C | still unsupported |
7172 | JavaScript Code | 0x0D | still unsupported |
7173 | Symbol | 0x0E | still unsupported |
7174 | JavaScript Code | 0x0F | still unsupported |
7175 | int32 | 0x10 | number_integer |
7176 | Timestamp | 0x11 | still unsupported |
7177 | 128-bit decimal float | 0x13 | still unsupported |
7178 | Max Key | 0x7F | still unsupported |
7179 | Min Key | 0xFF | still unsupported |
7180 | |
7181 | @warning The mapping is **incomplete**. The unsupported mappings |
7182 | are indicated in the table above. |
7183 | |
7184 | @param[in] i an input in BSON format convertible to an input adapter |
7185 | @param[in] strict whether to expect the input to be consumed until EOF |
7186 | (true by default) |
7187 | @param[in] allow_exceptions whether to throw exceptions in case of a |
7188 | parse error (optional, true by default) |
7189 | |
7190 | @return deserialized JSON value; in case of a parse error and |
7191 | @a allow_exceptions set to `false`, the return value will be |
7192 | value_t::discarded. |
7193 | |
7194 | @throw parse_error.114 if an unsupported BSON record type is encountered |
7195 | |
7196 | @complexity Linear in the size of the input @a i. |
7197 | |
7198 | @liveexample{The example shows the deserialization of a byte vector in |
7199 | BSON format to a JSON value.,from_bson} |
7200 | |
7201 | @sa http://bsonspec.org/spec.html |
7202 | @sa @ref to_bson(const basic_json&) for the analogous serialization |
7203 | @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the |
7204 | related CBOR format |
7205 | @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for |
7206 | the related MessagePack format |
7207 | @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the |
7208 | related UBJSON format |
7209 | */ |
7210 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7211 | static basic_json from_bson(detail::input_adapter&& i, |
7212 | const bool strict = true, |
7213 | const bool allow_exceptions = true) |
7214 | { |
7215 | basic_json result; |
7216 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
7217 | const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict); |
7218 | return res ? result : basic_json(value_t::discarded); |
7219 | } |
7220 | |
7221 | /*! |
7222 | @copydoc from_bson(detail::input_adapter&&, const bool, const bool) |
7223 | */ |
7224 | template<typename A1, typename A2, |
7225 | detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> |
7226 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7227 | static basic_json from_bson(A1 && a1, A2 && a2, |
7228 | const bool strict = true, |
7229 | const bool allow_exceptions = true) |
7230 | { |
7231 | basic_json result; |
7232 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); |
7233 | const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict); |
7234 | return res ? result : basic_json(value_t::discarded); |
7235 | } |
7236 | |
7237 | |
7238 | |
7239 | /// @} |
7240 | |
7241 | ////////////////////////// |
7242 | // JSON Pointer support // |
7243 | ////////////////////////// |
7244 | |
7245 | /// @name JSON Pointer functions |
7246 | /// @{ |
7247 | |
7248 | /*! |
7249 | @brief access specified element via JSON Pointer |
7250 | |
7251 | Uses a JSON pointer to retrieve a reference to the respective JSON value. |
7252 | No bound checking is performed. Similar to @ref operator[](const typename |
7253 | object_t::key_type&), `null` values are created in arrays and objects if |
7254 | necessary. |
7255 | |
7256 | In particular: |
7257 | - If the JSON pointer points to an object key that does not exist, it |
7258 | is created an filled with a `null` value before a reference to it |
7259 | is returned. |
7260 | - If the JSON pointer points to an array index that does not exist, it |
7261 | is created an filled with a `null` value before a reference to it |
7262 | is returned. All indices between the current maximum and the given |
7263 | index are also filled with `null`. |
7264 | - The special value `-` is treated as a synonym for the index past the |
7265 | end. |
7266 | |
7267 | @param[in] ptr a JSON pointer |
7268 | |
7269 | @return reference to the element pointed to by @a ptr |
7270 | |
7271 | @complexity Constant. |
7272 | |
7273 | @throw parse_error.106 if an array index begins with '0' |
7274 | @throw parse_error.109 if an array index was not a number |
7275 | @throw out_of_range.404 if the JSON pointer can not be resolved |
7276 | |
7277 | @liveexample{The behavior is shown in the example.,operatorjson_pointer} |
7278 | |
7279 | @since version 2.0.0 |
7280 | */ |
7281 | reference operator[](const json_pointer& ptr) |
7282 | { |
7283 | return ptr.get_unchecked(this); |
7284 | } |
7285 | |
7286 | /*! |
7287 | @brief access specified element via JSON Pointer |
7288 | |
7289 | Uses a JSON pointer to retrieve a reference to the respective JSON value. |
7290 | No bound checking is performed. The function does not change the JSON |
7291 | value; no `null` values are created. In particular, the the special value |
7292 | `-` yields an exception. |
7293 | |
7294 | @param[in] ptr JSON pointer to the desired element |
7295 | |
7296 | @return const reference to the element pointed to by @a ptr |
7297 | |
7298 | @complexity Constant. |
7299 | |
7300 | @throw parse_error.106 if an array index begins with '0' |
7301 | @throw parse_error.109 if an array index was not a number |
7302 | @throw out_of_range.402 if the array index '-' is used |
7303 | @throw out_of_range.404 if the JSON pointer can not be resolved |
7304 | |
7305 | @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} |
7306 | |
7307 | @since version 2.0.0 |
7308 | */ |
7309 | const_reference operator[](const json_pointer& ptr) const |
7310 | { |
7311 | return ptr.get_unchecked(this); |
7312 | } |
7313 | |
7314 | /*! |
7315 | @brief access specified element via JSON Pointer |
7316 | |
7317 | Returns a reference to the element at with specified JSON pointer @a ptr, |
7318 | with bounds checking. |
7319 | |
7320 | @param[in] ptr JSON pointer to the desired element |
7321 | |
7322 | @return reference to the element pointed to by @a ptr |
7323 | |
7324 | @throw parse_error.106 if an array index in the passed JSON pointer @a ptr |
7325 | begins with '0'. See example below. |
7326 | |
7327 | @throw parse_error.109 if an array index in the passed JSON pointer @a ptr |
7328 | is not a number. See example below. |
7329 | |
7330 | @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr |
7331 | is out of range. See example below. |
7332 | |
7333 | @throw out_of_range.402 if the array index '-' is used in the passed JSON |
7334 | pointer @a ptr. As `at` provides checked access (and no elements are |
7335 | implicitly inserted), the index '-' is always invalid. See example below. |
7336 | |
7337 | @throw out_of_range.403 if the JSON pointer describes a key of an object |
7338 | which cannot be found. See example below. |
7339 | |
7340 | @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. |
7341 | See example below. |
7342 | |
7343 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
7344 | changes in the JSON value. |
7345 | |
7346 | @complexity Constant. |
7347 | |
7348 | @since version 2.0.0 |
7349 | |
7350 | @liveexample{The behavior is shown in the example.,at_json_pointer} |
7351 | */ |
7352 | reference at(const json_pointer& ptr) |
7353 | { |
7354 | return ptr.get_checked(this); |
7355 | } |
7356 | |
7357 | /*! |
7358 | @brief access specified element via JSON Pointer |
7359 | |
7360 | Returns a const reference to the element at with specified JSON pointer @a |
7361 | ptr, with bounds checking. |
7362 | |
7363 | @param[in] ptr JSON pointer to the desired element |
7364 | |
7365 | @return reference to the element pointed to by @a ptr |
7366 | |
7367 | @throw parse_error.106 if an array index in the passed JSON pointer @a ptr |
7368 | begins with '0'. See example below. |
7369 | |
7370 | @throw parse_error.109 if an array index in the passed JSON pointer @a ptr |
7371 | is not a number. See example below. |
7372 | |
7373 | @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr |
7374 | is out of range. See example below. |
7375 | |
7376 | @throw out_of_range.402 if the array index '-' is used in the passed JSON |
7377 | pointer @a ptr. As `at` provides checked access (and no elements are |
7378 | implicitly inserted), the index '-' is always invalid. See example below. |
7379 | |
7380 | @throw out_of_range.403 if the JSON pointer describes a key of an object |
7381 | which cannot be found. See example below. |
7382 | |
7383 | @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. |
7384 | See example below. |
7385 | |
7386 | @exceptionsafety Strong guarantee: if an exception is thrown, there are no |
7387 | changes in the JSON value. |
7388 | |
7389 | @complexity Constant. |
7390 | |
7391 | @since version 2.0.0 |
7392 | |
7393 | @liveexample{The behavior is shown in the example.,at_json_pointer_const} |
7394 | */ |
7395 | const_reference at(const json_pointer& ptr) const |
7396 | { |
7397 | return ptr.get_checked(this); |
7398 | } |
7399 | |
7400 | /*! |
7401 | @brief return flattened JSON value |
7402 | |
7403 | The function creates a JSON object whose keys are JSON pointers (see [RFC |
7404 | 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all |
7405 | primitive. The original JSON value can be restored using the @ref |
7406 | unflatten() function. |
7407 | |
7408 | @return an object that maps JSON pointers to primitive values |
7409 | |
7410 | @note Empty objects and arrays are flattened to `null` and will not be |
7411 | reconstructed correctly by the @ref unflatten() function. |
7412 | |
7413 | @complexity Linear in the size the JSON value. |
7414 | |
7415 | @liveexample{The following code shows how a JSON object is flattened to an |
7416 | object whose keys consist of JSON pointers.,flatten} |
7417 | |
7418 | @sa @ref unflatten() for the reverse function |
7419 | |
7420 | @since version 2.0.0 |
7421 | */ |
7422 | basic_json flatten() const |
7423 | { |
7424 | basic_json result(value_t::object); |
7425 | json_pointer::flatten("" , *this, result); |
7426 | return result; |
7427 | } |
7428 | |
7429 | /*! |
7430 | @brief unflatten a previously flattened JSON value |
7431 | |
7432 | The function restores the arbitrary nesting of a JSON value that has been |
7433 | flattened before using the @ref flatten() function. The JSON value must |
7434 | meet certain constraints: |
7435 | 1. The value must be an object. |
7436 | 2. The keys must be JSON pointers (see |
7437 | [RFC 6901](https://tools.ietf.org/html/rfc6901)) |
7438 | 3. The mapped values must be primitive JSON types. |
7439 | |
7440 | @return the original JSON from a flattened version |
7441 | |
7442 | @note Empty objects and arrays are flattened by @ref flatten() to `null` |
7443 | values and can not unflattened to their original type. Apart from |
7444 | this example, for a JSON value `j`, the following is always true: |
7445 | `j == j.flatten().unflatten()`. |
7446 | |
7447 | @complexity Linear in the size the JSON value. |
7448 | |
7449 | @throw type_error.314 if value is not an object |
7450 | @throw type_error.315 if object values are not primitive |
7451 | |
7452 | @liveexample{The following code shows how a flattened JSON object is |
7453 | unflattened into the original nested JSON object.,unflatten} |
7454 | |
7455 | @sa @ref flatten() for the reverse function |
7456 | |
7457 | @since version 2.0.0 |
7458 | */ |
7459 | basic_json unflatten() const |
7460 | { |
7461 | return json_pointer::unflatten(*this); |
7462 | } |
7463 | |
7464 | /// @} |
7465 | |
7466 | ////////////////////////// |
7467 | // JSON Patch functions // |
7468 | ////////////////////////// |
7469 | |
7470 | /// @name JSON Patch functions |
7471 | /// @{ |
7472 | |
7473 | /*! |
7474 | @brief applies a JSON patch |
7475 | |
7476 | [JSON Patch](http://jsonpatch.com) defines a JSON document structure for |
7477 | expressing a sequence of operations to apply to a JSON) document. With |
7478 | this function, a JSON Patch is applied to the current JSON value by |
7479 | executing all operations from the patch. |
7480 | |
7481 | @param[in] json_patch JSON patch document |
7482 | @return patched document |
7483 | |
7484 | @note The application of a patch is atomic: Either all operations succeed |
7485 | and the patched document is returned or an exception is thrown. In |
7486 | any case, the original value is not changed: the patch is applied |
7487 | to a copy of the value. |
7488 | |
7489 | @throw parse_error.104 if the JSON patch does not consist of an array of |
7490 | objects |
7491 | |
7492 | @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory |
7493 | attributes are missing); example: `"operation add must have member path"` |
7494 | |
7495 | @throw out_of_range.401 if an array index is out of range. |
7496 | |
7497 | @throw out_of_range.403 if a JSON pointer inside the patch could not be |
7498 | resolved successfully in the current JSON value; example: `"key baz not |
7499 | found"` |
7500 | |
7501 | @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", |
7502 | "move") |
7503 | |
7504 | @throw other_error.501 if "test" operation was unsuccessful |
7505 | |
7506 | @complexity Linear in the size of the JSON value and the length of the |
7507 | JSON patch. As usually only a fraction of the JSON value is affected by |
7508 | the patch, the complexity can usually be neglected. |
7509 | |
7510 | @liveexample{The following code shows how a JSON patch is applied to a |
7511 | value.,patch} |
7512 | |
7513 | @sa @ref diff -- create a JSON patch by comparing two JSON values |
7514 | |
7515 | @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) |
7516 | @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) |
7517 | |
7518 | @since version 2.0.0 |
7519 | */ |
7520 | basic_json patch(const basic_json& json_patch) const |
7521 | { |
7522 | // make a working copy to apply the patch to |
7523 | basic_json result = *this; |
7524 | |
7525 | // the valid JSON Patch operations |
7526 | enum class patch_operations {add, remove, replace, move, copy, test, invalid}; |
7527 | |
7528 | const auto get_op = [](const std::string & op) |
7529 | { |
7530 | if (op == "add" ) |
7531 | { |
7532 | return patch_operations::add; |
7533 | } |
7534 | if (op == "remove" ) |
7535 | { |
7536 | return patch_operations::remove; |
7537 | } |
7538 | if (op == "replace" ) |
7539 | { |
7540 | return patch_operations::replace; |
7541 | } |
7542 | if (op == "move" ) |
7543 | { |
7544 | return patch_operations::move; |
7545 | } |
7546 | if (op == "copy" ) |
7547 | { |
7548 | return patch_operations::copy; |
7549 | } |
7550 | if (op == "test" ) |
7551 | { |
7552 | return patch_operations::test; |
7553 | } |
7554 | |
7555 | return patch_operations::invalid; |
7556 | }; |
7557 | |
7558 | // wrapper for "add" operation; add value at ptr |
7559 | const auto operation_add = [&result](json_pointer & ptr, basic_json val) |
7560 | { |
7561 | // adding to the root of the target document means replacing it |
7562 | if (ptr.empty()) |
7563 | { |
7564 | result = val; |
7565 | return; |
7566 | } |
7567 | |
7568 | // make sure the top element of the pointer exists |
7569 | json_pointer top_pointer = ptr.top(); |
7570 | if (top_pointer != ptr) |
7571 | { |
7572 | result.at(top_pointer); |
7573 | } |
7574 | |
7575 | // get reference to parent of JSON pointer ptr |
7576 | const auto last_path = ptr.back(); |
7577 | ptr.pop_back(); |
7578 | basic_json& parent = result[ptr]; |
7579 | |
7580 | switch (parent.m_type) |
7581 | { |
7582 | case value_t::null: |
7583 | case value_t::object: |
7584 | { |
7585 | // use operator[] to add value |
7586 | parent[last_path] = val; |
7587 | break; |
7588 | } |
7589 | |
7590 | case value_t::array: |
7591 | { |
7592 | if (last_path == "-" ) |
7593 | { |
7594 | // special case: append to back |
7595 | parent.push_back(val); |
7596 | } |
7597 | else |
7598 | { |
7599 | const auto idx = json_pointer::array_index(last_path); |
7600 | if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size())) |
7601 | { |
7602 | // avoid undefined behavior |
7603 | JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range" )); |
7604 | } |
7605 | |
7606 | // default case: insert add offset |
7607 | parent.insert(parent.begin() + static_cast<difference_type>(idx), val); |
7608 | } |
7609 | break; |
7610 | } |
7611 | |
7612 | // if there exists a parent it cannot be primitive |
7613 | default: // LCOV_EXCL_LINE |
7614 | assert(false); // LCOV_EXCL_LINE |
7615 | } |
7616 | }; |
7617 | |
7618 | // wrapper for "remove" operation; remove value at ptr |
7619 | const auto operation_remove = [&result](json_pointer & ptr) |
7620 | { |
7621 | // get reference to parent of JSON pointer ptr |
7622 | const auto last_path = ptr.back(); |
7623 | ptr.pop_back(); |
7624 | basic_json& parent = result.at(ptr); |
7625 | |
7626 | // remove child |
7627 | if (parent.is_object()) |
7628 | { |
7629 | // perform range check |
7630 | auto it = parent.find(last_path); |
7631 | if (JSON_HEDLEY_LIKELY(it != parent.end())) |
7632 | { |
7633 | parent.erase(it); |
7634 | } |
7635 | else |
7636 | { |
7637 | JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found" )); |
7638 | } |
7639 | } |
7640 | else if (parent.is_array()) |
7641 | { |
7642 | // note erase performs range check |
7643 | parent.erase(static_cast<size_type>(json_pointer::array_index(last_path))); |
7644 | } |
7645 | }; |
7646 | |
7647 | // type check: top level value must be an array |
7648 | if (JSON_HEDLEY_UNLIKELY(not json_patch.is_array())) |
7649 | { |
7650 | JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects" )); |
7651 | } |
7652 | |
7653 | // iterate and apply the operations |
7654 | for (const auto& val : json_patch) |
7655 | { |
7656 | // wrapper to get a value for an operation |
7657 | const auto get_value = [&val](const std::string & op, |
7658 | const std::string & member, |
7659 | bool string_type) -> basic_json & |
7660 | { |
7661 | // find value |
7662 | auto it = val.m_value.object->find(member); |
7663 | |
7664 | // context-sensitive error message |
7665 | const auto error_msg = (op == "op" ) ? "operation" : "operation '" + op + "'" ; |
7666 | |
7667 | // check if desired value is present |
7668 | if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) |
7669 | { |
7670 | JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'" )); |
7671 | } |
7672 | |
7673 | // check if result is of type string |
7674 | if (JSON_HEDLEY_UNLIKELY(string_type and not it->second.is_string())) |
7675 | { |
7676 | JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'" )); |
7677 | } |
7678 | |
7679 | // no error: return value |
7680 | return it->second; |
7681 | }; |
7682 | |
7683 | // type check: every element of the array must be an object |
7684 | if (JSON_HEDLEY_UNLIKELY(not val.is_object())) |
7685 | { |
7686 | JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects" )); |
7687 | } |
7688 | |
7689 | // collect mandatory members |
7690 | const std::string op = get_value("op" , "op" , true); |
7691 | const std::string path = get_value(op, "path" , true); |
7692 | json_pointer ptr(path); |
7693 | |
7694 | switch (get_op(op)) |
7695 | { |
7696 | case patch_operations::add: |
7697 | { |
7698 | operation_add(ptr, get_value("add" , "value" , false)); |
7699 | break; |
7700 | } |
7701 | |
7702 | case patch_operations::remove: |
7703 | { |
7704 | operation_remove(ptr); |
7705 | break; |
7706 | } |
7707 | |
7708 | case patch_operations::replace: |
7709 | { |
7710 | // the "path" location must exist - use at() |
7711 | result.at(ptr) = get_value("replace" , "value" , false); |
7712 | break; |
7713 | } |
7714 | |
7715 | case patch_operations::move: |
7716 | { |
7717 | const std::string from_path = get_value("move" , "from" , true); |
7718 | json_pointer from_ptr(from_path); |
7719 | |
7720 | // the "from" location must exist - use at() |
7721 | basic_json v = result.at(from_ptr); |
7722 | |
7723 | // The move operation is functionally identical to a |
7724 | // "remove" operation on the "from" location, followed |
7725 | // immediately by an "add" operation at the target |
7726 | // location with the value that was just removed. |
7727 | operation_remove(from_ptr); |
7728 | operation_add(ptr, v); |
7729 | break; |
7730 | } |
7731 | |
7732 | case patch_operations::copy: |
7733 | { |
7734 | const std::string from_path = get_value("copy" , "from" , true); |
7735 | const json_pointer from_ptr(from_path); |
7736 | |
7737 | // the "from" location must exist - use at() |
7738 | basic_json v = result.at(from_ptr); |
7739 | |
7740 | // The copy is functionally identical to an "add" |
7741 | // operation at the target location using the value |
7742 | // specified in the "from" member. |
7743 | operation_add(ptr, v); |
7744 | break; |
7745 | } |
7746 | |
7747 | case patch_operations::test: |
7748 | { |
7749 | bool success = false; |
7750 | JSON_TRY |
7751 | { |
7752 | // check if "value" matches the one at "path" |
7753 | // the "path" location must exist - use at() |
7754 | success = (result.at(ptr) == get_value("test" , "value" , false)); |
7755 | } |
7756 | JSON_INTERNAL_CATCH (out_of_range&) |
7757 | { |
7758 | // ignore out of range errors: success remains false |
7759 | } |
7760 | |
7761 | // throw an exception if test fails |
7762 | if (JSON_HEDLEY_UNLIKELY(not success)) |
7763 | { |
7764 | JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); |
7765 | } |
7766 | |
7767 | break; |
7768 | } |
7769 | |
7770 | default: |
7771 | { |
7772 | // op must be "add", "remove", "replace", "move", "copy", or |
7773 | // "test" |
7774 | JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid" )); |
7775 | } |
7776 | } |
7777 | } |
7778 | |
7779 | return result; |
7780 | } |
7781 | |
7782 | /*! |
7783 | @brief creates a diff as a JSON patch |
7784 | |
7785 | Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can |
7786 | be changed into the value @a target by calling @ref patch function. |
7787 | |
7788 | @invariant For two JSON values @a source and @a target, the following code |
7789 | yields always `true`: |
7790 | @code {.cpp} |
7791 | source.patch(diff(source, target)) == target; |
7792 | @endcode |
7793 | |
7794 | @note Currently, only `remove`, `add`, and `replace` operations are |
7795 | generated. |
7796 | |
7797 | @param[in] source JSON value to compare from |
7798 | @param[in] target JSON value to compare against |
7799 | @param[in] path helper value to create JSON pointers |
7800 | |
7801 | @return a JSON patch to convert the @a source to @a target |
7802 | |
7803 | @complexity Linear in the lengths of @a source and @a target. |
7804 | |
7805 | @liveexample{The following code shows how a JSON patch is created as a |
7806 | diff for two JSON values.,diff} |
7807 | |
7808 | @sa @ref patch -- apply a JSON patch |
7809 | @sa @ref merge_patch -- apply a JSON Merge Patch |
7810 | |
7811 | @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) |
7812 | |
7813 | @since version 2.0.0 |
7814 | */ |
7815 | JSON_HEDLEY_WARN_UNUSED_RESULT |
7816 | static basic_json diff(const basic_json& source, const basic_json& target, |
7817 | const std::string& path = "" ) |
7818 | { |
7819 | // the patch |
7820 | basic_json result(value_t::array); |
7821 | |
7822 | // if the values are the same, return empty patch |
7823 | if (source == target) |
7824 | { |
7825 | return result; |
7826 | } |
7827 | |
7828 | if (source.type() != target.type()) |
7829 | { |
7830 | // different types: replace value |
7831 | result.push_back( |
7832 | { |
7833 | {"op" , "replace" }, {"path" , path}, {"value" , target} |
7834 | }); |
7835 | return result; |
7836 | } |
7837 | |
7838 | switch (source.type()) |
7839 | { |
7840 | case value_t::array: |
7841 | { |
7842 | // first pass: traverse common elements |
7843 | std::size_t i = 0; |
7844 | while (i < source.size() and i < target.size()) |
7845 | { |
7846 | // recursive call to compare array values at index i |
7847 | auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); |
7848 | result.insert(result.end(), temp_diff.begin(), temp_diff.end()); |
7849 | ++i; |
7850 | } |
7851 | |
7852 | // i now reached the end of at least one array |
7853 | // in a second pass, traverse the remaining elements |
7854 | |
7855 | // remove my remaining elements |
7856 | const auto end_index = static_cast<difference_type>(result.size()); |
7857 | while (i < source.size()) |
7858 | { |
7859 | // add operations in reverse order to avoid invalid |
7860 | // indices |
7861 | result.insert(result.begin() + end_index, object( |
7862 | { |
7863 | {"op" , "remove" }, |
7864 | {"path" , path + "/" + std::to_string(i)} |
7865 | })); |
7866 | ++i; |
7867 | } |
7868 | |
7869 | // add other remaining elements |
7870 | while (i < target.size()) |
7871 | { |
7872 | result.push_back( |
7873 | { |
7874 | {"op" , "add" }, |
7875 | {"path" , path + "/" + std::to_string(i)}, |
7876 | {"value" , target[i]} |
7877 | }); |
7878 | ++i; |
7879 | } |
7880 | |
7881 | break; |
7882 | } |
7883 | |
7884 | case value_t::object: |
7885 | { |
7886 | // first pass: traverse this object's elements |
7887 | for (auto it = source.cbegin(); it != source.cend(); ++it) |
7888 | { |
7889 | // escape the key name to be used in a JSON patch |
7890 | const auto key = json_pointer::escape(it.key()); |
7891 | |
7892 | if (target.find(it.key()) != target.end()) |
7893 | { |
7894 | // recursive call to compare object values at key it |
7895 | auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); |
7896 | result.insert(result.end(), temp_diff.begin(), temp_diff.end()); |
7897 | } |
7898 | else |
7899 | { |
7900 | // found a key that is not in o -> remove it |
7901 | result.push_back(object( |
7902 | { |
7903 | {"op" , "remove" }, {"path" , path + "/" + key} |
7904 | })); |
7905 | } |
7906 | } |
7907 | |
7908 | // second pass: traverse other object's elements |
7909 | for (auto it = target.cbegin(); it != target.cend(); ++it) |
7910 | { |
7911 | if (source.find(it.key()) == source.end()) |
7912 | { |
7913 | // found a key that is not in this -> add it |
7914 | const auto key = json_pointer::escape(it.key()); |
7915 | result.push_back( |
7916 | { |
7917 | {"op" , "add" }, {"path" , path + "/" + key}, |
7918 | {"value" , it.value()} |
7919 | }); |
7920 | } |
7921 | } |
7922 | |
7923 | break; |
7924 | } |
7925 | |
7926 | default: |
7927 | { |
7928 | // both primitive type: replace value |
7929 | result.push_back( |
7930 | { |
7931 | {"op" , "replace" }, {"path" , path}, {"value" , target} |
7932 | }); |
7933 | break; |
7934 | } |
7935 | } |
7936 | |
7937 | return result; |
7938 | } |
7939 | |
7940 | /// @} |
7941 | |
7942 | //////////////////////////////// |
7943 | // JSON Merge Patch functions // |
7944 | //////////////////////////////// |
7945 | |
7946 | /// @name JSON Merge Patch functions |
7947 | /// @{ |
7948 | |
7949 | /*! |
7950 | @brief applies a JSON Merge Patch |
7951 | |
7952 | The merge patch format is primarily intended for use with the HTTP PATCH |
7953 | method as a means of describing a set of modifications to a target |
7954 | resource's content. This function applies a merge patch to the current |
7955 | JSON value. |
7956 | |
7957 | The function implements the following algorithm from Section 2 of |
7958 | [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396): |
7959 | |
7960 | ``` |
7961 | define MergePatch(Target, Patch): |
7962 | if Patch is an Object: |
7963 | if Target is not an Object: |
7964 | Target = {} // Ignore the contents and set it to an empty Object |
7965 | for each Name/Value pair in Patch: |
7966 | if Value is null: |
7967 | if Name exists in Target: |
7968 | remove the Name/Value pair from Target |
7969 | else: |
7970 | Target[Name] = MergePatch(Target[Name], Value) |
7971 | return Target |
7972 | else: |
7973 | return Patch |
7974 | ``` |
7975 | |
7976 | Thereby, `Target` is the current object; that is, the patch is applied to |
7977 | the current value. |
7978 | |
7979 | @param[in] apply_patch the patch to apply |
7980 | |
7981 | @complexity Linear in the lengths of @a patch. |
7982 | |
7983 | @liveexample{The following code shows how a JSON Merge Patch is applied to |
7984 | a JSON document.,merge_patch} |
7985 | |
7986 | @sa @ref patch -- apply a JSON patch |
7987 | @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) |
7988 | |
7989 | @since version 3.0.0 |
7990 | */ |
7991 | void merge_patch(const basic_json& apply_patch) |
7992 | { |
7993 | if (apply_patch.is_object()) |
7994 | { |
7995 | if (not is_object()) |
7996 | { |
7997 | *this = object(); |
7998 | } |
7999 | for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) |
8000 | { |
8001 | if (it.value().is_null()) |
8002 | { |
8003 | erase(it.key()); |
8004 | } |
8005 | else |
8006 | { |
8007 | operator[](it.key()).merge_patch(it.value()); |
8008 | } |
8009 | } |
8010 | } |
8011 | else |
8012 | { |
8013 | *this = apply_patch; |
8014 | } |
8015 | } |
8016 | |
8017 | /// @} |
8018 | }; |
8019 | |
8020 | /*! |
8021 | @brief user-defined to_string function for JSON values |
8022 | |
8023 | This function implements a user-defined to_string for JSON objects. |
8024 | |
8025 | @param[in] j a JSON object |
8026 | @return a std::string object |
8027 | */ |
8028 | |
8029 | NLOHMANN_BASIC_JSON_TPL_DECLARATION |
8030 | std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) |
8031 | { |
8032 | return j.dump(); |
8033 | } |
8034 | } // namespace nlohmann |
8035 | |
8036 | /////////////////////// |
8037 | // nonmember support // |
8038 | /////////////////////// |
8039 | |
8040 | // specialization of std::swap, and std::hash |
8041 | namespace std |
8042 | { |
8043 | |
8044 | /// hash value for JSON objects |
8045 | template<> |
8046 | struct hash<nlohmann::json> |
8047 | { |
8048 | /*! |
8049 | @brief return a hash value for a JSON object |
8050 | |
8051 | @since version 1.0.0 |
8052 | */ |
8053 | std::size_t operator()(const nlohmann::json& j) const |
8054 | { |
8055 | // a naive hashing via the string representation |
8056 | const auto& h = hash<nlohmann::json::string_t>(); |
8057 | return h(j.dump()); |
8058 | } |
8059 | }; |
8060 | |
8061 | /// specialization for std::less<value_t> |
8062 | /// @note: do not remove the space after '<', |
8063 | /// see https://github.com/nlohmann/json/pull/679 |
8064 | template<> |
8065 | struct less< ::nlohmann::detail::value_t> |
8066 | { |
8067 | /*! |
8068 | @brief compare two value_t enum values |
8069 | @since version 3.0.0 |
8070 | */ |
8071 | bool operator()(nlohmann::detail::value_t lhs, |
8072 | nlohmann::detail::value_t rhs) const noexcept |
8073 | { |
8074 | return nlohmann::detail::operator<(lhs, rhs); |
8075 | } |
8076 | }; |
8077 | |
8078 | /*! |
8079 | @brief exchanges the values of two JSON objects |
8080 | |
8081 | @since version 1.0.0 |
8082 | */ |
8083 | template<> |
8084 | inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept( |
8085 | is_nothrow_move_constructible<nlohmann::json>::value and |
8086 | is_nothrow_move_assignable<nlohmann::json>::value |
8087 | ) |
8088 | { |
8089 | j1.swap(j2); |
8090 | } |
8091 | |
8092 | } // namespace std |
8093 | |
8094 | /*! |
8095 | @brief user-defined string literal for JSON values |
8096 | |
8097 | This operator implements a user-defined string literal for JSON objects. It |
8098 | can be used by adding `"_json"` to a string literal and returns a JSON object |
8099 | if no parse error occurred. |
8100 | |
8101 | @param[in] s a string representation of a JSON object |
8102 | @param[in] n the length of string @a s |
8103 | @return a JSON object |
8104 | |
8105 | @since version 1.0.0 |
8106 | */ |
8107 | JSON_HEDLEY_NON_NULL(1) |
8108 | inline nlohmann::json operator "" _json(const char* s, std::size_t n) |
8109 | { |
8110 | return nlohmann::json::parse(s, s + n); |
8111 | } |
8112 | |
8113 | /*! |
8114 | @brief user-defined string literal for JSON pointer |
8115 | |
8116 | This operator implements a user-defined string literal for JSON Pointers. It |
8117 | can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer |
8118 | object if no parse error occurred. |
8119 | |
8120 | @param[in] s a string representation of a JSON Pointer |
8121 | @param[in] n the length of string @a s |
8122 | @return a JSON pointer object |
8123 | |
8124 | @since version 2.0.0 |
8125 | */ |
8126 | JSON_HEDLEY_NON_NULL(1) |
8127 | inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) |
8128 | { |
8129 | return nlohmann::json::json_pointer(std::string(s, n)); |
8130 | } |
8131 | |
8132 | #include <nlohmann/detail/macro_unscope.hpp> |
8133 | |
8134 | #endif // INCLUDE_NLOHMANN_JSON_HPP_ |
8135 | |