MySQL 9.6.0
Source Code Documentation
map_nested_storage.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_SETS_MAP_NESTED_STORAGE_H
25#define MYSQL_SETS_MAP_NESTED_STORAGE_H
26
27/// @file
28/// Experimental API header
29
30#include <concepts> // same_as
31#include <iterator> // next
32#include <map> // map
33#include "mysql/allocators/allocator.h" // Allocator
34#include "mysql/allocators/memory_resource.h" // Memory_resource
35#include "mysql/containers/basic_container_wrapper.h" // Basic_container_wrapper
36#include "mysql/containers/map_or_set_assign.h" // map_or_set_assign
37#include "mysql/iterators/meta.h" // Is_declared_legacy_bidirectional_iterator
38#include "mysql/ranges/meta.h" // Range_iterator_type
39#include "mysql/sets/nested_set_meta.h" // Is_nested_set_traits
40#include "mysql/sets/upper_lower_bound_interface.h" // Upper_lower_bound_interface
41#include "mysql/utils/call_and_catch.h" // call_and_catch
42#include "mysql/utils/return_status.h" // Return_status
43
44/// @addtogroup GroupLibsMysqlSets
45/// @{
46
47namespace mysql::sets {
48
49/// Storage for nested sets, backed by a std::map.
50///
51/// @tparam Set_traits_tp Nested set traits.
52///
53/// @tparam Map_tp Type of map. This should have an API similar to std::map,
54/// with key type equal to Set_traits_tp::Key_traits_t::Element_t and value type
55/// a Set with category Set_traits_tp::Mapped_category_t and traits
56/// Set_traits_tp::Mapped_traits_t.
57template <Is_nested_set_traits Set_traits_tp, class Map_tp>
60 Map_nested_storage<Set_traits_tp, Map_tp>, Map_tp>,
62 Map_nested_storage<Set_traits_tp, Map_tp>,
63 typename Set_traits_tp::Key_traits_t,
64 mysql::ranges::Range_iterator_type<Map_tp>,
65 mysql::ranges::Range_const_iterator_type<Map_tp>,
66 Iterator_get_first> {
67 public:
68 using Set_traits_t = Set_traits_tp;
69 using Map_t = Map_tp;
73
74 using Key_traits_t = typename Set_traits_t::Key_traits_t;
75 using Key_t = typename Key_traits_t::Element_t;
76 using Mapped_traits_t = typename Set_traits_t::Mapped_traits_t;
77 using Mapped_category_t = typename Set_traits_t::Mapped_category_t;
78
82 static_assert(std::bidirectional_iterator<Iterator_t>);
83 static_assert(
86
89
90 static_assert(std::same_as<Key_t, mysql::ranges::Map_key_type<Map_t>>);
91 static_assert(
93 Map_t>::Set_category_t>);
94 static_assert(std::same_as<
97
98 static_assert(std::same_as<Value_t, std::pair<const Key_t, Mapped_t>>);
99
101 const Memory_resource_t &memory_resource = Memory_resource_t{}) noexcept
102 : Basic_container_wrapper_t(Allocator_t(memory_resource)) {}
103
104 // use defaults for move/destructor; delete copy
105 Map_nested_storage(const This_t &) = delete;
107 This_t &operator=(const This_t &) = delete;
108 This_t &operator=(This_t &&) noexcept = default;
109 ~Map_nested_storage() = default;
110
112
113 template <class Iterator_t>
114 requires std::same_as<mysql::ranges::Iterator_value_type<Iterator_t>,
115 Mapped_t>
116 [[nodiscard]] auto assign(const Iterator_t &it1,
117 const Iterator_t &it2) noexcept {
118 return mysql::containers::map_or_set_assign(map(), it1, it2);
119 }
120
121 template <class Iterator_t>
122 [[nodiscard]] auto assign(const Iterator_t &it1,
123 const Iterator_t &it2) noexcept {
125 this->clear();
126 for (auto input = it1; input != it2; ++input) {
127 auto opt_output = this->emplace(input->first);
128 if (!opt_output.has_value()) return Return_status::error;
129 auto &output_mapped = opt_output.value()->second;
130 auto ret = output_mapped.assign(input->second);
131 if (ret == Return_status::error) return ret;
132 }
133 return Return_status::ok;
134 }
135
136 /// @return Non-const reference to the underlying map object.
137 [[nodiscard]] auto &map() noexcept { return this->wrapped(); }
138
139 /// @return Const reference to the underlying map object.
140 [[nodiscard]] const auto &map() const noexcept { return this->wrapped(); }
141
142 /// @return iterator to the entry with the given key, or end() if there is no
143 /// entry for the given key.
144 [[nodiscard]] Iterator_t find(const Key_t &key) noexcept {
145 auto ret = map().find(key);
146 return ret;
147 }
148
149 /// @return const iterator to the entry with the given key, or end() if there
150 /// is no entry for the given key.
151 [[nodiscard]] Const_iterator_t find(const Key_t &key) const noexcept {
152 auto ret = map().find(key);
153 return ret;
154 }
155
156 private:
157 /// Common implementation of the const and non-const versions of find(cursor,
158 /// key).
159 ///
160 /// @tparam Iter One of Iterator_t or Const_iterator_t
161 ///
162 /// @param the_map Reference or const reference to map().
163 ///
164 /// @param cursor Cursor position.
165 ///
166 /// @param key Key to search for.
167 ///
168 /// @return Iterator to element equal to @c key, or end() if none found.
169 template <class Iter>
170 [[nodiscard]] static Iter do_find(auto &the_map, Iter &cursor,
171 const Key_t &key) noexcept {
172 assert(cursor == the_map.begin() ||
173 Key_traits_t::lt(std::ranges::prev(cursor)->first, key));
174 // See if the hint allows us to return in constant time.
175 if (cursor != the_map.end()) {
176 auto order = Key_traits_t::cmp(key, cursor->first);
177 if (order == 0) {
178 // The key was found at the cursor position. Advance the cursor.
179 Iter ret = cursor;
180 ++cursor;
181 return ret;
182 }
183 if (order < 0) return the_map.end();
184 assert(order > 0);
185 }
186 // Look up the element in logarithmic time, update cursor, compute return
187 // value.
188 cursor = the_map.lower_bound(key);
189 if (cursor == the_map.end()) {
190 // Nothing found, and the cursor has moved to the end of the container.
191 return the_map.end();
192 }
193 if (cursor->first == key) {
194 // The key was found after the cursor position. Advance the cursor.
195 Iter ret{cursor};
196 ++cursor;
197 return ret;
198 }
199 // The key was not found, the cursor position may have advanced.
200 return the_map.end();
201 }
202
203 public:
204 /// @return iterator to the entry with the given key, or end() if there is no
205 /// entry for the given key. This uses the given cursor hint to make the
206 /// operation constant-time in case key <= cursor->first.
207 ///
208 /// @param[in,out] cursor Iterator hint. If this is greater than
209 /// map::lower_bound(key), the behavior is undefined. It will be updated to
210 /// the upper bound for the key. Thus, it is suitable to use in successive
211 /// calls to this function with increasing keys.
212 ///
213 /// @param key The key to find.
214 ///
215 /// @return Iterator to element equal to key, or end if no such element
216 /// exists.
217 [[nodiscard]] Iterator_t find(Iterator_t &cursor, const Key_t &key) noexcept {
218 return do_find(map(), cursor, key);
219 }
220
221 /// @return const iterator to the entry with the given key, or end() if there
222 /// is no entry for the given key. This uses the given cursor hint to make the
223 /// operation constant-time in case key <= cursor->first.
224 ///
225 /// @param[in,out] cursor Iterator hint. If this is greater than
226 /// map::lower_bound(key), the behavior is undefined. It will be updated to
227 /// the upper bound for the key. Thus, it is suitable to use in successive
228 /// calls to this function with increasing keys.
229 ///
230 /// @param key The key to find.
231 ///
232 /// @return Iterator to element equal to key, or end if no such element
233 /// exists.
235 const Key_t &key) const noexcept {
236 return do_find(map(), cursor, key);
237 }
238
239 /// If no entry with the given key exists, insert one using the given cursor
240 /// hint, and default-construct the mapped object.
241 ///
242 /// @param[in,out] cursor Iterator. If this points to the insertion position,
243 /// the insertion is O(1) time. Will be updated to the next element after the
244 /// inserted one.
245 ///
246 /// @param key Key to insert.
247 ///
248 /// @return std::optional<Iterator_t>, which holds an iterator to the inserted
249 /// element if the operation succeeded, and holds no value if an out-of-memory
250 /// condition occurred.
251 [[nodiscard]] auto emplace(Iterator_t &cursor, const Key_t &key) noexcept {
252 auto ret = mysql::utils::call_and_catch([&] {
253 return map().try_emplace(cursor, key, this->get_memory_resource());
254 });
255 if (ret.has_value()) cursor = std::next(ret.value());
256 return ret;
257 }
258
259 /// If no entry with the given key exists, insert one and default-construct
260 /// the mapped object.
261 ///
262 /// @param key Key to insert.
263 ///
264 /// @return std::optional<Iterator_t>, which holds an iterator to the inserted
265 /// element if the operation succeeded, and holds no value if an out-of-memory
266 /// condition occurred.
267 [[nodiscard]] auto emplace(const Key_t &key) noexcept {
268 return mysql::utils::call_and_catch([&] {
269 return map().try_emplace(key, this->get_memory_resource()).first;
270 });
271 }
272
273 /// If no entry with the given key exists, insert one and default-construct
274 /// the mapped object.
275 ///
276 /// @param position Position before which the element shall be inserted.
277 ///
278 /// @param source Map_nested_storage from which element shall be stolen.
279 ///
280 /// @param steal_element Iterator to element in `source` that shall be stolen.
281 ///
282 /// @return iterator to the inserted element
283 ///
284 /// This operation cannot fail.
285 [[nodiscard]] Iterator_t steal_and_insert(const Iterator_t &position,
286 This_t &source,
287 Iterator_t steal_element) noexcept {
288 assert(steal_element != source.end());
289 auto node = source.map().extract(steal_element);
290 return map().insert(position, std::move(node));
291 }
292
293 /// Remove the element that the iterator points to.
294 ///
295 /// @return Iterator to the next element after the removed one.
296 Iterator_t erase(const Iterator_t &iterator) { return map().erase(iterator); }
297
298 /// Remove the range of elements from first, inclusive, to last, exclusive.
299 ///
300 /// @return Iterator to the next element after the removed one.
301 Iterator_t erase(const Iterator_t &first, const Iterator_t &last) {
302 return map().erase(first, last);
303 }
304
305}; // class Map_nested_storage
306
307} // namespace mysql::sets
308
309// addtogroup GroupLibsMysqlSets
310/// @}
311
312#endif // ifndef MYSQL_SETS_MAP_NESTED_STORAGE_H
Experimental API header.
Experimental API header.
Allocator using a Memory_resource to do the allocation.
Definition: allocator.h:52
Polymorphism-free memory resource class with custom allocator and deallocator functions.
Definition: memory_resource.h:88
CRTP base class (mixin) to define a wrapper around a container.
Definition: basic_container_wrapper.h:59
void clear() noexcept
Clear the wrapped object.
Definition: basic_container_wrapper.h:128
auto get_memory_resource() const noexcept
Return the memory resource used by the wrapped object.
Definition: basic_container_wrapper.h:137
Storage for nested sets, backed by a std::map.
Definition: map_nested_storage.h:66
Map_nested_storage(const Memory_resource_t &memory_resource=Memory_resource_t{}) noexcept
Definition: map_nested_storage.h:100
Iterator_t steal_and_insert(const Iterator_t &position, This_t &source, Iterator_t steal_element) noexcept
If no entry with the given key exists, insert one and default-construct the mapped object.
Definition: map_nested_storage.h:285
Set_traits_tp Set_traits_t
Definition: map_nested_storage.h:68
typename Set_traits_t::Mapped_category_t Mapped_category_t
Definition: map_nested_storage.h:77
Const_iterator_t find(Const_iterator_t &cursor, const Key_t &key) const noexcept
Definition: map_nested_storage.h:234
typename Key_traits_t::Element_t Key_t
Definition: map_nested_storage.h:75
const auto & map() const noexcept
Definition: map_nested_storage.h:140
auto emplace(const Key_t &key) noexcept
If no entry with the given key exists, insert one and default-construct the mapped object.
Definition: map_nested_storage.h:267
Iterator_t erase(const Iterator_t &iterator)
Remove the element that the iterator points to.
Definition: map_nested_storage.h:296
auto assign(const Iterator_t &it1, const Iterator_t &it2) noexcept
Definition: map_nested_storage.h:116
auto & map() noexcept
Definition: map_nested_storage.h:137
mysql::ranges::Range_const_iterator_type< Map_t > Const_iterator_t
Definition: map_nested_storage.h:85
Const_iterator_t find(const Key_t &key) const noexcept
Definition: map_nested_storage.h:151
Map_tp Map_t
Definition: map_nested_storage.h:69
Iterator_t find(Iterator_t &cursor, const Key_t &key) noexcept
Definition: map_nested_storage.h:217
mysql::allocators::Allocator< Value_t > Allocator_t
Definition: map_nested_storage.h:88
mysql::ranges::Range_value_type< Map_t > Value_t
Definition: map_nested_storage.h:79
mysql::containers::Basic_container_wrapper< This_t, Map_t > Basic_container_wrapper_t
Definition: map_nested_storage.h:72
static Iter do_find(auto &the_map, Iter &cursor, const Key_t &key) noexcept
Common implementation of the const and non-const versions of find(cursor, key).
Definition: map_nested_storage.h:170
Iterator_t erase(const Iterator_t &first, const Iterator_t &last)
Remove the range of elements from first, inclusive, to last, exclusive.
Definition: map_nested_storage.h:301
typename Set_traits_t::Mapped_traits_t Mapped_traits_t
Definition: map_nested_storage.h:76
typename Set_traits_t::Key_traits_t Key_traits_t
Definition: map_nested_storage.h:74
mysql::ranges::Range_iterator_type< Map_t > Iterator_t
Definition: map_nested_storage.h:81
Map_nested_storage(const This_t &)=delete
Iterator_t find(const Key_t &key) noexcept
Definition: map_nested_storage.h:144
auto assign(const Iterator_t &it1, const Iterator_t &it2) noexcept
Definition: map_nested_storage.h:122
Map_nested_storage(This_t &&) noexcept=default
auto emplace(Iterator_t &cursor, const Key_t &key) noexcept
If no entry with the given key exists, insert one using the given cursor hint, and default-construct ...
Definition: map_nested_storage.h:251
mysql::ranges::Map_mapped_type< Map_t > Mapped_t
Definition: map_nested_storage.h:80
CRTP base class (mixin) to define a set that has upper_bound and lower_bound members.
Definition: upper_lower_bound_interface.h:193
True if the iterator is declared to meet LegacyBidirectionalIterator requirements.
Definition: meta.h:83
static int cmp(Bigint *a, Bigint *b)
Definition: dtoa.cc:1064
Allocator class that uses a polymorphic Memory_resource to allocate memory.
Experimental API header.
Experimental API header.
Experimental API header.
Class that wraps resources in a polymorphic manner.
void error(const char *format,...)
auto map_or_set_assign(auto &map_or_set, const Source_iterator_t &first, const std::sentinel_for< Source_iterator_t > auto &last) noexcept
Replace the contents of container with that of the range given by the two iterators,...
Definition: map_or_set_assign.h:154
std::remove_cvref_t< decltype(std::declval< Map_t >().begin() ->second)> Map_mapped_type
Gives the mapped type for any collection, deduced from begin()->first.
Definition: meta.h:88
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(*std::declval< Iterator_t >())> Iterator_value_type
Gives the value type for any iterator type, deduced from operator *.
Definition: meta.h:63
std::remove_cvref_t< decltype(std::declval< Range_t >().begin())> Range_iterator_type
Gives the iterator type, deduced from the begin() member.
Definition: meta.h:42
Iterator_value_type< Range_iterator_type< Range_t > > Range_value_type
Gives the value type for any collection, deduced from *begin().
Definition: meta.h:67
Definition: gtid_set.h:183
Return_status
Simple, strongly-typed enumeration to indicate internal status: ok, error.
Definition: return_status.h:40
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Definition: instrumented_condition_variable.h:32
Define std::hash<Gtid>.
Definition: gtid.h:355
Experimental API header.
required string key
Definition: replication_asynchronous_connection_failover.proto:60
repeated Source source
Definition: replication_asynchronous_connection_failover.proto:42
Experimental API header.
Experimental API header.