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