MySQL 9.6.0
Source Code Documentation
encode.h
Go to the documentation of this file.
1// Copyright (c) 2024, 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_STRCONV_ENCODE_H
25#define MYSQL_SETS_STRCONV_ENCODE_H
26
27/// @file
28/// Experimental API header
29
30#include <concepts> // integral
31#include "mysql/sets/boundary_set_meta.h" // Is_boundary_set
32#include "mysql/sets/interval.h" // Interval
33#include "mysql/sets/interval_set_interface.h" // make_interval_set_view
34#include "mysql/sets/interval_set_meta.h" // Is_interval_set
35#include "mysql/sets/nested_set_meta.h" // Is_nested_set
36#include "mysql/sets/strconv/boundary_set_text_format.h" // Boundary_set_text_format
37#include "mysql/sets/strconv/nested_set_text_format.h" // Nested_set_text_format
38#include "mysql/strconv/strconv.h" // Is_string_target
39
40/// @addtogroup GroupLibsMysqlSets
41/// @{
42
43namespace mysql::sets::strconv {
44
47
48/// Write an Interval in text format to the given Is_string_target. The Set
49/// traits must be _discrete_ (see Is_discrete_set_traits).
50///
51/// The format is "start" if the start is equal to the inclusive end, and
52/// "start<format.boundary_separator>inclusive_end" otherwise.
53///
54/// @param format Format tag used to write boundary values.
55///
56/// @param[out] target String_writer or String_counter to write to.
57///
58/// @param interval Interval to write.
59template <mysql::sets::Is_discrete_set_traits Set_traits_t>
60void interval_to_text(const Is_format auto &format,
61 Is_string_target auto &target,
63 target.write(format, interval.start());
64 if (interval.exclusive_end() != Set_traits_t::next(interval.start())) {
65 target.concat(format, format.m_boundary_separator,
66 Set_traits_t::prev(interval.exclusive_end()));
67 }
68}
69
70/// Write a Boundary_set in text format to the given Is_string_target. The Set
71/// traits must be _discrete_ (see Is_discrete_set_traits).
72///
73/// The format is a sequence of intervals, formatted according to @c
74/// interval_to_text, where adjacent pairs of intervals are separated by
75/// format.interval_separator.
76///
77/// @param format Format tag used to write intervals.
78///
79/// @param[out] target String_writer or String_counter to write to.
80///
81/// @param boundary_set Boundary set to write.
82template <mysql::sets::Is_boundary_set Boundary_set_t>
84 typename Boundary_set_t::Set_traits_t>
85void boundary_set_to_text(const Is_format auto &format,
86 Is_string_target auto &target,
87 const Boundary_set_t &boundary_set) {
88 bool first = true;
89 for (const auto &interval :
91 if (first)
92 first = false;
93 else
94 target.write(format, format.m_interval_separator);
95 target.write(format, interval);
96 }
97}
98
99/// Write a boundary set in a space-efficient binary format that uses
100/// variable-length integers, delta-compression, and an optimization to
101/// sometimes omit the first value. The Set traits must be _discrete_, _metric_
102/// (see Is_discrete_metric_set_traits).
103///
104/// The format has one integer for the sequence length, followed by a sequence
105/// where each element is the difference between adjacent boundaries, minus 1.
106/// Both the length and the boundaries are encoded according to format.
107/// Normally, the sequence contains all boundaries, but in the special case that
108/// the first boundary equals the minimum value, we omit it from the sequence.
109/// The decoder detects this case by observing that the sequence length is odd,
110/// in which case it assumes the start boundary of the first interval is the
111/// minimum value, and the exclusive_end is given by the first boundary stored
112/// explicitly.
113///
114/// If boundaries are integers and format is Binary_format, all numbers are
115/// stored in variable-length format, as specified by the `serialization`
116/// library. (We store differences rather than boundary values because that
117/// minimizes integer magnitudes, which saves space.)
118///
119/// @param format Format tag used to write boundary values.
120///
121/// @param[out] target String_writer or String_counter to write to.
122///
123/// @param boundary_set Boundary set to write.
124template <mysql::sets::Is_boundary_set Boundary_set_t>
126 typename Boundary_set_t::Set_traits_t>
127void boundary_set_to_binary(const Is_format auto &format,
128 Is_string_target auto &target,
129 const Boundary_set_t &boundary_set) {
130 using Set_traits_t = Boundary_set_t::Set_traits_t;
131 auto size = boundary_set.size();
132 auto next_min = Set_traits_t::min();
133 auto it = boundary_set.begin();
134 // Skip first boundary if it equals to min
135 if (it != boundary_set.end() && *it == next_min) {
136 --size;
137 ++it;
138 }
139 next_min = Set_traits_t::next(next_min);
140 // Write size
141 target.write(format, uint64_t(size));
142 // Write all remaining boundaries
143 for (; it != boundary_set.end(); ++it) {
144 auto boundary = *it;
145 target.write(format, Set_traits_t::sub(boundary, next_min));
146 next_min = Set_traits_t::next(boundary);
147 }
148}
149
150/// Write boundary sets in binary format with fixed-width integers to the given
151/// Is_string_target. The Set traits must be _bounded_ (see
152/// Is_bounded_set_traits).
153///
154/// The format consists of one integer for the number of intervals (i.e., number
155/// of boundaries divided by 2), followed by the sequence of all boundaries.
156/// Both the number and the boundaries are encoded according to format.
157///
158/// If boundaries are integers and format is Format_binary_fixint, all numbers
159/// are 64-bit little-endian integers.
160///
161/// @param format Format tag used to write boundary values.
162///
163/// @param[out] target String_writer or String_counter to write to.
164///
165/// @param boundary_set Boundary set to write.
166template <mysql::sets::Is_boundary_set Boundary_set_t>
168 typename Boundary_set_t::Set_traits_t>
169void boundary_set_to_binary_fixint(const Is_format auto &format,
170 Is_string_target auto &target,
171 const Boundary_set_t &boundary_set) {
172 target.write(format, boundary_set.size() / 2);
173 for (auto boundary : boundary_set) {
174 target.write(format, boundary);
175 }
176}
177
178/// Write an interval set to the given Is_string_target.
179///
180/// This delegates the work to the formatter for boundary sets.
181///
182/// @param format Format tag used to write boundary sets.
183///
184/// @param[out] target String_writer or String_counter to write to.
185///
186/// @param interval_set Interval set to write.
188 const Is_format auto &format, Is_string_target auto &target,
189 const mysql::sets::Is_interval_set auto &interval_set) {
190 target.write(format, interval_set.boundaries());
191}
192
193/// Write a nested set to the given Is_string_target.
194///
195/// This writes each key using the format format.m_nested_set_key_format, each
196/// mapped set using the format format.mnested_set_mapped_format, uses
197/// format.m_nested_set_key_mapped_separator to separate key and mapped set, and
198/// uses format.m_nested_set_item_separator to separate different pairs.
199///
200/// @param format Format tag.
201///
202/// @param[out] target String_writer or String_counter to write to.
203///
204/// @param nested_set Nested set to write.
207 Is_string_target auto &target,
208 const mysql::sets::Is_nested_set auto &nested_set) {
209 bool first = true;
210 for (auto &&pair : nested_set) {
211 if (first)
212 first = false;
213 else
214 target.write_raw(format.m_item_separator);
215 target.write(format.m_key_format, pair.first);
216 target.write(format, format.m_key_mapped_separator);
217 assert(!pair.second.empty());
218 target.write(format.m_mapped_format, pair.second);
219 }
220}
221
222} // namespace mysql::sets::strconv
223
224// Glue to make encode find the formatters.
225namespace mysql::strconv {
226
227/// Enable mysql::strconv::encode(Boundary_set_text_format, Interval), for
228/// intervals whose Set traits that are _discrete_.
229template <mysql::sets::Is_bounded_set_traits Set_traits_t>
231 Is_string_target auto &target,
234}
235
236/// Enable mysql::strconv::encode(Boundary_set_text_format, Interval), for
237/// boundary sets whose Set traits that are _discrete_.
238template <mysql::sets::Is_boundary_set Boundary_set_t>
240 Is_string_target auto &target,
241 const Boundary_set_t &boundary_set) {
243}
244
245/// Enable mysql::strconv::encode(Fixint_binary_format, Boundary_set), for
246/// boundary sets whose Set traits that are _discrete_.
247template <mysql::sets::Is_boundary_set Boundary_set_t>
249 Is_string_target auto &target,
250 const Boundary_set_t &boundary_set) {
252 boundary_set);
253}
254
255/// Enable mysql::strconv::encode(Binary_format, Boundary_set), for boundary
256/// sets whose Set traits that are _discrete_ and _metric_.
257template <mysql::sets::Is_boundary_set Boundary_set_t>
259 typename Boundary_set_t::Set_traits_t>
261 const Boundary_set_t &boundary_set) {
263}
264
265/// Enable mysql::strconv::encode(/*Format*/, Interval_set), by
266/// writing the boundaries in the given format.
267void encode_impl(const Is_format auto &format, Is_string_target auto &target,
268 const mysql::sets::Is_interval_set auto &interval_set) {
270}
271
272/// Enable mysql::strconv::encode(/*Format*/, Nested_set), by
273/// writing the boundaries in the given format.
275 Is_string_target auto &target,
276 const mysql::sets::Is_nested_set auto &nested_set) {
278}
279
280} // namespace mysql::strconv
281
282// addtogroup GroupLibsMysqlSets
283/// @}
284
285#endif // ifndef MYSQL_SETS_STRCONV_ENCODE_H
Experimental API header.
Experimental API header.
Holds the start boundary and endpoint boundary of an interval.
Definition: interval.h:178
True if Test is a "bounded" Set traits class.
Definition: set_traits.h:105
True if Test satisfies both Is_discrete_set_traits and Is_metric_set_traits.
Definition: set_traits.h:151
True if Test is a "discrete" Set traits class, i.e., it bounded, and it is possible to compute succes...
Definition: set_traits.h:119
Definition: interval_set_meta.h:75
True if Test is a nested set.
Definition: nested_set_meta.h:110
True if Test is a format.
Definition: format.h:42
Definition: nested_set_text_format.h:68
Concept that holds for String_counter and String_writer.
Definition: string_target.h:111
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.
static int interval
Definition: mysqladmin.cc:72
Type sub(Shards< COUNT > &shards, size_t id, size_t n)
Decrement the counter for a shard by n.
Definition: ut0counter.h:280
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
Definition: decode.h:39
void boundary_set_to_text(const Is_format auto &format, Is_string_target auto &target, const Boundary_set_t &boundary_set)
Write a Boundary_set in text format to the given Is_string_target.
Definition: encode.h:85
void interval_to_text(const Is_format auto &format, Is_string_target auto &target, const mysql::sets::Interval< Set_traits_t > &interval)
Write an Interval in text format to the given Is_string_target.
Definition: encode.h:60
void boundary_set_to_binary_fixint(const Is_format auto &format, Is_string_target auto &target, const Boundary_set_t &boundary_set)
Write boundary sets in binary format with fixed-width integers to the given Is_string_target.
Definition: encode.h:169
void nested_set_to_text(const mysql::strconv::Is_nested_set_text_format auto &format, Is_string_target auto &target, const mysql::sets::Is_nested_set auto &nested_set)
Write a nested set to the given Is_string_target.
Definition: encode.h:205
void boundary_set_to_binary(const Is_format auto &format, Is_string_target auto &target, const Boundary_set_t &boundary_set)
Write a boundary set in a space-efficient binary format that uses variable-length integers,...
Definition: encode.h:127
void encode_interval_set(const Is_format auto &format, Is_string_target auto &target, const mysql::sets::Is_interval_set auto &interval_set)
Write an interval set to the given Is_string_target.
Definition: encode.h:187
auto make_interval_set_view(const Boundary_set_t &boundary_set)
Definition: interval_set_interface.h:150
Definition: gtid_binary_format.h:41
void encode_impl(const Gtid_binary_format &format, Is_string_target auto &target, const mysql::gtids::Is_tag auto &tag)
Definition: gtid_binary_format_conv.h:48
size_t size(const char *const c)
Definition: base64.h:46
Experimental API header.
Experimental API header.
Format tag to identify binary format.
Definition: binary_format.h:38
Tag to identify the formatting algorithm for boundary sets of integrals, and provide the separator st...
Definition: boundary_set_text_format.h:51
Format tag to identify fixed-length-integer binary format.
Definition: fixint_binary_format.h:42