Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/json
8 : //
9 :
10 : #ifndef BOOST_JSON_OBJECT_HPP
11 : #define BOOST_JSON_OBJECT_HPP
12 :
13 : #include <boost/json/detail/config.hpp>
14 : #include <boost/json/detail/object.hpp>
15 : #include <boost/json/detail/value.hpp>
16 : #include <boost/json/kind.hpp>
17 : #include <boost/json/pilfer.hpp>
18 : #include <boost/system/result.hpp>
19 : #include <boost/json/storage_ptr.hpp>
20 : #include <boost/json/string_view.hpp>
21 : #include <cstdlib>
22 : #include <initializer_list>
23 : #include <iterator>
24 : #include <type_traits>
25 : #include <utility>
26 :
27 : namespace boost {
28 : namespace json {
29 :
30 : class value;
31 : class value_ref;
32 : class key_value_pair;
33 :
34 : /** A dynamically sized associative container of JSON key/value pairs.
35 :
36 : This is an associative container whose elements are key/value pairs with
37 : unique keys.
38 :
39 : The elements are stored contiguously; iterators are ordinary pointers,
40 : allowing random access pointer arithmetic for retrieving elements. In
41 : addition, the container maintains an internal index to speed up find
42 : operations, reducing the average complexity for most lookups and
43 : insertions.
44 :
45 : Reallocations are usually costly operations in terms of performance, as
46 : elements are copied and the internal index must be rebuilt. The @ref
47 : reserve function can be used to eliminate reallocations if the number of
48 : elements is known beforehand.
49 :
50 : @par Allocators
51 : All elements stored in the container, and their children if any, will use
52 : the same memory resource that was used to construct the container.
53 :
54 : @par Thread Safety
55 : Non-const member functions may not be called concurrently with any other
56 : member functions.
57 :
58 : @par Satisfies
59 : [ContiguousContainer](https://en.cppreference.com/w/cpp/named_req/ContiguousContainer),
60 : [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer), and
61 : {req_SequenceContainer}.
62 : */
63 : class object
64 : {
65 : struct table;
66 : class revert_construct;
67 : class revert_insert;
68 : friend class value;
69 : friend class object_test;
70 : using access = detail::access;
71 : using index_t = std::uint32_t;
72 : static index_t constexpr null_index_ =
73 : std::uint32_t(-1);
74 :
75 : storage_ptr sp_; // must come first
76 : kind k_ = kind::object; // must come second
77 : table* t_;
78 :
79 : BOOST_JSON_DECL
80 : static table empty_;
81 :
82 : template<class T>
83 : using is_inputit = typename std::enable_if<
84 : std::is_constructible<key_value_pair,
85 : typename std::iterator_traits<T>::reference
86 : >::value>::type;
87 :
88 : BOOST_JSON_DECL
89 : explicit
90 : object(detail::unchecked_object&& uo);
91 :
92 : public:
93 : /// Associated [Allocator](https://en.cppreference.com/w/cpp/named_req/Allocator)
94 : using allocator_type = container::pmr::polymorphic_allocator<value>;
95 :
96 : /** The type of keys.
97 :
98 : The function @ref string::max_size returns the
99 : maximum allowed size of strings used as keys.
100 : */
101 : using key_type = string_view;
102 :
103 : /// The type of mapped values
104 : using mapped_type = value;
105 :
106 : /// The element type
107 : using value_type = key_value_pair;
108 :
109 : /// The type used to represent unsigned integers
110 : using size_type = std::size_t;
111 :
112 : /// The type used to represent signed integers
113 : using difference_type = std::ptrdiff_t;
114 :
115 : /// A reference to an element
116 : using reference = value_type&;
117 :
118 : /// A const reference to an element
119 : using const_reference = value_type const&;
120 :
121 : /// A pointer to an element
122 : using pointer = value_type*;
123 :
124 : /// A const pointer to an element
125 : using const_pointer = value_type const*;
126 :
127 : /// A random access iterator to an element
128 : using iterator = value_type*;
129 :
130 : /// A const random access iterator to an element
131 : using const_iterator = value_type const*;
132 :
133 : /// A reverse random access iterator to an element
134 : using reverse_iterator =
135 : std::reverse_iterator<iterator>;
136 :
137 : /// A const reverse random access iterator to an element
138 : using const_reverse_iterator =
139 : std::reverse_iterator<const_iterator>;
140 :
141 : //------------------------------------------------------
142 :
143 : /** Destructor.
144 :
145 : The destructor for each element is called if needed, any used memory is
146 : deallocated, and shared ownership of the
147 : @ref boost::container::pmr::memory_resource is released.
148 :
149 : @par Complexity
150 : Constant, or linear in @ref size().
151 :
152 : @par Exception Safety
153 : No-throw guarantee.
154 : */
155 : BOOST_JSON_DECL
156 : ~object() noexcept;
157 :
158 : //------------------------------------------------------
159 :
160 : /** Constructors.
161 :
162 : Constructs an object.
163 :
164 : @li **(1)**--**(3)** the object is empty.
165 :
166 : @li **(4)** the object is filled with values in the range
167 : `[first, last)`.
168 :
169 : @li **(5)**, **(6)** the object is filled with copies of the values in
170 : `init`.
171 :
172 : @li **(7)**, **(8)** the object is filled with copies of the elements
173 : of `other`.
174 :
175 : @li **(9)** the object acquires ownership of the contents of `other`.
176 :
177 : @li **(10)** equivalent to **(9)** if `*sp == *other.storage()`;
178 : otherwise equivalent to **(8)**.
179 :
180 : @li **(11)** the object acquires ownership of the contents of `other`
181 : using pilfer semantics. This is more efficient than move
182 : construction, when it is known that the moved-from object will be
183 : immediately destroyed afterwards.
184 :
185 : Upon construction, @ref capacity() will be large enough to store the
186 : object's elements. In addition, with **(3)**, **(4)**, and **(6)** the
187 : capacity will not be smaller than `min_capacity`.
188 :
189 : With **(2)**--**(6)**, **(8)**, **(10)** the constructed object uses
190 : memory resource of `sp`. With **(7)**, **(9)**, **(11)** it uses
191 : `other`'s memory resource. In either case the object will share the
192 : ownership of the memory resource. With **(1)** it uses the
193 : \<\<default_memory_resource,default memory resource\>\>.
194 :
195 : After **(9)** `other` behaves as if newly constructed with its current
196 : storage pointer.
197 :
198 : After **(11)** `other` is not in a usable state and may only be
199 : destroyed.
200 :
201 : If `init` or `[first, last)` have elements with duplicate keys, only
202 : the first of those equivalent elements will be inserted.
203 :
204 : @par Constraints
205 : @code
206 : std::is_constructible_v<
207 : key_value_pair,
208 : std::iterator_traits<InputIt>::reference>
209 : @endcode
210 :
211 : @par Complexity
212 : @li **(1)**--**(3)**, **(9)**, **(11)** constant.
213 : @li **(4)** linear in `std::distance(first, last)`.
214 : @li **(5)**, **(6)** linear in `init.size()`.
215 : @li **(7)**, **(8)** linear in `other.size()`.
216 : @li **(10)** constant if `*sp == *other.storage()`; otherwise linear in
217 : `other.size()`.
218 :
219 : @par Exception Safety
220 : @li **(1)**, **(2)**, **(9)**, **(11)** no-throw guarantee.
221 : @li **(3)**, **(5)**, **(6)**--**(8)**, **(10)** strong guarantee.
222 : @li **(4)** strong guarantee if `InputIt` satisfies
223 : {req_ForwardIterator}, basic guarantee otherwise.
224 :
225 : Calls to `memory_resource::allocate` may throw.
226 :
227 : @see @ref pilfer,
228 : [Valueless Variants Considered Harmful](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html).
229 :
230 : @{
231 : */
232 77 : object() noexcept
233 77 : : t_(&empty_)
234 : {
235 77 : }
236 :
237 : /** Overload
238 :
239 : @param sp A pointer to the @ref boost::container::pmr::memory_resource
240 : to use.
241 : */
242 : explicit
243 484 : object(storage_ptr sp) noexcept
244 484 : : sp_(std::move(sp))
245 484 : , t_(&empty_)
246 : {
247 484 : }
248 :
249 : /** Overload
250 :
251 : @param min_capacity The minimum number of elements for which capacity
252 : is guaranteed without a subsequent reallocation.
253 : @param sp
254 : */
255 : BOOST_JSON_DECL
256 : object(
257 : std::size_t min_capacity,
258 : storage_ptr sp = {});
259 :
260 : /** Overload
261 :
262 : @param first An input iterator pointing to the first element to insert,
263 : or pointing to the end of the range.
264 : @param last An input iterator pointing to the end of the range.
265 : @param min_capacity
266 : @param sp
267 :
268 : @tparam InputIt a type satisfying the requirements of
269 : {req_InputIterator}.
270 : */
271 : template<
272 : class InputIt
273 : #ifndef BOOST_JSON_DOCS
274 : ,class = is_inputit<InputIt>
275 : #endif
276 : >
277 160 : object(
278 : InputIt first,
279 : InputIt last,
280 : std::size_t min_capacity = 0,
281 : storage_ptr sp = {})
282 160 : : sp_(std::move(sp))
283 160 : , t_(&empty_)
284 : {
285 160 : construct(
286 : first, last,
287 : min_capacity,
288 : typename std::iterator_traits<
289 : InputIt>::iterator_category{});
290 160 : }
291 :
292 : /** Overload
293 :
294 : @param init The initializer list to insert.
295 : @param sp
296 : */
297 339 : object(
298 : std::initializer_list<
299 : std::pair<string_view, value_ref>> init,
300 : storage_ptr sp = {})
301 339 : : object(init, 0, std::move(sp))
302 : {
303 246 : }
304 :
305 : /** Overload
306 :
307 : @param init
308 : @param min_capacity
309 : @param sp
310 : */
311 : BOOST_JSON_DECL
312 : object(
313 : std::initializer_list<
314 : std::pair<string_view, value_ref>> init,
315 : std::size_t min_capacity,
316 : storage_ptr sp = {});
317 :
318 : /** Overload
319 :
320 : @param other Another object.
321 : */
322 13 : object(
323 : object const& other)
324 13 : : object(other, other.sp_)
325 : {
326 13 : }
327 :
328 : /** Overload
329 :
330 : @param other
331 : @param sp
332 : */
333 : BOOST_JSON_DECL
334 : object(
335 : object const& other,
336 : storage_ptr sp);
337 :
338 : /** Overload
339 :
340 : @param other
341 : */
342 : BOOST_JSON_DECL
343 : object(object&& other) noexcept;
344 :
345 : /** Overload
346 :
347 : @param other
348 : @param sp
349 : */
350 : BOOST_JSON_DECL
351 : object(
352 : object&& other,
353 : storage_ptr sp);
354 :
355 : /** Overload
356 :
357 : @param other
358 : */
359 17 : object(pilfered<object> other) noexcept
360 17 : : sp_(std::move(other.get().sp_))
361 34 : , t_(detail::exchange(
362 17 : other.get().t_, &empty_))
363 : {
364 17 : }
365 : /// @}
366 :
367 : //------------------------------------------------------
368 : //
369 : // Assignment
370 : //
371 : //------------------------------------------------------
372 :
373 : /** Assignment operators.
374 :
375 : Replaces the contents of this object.
376 :
377 : @li **(1)** replaces with the copies of the elements of `other`.
378 : @li **(2)** takes ownership of `other`'s element storage if
379 : `*storage() == *other.storage()`; otherwise equivalent to **(1)**.
380 : @li **(3)** replaces with the elements of `init`.
381 :
382 : @par Complexity
383 : @li **(1)** linear in `size() + other.size()`.
384 : @li **(2)** constant if `*storage() == *other.storage()`; otherwise
385 : linear in `size() + other.size()`.
386 : @li **(3)** average case linear in `size() + init.size()`, worst case
387 : quadratic in `init.size()`.
388 :
389 : @par Exception Safety
390 : @li **(1)**, **(3)** strong guarantee.
391 : @li **(2)** no-throw guarantee if `*storage() == *other.storage()`;
392 : otherwise strong guarantee.
393 :
394 : Calls to `memory_resource::allocate` may throw.
395 :
396 : @par Complexity
397 :
398 : @param other Another object.
399 :
400 : @{
401 : */
402 : BOOST_JSON_DECL
403 : object&
404 : operator=(object const& other);
405 :
406 : BOOST_JSON_DECL
407 : object&
408 : operator=(object&& other);
409 :
410 : /** Overload
411 :
412 : @param init The initializer list to copy.
413 : */
414 : BOOST_JSON_DECL
415 : object&
416 : operator=(std::initializer_list<
417 : std::pair<string_view, value_ref>> init);
418 : /// @}
419 :
420 : //------------------------------------------------------
421 :
422 : /** Return the associated memory resource.
423 :
424 : This function returns a smart pointer to the
425 : @ref boost::container::pmr::memory_resource used by the container.
426 :
427 : @par Complexity
428 : Constant.
429 :
430 : @par Exception Safety
431 : No-throw guarantee.
432 : */
433 : storage_ptr const&
434 680 : storage() const noexcept
435 : {
436 680 : return sp_;
437 : }
438 :
439 : /** Return the associated allocator.
440 :
441 : This function returns an instance of @ref allocator_type constructed
442 : from the associated @ref boost::container::pmr::memory_resource.
443 :
444 : @par Complexity
445 : Constant.
446 :
447 : @par Exception Safety
448 : No-throw guarantee.
449 : */
450 : allocator_type
451 1 : get_allocator() const noexcept
452 : {
453 1 : return sp_.get();
454 : }
455 :
456 : //------------------------------------------------------
457 : //
458 : // Iterators
459 : //
460 : //------------------------------------------------------
461 :
462 : /** Return an iterator to the first element.
463 :
464 : If the container is empty, @ref end() is returned.
465 :
466 : @par Complexity
467 : Constant.
468 :
469 : @par Exception Safety
470 : No-throw guarantee.
471 :
472 : @{
473 : */
474 : inline
475 : iterator
476 : begin() noexcept;
477 :
478 : inline
479 : const_iterator
480 : begin() const noexcept;
481 : /// @}
482 :
483 : /** Return a const iterator to the first element.
484 :
485 : If the container is empty, @ref cend() is returned.
486 :
487 : @par Complexity
488 : Constant.
489 :
490 : @par Exception Safety
491 : No-throw guarantee.
492 : */
493 : inline
494 : const_iterator
495 : cbegin() const noexcept;
496 :
497 : /** Return an iterator to the element following the last element.
498 :
499 : The element acts as a placeholder; attempting
500 : to access it results in undefined behavior.
501 :
502 : @par Complexity
503 : Constant.
504 :
505 : @par Exception Safety
506 : No-throw guarantee.
507 :
508 : @{
509 : */
510 : inline
511 : iterator
512 : end() noexcept;
513 :
514 : inline
515 : const_iterator
516 : end() const noexcept;
517 : /// @}
518 :
519 : /** Return a const iterator to the element following the last element.
520 :
521 : The element acts as a placeholder; attempting
522 : to access it results in undefined behavior.
523 :
524 : @par Complexity
525 : Constant.
526 :
527 : @par Exception Safety
528 : No-throw guarantee.
529 : */
530 : inline
531 : const_iterator
532 : cend() const noexcept;
533 :
534 : /** Return a reverse iterator to the first element of the reversed container.
535 :
536 : The pointed-to element corresponds to the last element of the
537 : non-reversed container. If the container is empty, @ref rend() is
538 : returned.
539 :
540 : @par Complexity
541 : Constant.
542 :
543 : @par Exception Safety
544 : No-throw guarantee.
545 :
546 : @{
547 : */
548 : inline
549 : reverse_iterator
550 : rbegin() noexcept;
551 :
552 : inline
553 : const_reverse_iterator
554 : rbegin() const noexcept;
555 : /// @}
556 :
557 : /** Return a const reverse iterator to the first element of the reversed container.
558 :
559 : The pointed-to element corresponds to the
560 : last element of the non-reversed container.
561 : If the container is empty, @ref crend() is returned.
562 :
563 : @par Complexity
564 : Constant.
565 :
566 : @par Exception Safety
567 : No-throw guarantee.
568 : */
569 : inline
570 : const_reverse_iterator
571 : crbegin() const noexcept;
572 :
573 : /** Return a reverse iterator to the element following the last element of the reversed container.
574 :
575 : The pointed-to element corresponds to the element preceding the first
576 : element of the non-reversed container. The returned iterator only acts
577 : as a sentinel. Dereferencing it results in undefined behavior.
578 :
579 : @par Complexity
580 : Constant.
581 :
582 : @par Exception Safety
583 : No-throw guarantee.
584 :
585 : @{
586 : */
587 : inline
588 : reverse_iterator
589 : rend() noexcept;
590 :
591 : inline
592 : const_reverse_iterator
593 : rend() const noexcept;
594 : /// @}
595 :
596 : /** Return a const reverse iterator to the element following the last element of the reversed container.
597 :
598 : The pointed-to element corresponds to the element preceding the first
599 : element of the non-reversed container. The returned iterator only acts
600 : as a sentinel. Dereferencing it results in undefined behavior.
601 :
602 : @par Complexity
603 : Constant.
604 :
605 : @par Exception Safety
606 : No-throw guarantee.
607 : */
608 : inline
609 : const_reverse_iterator
610 : crend() const noexcept;
611 :
612 : //------------------------------------------------------
613 : //
614 : // Capacity
615 : //
616 : //------------------------------------------------------
617 :
618 : /** Return whether there are no elements.
619 :
620 : Returns `true` if there are no elements in
621 : the container, i.e. @ref size() returns 0.
622 :
623 : @par Complexity
624 : Constant.
625 :
626 : @par Exception Safety
627 : No-throw guarantee.
628 : */
629 : inline
630 : bool
631 : empty() const noexcept;
632 :
633 : /** Return the number of elements.
634 :
635 : This returns the number of elements in the container.
636 :
637 : @par Complexity
638 : Constant.
639 :
640 : @par Exception Safety
641 : No-throw guarantee.
642 : */
643 : inline
644 : std::size_t
645 : size() const noexcept;
646 :
647 : /** The maximum number of elements an object can hold.
648 :
649 : The maximum is an implementation-defined number dependent on system or
650 : library implementation. This value is a theoretical limit; at runtime,
651 : the actual maximum size may be less due to resource limits.
652 :
653 : @par Complexity
654 : Constant.
655 :
656 : @par Exception Safety
657 : No-throw guarantee.
658 : */
659 : static
660 : constexpr
661 : std::size_t
662 : max_size() noexcept;
663 :
664 : /** Return the number of elements that can be held in currently allocated memory.
665 :
666 : Returns the number of elements that the container has currently
667 : allocated space for. This number is never smaller than the value
668 : returned by @ref size().
669 :
670 : @par Complexity
671 : Constant.
672 :
673 : @par Exception Safety
674 : No-throw guarantee.
675 : */
676 : inline
677 : std::size_t
678 : capacity() const noexcept;
679 :
680 : /** Increase the capacity to at least a certain amount.
681 :
682 : This increases the @ref capacity() to a value that is greater than or
683 : equal to `new_capacity`. If `new_capacity > capacity()`, new memory is
684 : allocated. Otherwise, the call has no effect. The number of elements
685 : and therefore the @ref size() of the container is not changed.
686 :
687 : If new memory is allocated, all iterators including any past-the-end
688 : iterators, and all references to the elements are invalidated.
689 : Otherwise, no iterators or references are invalidated.
690 :
691 : @par Complexity
692 : Constant if no reallocation occurs. Otherwise, average case linear in
693 : @ref size(), worst case quadratic in @ref size().
694 :
695 : @par Exception Safety
696 : Strong guarantee. Calls to `memory_resource::allocate` may throw.
697 :
698 : @param new_capacity The new minimum capacity.
699 :
700 : @throw boost::system::system_error `new_capacity >` @ref max_size().
701 : */
702 : inline
703 : void
704 : reserve(std::size_t new_capacity);
705 :
706 : //------------------------------------------------------
707 : //
708 : // Modifiers
709 : //
710 : //------------------------------------------------------
711 :
712 : /** Erase all elements.
713 :
714 : Erases all elements from the container. After this call, @ref size()
715 : returns zero but @ref capacity() is unchanged. All references,
716 : pointers, and iterators are invalidated.
717 :
718 : @par Complexity
719 : Linear in @ref size().
720 :
721 : @par Exception Safety
722 : No-throw guarantee.
723 : */
724 : BOOST_JSON_DECL
725 : void
726 : clear() noexcept;
727 :
728 : /** Insert elements.
729 :
730 : @li **(1)** inserts a new element constructed as if via
731 : `value_type( std::forward<P>(p) )`.
732 : @li **(2)** the elements in the range `[first, last)` are inserted one
733 : at a time, in order.
734 : @li **(3)** the elements in the initializer list are inserted one at a
735 : time, in order.
736 :
737 : Any element with key that is a duplicate of a key already present in
738 : container will be skipped. This also means, that if there are two keys
739 : within the inserted range that are equal to each other, only the
740 : first will be inserted.
741 :
742 : If an insertion would result in the new number of elements exceeding
743 : @ref capacity(), a reallocation and a rehashing occur. In that case all
744 : iterators and references are invalidated. Otherwise, they are not
745 : affected.
746 :
747 : @pre
748 : `first` and `last` are not iterators into `*this`. `first` and `last`
749 : form a valid range.
750 :
751 : @par Constraints
752 : @code
753 : std::is_constructible_v<value_type, P>
754 : std::is_constructible_v<value_type, std::iterator_traits<InputIt>::reference>
755 : @endcode
756 :
757 : @par Complexity
758 : @li **(1)** constant on average, worst case linear in @ref size().
759 : @li **(2)** linear in `std::distance(first, last)`.
760 : @li **(3)** linear in `init.size()`.
761 :
762 : @par Exception Safety
763 : @li **(1)** strong guarantee.
764 : @li **(2)** strong guarantee if `InputIt` satisfies
765 : {req_ForwardIterator}, basic guarantee otherwise.
766 : @li **(3)** basic guarantee.
767 :
768 : Calls to `memory_resource::allocate` may throw.
769 :
770 : @param p The value to insert.
771 :
772 : @throw boost::system::system_error The size of a key would exceed
773 : @ref string::max_size.
774 : @throw `boost::system::system_error` @ref size() >= @ref max_size().
775 :
776 : @return **(1)** returns a @ref std::pair where `first` is an iterator
777 : to the existing or inserted element, and `second` is `true` if the
778 : insertion took place or `false` otherwise. **(2)** returns `void`.
779 :
780 : @{
781 : */
782 : template<class P
783 : #ifndef BOOST_JSON_DOCS
784 : ,class = typename std::enable_if<
785 : std::is_constructible<key_value_pair,
786 : P, storage_ptr>::value>::type
787 : #endif
788 : >
789 : std::pair<iterator, bool>
790 : insert(P&& p);
791 :
792 : /** Overload
793 :
794 : @param first An input iterator pointing to the first element to insert,
795 : or pointing to the end of the range.
796 :
797 : @param last An input iterator pointing to the end of the range.
798 :
799 : @tparam InputIt a type satisfying the requirements
800 : of {req_InputIterator}.
801 : */
802 : template<
803 : class InputIt
804 : #ifndef BOOST_JSON_DOCS
805 : ,class = is_inputit<InputIt>
806 : #endif
807 : >
808 : void
809 174 : insert(InputIt first, InputIt last)
810 : {
811 174 : insert(first, last, typename
812 : std::iterator_traits<InputIt
813 : >::iterator_category{});
814 8 : }
815 :
816 : /** Overload
817 :
818 : @param init The initializer list to insert.
819 : */
820 : BOOST_JSON_DECL
821 : void
822 : insert(std::initializer_list<
823 : std::pair<string_view, value_ref>> init);
824 : /// @}
825 :
826 : /** Insert an element or assign to an existing element.
827 :
828 : If the key equal to `key` already exists in the container, assigns
829 : `std::forward<M>(m)` to the @ref mapped_type corresponding to that key.
830 : Otherwise, inserts the as if by @ref insert, constructing it using
831 : `value_type(key, std::forward<M>(m))`.
832 :
833 : If insertion would result in the new number of elements exceeding
834 : @ref capacity(), a reallocation and a rehashing occur. In that case all
835 : iterators and references are invalidated. Otherwise, they are not
836 : affected.
837 :
838 : @par Complexity
839 : Constant on average, worst case linear in @ref size().
840 :
841 : @par Exception Safety
842 : Strong guarantee. Calls to `memory_resource::allocate` may throw.
843 :
844 : @return A @ref std::pair where `first` is an iterator to the existing
845 : or inserted element, and `second` is `true` if the insertion took place
846 : or `false` if the assignment took place.
847 :
848 : @param key The key used for lookup and insertion.
849 : @param m The value to insert or assign.
850 :
851 : @throw boost::system::system_error The size of a key would exceed
852 : @ref string::max_size.
853 : */
854 : template<class M>
855 : std::pair<iterator, bool>
856 : insert_or_assign(
857 : string_view key, M&& m);
858 :
859 : /** Construct an element in-place.
860 :
861 : Inserts a new element into the container constructed
862 : in-place with the given argument if there is no
863 : element with the `key` in the container.
864 :
865 : If the insertion occurs and results in a rehashing of the container,
866 : all iterators and references are invalidated. Otherwise, they are not
867 : affected. Rehashing occurs only if the new number of elements is
868 : greater than @ref capacity().
869 :
870 : @par Complexity
871 : Constant on average, worst case linear in @ref size().
872 :
873 : @par Exception Safety
874 : Strong guarantee.
875 : Calls to `memory_resource::allocate` may throw.
876 :
877 : @return A @ref std::pair where `first` is an iterator
878 : to the existing or inserted element, and `second`
879 : is `true` if the insertion took place or `false` otherwise.
880 :
881 : @param key The key used for lookup and insertion.
882 :
883 : @param arg The argument used to construct the value.
884 : This will be passed as `std::forward<Arg>(arg)` to
885 : the @ref value constructor.
886 :
887 : @throw boost::system::system_error The size of the key would exceed
888 : @ref string::max_size.
889 :
890 : */
891 : template<class Arg>
892 : std::pair<iterator, bool>
893 : emplace(string_view key, Arg&& arg);
894 :
895 : /** Remove an element.
896 :
897 : @li **(1)** the element at `pos` is removed.
898 : @li **(2)** the element with the key `key` is removed, if it exists.
899 :
900 : `pos` must be valid and dereferenceable. References and iterators to
901 : the erased element are invalidated. Other iterators and references are
902 : not invalidated.
903 :
904 : @attention The @ref end() iterator (which is valid but cannot be
905 : dereferenced) cannot be used as a value for `pos`.
906 :
907 : @par Complexity
908 : Constant on average, worst case linear in @ref size().
909 :
910 : @par Exception Safety
911 : No-throw guarantee.
912 :
913 : @return
914 : @li **(1)** an iterator following the removed element.
915 : @li **(2)** the number of elements removed, which will be either
916 : 0 or 1.
917 :
918 : @param pos An iterator pointing to the element to be removed.
919 :
920 : @{
921 : */
922 : BOOST_JSON_DECL
923 : iterator
924 : erase(const_iterator pos) noexcept;
925 :
926 : /** Overload
927 :
928 : @param key The key to match.
929 : */
930 : BOOST_JSON_DECL
931 : std::size_t
932 : erase(string_view key) noexcept;
933 : /// @}
934 :
935 : /** Erase an element preserving order.
936 :
937 : @li **(1)** Remove the element pointed to by `pos`, which must be valid
938 : and dereferenceable. References and iterators from `pos` to @ref end(),
939 : both included, are invalidated. Other iterators and references are not
940 : invalidated.
941 : @li **(2)** Remove the element which matches `key`, if it exists. All
942 : references and iterators are invalidated.
943 :
944 : The relative order of remaining elements is preserved.
945 :
946 : @attention The @ref end() iterator (which is valid but cannot be
947 : dereferenced) cannot be used as a value for `pos`.
948 :
949 : @par Complexity
950 : Linear in @ref size().
951 :
952 : @par Exception Safety
953 : No-throw guarantee.
954 :
955 : @return
956 : @li An iterator following the removed element.
957 : @li The number of elements removed, which will be either 0 or 1.
958 :
959 : @param pos An iterator pointing to the element to be
960 : removed.
961 :
962 : @{
963 : */
964 : BOOST_JSON_DECL
965 : iterator
966 : stable_erase(const_iterator pos) noexcept;
967 :
968 : /** Overload
969 :
970 : @param key The key to match.
971 : */
972 : BOOST_JSON_DECL
973 : std::size_t
974 : stable_erase(string_view key) noexcept;
975 : /// @}
976 :
977 : /** Swap two objects.
978 :
979 : Exchanges the contents of this object with another object. Ownership of
980 : the respective @ref boost::container::pmr::memory_resource objects is
981 : not transferred. If `this == &other`, this function call has no effect.
982 :
983 : @li If `*storage() == *other.storage()` all iterators and references
984 : remain valid.
985 :
986 : @li Otherwise, the contents are logically swapped by making copies,
987 : which can throw. In this case all iterators and references are
988 : invalidated.
989 :
990 : @par Complexity
991 : If `*storage() == *other.storage()`, then constant; otherwise linear in
992 : `size() + other.size()`.
993 :
994 : @par Exception Safety
995 : No-throw guarantee if `*storage() == *other.storage()`. Otherwise
996 : strong guarantee. Calls to `memory_resource::allocate` may throw.
997 :
998 : @param other The object to swap with.
999 : */
1000 : BOOST_JSON_DECL
1001 : void
1002 : swap(object& other);
1003 :
1004 : /** Swap two objects.
1005 :
1006 : Exchanges the contents of the object `lhs` with another object `rhs`.
1007 : Ownership of the respective @ref boost::container::pmr::memory_resource
1008 : objects is not transferred. If `&lhs == &rhs`, this function call has
1009 : no effect.
1010 :
1011 : @li If `*lhs.storage() == *rhs.storage()` all iterators and references
1012 : remain valid.
1013 :
1014 : @li Otherwise, the contents are logically swapped by making copies,
1015 : which can throw. In this case all iterators and references are
1016 : invalidated.
1017 :
1018 : @par Complexity
1019 : If `*lhs.storage() == *rhs.storage()`, then constant; otherwise linear
1020 : in `lhs.size() + rhs.size()`.
1021 :
1022 : @par Exception Safety
1023 : No-throw guarantee if `*lhs.storage() == *rhs.storage()`. Otherwise
1024 : strong guarantee. Calls to `memory_resource::allocate` may throw.
1025 :
1026 : @param lhs The object to exchange.
1027 :
1028 : @param rhs The object to exchange.
1029 :
1030 : @see @ref object::swap
1031 : */
1032 : friend
1033 : void
1034 11 : swap(object& lhs, object& rhs)
1035 : {
1036 11 : lhs.swap(rhs);
1037 3 : }
1038 :
1039 : //------------------------------------------------------
1040 : //
1041 : // Lookup
1042 : //
1043 : //------------------------------------------------------
1044 :
1045 : /** Access the specified element, with bounds checking.
1046 :
1047 : Returns @ref boost::system::result containing a reference to the
1048 : mapped value of the element that matches `key`. Otherwise the result
1049 : contains an `error_code`.
1050 :
1051 : @par Exception Safety
1052 : No-throw guarantee.
1053 :
1054 : @param key The key of the element to find.
1055 :
1056 : @par Complexity
1057 : Constant on average, worst case linear in @ref size().
1058 :
1059 : @{
1060 : */
1061 : BOOST_JSON_DECL
1062 : system::result<value&>
1063 : try_at(string_view key) noexcept;
1064 :
1065 : BOOST_JSON_DECL
1066 : system::result<value const&>
1067 : try_at(string_view key) const noexcept;
1068 : /// @}
1069 :
1070 : /** Access the specified element, with bounds checking.
1071 :
1072 : Returns a reference to the mapped value of the element that matches
1073 : `key`, otherwise throws.
1074 :
1075 : @par Complexity
1076 : Constant on average, worst case linear in @ref size().
1077 :
1078 : @par Exception Safety
1079 : Strong guarantee.
1080 :
1081 : @return A reference to the mapped value.
1082 :
1083 : @param key The key of the element to find.
1084 : @param loc @ref boost::source_location to use in thrown exception; the
1085 : source location of the call site by default.
1086 :
1087 : @throw `boost::system::system_error` if no such element exists.
1088 :
1089 : @see @ref operator[], @ref try_at.
1090 :
1091 : @{
1092 : */
1093 : inline
1094 : value&
1095 : at(
1096 : string_view key,
1097 : source_location const& loc = BOOST_CURRENT_LOCATION) &;
1098 :
1099 : inline
1100 : value&&
1101 : at(
1102 : string_view key,
1103 : source_location const& loc = BOOST_CURRENT_LOCATION) &&;
1104 :
1105 : BOOST_JSON_DECL
1106 : value const&
1107 : at(
1108 : string_view key,
1109 : source_location const& loc = BOOST_CURRENT_LOCATION) const&;
1110 : /// @}
1111 :
1112 : /** Access or insert an element.
1113 :
1114 : Returns a reference to the value that is mapped to `key`. If such value
1115 : does not already exist, performs an insertion of a null value.
1116 :
1117 : If an insertion occurs and results in a rehashing of the container, all
1118 : iterators including any past-the-end iterators, and all references to
1119 : the elements are invalidated. Otherwise, no iterators or references are
1120 : invalidated.
1121 :
1122 : @par Complexity
1123 : Constant on average, worst case linear in @ref size().
1124 :
1125 : @par Exception Safety
1126 : Strong guarantee. Calls to `memory_resource::allocate` may throw.
1127 :
1128 : @return A reference to the mapped value.
1129 :
1130 : @param key The key of the element to find.
1131 : */
1132 : BOOST_JSON_DECL
1133 : value&
1134 : operator[](string_view key);
1135 :
1136 : /** Count the number of elements with a specific key.
1137 :
1138 : Returns the number of elements with keys equal to `key`. The only
1139 : possible return values are 0 and 1.
1140 :
1141 : @par Complexity
1142 : Constant on average, worst case linear in @ref size().
1143 :
1144 : @par Exception Safety
1145 : No-throw guarantee.
1146 :
1147 : @param key The key of the element to find.
1148 : */
1149 : BOOST_JSON_DECL
1150 : std::size_t
1151 : count(string_view key) const noexcept;
1152 :
1153 : /** Find an element with a specific key.
1154 :
1155 : This function returns an iterator to the element
1156 : matching `key` if it exists, otherwise returns
1157 : @ref end().
1158 :
1159 : @par Complexity
1160 : Constant on average, worst case linear in @ref size().
1161 :
1162 : @par Exception Safety
1163 : No-throw guarantee.
1164 :
1165 : @param key The key of the element to find.
1166 :
1167 : @{
1168 : */
1169 : BOOST_JSON_DECL
1170 : iterator
1171 : find(string_view key) noexcept;
1172 :
1173 : BOOST_JSON_DECL
1174 : const_iterator
1175 : find(string_view key) const noexcept;
1176 : /// @}
1177 :
1178 : /** Return `true` if the key is found.
1179 :
1180 : Checks if there is an element with key equal to `key`.
1181 :
1182 : @par Effects
1183 : @code
1184 : return find(key) != end();
1185 : @endcode
1186 :
1187 : @par Complexity
1188 : Constant on average, worst case linear in @ref size().
1189 :
1190 : @par Exception Safety
1191 : No-throw guarantee.
1192 :
1193 : @param key The key of the element to find.
1194 :
1195 : @see @ref find.
1196 : */
1197 : BOOST_JSON_DECL
1198 : bool
1199 : contains(string_view key) const noexcept;
1200 :
1201 : /** Return a pointer to the value if the key is found, or null
1202 :
1203 : This function searches for a value with the given
1204 : key, and returns a pointer to it if found. Otherwise
1205 : it returns null.
1206 :
1207 : @par Example
1208 : @code
1209 : if( auto p = obj.if_contains( "key" ) )
1210 : std::cout << *p;
1211 : @endcode
1212 :
1213 : @par Complexity
1214 : Constant on average, worst case linear in @ref size().
1215 :
1216 : @par Exception Safety
1217 : No-throw guarantee.
1218 :
1219 : @param key The key of the element to find.
1220 :
1221 : @see @ref find.
1222 :
1223 : @{
1224 : */
1225 : BOOST_JSON_DECL
1226 : value const*
1227 : if_contains(string_view key) const noexcept;
1228 :
1229 : BOOST_JSON_DECL
1230 : value*
1231 : if_contains(string_view key) noexcept;
1232 : /// @}
1233 :
1234 : /** Compare two objects for equality.
1235 :
1236 : Objects are equal when their sizes are the same,
1237 : and when for each key in `lhs` there is a matching
1238 : key in `rhs` with the same value.
1239 :
1240 : @par Complexity
1241 : Average case linear and worst case quadratic in `lhs.size()`.
1242 :
1243 : @par Exception Safety
1244 : No-throw guarantee.
1245 : */
1246 : // inline friend speeds up overload resolution
1247 : friend
1248 : bool
1249 75 : operator==(
1250 : object const& lhs,
1251 : object const& rhs) noexcept
1252 : {
1253 75 : return lhs.equal(rhs);
1254 : }
1255 :
1256 : /** Compare two objects for inequality.
1257 :
1258 : Objects are equal when their sizes are the same, and when for each key
1259 : in `lhs` there is a matching key in `rhs` with the same value.
1260 :
1261 : @par Complexity
1262 : Average casee linear and worst case quadratic in `lhs.size()`.
1263 :
1264 : @par Exception Safety
1265 : No-throw guarantee.
1266 : */
1267 : // inline friend speeds up overload resolution
1268 : friend
1269 : bool
1270 6 : operator!=(
1271 : object const& lhs,
1272 : object const& rhs) noexcept
1273 : {
1274 6 : return ! (lhs == rhs);
1275 : }
1276 :
1277 : /** Serialize to an output stream.
1278 :
1279 : This function serializes an `object` as JSON into the output stream.
1280 :
1281 : @return Reference to `os`.
1282 :
1283 : @par Complexity
1284 : Constant or linear in the size of `obj`.
1285 :
1286 : @par Exception Safety
1287 : Strong guarantee.
1288 : Calls to `memory_resource::allocate` may throw.
1289 :
1290 : @param os The output stream to serialize to.
1291 :
1292 : @param obj The value to serialize.
1293 : */
1294 : BOOST_JSON_DECL
1295 : friend
1296 : std::ostream&
1297 : operator<<(
1298 : std::ostream& os,
1299 : object const& obj);
1300 : private:
1301 : #ifndef BOOST_JSON_DOCS
1302 : // VFALCO friending a detail function makes it public
1303 : template<class CharRange>
1304 : friend
1305 : std::pair<key_value_pair*, std::size_t>
1306 : detail::find_in_object(
1307 : object const& obj,
1308 : CharRange key) noexcept;
1309 : #endif
1310 :
1311 : template<class InputIt>
1312 : void
1313 : construct(
1314 : InputIt first,
1315 : InputIt last,
1316 : std::size_t min_capacity,
1317 : std::input_iterator_tag);
1318 :
1319 : template<class InputIt>
1320 : void
1321 : construct(
1322 : InputIt first,
1323 : InputIt last,
1324 : std::size_t min_capacity,
1325 : std::forward_iterator_tag);
1326 :
1327 : template<class InputIt>
1328 : void
1329 : insert(
1330 : InputIt first,
1331 : InputIt last,
1332 : std::input_iterator_tag);
1333 :
1334 : template<class InputIt>
1335 : void
1336 : insert(
1337 : InputIt first,
1338 : InputIt last,
1339 : std::forward_iterator_tag);
1340 :
1341 : template< class... Args >
1342 : std::pair<iterator, bool>
1343 : emplace_impl(string_view key, Args&& ... args );
1344 :
1345 : BOOST_JSON_DECL
1346 : key_value_pair*
1347 : insert_impl(
1348 : pilfered<key_value_pair> p,
1349 : std::size_t hash);
1350 :
1351 : BOOST_JSON_DECL
1352 : table*
1353 : reserve_impl(std::size_t new_capacity);
1354 :
1355 : BOOST_JSON_DECL
1356 : bool
1357 : equal(object const& other) const noexcept;
1358 :
1359 : inline
1360 : std::size_t
1361 : growth(
1362 : std::size_t new_size) const;
1363 :
1364 : inline
1365 : void
1366 : remove(
1367 : index_t& head,
1368 : key_value_pair& p) noexcept;
1369 :
1370 : inline
1371 : void
1372 : destroy() noexcept;
1373 :
1374 : inline
1375 : void
1376 : destroy(
1377 : key_value_pair* first,
1378 : key_value_pair* last) noexcept;
1379 :
1380 : template<class FS, class FB>
1381 : auto
1382 : do_erase(
1383 : const_iterator pos,
1384 : FS small_reloc,
1385 : FB big_reloc) noexcept
1386 : -> iterator;
1387 :
1388 : inline
1389 : void
1390 : reindex_relocate(
1391 : key_value_pair* src,
1392 : key_value_pair* dst) noexcept;
1393 : };
1394 :
1395 : } // namespace json
1396 : } // namespace boost
1397 :
1398 : #ifndef BOOST_JSON_DOCS
1399 : // boost::hash trait
1400 : namespace boost
1401 : {
1402 : namespace container_hash
1403 : {
1404 :
1405 : template< class T > struct is_unordered_range;
1406 :
1407 : template<>
1408 : struct is_unordered_range< json::object >
1409 : : std::true_type
1410 : {};
1411 :
1412 : } // namespace container_hash
1413 : } // namespace boost
1414 :
1415 : // std::hash specialization
1416 : namespace std {
1417 : template <>
1418 : struct hash< ::boost::json::object > {
1419 : BOOST_JSON_DECL
1420 : std::size_t
1421 : operator()(::boost::json::object const& jo) const noexcept;
1422 : };
1423 : } // std
1424 : #endif
1425 :
1426 :
1427 : // Must be included here for this file to stand alone
1428 : #include <boost/json/value.hpp>
1429 :
1430 : // includes are at the bottom of <boost/json/value.hpp>
1431 :
1432 : #endif
|