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