MySQL 9.6.0
Source Code Documentation
out_str_write.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_STRCONV_ENCODE_OUT_STR_WRITE_H
25#define MYSQL_STRCONV_ENCODE_OUT_STR_WRITE_H
26
27/// @file
28/// Experimental API header
29
30#include <cassert> // assert
31#include "mysql/strconv/encode/out_str.h" // Is_out_str
32#include "mysql/strconv/encode/string_counter.h" // detail::Constructible_string_counter
33#include "mysql/strconv/encode/string_writer.h" // detail::Constructible_string_writer
34#include "mysql/utils/return_status.h" // Return_status
35
36/// @addtogroup GroupLibsMysqlStrconv
37/// @{
38
39namespace mysql::strconv::detail {
40/// Lambda that takes no argument, does nothing, and returns void.
41inline auto nop = [] {};
42
43/// Type of `nop`.
44using Nop_t = decltype(nop);
45} // namespace mysql::strconv::detail
46
47namespace mysql::strconv {
48
49/// True if Test can be invoked with a `String_counter &` argument and returns
50/// void or Return_status.
51template <class Test>
53 std::is_invocable_r_v<void, Test, String_counter &> ||
54 std::is_invocable_r_v<mysql::utils::Return_status, Test, String_counter &>;
55
56/// True if Test can be invoked with a `String_writer &` argument and returns
57/// void or Return_status.
58template <class Test>
60 std::is_invocable_r_v<void, Test, String_writer &> ||
61 std::is_invocable_r_v<mysql::utils::Return_status, Test, String_writer &>;
62
63/// True for pairs of string producer counters/writers that can be used with
64/// `out_str_write`, i.e., the counter accepts a `String_counter &`, the writer
65/// accepts a `String_writer &`, and the return types are either void or
66/// `Return_status`.
67///
68/// Moreover, the same semantic requirements as for `Is_string_producer` apply.
69template <class Counter, class Writer>
72
73/// True for invocables that can be used with `out_str_write`, i.e., which
74/// accept either a `String_writer &` or a `String_counter &` argument, and the
75/// return type is either void or `Return_status`.
76///
77/// Moreover, semantic requirements related to determinism apply. For an object
78/// `obj` of type `Test`, say that `obj(...)` *succeeds* if either the return
79/// type is void, or the call returns Return_status::ok. Let `sc` be a
80/// `String_counter` object and `sw` a `String_writer` object.
81///
82/// - If `obj(sc)` succeeds, and `sw.remaining_size() < sc.size()`, then
83/// `obj(sw)` must succeed.
84///
85/// - `obj(sc)` must not have side effects. (If it modifies the state of other
86/// objects, it must restore those side effects.)
87template <class Test>
89
90namespace detail {
91/// Common implementation for the two overloads of `out_str_write(out_str,
92/// producer_counter, producer_writer, oom_action)`.
93template <Is_out_str Out_str_t, class Producer_counter_t,
94 class Producer_writer_t, std::invocable Oom_action_t>
97 const Out_str_t &out_str, const Producer_counter_t &producer_counter,
98 const Producer_writer_t &producer_writer, const Oom_action_t &oom_action) {
100
101 // 1. Obtain an upper bound on the output size.
102 std::size_t size{};
103 [[maybe_unused]] std::size_t old_size{};
104 if constexpr (Out_str_t::resize_policy == Resize_policy::fixed) {
105 // User has guaranteed that the initial capacity suffices.
106 size = out_str.initial_capacity();
107 old_size = out_str.size();
108 } else {
109 // Compute exact size.
111 Return_status ret =
112 mysql::utils::void_to_ok([&] { return producer_counter(counter); });
113 if (ret != Return_status::ok) return Return_status::error;
114 size = counter.size();
115 }
116
117 // 2. Resize.
118 if (mysql::utils::void_to_ok([&] { return out_str.resize(size); }) !=
119 Return_status::ok) {
120 oom_action();
122 }
123
124 // 3. Write output
126 Return_status ret =
127 mysql::utils::void_to_ok([&] { return producer_writer(writer); });
128 if constexpr (Out_str_t::resize_policy == Resize_policy::fixed) {
129 if (ret != Return_status::ok) {
130 // Restore size.
131 out_str.resize(old_size);
133 }
134 // Trim size: it was an upper bound, now we know the actual size.
135 out_str.resize(writer.pos() - out_str.data());
136 } else {
137 // Since producer_counter succeeded, producer_writer should succeed too.
138 // (semantic requirment of Is_string_producer_pair).
139 assert(ret == Return_status::ok);
140 }
141 return Return_status::ok;
142}
143} // namespace detail
144
145/// Given an Is_out_str object, a String_producer_counter, and a
146/// String_producer_writer, resizes the object as needed and then writes to it.
147///
148/// This overload is for when there are error cases, i.e., when either the
149/// producer can return errors, or the Output String Wrapper is growable.
150///
151/// @tparam Out_str_t Type of Output String Wrapper.
152///
153/// @tparam Producer_counter_t Type of the producer counter function.
154///
155/// @tparam Producer_writer_t Type of the producer writer function.
156/// `Producer_counter_t` and `Producer_writer_t` must satisfy
157/// `Is_string_producer_pair` (including the semantic requirements).
158///
159/// @param out_str Wrapper around the output, typically obtained from one of the
160/// `out_str_*` functions.
161///
162/// @param producer_counter Function that writes to its `String_counter &`
163/// parameter, and returns either `Return_status` indicating success or failure,
164/// or `void` (if it can't fail).
165///
166/// @param producer_writer Function that writes to its `String_writer &`
167/// parameter, and returns either `Return_status` indicating success or failure,
168/// or `void` (if it can't fail).
169///
170/// @param oom_action Optional callback function. If given, will be invoked in
171/// case an out-of-memory condition occurs.
172///
173/// @return `Return_status::error` if either `write` or `out_str.resize` returns
174/// `Return_status::error`; otherwise `Return_status::ok`.
175template <Is_out_str Out_str_t, class Producer_counter_t,
176 class Producer_writer_t, std::invocable Oom_action_t = detail::Nop_t>
177 requires Is_string_producer_pair<Producer_counter_t, Producer_writer_t>
179 const Out_str_t &out_str, const Producer_counter_t &producer_counter,
180 const Producer_writer_t &producer_writer,
181 const Oom_action_t &oom_action = detail::nop) {
182 return do_out_str_write(out_str, producer_counter, producer_writer,
183 oom_action);
184}
185
186/// Given an Is_out_str object, a String_producer_counter, and a
187/// String_producer_writer, resizes the object as needed and then writes to it.
188///
189/// This overload is for when there are no error cases, i.e., when the producer
190/// returns void and the Output String Wrapper is fixed-size.
191///
192/// @tparam Out_str_t Type of output wrapper.
193///
194/// @tparam Producer_counter_t Type of the producer counter function.
195///
196/// @tparam Producer_writer_t Type of the producer writer function.
197/// `Producer_counter_t` and `Producer_writer_t` must satisfy
198/// `Is_string_producer_pair` (including the semantic requirements).
199///
200/// @param out_str Wrapper around the output, typically obtained from one of the
201/// `out_str_*` functions.
202///
203/// @param producer_counter Function that writes to its `String_counter &`
204/// parameter, and returns either `Return_status` indicating success or failure,
205/// or `void` (if it can't fail).
206///
207/// @param producer_writer Function that writes to its `String_writer &`
208/// parameter, and returns either `Return_status` indicating success or failure,
209/// or `void` (if it can't fail).
210///
211/// @param oom_action Optional callback function. If given, will be invoked in
212/// case an out-of-memory condition occurs.
213template <Is_out_str_fixed Out_str_t, class Producer_counter_t,
214 class Producer_writer_t, std::invocable Oom_action_t = detail::Nop_t>
215 requires Is_string_producer_pair<Producer_counter_t, Producer_writer_t> &&
216 (std::same_as<
217 std::invoke_result_t<Producer_counter_t, String_counter &>,
218 void>) &&
219 (std::same_as<
220 std::invoke_result_t<Producer_writer_t, String_writer &>, void>)
221void out_str_write(const Out_str_t &out_str,
222 const Producer_counter_t &producer_counter,
223 const Producer_writer_t &producer_writer,
224 const Oom_action_t &oom_action = detail::nop) {
225 [[maybe_unused]] auto ret =
226 do_out_str_write(out_str, producer_counter, producer_writer, oom_action);
227 assert(ret == mysql::utils::Return_status::ok);
228}
229
230/// Given an `Is_out_str object` and an `Is_string_producer`, resize the object
231/// as needed and then write to it.
232///
233/// @param out_str Wrapper around the output, typically obtained from one of the
234/// `out_str_*` functions.
235///
236/// @param producer Function that writes to its `Is_string_target` parameter,
237/// and returns either `Return_status` indicating success or failure, or (if it
238/// can't fail) `void`.
239///
240/// @param oom_action Optional callback function. If given, will be invoked in
241/// case an out-of-memory condition occurs.
242///
243/// @return If `out_str` is growable or `producer` returns non-void, returns
244/// `Return_status` to indicate success or failure; otherwise returns void.
245template <std::invocable Oom_action_t = detail::Nop_t>
246[[nodiscard]] auto out_str_write(const Is_out_str auto &out_str,
247 const Is_string_producer auto &producer,
248 const Oom_action_t &oom_action = detail::nop) {
249 return out_str_write(out_str, producer, producer, oom_action);
250}
251
252/// Copy the given `string_view` to the Output String Wrapper, resizing as
253/// needed.
254///
255/// @param out_str Output String Wrapper to write to.
256///
257/// @param sv `string_view` to write.
258///
259/// @param oom_action Optional callback function. If given, will be invoked in
260/// case an out-of-memory condition occurs.
261///
262/// @return If `out_str` is growable, return `Return_status::ok` on success and
263/// `Return_status::error` on out-of-memory error; if `out_str` is fixed-size,
264/// return void.
265template <std::invocable Oom_action_t = detail::Nop_t>
266[[nodiscard]] auto out_str_copy(const Is_out_str auto &out_str,
267 const std::string_view &sv,
268 const Oom_action_t &oom_action = detail::nop) {
269 return out_str_write(
270 out_str, [&](Is_string_target auto &target) { target.write_raw(sv); },
271 oom_action);
272}
273
274} // namespace mysql::strconv
275
276// addtogroup GroupLibsMysqlStrconv
277/// @}
278
279#endif // ifndef MYSQL_STRCONV_ENCODE_OUT_STR_WRITE_H
String_counter subclass that can be instantiated.
Definition: string_counter.h:97
String_writer subclass that can be instantiated.
Definition: string_writer.h:182
True if Test is an Output String Wrapper, i.e., derived from Out_str_base.
Definition: out_str.h:219
True if Test can be invoked with a String_counter & argument and returns void or Return_status.
Definition: out_str_write.h:52
True for pairs of string producer counters/writers that can be used with out_str_write,...
Definition: out_str_write.h:70
True if Test can be invoked with a String_writer & argument and returns void or Return_status.
Definition: out_str_write.h:59
True for invocables that can be used with out_str_write, i.e., which accept either a String_writer & ...
Definition: out_str_write.h:88
Concept that holds for String_counter and String_writer.
Definition: string_target.h:111
void error(const char *format,...)
uint counter
Definition: mysqlimport.cc:58
Definition: fts0fts.cc:236
Definition: gtid_binary_format_conv.h:252
mysql::utils::Return_status do_out_str_write(const Out_str_t &out_str, const Producer_counter_t &producer_counter, const Producer_writer_t &producer_writer, const Oom_action_t &oom_action)
Common implementation for the two overloads of out_str_write(out_str, producer_counter,...
Definition: out_str_write.h:96
auto nop
Lambda that takes no argument, does nothing, and returns void.
Definition: out_str_write.h:41
decltype(nop) Nop_t
Type of nop.
Definition: out_str_write.h:44
Definition: gtid_binary_format.h:41
auto out_str_copy(const Is_out_str auto &out_str, const std::string_view &sv, const Oom_action_t &oom_action=detail::nop)
Copy the given string_view to the Output String Wrapper, resizing as needed.
Definition: out_str_write.h:266
mysql::utils::Return_status out_str_write(const Out_str_t &out_str, const Producer_counter_t &producer_counter, const Producer_writer_t &producer_writer, const Oom_action_t &oom_action=detail::nop)
Given an Is_out_str object, a String_producer_counter, and a String_producer_writer,...
Definition: out_str_write.h:178
Return_status
Simple, strongly-typed enumeration to indicate internal status: ok, error.
Definition: return_status.h:40
@ ok
operation succeeded
Return_t void_to_ok(const Func_t &func, Args_t &&...args)
Helper that calls the given function and returns its result, or returns Return_status::ok if the func...
Definition: return_status.h:113
size_t size(const char *const c)
Definition: base64.h:46
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.