1 // Copyright 2017 The Chromium Authors. All rights reserved. 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/containers/flat_map.h" 13 #include "base/macros.h" 14 15 namespace base { 16 17 class Value; 18 19 namespace detail { 20 21 using DictStorage = base::flat_map<std::string, std::unique_ptr<Value>>; 22 23 // This iterator closely resembles DictStorage::iterator, with one 24 // important exception. It abstracts the underlying unique_ptr away, meaning its 25 // value_type is std::pair<const std::string, Value>. It's reference type is a 26 // std::pair<const std::string&, Value&>, so that callers have read-write 27 // access without incurring a copy. 28 class dict_iterator { 29 public: 30 using difference_type = DictStorage::iterator::difference_type; 31 using value_type = std::pair<const std::string, Value>; 32 using reference = std::pair<const std::string&, Value&>; 33 using iterator_category = std::bidirectional_iterator_tag; 34 35 class pointer { 36 public: 37 explicit pointer(const reference& ref); 38 pointer(const pointer& ptr); 39 pointer& operator=(const pointer& ptr) = delete; 40 41 reference* operator->() { return &ref_; } 42 43 private: 44 reference ref_; 45 }; 46 47 explicit dict_iterator(DictStorage::iterator dict_iter); 48 dict_iterator(const dict_iterator& dict_iter); 49 dict_iterator& operator=(const dict_iterator& dict_iter); 50 ~dict_iterator(); 51 52 reference operator*(); 53 pointer operator->(); 54 55 dict_iterator& operator++(); 56 dict_iterator operator++(int); 57 dict_iterator& operator--(); 58 dict_iterator operator--(int); 59 60 friend bool operator==(const dict_iterator& lhs, const dict_iterator& rhs); 61 friend bool operator!=(const dict_iterator& lhs, const dict_iterator& rhs); 62 63 private: 64 DictStorage::iterator dict_iter_; 65 }; 66 67 // This iterator closely resembles DictStorage::const_iterator, with one 68 // important exception. It abstracts the underlying unique_ptr away, meaning its 69 // value_type is std::pair<const std::string, Value>. It's reference type is a 70 // std::pair<const std::string&, const Value&>, so that callers have read-only 71 // access without incurring a copy. 72 class const_dict_iterator { 73 public: 74 using difference_type = DictStorage::const_iterator::difference_type; 75 using value_type = std::pair<const std::string, Value>; 76 using reference = std::pair<const std::string&, const Value&>; 77 using iterator_category = std::bidirectional_iterator_tag; 78 79 class pointer { 80 public: 81 explicit pointer(const reference& ref); 82 pointer(const pointer& ptr); 83 pointer& operator=(const pointer& ptr) = delete; 84 85 const reference* operator->() const { return &ref_; } 86 87 private: 88 const reference ref_; 89 }; 90 91 explicit const_dict_iterator(DictStorage::const_iterator dict_iter); 92 const_dict_iterator(const const_dict_iterator& dict_iter); 93 const_dict_iterator& operator=(const const_dict_iterator& dict_iter); 94 ~const_dict_iterator(); 95 96 reference operator*() const; 97 pointer operator->() const; 98 99 const_dict_iterator& operator++(); 100 const_dict_iterator operator++(int); 101 const_dict_iterator& operator--(); 102 const_dict_iterator operator--(int); 103 104 friend bool operator==(const const_dict_iterator& lhs, 105 const const_dict_iterator& rhs); 106 friend bool operator!=(const const_dict_iterator& lhs, 107 const const_dict_iterator& rhs); 108 109 private: 110 DictStorage::const_iterator dict_iter_; 111 }; 112 113 // This class wraps the various |begin| and |end| methods of the underlying 114 // DictStorage in dict_iterators and const_dict_iterators. This allows callers 115 // to use this class for easy iteration over the underlying values, granting 116 // them either read-only or read-write access, depending on the 117 // const-qualification. 118 class dict_iterator_proxy { 119 public: 120 using key_type = DictStorage::key_type; 121 using mapped_type = DictStorage::mapped_type::element_type; 122 using value_type = std::pair<key_type, mapped_type>; 123 using key_compare = DictStorage::key_compare; 124 using size_type = DictStorage::size_type; 125 using difference_type = DictStorage::difference_type; 126 127 using iterator = dict_iterator; 128 using const_iterator = const_dict_iterator; 129 using reverse_iterator = std::reverse_iterator<iterator>; 130 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 131 132 explicit dict_iterator_proxy(DictStorage* storage); 133 134 iterator begin(); 135 const_iterator begin() const; 136 iterator end(); 137 const_iterator end() const; 138 139 reverse_iterator rbegin(); 140 const_reverse_iterator rbegin() const; 141 reverse_iterator rend(); 142 const_reverse_iterator rend() const; 143 144 const_dict_iterator cbegin() const; 145 const_dict_iterator cend() const; 146 const_reverse_iterator crbegin() const; 147 const_reverse_iterator crend() const; 148 149 private: 150 DictStorage* storage_; 151 }; 152 153 // This class wraps the various const |begin| and |end| methods of the 154 // underlying DictStorage in const_dict_iterators. This allows callers to use 155 // this class for easy iteration over the underlying values, granting them 156 // either read-only access. 157 class const_dict_iterator_proxy { 158 public: 159 using key_type = const DictStorage::key_type; 160 using mapped_type = const DictStorage::mapped_type::element_type; 161 using value_type = std::pair<key_type, mapped_type>; 162 using key_compare = DictStorage::key_compare; 163 using size_type = DictStorage::size_type; 164 using difference_type = DictStorage::difference_type; 165 166 using iterator = const_dict_iterator; 167 using const_iterator = const_dict_iterator; 168 using reverse_iterator = std::reverse_iterator<iterator>; 169 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 170 171 explicit const_dict_iterator_proxy(const DictStorage* storage); 172 173 const_iterator begin() const; 174 const_iterator end() const; 175 176 const_reverse_iterator rbegin() const; 177 const_reverse_iterator rend() const; 178 179 const_iterator cbegin() const; 180 const_iterator cend() const; 181 const_reverse_iterator crbegin() const; 182 const_reverse_iterator crend() const; 183 184 private: 185 const DictStorage* storage_; 186 }; 187 } // namespace detail 188 189 } // namespace base 190 191 #endif // BASE_VALUE_ITERATORS_H_ 192