1 // Copyright 2017 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_VALUE_ITERATORS_H_ 6 #define BASE_VALUE_ITERATORS_H_ 7 8 #include <memory> 9 #include <string> 10 #include <utility> 11 12 #include "base/base_export.h" 13 #include "base/compiler_specific.h" 14 #include "base/containers/flat_map.h" 15 #include "base/memory/raw_ptr.h" 16 17 namespace base { 18 19 class Value; 20 21 namespace detail { 22 23 using DictStorage = base::flat_map<std::string, std::unique_ptr<Value>>; 24 25 // This iterator closely resembles DictStorage::iterator, with one 26 // important exception. It abstracts the underlying unique_ptr away, meaning its 27 // value_type is std::pair<const std::string, Value>. It's reference type is a 28 // std::pair<const std::string&, Value&>, so that callers have read-write 29 // access without incurring a copy. 30 class BASE_EXPORT dict_iterator { 31 public: 32 using difference_type = DictStorage::iterator::difference_type; 33 using value_type = std::pair<const std::string, Value>; 34 using reference = std::pair<const std::string&, Value&>; 35 using iterator_category = std::bidirectional_iterator_tag; 36 37 class pointer { 38 public: 39 explicit pointer(const reference& ref); 40 pointer(const pointer& ptr); 41 pointer& operator=(const pointer& ptr) = delete; 42 43 reference* operator->() { return &ref_; } 44 45 private: 46 reference ref_; 47 }; 48 49 constexpr dict_iterator() = default; 50 explicit dict_iterator(DictStorage::iterator dict_iter); 51 dict_iterator(const dict_iterator& dict_iter); 52 dict_iterator& operator=(const dict_iterator& dict_iter); 53 ~dict_iterator(); 54 55 reference operator*(); 56 pointer operator->(); 57 58 dict_iterator& operator++(); 59 dict_iterator operator++(int); 60 dict_iterator& operator--(); 61 dict_iterator operator--(int); 62 63 BASE_EXPORT friend bool operator==(const dict_iterator& lhs, 64 const dict_iterator& rhs); 65 BASE_EXPORT friend bool operator!=(const dict_iterator& lhs, 66 const dict_iterator& rhs); 67 68 // Currently, there is no easy way to friend Value::Dict. Once dictionary 69 // storage is updated to not require a proxy iterator, the implementation can 70 // be folded into //base/values.h and a standard friend declaration can be 71 // used instead. GetUnderlyingIteratorDoNotUse()72 const DictStorage::iterator& GetUnderlyingIteratorDoNotUse() const 73 LIFETIME_BOUND { 74 return dict_iter_; 75 } 76 77 private: 78 DictStorage::iterator dict_iter_; 79 }; 80 81 // This iterator closely resembles DictStorage::const_iterator, with one 82 // important exception. It abstracts the underlying unique_ptr away, meaning its 83 // value_type is std::pair<const std::string, Value>. It's reference type is a 84 // std::pair<const std::string&, const Value&>, so that callers have read-only 85 // access without incurring a copy. 86 class BASE_EXPORT const_dict_iterator { 87 public: 88 using difference_type = DictStorage::const_iterator::difference_type; 89 using value_type = std::pair<const std::string, Value>; 90 using reference = std::pair<const std::string&, const Value&>; 91 using iterator_category = std::bidirectional_iterator_tag; 92 93 class pointer { 94 public: 95 explicit pointer(const reference& ref); 96 pointer(const pointer& ptr); 97 pointer& operator=(const pointer& ptr) = delete; 98 99 const reference* operator->() const { return &ref_; } 100 101 private: 102 const reference ref_; 103 }; 104 105 constexpr const_dict_iterator() = default; 106 explicit const_dict_iterator(DictStorage::const_iterator dict_iter); 107 const_dict_iterator(const const_dict_iterator& dict_iter); 108 const_dict_iterator& operator=(const const_dict_iterator& dict_iter); 109 ~const_dict_iterator(); 110 111 reference operator*() const; 112 pointer operator->() const; 113 114 const_dict_iterator& operator++(); 115 const_dict_iterator operator++(int); 116 const_dict_iterator& operator--(); 117 const_dict_iterator operator--(int); 118 119 BASE_EXPORT friend bool operator==(const const_dict_iterator& lhs, 120 const const_dict_iterator& rhs); 121 BASE_EXPORT friend bool operator!=(const const_dict_iterator& lhs, 122 const const_dict_iterator& rhs); 123 124 // Currently, there is no easy way to friend Value::Dict. Once dictionary 125 // storage is updated to not require a proxy iterator, the implementation can 126 // be folded into //base/values.h and a standard friend declaration can be 127 // used instead. GetUnderlyingIteratorDoNotUse()128 const DictStorage::const_iterator& GetUnderlyingIteratorDoNotUse() { 129 return dict_iter_; 130 } 131 132 private: 133 DictStorage::const_iterator dict_iter_; 134 }; 135 136 } // namespace detail 137 138 } // namespace base 139 140 #endif // BASE_VALUE_ITERATORS_H_ 141