MySQL Connector/C++ 9.3.0
MySQL connector library for C and C++ applications
All Classes Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
util.h
1/*
2 * Copyright (c) 2015, 2024, Oracle and/or its affiliates.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2.0, as
6 * published by the Free Software Foundation.
7 *
8 * This program is designed to work with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms, as
10 * designated in a particular file or component or in included license
11 * documentation. The authors of MySQL hereby grant you an additional
12 * permission to link the program and your derivative works with the
13 * separately licensed software that they have either included with
14 * the program or referenced in the documentation.
15 *
16 * Without limiting anything contained in the foregoing, this file,
17 * which is part of Connector/C++, is also subject to the
18 * Universal FOSS Exception, version 1.0, a copy of which can be found at
19 * https://oss.oracle.com/licenses/universal-foss-exception.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 * See the GNU General Public License, version 2.0, for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31#ifndef MYSQLX_COMMON_UTIL_H
32#define MYSQLX_COMMON_UTIL_H
33
34#include "api.h"
35#include <limits>
36
37/*
38 Macros used to disable warnings for fragments of code.
39*/
40
41#if defined _MSC_VER
42
43
44#define PRAGMA(X) __pragma(X)
45#define DISABLE_WARNING(W) PRAGMA(warning (disable:W))
46
47#define DIAGNOSTIC_PUSH PRAGMA(warning (push))
48#define DIAGNOSTIC_POP PRAGMA(warning (pop))
49
50#elif defined __GNUC__ || defined __clang__
51
52#define PRAGMA(X) _Pragma(#X)
53#define DISABLE_WARNING(W) PRAGMA(GCC diagnostic ignored #W)
54
55#if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
56#define DIAGNOSTIC_PUSH PRAGMA(GCC diagnostic push)
57#define DIAGNOSTIC_POP PRAGMA(GCC diagnostic pop)
58#else
59#define DIAGNOSTIC_PUSH
60#define DIAGNOSTIC_POP
61#endif
62
63#else
64
65#define PRAGMA(X)
66#define DISABLE_WARNING(W)
67
68#define DIAGNOSTIC_PUSH
69#define DIAGNOSTIC_POP
70
71#endif
72
73
74/*
75 Macros to disable compile warnings in system headers. Put
76 PUSH_SYS_WARNINGS/POP_SYS_WARNINGS around sytem header includes.
77*/
78
79#if defined _MSC_VER
80
81/*
82 Warning 4350 is triggered by std::shared_ptr<> implementation
83 - see https://msdn.microsoft.com/en-us/library/0eestyah.aspx
84
85 Warning 4365 conversion from 'type_1' to 'type_2', signed/unsigned mismatch
86 - see https://msdn.microsoft.com/en-us/library/ms173683.aspx
87
88 Warning 4774 format string expected in argument <position> is not a
89 string literal
90*/
91
92#define PUSH_SYS_WARNINGS \
93 PRAGMA(warning (push,2)) \
94 DISABLE_WARNING(4350) \
95 DISABLE_WARNING(4738) \
96 DISABLE_WARNING(4548) \
97 DISABLE_WARNING(4365) \
98 DISABLE_WARNING(4774) \
99 DISABLE_WARNING(4244)
100
101#else
102
103#define PUSH_SYS_WARNINGS DIAGNOSTIC_PUSH
104
105#endif
106
107#define POP_SYS_WARNINGS DIAGNOSTIC_POP
108
109PUSH_SYS_WARNINGS
110
111#include <string>
112#include <stdexcept>
113#include <ostream>
114#include <memory>
115#include <forward_list>
116#include <string.h> // for memcpy
117#include <utility> // std::move etc
118#include <algorithm>
119#include <functional>
120#include <type_traits>
121
122POP_SYS_WARNINGS
123
124/*
125 Macro to be used to disable "implicit fallthrough" gcc warning
126 <https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html>
127*/
128
129#ifndef FALLTHROUGH
130# ifdef __GNUC__
131# if __GNUC__ < 7
132# define FALLTHROUGH // fallthrough
133# else
134# if __cplusplus >= 201703L
135# define FALLTHROUGH [[fallthrough]] // C++17
136# elif __cplusplus >= 201103L
137# define FALLTHROUGH [[gnu::fallthrough]] // C++11 and C++14
138# else
139# define FALLTHROUGH __attribute__((fallthrough))
140# endif
141# endif
142# else
143# define FALLTHROUGH // fallthrough
144# endif
145#endif //FALLTHROUGH
146
147/*
148 Note: we add throw statement to the definition of THROW() so that compiler won't
149 complain if it is used in contexts where, e.g., a value should be returned from
150 a function.
151*/
152
153#undef THROW
154
155#ifdef THROW_AS_ASSERT
156
157#define THROW(MSG) do { assert(false && (MSG)); throw (MSG); } while(false)
158
159#else
160
161#define THROW(MSG) do { throw_error(MSG); throw (MSG); } while(false)
162
163#endif
164
165
166/*
167 Macros used to disable warnings for fragments of code.
168*/
169
170#undef PRAGMA
171#undef DISABLE_WARNING
172#undef DIAGNOSTIC_PUSH
173#undef DIAGNOSTIC_POP
174
175#if defined _MSC_VER
176
177#define PRAGMA(X) __pragma(X)
178#define DISABLE_WARNING(W) PRAGMA(warning(disable : W))
179
180#define DIAGNOSTIC_PUSH PRAGMA(warning(push))
181#define DIAGNOSTIC_POP PRAGMA(warning(pop))
182
183#elif defined __GNUC__ || defined __clang__
184
185#define PRAGMA(X) _Pragma(#X)
186#define DISABLE_WARNING(W) PRAGMA(GCC diagnostic ignored #W)
187
188#if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
189#define DIAGNOSTIC_PUSH PRAGMA(GCC diagnostic push)
190#define DIAGNOSTIC_POP PRAGMA(GCC diagnostic pop)
191#else
192#define DIAGNOSTIC_PUSH
193#define DIAGNOSTIC_POP
194#endif
195
196#else
197
198#define PRAGMA(X)
199#define DISABLE_WARNING(W)
200
201#define DIAGNOSTIC_PUSH
202#define DIAGNOSTIC_POP
203
204#endif
205
206
207/*
208 On Windows, MSVC issues warnings if public API class definition uses
209 another class which is not exported as public API (either as a base class
210 or type of member). This is indeed dangerous because client code might get
211 the class definition wrong if the non-exported component is not available or
212 (worse) is defined in a different way than the same component during connector
213 build time.
214
215 We can not completely avoid these warnings because for some API classes we
216 use standard C++ library classes as components. For example, we use
217 std::shared_ptr<> a lot. We can not modify standard library headers to export
218 these classes. As is the common practice, we ignore this issue assuming that
219 the code that uses our connector is built with the same C++ runtime
220 implementation as the one used to build the connector. To silence the warnings,
221 uses of standard library classes in our public API classes should be surrounded
222 with DLL_WARNINGS_PUSH/POP macros.
223*/
224
225#if defined _MSC_VER
226
227#define DLL_WARNINGS_PUSH DIAGNOSTIC_PUSH \
228 DISABLE_WARNING(4251) \
229 DISABLE_WARNING(4275)
230#define DLL_WARNINGS_POP DIAGNOSTIC_POP
231
232#else
233
234#define DLL_WARNINGS_PUSH
235#define DLL_WARNINGS_POP
236
237#endif
238
239
240/*
241 A dirty trick to help Doxygen to process 'enum class' declarations, which
242 are not fully supported. Thus we replace them by plain 'enum' when processing
243 sources by Doxygen.
244*/
245
246#ifdef DOXYGEN
247#define enum_class enum
248#else
249#define enum_class enum class
250#endif
251
252
253/*
254 Macro to put at the end of other macros that define lists of items. This is
255 another dirty trick for Doxygen to hide from it a documentation of the last
256 item in the list. Otherwise, in a situation like this:
257
258 #define ITEM_LIST(X) \
259 X(item1) \
260 ...
261 X(itemN) /##< Doc for last item #/
262
263 Doxegen treats the documentation of the last item as documentation for
264 the whole ITEM_LIST() macro. This does not happen if END_LIST is added at
265 the end:
266
267 #define ITEM_LIST(X) \
268 X(item1) \
269 ...
270 X(itemN) /##< Doc for last item #/ \
271 END_LIST
272*/
273
274#define END_LIST
275
276
277#ifdef __cplusplus
278
279namespace mysqlx {
280MYSQLX_ABI_BEGIN(2,0)
281
282namespace common {
283
284/*
285 Convenience for checking numeric limits (to be used when doing numeric
286 casts).
287
288 TODO: Maybe more templates are needed for the case where T is a float/double
289 type and U is an integer type or vice versa.
290*/
291
292template <
293 typename T, typename U,
294 typename std::enable_if<std::is_unsigned<U>::value>::type* = nullptr
295>
296inline
297bool check_num_limits(U val)
298{
299 using UT = typename std::make_unsigned<T>::type;
300 return !(val > (UT)std::numeric_limits<T>::max());
301}
302
303template <
304 typename T, typename U,
305 typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr,
306 typename std::enable_if<!std::is_unsigned<U>::value>::type* = nullptr
307>
308inline
309bool check_num_limits(U val)
310{
311 return !(val < 0) && !(val > std::numeric_limits<T>::max());
312}
313
314template <
315 typename T, typename U,
316 typename std::enable_if<!std::is_unsigned<T>::value>::type* = nullptr,
317 typename std::enable_if<!std::is_unsigned<U>::value>::type* = nullptr
318>
319inline
320bool check_num_limits(U val)
321{
322 return
323 !((val > std::numeric_limits<T>::max())
324 || (val < std::numeric_limits<T>::lowest()));
325}
326
327#define ASSERT_NUM_LIMITS(T,V) assert(::mysqlx::common::check_num_limits<T>(V))
328
329
330
331inline
332std::string to_upper(const std::string &val)
333{
334 using std::transform;
335
336 std::string uc_val;
337 uc_val.resize(val.size());
338 transform(val.begin(), val.end(), uc_val.begin(), ::toupper);
339 return uc_val;
340}
341
342inline
343std::string to_lower(const std::string &val)
344{
345 using std::transform;
346
347 std::string uc_val;
348 uc_val.resize(val.size());
349 transform(val.begin(), val.end(), uc_val.begin(), ::tolower);
350 return uc_val;
351}
352
353} // common
354
355
356namespace common {
357
358#ifdef USE_NATIVE_BYTE
359 using ::byte;
360#else
361 typedef unsigned char byte;
362#endif
363
364 class nocopy
365 {
366 public:
367 nocopy(const nocopy&) = delete;
368 nocopy& operator=(const nocopy&) = delete;
369 protected:
370 nocopy() {}
371 };
372
373
374 class Printable
375 {
376 virtual void print(std::ostream&) const = 0;
377 friend std::ostream& operator<<(std::ostream&, const Printable&);
378 };
379
380 inline
381 std::ostream& operator<<(std::ostream &out, const Printable &obj)
382 {
383 obj.print(out);
384 return out;
385 }
386
387
388} // common
389
390
391namespace common {
392
393using std::find_if;
394
395/*
396 Remove from a container all elements that satisfy the given predicate.
397*/
398
399template <class CONT, class PRED>
400void remove_from(CONT &cont, PRED pred)
401{
402 using It = typename CONT::iterator;
403 It end = std::remove_if(cont.begin(), cont.end(), pred);
404 cont.erase(end, cont.end());
405}
406
407
408} // common
409MYSQLX_ABI_END(2,0)
410} // mysqlx
411
412#endif // __cplusplus
413
414#endif