JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
value.hpp
Go to the documentation of this file.
1/// \file jsonv/value.hpp
2///
3/// Copyright (c) 2012-2020 by Travis Gockel. All rights reserved.
4///
5/// This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
6/// as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
7/// version.
8///
9/// \author Travis Gockel (travis@gockelhut.com)
10#pragma once
11
12#include <jsonv/config.hpp>
13#include <jsonv/kind.hpp>
14#include <string_view>
16
17#include <cstddef>
18#include <cstdint>
19#include <initializer_list>
20#include <iosfwd>
21#include <iterator>
22#include <functional>
23#include <map>
24#include <stdexcept>
25#include <string>
26#include <type_traits>
27#include <utility>
28
29namespace jsonv
30{
31
32class path;
33class value;
34class object_node_handle;
35
36namespace detail
37{
38
39class object_impl;
40class array_impl;
41class string_impl;
42
43union value_storage
44{
45 object_impl* object;
46 array_impl* array;
47 string_impl* string;
48 int64_t integer;
49 double decimal;
50 bool boolean;
51
52 constexpr value_storage() :
53 object(nullptr)
54 { }
55};
56
57}
58
59/// \defgroup Value
60/// JSON \ref value instances.
61/// \{
62
63/// Get a string representation of the given \c value.
64JSONV_PUBLIC std::string to_string(const value&);
65
66/// Thrown from various \c value methods when attempting to perform an operation which is not valid for the \c kind of
67/// value.
69 public std::logic_error
70{
71public:
72 explicit kind_error(const std::string& description);
73
74 virtual ~kind_error() noexcept;
75};
76
77/// Represents a single JSON value, which can be any one of a potential \c kind, each behaving slightly differently.
78/// Instances will vary their behavior based on their kind -- functions will throw a \c kind_error if the operation does
79/// not apply to the value's kind. For example, it does not make sense to call \c find on an \c integer.
80///
81/// - \c kind::null
82/// You cannot do anything with this...it is just null.
83/// - \c kind::boolean
84/// These values can be \c true or \c false.
85/// - \c kind::integer
86/// A numeric value which can be added, subtracted and all the other things you would expect.
87/// - \c kind::decimal
88/// Floating-point values should be considered "more general" than integers -- you may request an integer value as a
89/// decimal, but you cannot request a decimal as an integer, even when doing so would not require rounding. The
90/// literal \c 20.0 will always have \c kind::decimal.
91/// - \c kind::string
92/// A UTF-8 encoded string which is mostly accessed through the \c std::string class. Some random functions work in
93/// the cases where it makes sense (for example: \c empty and \c size), but in general, string manipulation should be
94/// done after calling \c as_string.
95/// - \c kind::array
96/// An array behaves like a \c std::vector because it is ultimately backed by one. If you feel the documentation is
97/// lacking, read this: http://en.cppreference.com/w/cpp/container/vector.
98/// - \c kind::object
99/// An object behaves lake a \c std::map because it is ultimately backed by one. If you feel the documentation is
100/// lacking, read this: http://en.cppreference.com/w/cpp/container/map. This library follows the recommendation in
101/// RFC 7159 to not allow for duplicate keys because most other libraries can not deal with it. It would also make
102/// the AST significantly more painful.
103///
104/// \see http://json.org/
105/// \see http://tools.ietf.org/html/rfc7159
107{
108public:
109 typedef std::size_t size_type;
110 typedef std::ptrdiff_t difference_type;
111
112 /** The base type for iterating over array values. **/
113 template <typename T, typename TArrayView>
115 {
116 public:
117 using iterator_category = std::random_access_iterator_tag;
118 using value_type = T;
119 using difference_type = std::ptrdiff_t;
120 using pointer = T*;
121 using reference = T&;
123 _owner(0),
124 _index(0)
125 { }
126
127 basic_array_iterator(TArrayView* owner, size_type index) :
128 _owner(owner),
129 _index(index)
130 { }
131
132 template <typename U, typename UArrayView>
134 typename std::enable_if<std::is_convertible<U*, T*>::value>::type* = 0
135 ) :
136 _owner(source._owner),
137 _index(source._index)
138 { }
139
140 basic_array_iterator& operator++()
141 {
142 ++_index;
143 return *this;
144 }
145
146 basic_array_iterator operator++(int) const
147 {
149 ++clone;
150 return clone;
151 }
152
153 basic_array_iterator& operator--()
154 {
155 --_index;
156 return *this;
157 }
158
159 basic_array_iterator operator--(int) const
160 {
162 --clone;
163 return clone;
164 }
165
166 template <typename U, typename UArrayView>
167 bool operator==(const basic_array_iterator<U, UArrayView>& other) const
168 {
169 return _owner == other._owner && _index == other._index;
170 }
171
172 template <typename U, typename UArrayView>
173 bool operator!=(const basic_array_iterator<U, UArrayView>& other) const
174 {
175 return !operator==(other);
176 }
177
178 T& operator*() const
179 {
180 return _owner->operator[](_index);
181 }
182
183 T* operator->() const
184 {
185 return &_owner->operator[](_index);
186 }
187
188 basic_array_iterator& operator+=(size_type n)
189 {
190 _index += n;
191 return *this;
192 }
193
194 basic_array_iterator operator+(size_type n) const
195 {
197 clone += n;
198 return clone;
199 }
200
201 basic_array_iterator& operator-=(size_type n)
202 {
203 _index -= n;
204 return *this;
205 }
206
207 basic_array_iterator operator-(size_type n) const
208 {
210 clone -= n;
211 return clone;
212 }
213
214 difference_type operator-(const basic_array_iterator& other) const
215 {
216 return difference_type(_index) - difference_type(other._index);
217 }
218
219 bool operator<(const basic_array_iterator& rhs) const
220 {
221 return _index < rhs._index;
222 }
223
224 bool operator<=(const basic_array_iterator& rhs) const
225 {
226 return _index <= rhs._index;
227 }
228
229 bool operator>(const basic_array_iterator& rhs) const
230 {
231 return _index > rhs._index;
232 }
233
234 bool operator>=(const basic_array_iterator& rhs) const
235 {
236 return _index >= rhs._index;
237 }
238
239 T& operator[](size_type n) const
240 {
241 return _owner->operator[](_index + n);
242 }
243 private:
244 template <typename U, typename UArrayView>
245 friend struct basic_array_iterator;
246
247 friend class value;
248
249 private:
250 TArrayView* _owner;
251 size_type _index;
252 };
253
254 /** The \c array_iterator is applicable when \c kind is \c kind::array. It allows you to use algorithms as if
255 * a \c value was a normal sequence container.
256 **/
259
260 /** If \c kind is \c kind::array, an \c array_view allows you to access a value as a sequence container. This is
261 * most useful for range-based for loops.
262 **/
263 typedef detail::basic_view<array_iterator, const_array_iterator> array_view;
264 typedef detail::basic_view<const_array_iterator> const_array_view;
265 typedef detail::basic_owning_view<value, array_iterator, const_array_iterator> owning_array_view;
266
267 /** The base iterator type for iterating over object types. It is a bidirectional iterator similar to a
268 * \c std::map<std::string, jsonv::value>.
269 **/
270 template <typename T, typename TIterator>
272 {
273 public:
274 using iterator_category = std::bidirectional_iterator_tag;
275 using value_type = T;
276 using difference_type = std::ptrdiff_t;
277 using pointer = T*;
278 using reference = T&;
279
281 _impl()
282 { }
283
285 _impl(source._impl)
286 { }
287
288 /** This allows assignment from an \c object_iterator to a \c const_object_iterator. **/
289 template <typename U, typename UIterator>
291 typename std::enable_if<std::is_convertible<U*, T*>::value>::type* = 0
292 ) :
293 _impl(source._impl)
294 { }
295
297 {
298 _impl = source._impl;
299 return *this;
300 }
301
302 template <typename U, typename UIterator>
303 typename std::enable_if<std::is_convertible<U*, T*>::value, basic_object_iterator&>::type
305 {
306 return operator=(basic_object_iterator(source));
307 }
308
309 basic_object_iterator& operator++()
310 {
311 increment();
312 return *this;
313 }
314
315 basic_object_iterator operator++(int) const
316 {
317 basic_object_iterator clone(*this);
318 clone.increment();
319 return clone;
320 }
321
322 basic_object_iterator& operator--()
323 {
324 decrement();
325 return *this;
326 }
327
328 basic_object_iterator operator--(int) const
329 {
330 basic_object_iterator clone(*this);
331 clone.decrement();
332 return clone;
333 }
334
335 template <typename U, typename UIterator>
336 bool operator ==(const basic_object_iterator<U, UIterator>& other) const
337 {
338 return _impl == other._impl;
339 }
340
341 template <typename U, typename UIterator>
342 bool operator !=(const basic_object_iterator<U, UIterator>& other) const
343 {
344 return _impl != other._impl;
345 }
346
347 T& operator *() const
348 {
349 return current();
350 }
351
352 T* operator ->() const
353 {
354 return &current();
355 }
356
357 private:
358 friend class value;
359
360 template <typename UIterator>
361 explicit basic_object_iterator(const UIterator& iter) :
362 _impl(iter)
363 { }
364
365 void increment()
366 {
367 ++_impl;
368 }
369
370 void decrement()
371 {
372 --_impl;
373 }
374
375 T& current() const
376 {
377 return *_impl;
378 }
379
380 private:
381 TIterator _impl;
382 };
383
384 /** The type of value stored when \c kind is \c kind::object. **/
385 typedef std::pair<const std::string, value> object_value_type;
386
387 /** The \c object_iterator is applicable when \c kind is \c kind::object. It allows you to use algorithms as if
388 * a \c value was a normal associative container.
389 **/
392
393 /** If \c kind is \c kind::object, an \c object_view allows you to access a value as an associative container.
394 * This is most useful for range-based for loops.
395 **/
396 typedef detail::basic_view<object_iterator, const_object_iterator> object_view;
397 typedef detail::basic_view<const_object_iterator> const_object_view;
398 typedef detail::basic_owning_view<value, object_iterator, const_object_iterator> owning_object_view;
399
400 /// Type returned from \c insert operations when this has \ref kind::object. It is generally compatible with the
401 /// \c insert_return_type of \c std::map, with the notable lack of \c node.
402 ///
403 /// \see insert
405 {
406 /// The position of the inserted node or node with the duplicate key.
408
409 /// Did the insert operation perform an insert? A value of \c false indicates there was a key already present
410 /// with the same name.
412 };
413
414public:
415 /** Default-construct this to null. **/
416 constexpr value() :
417 _kind(jsonv::kind::null)
418 { }
419
420 /// The nullptr overload will fail to compile -- use \c jsonv::null if you want a \c kind::null.
421 value(std::nullptr_t) = delete;
422
423 /** Copy the contents of \a source into a new instance. **/
425
426 /** Create a \c kind::string with the given \a value. **/
427 value(const std::string& value);
428
429 /** Create a \c kind::string with the given \a value. **/
430 value(const std::string_view& value);
431
432 /// Create a \c kind::string with the given \a value.
433 ///
434 /// \param value The value to create with. This must be null-terminated.
435 value(const char* value);
436
437 /// Create a \c kind::string with the given \a value. Keep in mind that it will be converted to and stored as a
438 /// UTF-8 encoded string.
439 value(const std::wstring& value);
440
441 /** Create a \c kind::string with the given \a value. Keep in mind that it will be converted to and stored as a
442 * UTF-8 encoded string.
443 *
444 * \param value The value to create with. This must be null-terminated.
445 **/
446 value(const wchar_t* value);
447
448 /** Create a \c kind::integer with the given \a value. **/
450
451 /** Create a \c kind::decimal with the given \a value. **/
452 value(double value);
453
454 /** Create a \c kind::decimal with the given \a value. **/
455 value(float value);
456
457 /** Create a \c kind::boolean with the given \a value. **/
459
460 #define JSONV_VALUE_INTEGER_ALTERNATIVE_CTOR_PROTO_GENERATOR(type_) \
461 value(type_ val);
462 JSONV_INTEGER_ALTERNATES_LIST(JSONV_VALUE_INTEGER_ALTERNATIVE_CTOR_PROTO_GENERATOR)
463
464 /** Destruction will never throw. **/
466
467 /** Copy-assigns \c source to this.
468 *
469 * If an exception is thrown during the copy, it is propagated out. This instance will remain unchanged.
470 **/
472
473 /** Move-construct this instance, leaving \a source as a null value. **/
475
476 /** Move-assigns \c source to this, leaving \a source as a null value.
477 *
478 * Unlike a copy, this will never throw.
479 **/
481
482 /** Get this value as a string.
483 *
484 * \throws kind_error if this value does not represent a string.
485 **/
486 const std::string& as_string() const;
487
488 /** Tests if this \c kind is \c kind::string. **/
489 bool is_string() const;
490
491 /** Get this value as a \c std::string_view. It is your responsibility to ensure the \c value instance remains valid.
492 *
493 * \throws kind_error if this value does not represent a string.
494 **/
495 std::string_view as_string_view() const &;
496
497 /** Get this value as a wide string. Keep in mind that this is slower than \c as_string, as the internal storage is
498 * the \c char base \c std::string.
499 *
500 * \throws kind_error if this value does not represent a string.
501 **/
502 std::wstring as_wstring() const;
503
504 /** Get this value as an integer.
505 *
506 * \throws kind_error if this value does not represent an integer.
507 **/
508 int64_t as_integer() const;
509
510 /** Tests if this \c kind is \c kind::integer. **/
511 bool is_integer() const;
512
513 /** Get this value as a decimal. If the value's underlying kind is actually an integer type, cast the integer to a
514 * double before returning. This ignores the potential loss of precision.
515 *
516 * \throws kind_error if this value does not represent a decimal or integer.
517 **/
518 double as_decimal() const;
519
520 /** Tests if this \c kind is \c kind::integer or \c kind::decimal. **/
521 bool is_decimal() const;
522
523 /** Get this value as a boolean.
524 *
525 * \throws kind_error if this value does not represent a boolean.
526 **/
527 bool as_boolean() const;
528
529 /** Tests if this \c kind is \c kind::boolean. **/
530 bool is_boolean() const;
531
532 /** Tests if this \c kind is \c kind::array. **/
533 bool is_array() const;
534
535 /** Tests if this \c kind is \c kind::object. **/
536 bool is_object() const;
537
538 /** Tests if this \c kind is \c kind::null. **/
539 bool is_null() const;
540
541 /** Resets this value to null. **/
542 void clear();
543
544 /** Get this value's kind. **/
545 inline jsonv::kind kind() const
546 {
547 return _kind;
548 }
549
550 /** Get the value specified by the path \a p.
551 *
552 * \throws std::out_of_range if any path along the chain did not exist.
553 * \throws kind_error if the path traversal is not valid for the value (for example: if the path specifies an array
554 * index when the value is a string).
555 * \throws parse_error if a \c std::string_view was specified that did not have a valid specification (see
556 * \c path::create).
557 **/
558 value& at_path(const path& p);
559 value& at_path(std::string_view p);
560 value& at_path(size_type p);
561 const value& at_path(const path& p) const;
562 const value& at_path(std::string_view p) const;
563 const value& at_path(size_type p) const;
564
565 /** Similar to \c count, but walks the given path \a p to determine its presence.
566 *
567 * \returns \c 1 if the path finds an element; \c 0 if there is no such path in the tree.
568 *
569 * \throws parse_error if a \c std::string_view was specified that did not have a valid specification (see
570 * \c path::create).
571 **/
572 size_type count_path(const path& p) const;
573 size_type count_path(std::string_view p) const;
574 size_type count_path(size_type p) const;
575
576 /** Get or create the value specified by the path \a p. This is the moral equivalent to \c operator[] for paths. If
577 * no value exists at the path, a new one is created as the default (\c null) value. If any path along the way
578 * either does not exist or is \c null, it is created for you, based on the \e implications of the specification
579 * \a p. Unlike \c at_path, which will throw if accessing a non-existent key of an \c object or going past the end
580 * of an \c array, this will simply create that path and fill in the blanks with \c null values.
581 *
582 * \throws kind_error if the path traversal is not valid for the value (for example: if the path specifies an array
583 * index when the value is a string).
584 * \throws parse_error if a \c std::string_view was specified that did not have a valid specification (see
585 * \c path::create).
586 *
587 * \see at_path
588 **/
589 value& path(const path& p);
590 value& path(std::string_view p);
591 value& path(size_type p);
592
593 /** Swap the value this instance represents with \a other. **/
594 void swap(value& other) noexcept;
595
596 /** Compares two JSON values for equality. Two JSON values are equal if and only if all of the following conditions
597 * apply:
598 *
599 * 1. They have the same valid value for \c kind.
600 * - If \c kind is invalid (memory corruption), then two JSON values are \e not equal, even if they have been
601 * corrupted in the same way and even if they share \c this (a corrupt object is not equal to itself).
602 * 2. The kind comparison is also equal:
603 * - Two null values are always equivalent.
604 * - string, integer, decimal and boolean follow the classic rules for their type.
605 * - objects are equal if they have the same keys and values corresponding with the same key are also equal.
606 * - arrays are equal if they have the same length and the values at each index are also equal.
607 *
608 * \note
609 * The rules for equality are based on Python \c dict and \c list.
610 **/
611 bool operator==(const value& other) const;
612
613 /** Compares two JSON values for inequality. The rules for inequality are the exact opposite of equality.
614 **/
615 bool operator!=(const value& other) const;
616
617 /** Used to build a strict-ordering of JSON values. When comparing values of the same kind, the ordering should
618 * align with your intuition. When comparing values of different kinds, some arbitrary rules were created based on
619 * how "complicated" the author thought the type to be.
620 *
621 * - null: less than everything but null, which it is equal to.
622 * - boolean: false is less than true.
623 * - integer, decimal: compared by their numeric value. Comparisons between two integers do not cast, but comparison
624 * between an integer and a decimal will coerce to decimal.
625 * - string: compared lexicographically by character code (with basic char strings and non-ASCII encoding, this
626 * might lead to surprising results)
627 * - array: compared lexicographically by elements (recursively following this same technique)
628 * - object: entries in the object are sorted and compared lexicographically, first by key then by value
629 *
630 * \returns -1 if this is less than other by the rules stated above; 0 if this is equal to other; -1 if otherwise.
631 **/
632 int compare(const value& other) const;
633
634 bool operator< (const value& other) const;
635 bool operator> (const value& other) const;
636 bool operator<=(const value& other) const;
637 bool operator>=(const value& other) const;
638
639 /// Output this value to a stream.
640 friend std::ostream& operator<<(std::ostream& stream, const value& val);
641
642 /// Get a string representation of the given \c value.
643 friend std::string to_string(const value&);
644
645 /// \{
646 /// Get an iterator to the beginning of this array.
647 ///
648 /// \throws kind_error if the kind is not an array.
650 const_array_iterator begin_array() const;
651 /// \}
652
653 /// \{
654 /// Get an iterator to the end of this array.
655 ///
656 /// \throws kind_error if the kind is not an array.
658 const_array_iterator end_array() const;
659 /// \}
660
661 /// \{
662 /// View this instance as an array.
663 ///
664 /// \throws kind_error if the kind is not an array.
666 const_array_view as_array() const &;
667 owning_array_view as_array() &&;
668 /// \}
669
670 /// \{
671 /// Get the value in this array at the given \a idx. The overloads which accept an \c int are required to resolve
672 /// the type ambiguity of the literal \c 0 between a size_type and a char*.
673 ///
674 /// \throws kind_error if the kind is not an array.
675 value& operator[](size_type idx);
676 const value& operator[](size_type idx) const;
677 inline value& operator[](int idx) { return operator[](size_type(idx)); }
678 inline const value& operator[](int idx) const { return operator[](size_type(idx)); }
679 /// \}
680
681 /// \{
682 /// Get the value in this array at the given \a idx.
683 ///
684 /// \throws kind_error if the kind is not an array.
685 /// \throws std::out_of_range if the provided \a idx is above \c size.
686 ///
687 value& at(size_type idx);
688 const value& at(size_type idx) const;
689 /// \}
690
691 /// \{
692 /// Push \a item to the back of this array.
693 ///
694 /// \throws kind_error if the kind is not an array.
696 void push_back(const value& item);
697 /// \}
698
699 /// Pop an item off the back of this array.
700 ///
701 /// \throws kind_error if the kind is not an array.
702 /// \throws std::logic_error if the array is empty.
703 void pop_back();
704
705 /// Insert an item into \a position on this array.
706 ///
707 /// \throws kind_error if the kind is not an array.
709
710 /// Insert the range defined by [\a first, \a last) at \a position in this array.
711 ///
712 /// \throws kind_error if the kind is not an array.
713 template <typename TForwardIterator>
715 {
716 difference_type orig_offset = std::distance(const_array_iterator(begin_array()), position);
717
718 for (difference_type offset = orig_offset ; first != last; ++first, ++offset)
719 insert(begin_array() + offset, *first);
720 return begin_array() + orig_offset;
721 }
722
723 /// Assign \a count elements to this array with \a val.
724 ///
725 /// \throws kind_error if the kind is not an array.
726 void assign(size_type count, const value& val);
727
728 /// Assign the contents of range [\a first, \a last) to this array.
729 ///
730 /// \throws kind_error if the kind is not an array.
731 template <typename TForwardIterator>
733 {
734 resize(std::distance(first, last), value());
735 auto iter = begin_array();
736 while (first != last)
737 {
738 *iter = *first;
739 ++iter;
740 ++first;
741 }
742 }
743
744 /// Assign the given \a items to this array.
745 ///
746 /// \throws kind_error if the kind is not an array.
747 void assign(std::initializer_list<value> items);
748
749 /// Reserve at least \a count elements in the array.
750 ///
751 /// \throws kind_error if the kind is not an array.
752 void reserve(size_type count);
753
754 /// Resize the length of this array to \a count items. If the resize creates new elements, fill those newly-created
755 /// elements with \a val.
756 ///
757 /// \throws kind_error if the kind is not an array.
758 void resize(size_type count, const value& val = value());
759
760 /// Erase the item at this array's \a position.
761 ///
762 /// \throws kind_error if the kind is not an array.
764
765 /// Erase the range [\a first, \a last) from this array.
766 ///
767 /// \throws kind_error if the kind is not an array.
769
770 /** Get an iterator to the first key-value pair in this object.
771 *
772 * \throws kind_error if the kind is not an object.
773 **/
775 const_object_iterator begin_object() const;
776
777 /** Get an iterator to the one past the end of this object.
778 *
779 * \throws kind_error if the kind is not an object.
780 **/
782 const_object_iterator end_object() const;
783
784 /** View this instance as an object.
785 *
786 * \throws kind_error if the kind is not an object.
787 **/
789 const_object_view as_object() const &;
790 owning_object_view as_object() &&;
791
792 /** Get the value associated with the given \a key of this object. If the \a key does not exist, it will be created.
793 *
794 * \throws kind_error if the kind is not an object.
795 **/
796 value& operator[](const std::string& key);
797 value& operator[](std::string&& key);
798 value& operator[](const std::wstring& key);
799
800 /** Get the value associated with the given \a key of this object.
801 *
802 * \throws kind_error if the kind is not an object.
803 * \throws std::out_of_range if the \a key is not in this object.
804 **/
805 value& at(const std::string& key);
806 value& at(const std::wstring& key);
807 const value& at(const std::string& key) const;
808 const value& at(const std::wstring& key) const;
809
810 /** Check if the given \a key exists in this object.
811 *
812 * \throws kind_error if the kind is not an object.
813 **/
814 size_type count(const std::string& key) const;
815 size_type count(const std::wstring& key) const;
816
817 /** Attempt to locate a key-value pair with the provided \a key in this object.
818 *
819 * \throws kind_error if the kind is not an object.
820 **/
821 object_iterator find(const std::string& key);
822 object_iterator find(const std::wstring& key);
823 const_object_iterator find(const std::string& key) const;
824 const_object_iterator find(const std::wstring& key) const;
825
826 /// \{
827 /// Insert \a pair into this object. If \a hint is provided, this insertion could be optimized.
828 ///
829 /// \returns A pair whose \c first refers to the newly-inserted element (or the element which shares the key).
830 /// \throws kind_error if the kind is not an object.
831 std::pair<object_iterator, bool> insert(std::pair<std::string, value> pair);
832 std::pair<object_iterator, bool> insert(std::pair<std::wstring, value> pair);
835
836 /// Insert range defined by [\a first, \a last) into this object.
837 ///
838 /// \throws kind_error if the kind is not an object.
841 {
842 for ( ; first != last; ++first)
843 insert(*first);
844 }
845
846 /// Insert the contents of \a handle. If \a handle is empty, this does nothing.
847 ///
848 /// \returns If \a handle is empty, \c inserted is \c false and \c position is `end_object()`. If the insertion took
849 /// place, \c inserted is \c true and \c position points to the inserted element. If the insertion was attempted
850 /// but failed, \c inserted is \c false and \c position points to an element with a key equivalent to
851 /// `handle.key()`.
852 /// \throws kind_error if the kind is not an object.
854
855 /// If \a handle is an empty node handle, does nothing and returns \ref end_object. Otherwise, inserts the element
856 /// owned by \a handle into the container, if the container doesn't already contain an element with a key equivalent
857 /// to `handle.key()` and returns the iterator pointing to the element with key equivalent to `handle.key()`. If the
858 /// insertion succeeds, \a handle is moved from, otherwise it retains ownership of the element. The element is
859 /// inserted as close as possible to the position just prior to \a hint.
860 ///
861 /// \returns An iterator pointing to an element with a key equivalent to `handle.key()` if \a handle was not empty.
862 /// If \a handle was empty, `end_object()`.
863 /// \throws kind_error if the kind is not an object.
865
866 /// Insert \a items into this object.
867 ///
868 /// \throws kind_error if the kind is not an object.
869 void insert(std::initializer_list<std::pair<std::string, value>> items);
870 void insert(std::initializer_list<std::pair<std::wstring, value>> items);
871 /// \}
872
873 /// \{
874 /// Erase the item with the given \a key.
875 ///
876 /// \returns 1 if \a key was erased; 0 if it did not.
877 /// \throws kind_error if the kind is not an object.
878 size_type erase(const std::string& key);
879 size_type erase(const std::wstring& key);
880
881 /// Erase the item at the given \a position.
882 ///
883 /// \throws kind_error if the kind is not an object.
885
886 /// Erase the range defined by [\a first, \a last).
887 ///
888 /// \throws kind_error if the kind is not an object.
890 /// \}
891
892 /// \{
893 /// Unlinks the node that contains the element pointed to by position and returns a node handle that owns it.
894 ///
895 /// \throws kind_error if the kind is not an object.
897
898 /// If the container has an element with the given \a key, unlinks the node that contains that element from the
899 /// container and returns a node handle that owns it. Otherwise, returns an empty node handle.
900 ///
901 /// \throws kind_error if the kind is not an object.
902 object_node_handle extract(const std::string& key);
903 object_node_handle extract(const std::wstring& key);
904 /// \}
905
906 /** Is the underlying structure empty?
907 *
908 * - object: Are there no keys?
909 * - array: Are there no values?
910 * - string: Is the string 0 length?
911 * - null: true (always)
912 * - all other types: false (always)
913 *
914 * \throws nothing
915 **/
917
918 /** Get the number of items in this value.
919 *
920 * - object: The number of key/value pairs.
921 * - array: The number of values.
922 * - string: The number of code points in the string (including \c \\0 values and counting multi-byte encodings as
923 * more than one value).
924 *
925 * \throws kind_error if the kind is not an object, array or string.
926 **/
927 size_type size() const;
928
929 /** \addtogroup Algorithm
930 * \{
931 **/
932
933 /** Run a function over the values of this instance. The behavior of this function is different, depending on the
934 * \c kind. For scalar kinds (\c kind::integer, \c kind::null, etc), \a func is called once with the value. If this
935 * is \c kind::array, \c func is called for every value in the array and the output will be an array with each
936 * element transformed by \a func. If this is \c kind::object, the result will be an object with each key
937 * transformed by \a func.
938 *
939 * \param func The function to apply to the element or elements of this instance.
940 **/
942
943 /** Run a function over the values of this instance. The behavior of this function is different, depending on the
944 * \c kind. For scalar kinds (\c kind::integer, \c kind::null, etc), \a func is called once with the value. If this
945 * is \c kind::array, \c func is called for every value in the array and the output will be an array with each
946 * element transformed by \a func. If this is \c kind::object, the result will be an object with each key
947 * transformed by \a func.
948 *
949 * \param func The function to apply to the element or elements of this instance.
950 *
951 * \note
952 * This version of \c map provides only a basic exception-safety guarantee. If an exception is thrown while
953 * transforming a non-scalar \c kind, there is no rollback action, so \c this is left in a usable, but
954 * \e unpredictable state. If you need a strong exception guarantee, use the constant reference version of \c map.
955 **/
957
958 /** \} **/
959
960private:
963
964private:
965 detail::value_storage _data;
966 jsonv::kind _kind;
967};
968
969/** An instance with \c kind::null. This is intended to be used for convenience and readability (as opposed to using the
970 * default constructor of \c value.
971**/
973
974/** A user-defined literal for parsing JSON. Uses the default (non-strict) \c parse_options.
975 *
976 * \code
977 * R"({
978 * "taco": "cat",
979 * "burrito": "dog",
980 * "whatever": [ "goes", "here", 1, 2, 3, 4 ]
981 * })"_json;
982 * \endcode
983**/
985
986/** Swap the values \a a and \a b. **/
988
989/** Create an empty array value. **/
991
992/** Create an array value from the given source. **/
994
995/** Create an array with contents defined by range [\a first, \a last). **/
998{
999 value arr = array();
1000 arr.assign(first, last);
1001 return arr;
1002}
1003
1004/** Create an empty object. **/
1006
1007/** Create an object with key-value pairs from the given \a source. **/
1008JSONV_PUBLIC value object(std::initializer_list<std::pair<std::string, value>> source);
1009JSONV_PUBLIC value object(std::initializer_list<std::pair<std::wstring, value>> source);
1010
1011/** Create an object whose contents are defined by range [\a first, \a last). **/
1012template <typename TForwardIterator>
1014{
1015 value obj = object();
1016 obj.insert(first, last);
1017 return obj;
1018}
1019
1020/// A <a href="http://en.cppreference.com/w/cpp/container/node_handle">node handle</a> used when a value is
1021/// \ref kind::object to access elements of the object in potentially destructive manner. This makes it possible to
1022/// modify the contents of a node extracted from an object, and then re-insert it without having to copy the element.
1024{
1025public:
1026 /// The key type of the object.
1027 using key_type = std::string;
1028
1029 /// The mapped type of the object.
1031
1032public:
1033 explicit object_node_handle() noexcept :
1034 _has_value(false)
1035 { }
1036
1038
1040
1042
1043 /// \returns \c true if the node handle is empty; \c false if otherwise.
1044 bool empty() const noexcept { return !_has_value; }
1045
1046 /// \returns \c false if the node handle is empty; \c true if otherwise.
1047 explicit operator bool() const noexcept { return _has_value; }
1048
1049 /// Returns a non-const reference to the \ref key_type member of the element.
1050 ///
1051 /// \throws std::invalid_argument if the node handle is \ref empty.
1052 key_type& key() const;
1053
1054 /// Returns a non-const reference to the \ref mapped_type member of the element.
1055 ///
1056 /// \throws std::invalid_argument if the node handle is \ref empty.
1058
1059private:
1060 enum class purposeful_construction
1061 { };
1062
1063 explicit object_node_handle(purposeful_construction, key_type, mapped_type) noexcept;
1064
1065 friend class value;
1066
1067private:
1068 bool _has_value;
1069 mutable key_type _key;
1070 mutable mapped_type _value;
1071};
1072
1073/// \}
1074
1075}
1076
1077namespace std
1078{
1079
1080/// Explicit specialization of \c std::hash for \c jsonv::value types so you can store a \c value in an unordered
1081/// container. Hashing results depend on the \c kind for the provided value -- most kinds directly use the hasher for
1082/// their kind (hashing a \c jsonv::value for integer \c 5 should have the same hash value as directly hashing the same
1083/// integer). For aggregate kinds \c array and \c object, hashing visits every sub-element recursively. This might be
1084/// expensive, but is required when storing multiple values with similar layouts in the a set (which is the most common
1085/// use case).
1086template <>
1087struct JSONV_PUBLIC hash<jsonv::value>
1088{
1089 std::size_t operator()(const jsonv::value& val) const noexcept;
1090};
1091
1092}
Copyright (c) 2014-2020 by Travis Gockel.
An adapter for enumeration types.
Thrown from various value methods when attempting to perform an operation which is not valid for the ...
Definition value.hpp:70
A node handle used when a value is kind::object to access elements of the object in potentially destr...
Definition value.hpp:1024
key_type & key() const
Returns a non-const reference to the key_type member of the element.
mapped_type & mapped() const
Returns a non-const reference to the mapped_type member of the element.
std::string key_type
The key type of the object.
Definition value.hpp:1027
Represents an exact path in some JSON structure.
Definition path.hpp:83
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:107
void assign(TForwardIterator first, TForwardIterator last)
Assign the contents of range [first, last) to this array.
Definition value.hpp:732
value(const std::string_view &value)
Create a kind::string with the given value.
constexpr value()
Default-construct this to null.
Definition value.hpp:416
value(std::nullptr_t)=delete
The nullptr overload will fail to compile – use jsonv::null if you want a kind::null.
array_iterator erase(const_array_iterator first, const_array_iterator last)
Erase the range [first, last) from this array.
value(float value)
Create a kind::decimal with the given value.
value & at_path(const path &p)
Get the value specified by the path p.
value & path(const path &p)
Get or create the value specified by the path p.
friend std::ostream & operator<<(std::ostream &stream, const value &val)
Output this value to a stream.
basic_object_iterator< object_value_type, std::map< std::string, value >::iterator > object_iterator
The object_iterator is applicable when kind is kind::object.
Definition value.hpp:390
void assign(size_type count, const value &val)
Assign count elements to this array with val.
object_iterator erase(const_object_iterator position)
Erase the item at the given position.
size_type count_path(const path &p) const
Similar to count, but walks the given path p to determine its presence.
bool operator!=(const value &other) const
Compares two JSON values for inequality.
detail::basic_view< object_iterator, const_object_iterator > object_view
If kind is kind::object, an object_view allows you to access a value as an associative container.
Definition value.hpp:396
array_view as_array() &
object_iterator end_object()
Get an iterator to the one past the end of this object.
int compare(const value &other) const
Used to build a strict-ordering of JSON values.
object_node_handle extract(const_object_iterator position)
detail::basic_view< array_iterator, const_array_iterator > array_view
If kind is kind::array, an array_view allows you to access a value as a sequence container.
Definition value.hpp:263
object_node_handle extract(const std::string &key)
If the container has an element with the given key, unlinks the node that contains that element from ...
value(const wchar_t *value)
Create a kind::string with the given value.
object_insert_return_type insert(object_node_handle &&handle)
Insert the contents of handle.
object_iterator insert(const_object_iterator hint, object_node_handle &&handle)
If handle is an empty node handle, does nothing and returns end_object.
array_iterator erase(const_array_iterator position)
Erase the item at this array's position.
bool operator==(const value &other) const
Compares two JSON values for equality.
array_iterator insert(const_array_iterator position, TForwardIterator first, TForwardIterator last)
Insert the range defined by [first, last) at position in this array.
Definition value.hpp:714
void push_back(value &&item)
void resize(size_type count, const value &val=value())
Resize the length of this array to count items.
value & at(size_type idx)
value(const std::wstring &value)
Create a kind::string with the given value.
value(bool value)
Create a kind::boolean with the given value.
basic_array_iterator< value, value > array_iterator
The array_iterator is applicable when kind is kind::array.
Definition value.hpp:257
~value() noexcept
Destruction will never throw.
value(const value &source)
Copy the contents of source into a new instance.
std::pair< const std::string, value > object_value_type
The type of value stored when kind is kind::object.
Definition value.hpp:385
const_object_iterator position
The position of the inserted node or node with the duplicate key.
Definition value.hpp:407
value(const std::string &value)
Create a kind::string with the given value.
void swap(value &other) noexcept
Swap the value this instance represents with other.
object_iterator begin_object()
Get an iterator to the first key-value pair in this object.
void insert(std::initializer_list< std::pair< std::string, value > > items)
Insert items into this object.
bool inserted
Did the insert operation perform an insert? A value of false indicates there was a key already presen...
Definition value.hpp:411
object_view as_object() &
View this instance as an object.
bool empty() const noexcept
Is the underlying structure empty?
friend std::string to_string(const value &)
Get a string representation of the given value.
value(const char *value)
Create a kind::string with the given value.
void pop_back()
Pop an item off the back of this array.
object_iterator erase(const_object_iterator first, const_object_iterator last)
Erase the range defined by [first, last).
array_iterator insert(const_array_iterator position, value item)
Insert an item into position on this array.
size_type erase(const std::string &key)
array_iterator begin_array()
array_iterator end_array()
value(double value)
Create a kind::decimal with the given value.
void assign(std::initializer_list< value > items)
Assign the given items to this array.
value(int64_t value)
Create a kind::integer with the given value.
void reserve(size_type count)
Reserve at least count elements in the array.
Type returned from insert operations when this has kind::object.
Definition value.hpp:405
Copyright (c) 2014-2020 by Travis Gockel.
#define JSONV_INTEGER_ALTERNATES_LIST(item)
An item list of types to also consider as an integer.
Definition config.hpp:134
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Definition config.hpp:102
T extract(const value &from, const formats &fmts)
Extract a C++ value from from using the provided fmts.
@ insert
Insert the correct key/value pair as part of serialization.
kind
Describes the kind of data a value holds.
Definition kind.hpp:31
JSONV_PUBLIC value object()
Create an empty object.
JSONV_PUBLIC const value null
An instance with kind::null.
JSONV_PUBLIC value array()
Create an empty array value.
Copyright (c) 2019-2020 by Travis Gockel.
STL namespace.
The base type for iterating over array values.
Definition value.hpp:115
The base iterator type for iterating over object types.
Definition value.hpp:272
basic_object_iterator(const basic_object_iterator< U, UIterator > &source, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=0)
This allows assignment from an object_iterator to a const_object_iterator.
Definition value.hpp:290