MySQL 9.6.0
Source Code Documentation
flat_view.h
Go to the documentation of this file.
1// Copyright (c) 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_RANGES_FLAT_VIEW_H
25#define MYSQL_RANGES_FLAT_VIEW_H
26
27/// @file
28/// Experimental API header
29
30#include <ranges> // view_base
31#include "mysql/iterators/iterator_interface.h" // Iterator_interface
32#include "mysql/ranges/collection_interface.h" // Collection_interface
33#include "mysql/ranges/iterator_with_range.h" // Iterator_with_range
34#include "mysql/ranges/meta.h" // Iterator_value_type
35#include "mysql/ranges/view_sources.h" // View_source
36
37/// @addtogroup GroupLibsMysqlRanges
38/// @{
39
40namespace mysql::ranges {
41
42/// Default Unfold class.
43///
44/// In general, an *Unfold class* has a static member function `unfold` that
45/// takes an object as argument and returns a `range` (satisfying
46/// `std::ranges::range`). `T` can be thought of as a "placeholder" from which
47/// an appropriate Unfold class can extract a range.
48///
49/// This Unfold class is defined for the special case that `T` is a range
50/// already, and its `unfold` member function returns the parameter unchanged.
52 [[nodiscard]] static constexpr const auto &unfold(
53 const std::ranges::range auto &source) {
54 return source;
55 }
56};
57
58/// True if `Unfold_t<Source_t>::unfold(Source_t)` is defined and returns a
59/// range.
60template <class Source_t, class Unfold_t>
61concept Can_unfold_with = requires(Source_t source) {
62 { Unfold_t::unfold(source) } -> std::ranges::range;
63 };
64
65/// Provides the type of the range returned from `unfold<Unfold_t>(Source_t)`.
66template <class Source_t, class Unfold_t>
68 std::remove_cvref_t<decltype(Unfold_t::unfold(std::declval<Source_t>()))>;
69
70/// True if Source_t can be unfolded, and also the value type for the unfolded
71/// range can be unfolded, using the given Unfold_t function.
72template <class Source_t, class Unfold_t>
76 Unfold_t>;
77
78/// Forward declaration.
79template <class Source_tp, class Unfold_tp>
80class Flat_view;
81
82/// Factory function to create a range view over a flattened sequence of
83/// elements from given source.
84///
85/// For example, if `source` is of type `std::vector<std::map<A,
86/// std::list<B>>>`, `make_flat_view(source)` is a range view over `B` objects.
87///
88/// In case any map or list is empty, it is only skipped over; the resulting
89/// range contains only valid elements and no "gaps".
90///
91/// @tparam Unfold_t Unfold class. This is used to obtain ranges from the
92/// source, and from its sub-objects. For example, we expect
93/// `make_flat_view(std::map<A, std::map<B, C>>&)` to provide iterators over
94/// `C`. While unfolding the outer map, the implementation needs a range over
95/// `std::map<B, C>` objects, and while unfolding each such inner `std::map<B,
96/// C>` object, the implementation needs a range over `C` objects. But
97/// `std::map` does not give that; it only gives ranges over `std::pair<A,
98/// std::map<B, C>>` and `std::pair<B, C>`. In such cases, the user needs to
99/// provide a custom Unfold class through this parameter, which should have a
100/// member function `unfold(std::map<X, Y>)` returning a range over `Y` objects.
101///
102/// @tparam Source_t Type of source.
103///
104/// @param source Source object.
105template <class Unfold_t = Default_unfold, Can_unfold_with<Unfold_t> Source_t>
106[[nodiscard]] decltype(auto) make_flat_view(const Source_t &source) {
109 } else {
110 return Unfold_t::unfold(source);
111 }
112}
113
114/// Type of the `flat view` returned from `make_flat_view<Unfold_t>(Source_T&)`.
115template <class Source_t, class Unfold_t>
116 requires Can_unfold_with<Source_t, Unfold_t>
117using Flat_view_type = std::remove_cvref_t<decltype(make_flat_view<Unfold_t>(
118 std::declval<Source_t>()))>;
119
120/// Iterator adaptor that recursively flattens the sequence of a given iterator
121/// over a nested sequence.
122///
123/// For each value `v` yielded by iterators of the range unfolded from the given
124/// source, this iterator recursively flattens the range given by
125/// Unfold_t::unfold(v), and yields all elements in that flattened sequence.
126///
127/// This iterator implements the recursive step of procedure to flatten a range.
128/// The base case occurs when `Unfold::unfold(v)` is not defined, in which case
129/// make_flat_view provides the range unfolded from the source without using
130/// this class to attempt to flatten it.
131///
132/// @tparam Outer_range_tp Type of the outermost range. It is required that
133/// `Unfold_tp::unfold(v)` is defined, where `v` is an object of the range's
134/// value type.
135///
136/// @tparam Unfold_tp Class to obtain range views from the range's values; from
137/// the values of those range views, and so on, recursively.
138template <class Outer_range_tp, class Unfold_tp>
140 Flat_iterator<Outer_range_tp, Unfold_tp>> {
141 // Example: Suppose we have the nested structure `set<map<int, float>>` and we
142 // wish to get a linear sequence of all `float` values. Then we instantiate
143 // this class with the following template parameters:
144 //
145 // - Outer_range_tp = set<map<int float>>
146 //
147 // - Unfold_tp is class such that `Unfold_tp::unfold(x)` returns
148 // `make_value_view(x)` whenever `x` is of type `map<int, float>`.
149 //
150 // The member types are then as follows:
151 //
152 // Outer_iterator_t = set<map<int, float>>::iterator
153 // Inner_source_t = map<int, float>
154 // Inner_range_t = Value_view<map<int, float>>
155 using Outer_range_t = Outer_range_tp;
156 using Unfold_t = Unfold_tp;
161
164
165 public:
166 Flat_iterator() = default;
167 explicit Flat_iterator(const Outer_range_t &outer_range,
168 const Outer_iterator_t &outer_iterator)
169 : m_outer(outer_range, outer_iterator) {
170 if (!m_outer.is_end()) {
171 reset_inner();
172 fix_position();
173 }
174 }
175 explicit Flat_iterator(const Outer_range_t &outer_range)
176 : Flat_iterator(outer_range, outer_range.begin()) {}
177
178 [[nodiscard]] decltype(auto) get() const { return *m_inner; }
179
180 void next() {
181 ++m_inner;
182 fix_position();
183 }
184
185 [[nodiscard]] bool is_equal(const Flat_iterator &other) const {
186 if (m_outer != other.m_outer) return false;
187 if (m_outer.is_end()) return true;
188 return m_inner == other.m_inner;
189 }
190
191 private:
192 void reset_inner() { m_inner = Inner_t(make_flat_view<Unfold_t>(*m_outer)); }
193
194 /// While not at a valid position, advance the positions.
195 ///
196 /// A "valid position" is one where either the outer iterator points to the
197 /// end, or the inner iterator does not point to the end.
199 while (m_inner.is_end()) {
200 ++m_outer;
201 if (m_outer.is_end()) return;
202 reset_inner();
203 }
204 }
205
206 /// The outer range and current iterator to it.
208
209 /// The range and iterator that m_outer.iterator() currently points to.
211}; // class Flat_iterator
212
213/// Returns a flat iterator over the range starting at `iterator`. This is the
214/// appropriate `Flat_iterator` wrapper if `Can_unfold_with` is true for
215/// `Iterator_t`'s value type; otherwise it is `iterator` itself.
216template <class Unfold_t, class Range_t>
217[[nodiscard]] auto make_flat_iterator(
218 const Range_t &range, const Range_const_iterator_type<Range_t> &iterator) {
219 constexpr bool has_inner_range =
221 if constexpr (has_inner_range) {
222 return Flat_iterator<Range_t, Unfold_t>(range, iterator);
223 } else {
224 return iterator;
225 }
226}
227
228/// Flat view over the innermost elements of a type that unfolds to a range,
229/// whose value type also unfolds to a range (possibly recursively).
230///
231/// @tparam Source_tp Type that can be unfolded to a range.
232///
233/// @tparam Unfold_tp Unfold function.
234template <class Source_tp, class Unfold_tp>
235class Flat_view : public Collection_interface<Flat_view<Source_tp, Unfold_tp>>,
236 public std::ranges::view_base {
237 using Source_t = Source_tp;
238 using Unfold_t = Unfold_tp;
239
242
243 public:
244 Flat_view() = default;
245 explicit Flat_view(const Source_t &source)
246 : m_range(Unfold_t::unfold(source)) {}
247
248 [[nodiscard]] auto begin() const {
249 decltype(auto) range = m_range.get();
250 return make_flat_iterator<Unfold_t>(range, range.begin());
251 }
252 [[nodiscard]] auto end() const {
253 decltype(auto) range = m_range.get();
254 return make_flat_iterator<Unfold_t>(range, range.end());
255 }
256
257 private:
259}; // class Flat_view
260
261} // namespace mysql::ranges
262
263// addtogroup GroupLibsMysqlRanges
264/// @}
265
266#endif // ifndef MYSQL_RANGES_FLAT_VIEW_H
CRTP base class (mixin) that makes your class a standard-compliant iterator, given only a minimal set...
Definition: iterator_interface.h:370
CRTP base class to provide members of a collection based on an implementation that provides begin/end...
Definition: collection_interface.h:90
Iterator adaptor that recursively flattens the sequence of a given iterator over a nested sequence.
Definition: flat_view.h:140
void next()
Definition: flat_view.h:180
void reset_inner()
Definition: flat_view.h:192
Outer_t m_outer
The outer range and current iterator to it.
Definition: flat_view.h:207
Flat_iterator(const Outer_range_t &outer_range)
Definition: flat_view.h:175
bool is_equal(const Flat_iterator &other) const
Definition: flat_view.h:185
Flat_view_type< Inner_source_t, Unfold_t > Inner_range_t
Definition: flat_view.h:160
Iterator_value_type< Outer_iterator_t > Inner_source_t
Definition: flat_view.h:159
mysql::ranges::Range_const_iterator_type< Outer_range_t > Outer_iterator_t
Definition: flat_view.h:158
void fix_position()
While not at a valid position, advance the positions.
Definition: flat_view.h:198
Inner_t m_inner
The range and iterator that m_outer.iterator() currently points to.
Definition: flat_view.h:210
Iterator_with_range< Inner_range_t > Inner_t
Definition: flat_view.h:163
Unfold_tp Unfold_t
Definition: flat_view.h:156
Outer_range_tp Outer_range_t
Definition: flat_view.h:155
decltype(auto) get() const
Definition: flat_view.h:178
Flat_iterator(const Outer_range_t &outer_range, const Outer_iterator_t &outer_iterator)
Definition: flat_view.h:167
Forward declaration.
Definition: flat_view.h:236
auto begin() const
Definition: flat_view.h:248
Unfold_tp Unfold_t
Definition: flat_view.h:238
auto end() const
Definition: flat_view.h:252
Flat_view(const Source_t &source)
Definition: flat_view.h:245
Source_tp Source_t
Definition: flat_view.h:237
Unfolded_type< Source_t, Unfold_t > Range_t
Definition: flat_view.h:240
Range_ref_t m_range
Definition: flat_view.h:258
bool is_end() const
Definition: iterator_with_range.h:103
const Raw_source_t & get() const
Return a copy of the stored object if it is owned; otherwise a reference to it.
Definition: view_sources.h:125
Experimental API header.
True if Source_t can be unfolded, and also the value type for the unfolded range can be unfolded,...
Definition: flat_view.h:73
True if Unfold_t<Source_t>unfold(Source_t) is defined and returns a range.
Definition: flat_view.h:61
Experimental API header.
Experimental API header.
Experimental API header.
Definition: buffer_interface.h:40
std::remove_cvref_t< decltype(std::declval< const Range_t >().begin())> Range_const_iterator_type
Gives the const_iterator type, deduced from the begin() const member.
Definition: meta.h:47
std::remove_cvref_t< decltype(make_flat_view< Unfold_t >(std::declval< Source_t >()))> Flat_view_type
Type of the flat view returned from make_flat_view<Unfold_t>(Source_T&).
Definition: flat_view.h:118
std::remove_cvref_t< decltype(Unfold_t::unfold(std::declval< Source_t >()))> Unfolded_type
Provides the type of the range returned from unfold<Unfold_t>(Source_t).
Definition: flat_view.h:68
std::remove_cvref_t< decltype(*std::declval< Iterator_t >())> Iterator_value_type
Gives the value type for any iterator type, deduced from operator *.
Definition: meta.h:63
auto make_flat_iterator(const Range_t &range, const Range_const_iterator_type< Range_t > &iterator)
Returns a flat iterator over the range starting at iterator.
Definition: flat_view.h:217
decltype(auto) make_flat_view(const Source_t &source)
Factory function to create a range view over a flattened sequence of elements from given source.
Definition: flat_view.h:106
const char * begin(const char *const c)
Definition: base64.h:44
repeated Source source
Definition: replication_asynchronous_connection_failover.proto:42
Default Unfold class.
Definition: flat_view.h:51
static constexpr const auto & unfold(const std::ranges::range auto &source)
Definition: flat_view.h:52
Definition: gen_lex_token.cc:149
const int end
Definition: gen_lex_token.cc:233
Experimental API header.