MySQL 8.0.39
Source Code Documentation
ut0core.h
Go to the documentation of this file.
1/* Copyright (c) 2021, 2024, 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
25/** @file include/ut0log.h Base of InnoDB utilities. */
26
27#ifndef ut0core_h
28#define ut0core_h
29
30#include "ut0dbg.h"
31
32namespace ut {
33struct Location {
34 const char *filename;
35 size_t line;
36 std::ostream &print(std::ostream &out) const {
37 out << "[Location: file=" << filename << ", line=" << line << "]";
38 return out;
39 }
40};
41} // namespace ut
42
43inline std::ostream &operator<<(std::ostream &out, const ut::Location &obj) {
44 return obj.print(out);
45}
46
47#define UT_LOCATION_HERE (ut::Location{__FILE__, __LINE__})
48
49namespace ib {
50
51#ifdef UNIV_DEBUG
52/** Finds the first format specifier in `fmt` format string
53@param[in] fmt The format string
54@return Either the longest suffix of `fmt` which starts with format specifier,
55or `nullptr` if could not find any format specifier inside `fmt`.
56*/
57static inline const char *get_first_format(const char *fmt) {
58 const char *pos = strchr(fmt, '%');
59 if (pos != nullptr && pos[1] == '%') {
60 return (get_first_format(pos + 2));
61 }
62 return (pos);
63}
64
65/** Verifies that the `fmt` format string does not require any arguments
66@param[in] fmt The format string
67@return true if and only if there is no format specifier inside `fmt` which
68requires passing an argument */
69static inline bool verify_fmt_match(const char *fmt) {
70 return (get_first_format(fmt) == nullptr);
71}
72
73/** Verifies that the `fmt` format string contains format specifiers which match
74the type and order of the arguments
75@param[in] fmt The format string
76@param[in] head The first argument
77@param[in] tail Others (perhaps none) arguments
78@return true if and only if the format specifiers found in `fmt` correspond to
79types of head, tail...
80*/
81template <typename Head, typename... Tail>
82static bool verify_fmt_match(const char *fmt, Head &&head [[maybe_unused]],
83 Tail &&... tail) {
84 using H =
86 const char *pos = get_first_format(fmt);
87 if (pos == nullptr) {
88 return (false);
89 }
90 /* We currently only handle :
91 %[-0-9.*]*(d|ld|lld|u|lu|llu|zu|zx|zd|s|x|i|f|c|X|p|lx|llx|lf)
92 Feel free to extend the parser, if you need something more, as the parser is
93 not intended to be any stricter than real printf-format parser, and if it does
94 not handle something, it is only to keep the code simpler. */
95 const std::string skipable("-+ #0123456789.*");
96
97 pos++;
98 while (*pos != '\0' && skipable.find_first_of(*pos) != std::string::npos) {
99 pos++;
100 }
101 if (*pos == '\0') {
102 return (false);
103 }
104 bool is_ok = true;
105 if (pos[0] == 'l') {
106 if (pos[1] == 'l') {
107 if (pos[2] == 'd') {
108 is_ok = std::is_same<H, long long int>::value;
109 } else if (pos[2] == 'u' || pos[2] == 'x') {
110 is_ok = std::is_same<H, unsigned long long int>::value;
111 } else {
112 is_ok = false;
113 }
114 } else if (pos[1] == 'd') {
115 is_ok = std::is_same<H, long int>::value;
116 } else if (pos[1] == 'u') {
117 is_ok = std::is_same<H, unsigned long int>::value;
118 } else if (pos[1] == 'x') {
119 is_ok = std::is_same<H, unsigned long int>::value;
120 } else if (pos[1] == 'f') {
121 is_ok = std::is_same<H, double>::value;
122 } else {
123 is_ok = false;
124 }
125 } else if (pos[0] == 'd') {
126 is_ok = std::is_same<H, int>::value;
127 } else if (pos[0] == 'u') {
128 is_ok = std::is_same<H, unsigned int>::value;
129 } else if (pos[0] == 'x') {
130 is_ok = std::is_same<H, unsigned int>::value;
131 } else if (pos[0] == 'X') {
132 is_ok = std::is_same<H, unsigned int>::value;
133 } else if (pos[0] == 'i') {
134 is_ok = std::is_same<H, int>::value;
135 } else if (pos[0] == 'f') {
136 is_ok = std::is_same<H, float>::value;
137 } else if (pos[0] == 'c') {
138 is_ok = std::is_same<H, char>::value;
139 } else if (pos[0] == 'p') {
140 is_ok = std::is_pointer<H>::value;
141 } else if (pos[0] == 's') {
142 is_ok = (std::is_same<H, char *>::value ||
143 std::is_same<H, char const *>::value ||
144 (std::is_array<H>::value &&
145 std::is_same<typename std::remove_cv<
147 char>::value));
148 } else if (pos[0] == 'z') {
149 if (pos[1] == 'u') {
150 is_ok = std::is_same<H, size_t>::value;
151 } else if (pos[1] == 'x') {
152 is_ok = std::is_same<H, size_t>::value;
153 } else if (pos[1] == 'd') {
154 is_ok = std::is_same<H, ssize_t>::value;
155 } else {
156 is_ok = false;
157 }
158 } else {
159 is_ok = false;
160 }
161 return (is_ok && verify_fmt_match(pos + 1, std::forward<Tail>(tail)...));
162}
163#endif /* UNIV_DEBUG */
164
165/** This is a wrapper class, used to print any unsigned integer type
166in hexadecimal format. The main purpose of this data type is to
167overload the global operator<<, so that we can print the given
168wrapper value in hex. */
169struct hex {
170 explicit hex(uintmax_t t) : m_val(t) {}
171 const uintmax_t m_val;
172};
173
174/** This is an overload of the global operator<< for the user defined type
175ib::hex. The unsigned value held in the ib::hex wrapper class will be printed
176into the given output stream in hexadecimal format.
177@param[in,out] lhs the output stream into which rhs is written.
178@param[in] rhs the object to be written into lhs.
179@retval reference to the output stream. */
180inline std::ostream &operator<<(std::ostream &lhs, const hex &rhs) {
181 std::ios_base::fmtflags ff = lhs.flags();
182 lhs << std::showbase << std::hex << rhs.m_val;
183 lhs.setf(ff);
184 return (lhs);
185}
186
187} // namespace ib
188
189#endif
constexpr pos_type Head
Definition: http_request.h:258
Definition: ut0core.h:49
static bool verify_fmt_match(const char *fmt)
Verifies that the fmt format string does not require any arguments.
Definition: ut0core.h:69
static const char * get_first_format(const char *fmt)
Finds the first format specifier in fmt format string.
Definition: ut0core.h:57
std::ostream & operator<<(std::ostream &lhs, const hex &rhs)
This is an overload of the global operator<< for the user defined type ib::hex.
Definition: ut0core.h:180
This file contains a set of libraries providing overloads for regular dynamic allocation routines whi...
Definition: aligned_alloc.h:48
required string type
Definition: replication_group_member_actions.proto:34
This is a wrapper class, used to print any unsigned integer type in hexadecimal format.
Definition: ut0core.h:169
const uintmax_t m_val
Definition: ut0core.h:171
hex(uintmax_t t)
Definition: ut0core.h:170
Definition: ut0core.h:33
const char * filename
Definition: ut0core.h:34
size_t line
Definition: ut0core.h:35
std::ostream & print(std::ostream &out) const
Definition: ut0core.h:36
std::ostream & operator<<(std::ostream &out, const ut::Location &obj)
Definition: ut0core.h:43
Debug utilities for Innobase.