summaryrefslogtreecommitdiff
path: root/chromium/base/value_iterators.h
blob: 928bda41204ce31021db67a667db6b53457d6e12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_VALUE_ITERATORS_H_
#define BASE_VALUE_ITERATORS_H_

#include <memory>
#include <string>
#include <utility>

#include "base/base_export.h"
#include "base/containers/flat_map.h"

namespace base {

class Value;

namespace detail {

using DictStorage = base::flat_map<std::string, std::unique_ptr<Value>>;

// This iterator closely resembles DictStorage::iterator, with one
// important exception. It abstracts the underlying unique_ptr away, meaning its
// value_type is std::pair<const std::string, Value>. It's reference type is a
// std::pair<const std::string&, Value&>, so that callers have read-write
// access without incurring a copy.
class BASE_EXPORT dict_iterator {
 public:
  using difference_type = DictStorage::iterator::difference_type;
  using value_type = std::pair<const std::string, Value>;
  using reference = std::pair<const std::string&, Value&>;
  using iterator_category = std::bidirectional_iterator_tag;

  class pointer {
   public:
    explicit pointer(const reference& ref);
    pointer(const pointer& ptr);
    pointer& operator=(const pointer& ptr) = delete;

    reference* operator->() { return &ref_; }

   private:
    reference ref_;
  };

  explicit dict_iterator(DictStorage::iterator dict_iter);
  dict_iterator(const dict_iterator& dict_iter);
  dict_iterator& operator=(const dict_iterator& dict_iter);
  ~dict_iterator();

  reference operator*();
  pointer operator->();

  dict_iterator& operator++();
  dict_iterator operator++(int);
  dict_iterator& operator--();
  dict_iterator operator--(int);

  BASE_EXPORT friend bool operator==(const dict_iterator& lhs,
                                     const dict_iterator& rhs);
  BASE_EXPORT friend bool operator!=(const dict_iterator& lhs,
                                     const dict_iterator& rhs);

 private:
  DictStorage::iterator dict_iter_;
};

// This iterator closely resembles DictStorage::const_iterator, with one
// important exception. It abstracts the underlying unique_ptr away, meaning its
// value_type is std::pair<const std::string, Value>. It's reference type is a
// std::pair<const std::string&, const Value&>, so that callers have read-only
// access without incurring a copy.
class BASE_EXPORT const_dict_iterator {
 public:
  using difference_type = DictStorage::const_iterator::difference_type;
  using value_type = std::pair<const std::string, Value>;
  using reference = std::pair<const std::string&, const Value&>;
  using iterator_category = std::bidirectional_iterator_tag;

  class pointer {
   public:
    explicit pointer(const reference& ref);
    pointer(const pointer& ptr);
    pointer& operator=(const pointer& ptr) = delete;

    const reference* operator->() const { return &ref_; }

   private:
    const reference ref_;
  };

  explicit const_dict_iterator(DictStorage::const_iterator dict_iter);
  const_dict_iterator(const const_dict_iterator& dict_iter);
  const_dict_iterator& operator=(const const_dict_iterator& dict_iter);
  ~const_dict_iterator();

  reference operator*() const;
  pointer operator->() const;

  const_dict_iterator& operator++();
  const_dict_iterator operator++(int);
  const_dict_iterator& operator--();
  const_dict_iterator operator--(int);

  BASE_EXPORT friend bool operator==(const const_dict_iterator& lhs,
                                     const const_dict_iterator& rhs);
  BASE_EXPORT friend bool operator!=(const const_dict_iterator& lhs,
                                     const const_dict_iterator& rhs);

 private:
  DictStorage::const_iterator dict_iter_;
};

// This class wraps the various |begin| and |end| methods of the underlying
// DictStorage in dict_iterators and const_dict_iterators. This allows callers
// to use this class for easy iteration over the underlying values, granting
// them either read-only or read-write access, depending on the
// const-qualification.
class BASE_EXPORT dict_iterator_proxy {
 public:
  using key_type = DictStorage::key_type;
  using mapped_type = DictStorage::mapped_type::element_type;
  using value_type = std::pair<key_type, mapped_type>;
  using key_compare = DictStorage::key_compare;
  using size_type = DictStorage::size_type;
  using difference_type = DictStorage::difference_type;

  using iterator = dict_iterator;
  using const_iterator = const_dict_iterator;
  using reverse_iterator = std::reverse_iterator<iterator>;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  explicit dict_iterator_proxy(DictStorage* storage);

  iterator begin();
  const_iterator begin() const;
  iterator end();
  const_iterator end() const;

  reverse_iterator rbegin();
  const_reverse_iterator rbegin() const;
  reverse_iterator rend();
  const_reverse_iterator rend() const;

  const_dict_iterator cbegin() const;
  const_dict_iterator cend() const;
  const_reverse_iterator crbegin() const;
  const_reverse_iterator crend() const;

 private:
  DictStorage* storage_;
};

// This class wraps the various const |begin| and |end| methods of the
// underlying DictStorage in const_dict_iterators. This allows callers to use
// this class for easy iteration over the underlying values, granting them
// either read-only access.
class BASE_EXPORT const_dict_iterator_proxy {
 public:
  using key_type = const DictStorage::key_type;
  using mapped_type = const DictStorage::mapped_type::element_type;
  using value_type = std::pair<key_type, mapped_type>;
  using key_compare = DictStorage::key_compare;
  using size_type = DictStorage::size_type;
  using difference_type = DictStorage::difference_type;

  using iterator = const_dict_iterator;
  using const_iterator = const_dict_iterator;
  using reverse_iterator = std::reverse_iterator<iterator>;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  explicit const_dict_iterator_proxy(const DictStorage* storage);

  const_iterator begin() const;
  const_iterator end() const;

  const_reverse_iterator rbegin() const;
  const_reverse_iterator rend() const;

  const_iterator cbegin() const;
  const_iterator cend() const;
  const_reverse_iterator crbegin() const;
  const_reverse_iterator crend() const;

 private:
  const DictStorage* storage_;
};
}  // namespace detail

}  // namespace base

#endif  // BASE_VALUE_ITERATORS_H_