blob: ab5c2cc1796dbe20242c35e24a6ea7919cdf71ba [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2017 The Chromium Authors
jdoerrie44efa9d2017-07-14 14:47:202// 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"
Tom Sepez04e98bf2024-10-25 18:19:3113#include "base/compiler_specific.h"
jdoerrie44efa9d2017-07-14 14:47:2014#include "base/containers/flat_map.h"
Keishi Hattorie175ac52022-06-07 06:24:5715#include "base/memory/raw_ptr.h"
jdoerrie44efa9d2017-07-14 14:47:2016
17namespace base {
18
19class Value;
20
21namespace detail {
22
23using 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.
30class 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
Daniel Chengbe3ac3a2024-05-15 17:38:2349 constexpr dict_iterator() = default;
jdoerrie44efa9d2017-07-14 14:47:2050 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
Daniel Chenga367fe52022-02-15 18:08:4868 // 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.
Tom Sepez04e98bf2024-10-25 18:19:3172 const DictStorage::iterator& GetUnderlyingIteratorDoNotUse() const
73 LIFETIME_BOUND {
Daniel Chenga367fe52022-02-15 18:08:4874 return dict_iter_;
75 }
76
jdoerrie44efa9d2017-07-14 14:47:2077 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.
86class 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
Daniel Chengbe3ac3a2024-05-15 17:38:23105 constexpr const_dict_iterator() = default;
jdoerrie44efa9d2017-07-14 14:47:20106 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
Daniel Chenga367fe52022-02-15 18:08:48124 // 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.
128 const DictStorage::const_iterator& GetUnderlyingIteratorDoNotUse() {
129 return dict_iter_;
130 }
131
jdoerrie44efa9d2017-07-14 14:47:20132 private:
133 DictStorage::const_iterator dict_iter_;
134};
135
jdoerrie44efa9d2017-07-14 14:47:20136} // namespace detail
137
138} // namespace base
139
140#endif // BASE_VALUE_ITERATORS_H_