blob: 49d78085dce85905658d221e313c2303ab1a7941 [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
Peter Kastingc573e2d2025-01-10 21:00:0027// reference type is a std::pair<const std::string&, Value&>, so that callers
28// have read-write access without incurring a copy.
jdoerrie44efa9d2017-07-14 14:47:2029class BASE_EXPORT dict_iterator {
30 public:
31 using difference_type = DictStorage::iterator::difference_type;
Peter Kastingc573e2d2025-01-10 21:00:0032 using value_type = std::pair<const std::string&, Value&>;
33 using reference = value_type;
jdoerrie44efa9d2017-07-14 14:47:2034 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
Daniel Chengbe3ac3a2024-05-15 17:38:2348 constexpr dict_iterator() = default;
jdoerrie44efa9d2017-07-14 14:47:2049 explicit dict_iterator(DictStorage::iterator dict_iter);
50 dict_iterator(const dict_iterator& dict_iter);
51 dict_iterator& operator=(const dict_iterator& dict_iter);
52 ~dict_iterator();
53
Peter Kastingc573e2d2025-01-10 21:00:0054 reference operator*() const;
55 pointer operator->() const;
jdoerrie44efa9d2017-07-14 14:47:2056
57 dict_iterator& operator++();
58 dict_iterator operator++(int);
59 dict_iterator& operator--();
60 dict_iterator operator--(int);
61
62 BASE_EXPORT friend bool operator==(const dict_iterator& lhs,
63 const dict_iterator& rhs);
64 BASE_EXPORT friend bool operator!=(const dict_iterator& lhs,
65 const dict_iterator& rhs);
66
Daniel Chenga367fe52022-02-15 18:08:4867 // Currently, there is no easy way to friend Value::Dict. Once dictionary
68 // storage is updated to not require a proxy iterator, the implementation can
69 // be folded into //base/values.h and a standard friend declaration can be
70 // used instead.
Tom Sepez04e98bf2024-10-25 18:19:3171 const DictStorage::iterator& GetUnderlyingIteratorDoNotUse() const
72 LIFETIME_BOUND {
Daniel Chenga367fe52022-02-15 18:08:4873 return dict_iter_;
74 }
75
jdoerrie44efa9d2017-07-14 14:47:2076 private:
77 DictStorage::iterator dict_iter_;
78};
79
80// This iterator closely resembles DictStorage::const_iterator, with one
81// important exception. It abstracts the underlying unique_ptr away, meaning its
Peter Kastingc573e2d2025-01-10 21:00:0082// reference type is a std::pair<const std::string&, const Value&>, so that
83// callers have read-only access without incurring a copy.
jdoerrie44efa9d2017-07-14 14:47:2084class BASE_EXPORT const_dict_iterator {
85 public:
86 using difference_type = DictStorage::const_iterator::difference_type;
Peter Kastingc573e2d2025-01-10 21:00:0087 using value_type = std::pair<const std::string&, const Value&>;
88 using reference = value_type;
jdoerrie44efa9d2017-07-14 14:47:2089 using iterator_category = std::bidirectional_iterator_tag;
90
91 class pointer {
92 public:
93 explicit pointer(const reference& ref);
94 pointer(const pointer& ptr);
95 pointer& operator=(const pointer& ptr) = delete;
96
97 const reference* operator->() const { return &ref_; }
98
99 private:
100 const reference ref_;
101 };
102
Daniel Chengbe3ac3a2024-05-15 17:38:23103 constexpr const_dict_iterator() = default;
jdoerrie44efa9d2017-07-14 14:47:20104 explicit const_dict_iterator(DictStorage::const_iterator dict_iter);
105 const_dict_iterator(const const_dict_iterator& dict_iter);
106 const_dict_iterator& operator=(const const_dict_iterator& dict_iter);
107 ~const_dict_iterator();
108
109 reference operator*() const;
110 pointer operator->() const;
111
112 const_dict_iterator& operator++();
113 const_dict_iterator operator++(int);
114 const_dict_iterator& operator--();
115 const_dict_iterator operator--(int);
116
117 BASE_EXPORT friend bool operator==(const const_dict_iterator& lhs,
118 const const_dict_iterator& rhs);
119 BASE_EXPORT friend bool operator!=(const const_dict_iterator& lhs,
120 const const_dict_iterator& rhs);
121
Daniel Chenga367fe52022-02-15 18:08:48122 // Currently, there is no easy way to friend Value::Dict. Once dictionary
123 // storage is updated to not require a proxy iterator, the implementation can
124 // be folded into //base/values.h and a standard friend declaration can be
125 // used instead.
126 const DictStorage::const_iterator& GetUnderlyingIteratorDoNotUse() {
127 return dict_iter_;
128 }
129
jdoerrie44efa9d2017-07-14 14:47:20130 private:
131 DictStorage::const_iterator dict_iter_;
132};
133
jdoerrie44efa9d2017-07-14 14:47:20134} // namespace detail
135
136} // namespace base
137
138#endif // BASE_VALUE_ITERATORS_H_