MySQL 9.6.0
Source Code Documentation
text_basic.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_CONV_TEXT_BASIC_H
25#define MYSQL_STRCONV_CONV_TEXT_BASIC_H
26
27/// @file
28/// Experimental API header
29
30#include <charconv> // to_chars
31#include <concepts> // unsigned_integral
32#include <type_traits> // conditional
33#include "mysql/math/int_pow.h" // int_log
34#include "mysql/strconv/decode/parser.h" // Parser
35#include "mysql/strconv/formats/text_format.h" // Text_format
36
37/// @addtogroup GroupLibsMysqlStrconv
38/// @{
39
40namespace mysql::strconv {
41
42// ==== Format integers and strings into text format ====
43
44/// Compute the length of a text-formatted integer.
45///
46/// @tparam Value_t Type of the value.
47///
48/// @param format Type tag to identify that this relates to text format.
49///
50/// @param[out] counter String_counter object to which the string will be
51/// written.
52///
53/// @param value The value to compute the text representation length for.
54template <std::integral Value_t>
55constexpr void encode_impl(const Text_format &format [[maybe_unused]],
56 String_counter &counter, Value_t value) {
57 if constexpr (std::same_as<Value_t, bool>) {
58 // Special case for bool because make_unsigned is not defined for bool.
59 counter.advance(1);
60 } else {
61 using Unsigned_value_t = std::make_unsigned_t<Value_t>;
62 Unsigned_value_t unsigned_value{};
63 if constexpr (std::signed_integral<Value_t>) {
64 if (value < 0) {
65 // Minus sign, then the positive part.
66 counter.advance(1);
67 // Negating MIN_INT, or casting a negative signed value to unsigned,
68 // are both undefined behavior. Instead, invert the bits, cast to
69 // unsigned, and add 1. This sequence of arithmetic operations is
70 // equivalent to negation, and all steps are defined.
71 unsigned_value = Unsigned_value_t(~value) + Unsigned_value_t(1);
72 } else {
73 unsigned_value = Unsigned_value_t(value);
74 }
75 } else {
76 unsigned_value = value;
77 }
78 counter.advance(1 +
79 mysql::math::int_log<Unsigned_value_t(10)>(unsigned_value));
80 }
81}
82
83/// Write a text-formatted integer to a String_writer.
84///
85/// @tparam Value_t Type of the value.
86///
87/// @param format Type tag to identify that this relates to text format.
88///
89/// @param[out] writer String_writer object to which the string will be written.
90///
91/// @param value The value to write.
92template <std::integral Value_t>
93constexpr void encode_impl(const Text_format &format [[maybe_unused]],
94 String_writer &writer, Value_t value) {
95 // to_chars is not defined for bool, so cast bool to char.
96 using Store_t =
97 std::conditional_t<std::same_as<Value_t, bool>, char, Value_t>;
98 auto ret = std::to_chars(writer.pos(), writer.end(), Store_t(value));
99 // It is required that the caller provides a sufficient buffer. This is
100 // guaranteed by this library, so we assert it.
101 assert(ret.ec == std::errc());
102 writer.advance(ret.ptr - writer.pos());
103}
104
105/// Format the given string_view in text format, by copying the string data
106/// literally to the output buffer.
107///
108/// Note that neither the string length nor any delimiter is written to the
109/// output, so a parser cannot in general compute the end in case the written
110/// string is followed by other text. Therefore there is no corresponding
111/// `decode_impl` function.
112///
113/// @param format Type tag to identify that this relates to text format.
114///
115/// @param[out] target Target object to which the string will be written.
116///
117/// @param sv Input string.
118void encode_impl(const Text_format &format [[maybe_unused]],
119 Is_string_target auto &target, const std::string_view &sv) {
120 target.write_raw(sv);
121}
122
123// ==== Parse integers from text format ====
124
125/// Parse an integer in text format into out.
126///
127/// @param format Type tag to identify that this relates to text format.
128///
129/// @param[in,out] parser Parser position.
130///
131/// @param[out] out Destination value.
132///
133/// The possible error states are:
134///
135/// - not found: The position was at end-of-string, or the first character was a
136/// non-number.
137///
138/// - parse_error: The number was out of range.
139template <std::integral Value_t>
140void decode_impl(const Text_format &format [[maybe_unused]], Parser &parser,
141 Value_t &out) {
142 Value_t value;
143 auto ret = std::from_chars(parser.pos(), parser.end(), value);
144 switch (ret.ec) {
145 case std::errc::invalid_argument:
146 parser.set_parse_error("Expected number");
147 break;
148 case std::errc::result_out_of_range:
149 parser.set_parse_error("Number out of range");
150 break;
151 default:
152 assert(ret.ec == std::errc());
153 out = value;
154 parser += (ret.ptr - parser.pos());
155 break;
156 }
157}
158
159} // namespace mysql::strconv
160
161// addtogroup GroupLibsMysqlStrconv
162/// @}
163
164#endif // ifndef MYSQL_STRCONV_CONV_TEXT_BASIC_H
Object used to parse strings.
Definition: parser.h:69
void set_parse_error(const std::string_view &message)
Store a result representing that the requested object could not be parsed because the string is wrong...
Definition: parser.h:94
Class that serves as the target for encode(..., Is_string_target), which never writes anything and on...
Definition: string_counter.h:40
Class that serves as the target for encode(..., Is_string_target), which writes to a char * buffer wi...
Definition: string_writer.h:43
const char * end() const
Return pointer to the end of the underlying string.
Definition: parse_position.h:138
const char * pos() const
Return the current position as a char pointer.
Definition: parse_position.h:110
Concept that holds for String_counter and String_writer.
Definition: string_target.h:111
Experimental API header.
uint counter
Definition: mysqlimport.cc:58
struct Parser parser
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
stdx::expected< T, std::error_code > from_chars(const std::string &value, int base=10)
convert a numeric string to a number.
Definition: destination.cc:61
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
constexpr unsigned int_log(Value_t value)
Return the base-base logarithm of value.
Definition: int_pow.h:159
Definition: gtid_binary_format.h:41
void decode_impl(const Gtid_binary_format &format, Parser &parser, mysql::gtids::Is_tag auto &tag)
Definition: gtid_binary_format_conv.h:63
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
Experimental API header.
Format tag to identify text format.
Definition: text_format.h:38
Experimental API header.