libpqxx  7.3.0
util.hxx
1 /* Various utility definitions for libpqxx.
2  *
3  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
4  *
5  * Copyright (c) 2000-2020, Jeroen T. Vermeulen.
6  *
7  * See COPYING for copyright license. If you did not receive a file called
8  * COPYING with this source code, please notify the distributor of this
9  * mistake, or contact the author.
10  */
11 #ifndef PQXX_H_UTIL
12 #define PQXX_H_UTIL
13 
14 #include "pqxx/compiler-public.hxx"
15 #include "pqxx/internal/compiler-internal-pre.hxx"
16 
17 #include <cctype>
18 #include <cstdio>
19 #include <functional>
20 #include <iterator>
21 #include <limits>
22 #include <memory>
23 #include <stdexcept>
24 #include <string>
25 #include <string_view>
26 #include <type_traits>
27 #include <typeinfo>
28 #include <vector>
29 
30 #include "pqxx/except.hxx"
31 #include "pqxx/internal/encodings.hxx"
32 #include "pqxx/types.hxx"
33 #include "pqxx/version.hxx"
34 
35 
37 namespace pqxx
38 {}
39 
40 #include <pqxx/internal/libpq-forward.hxx>
41 
42 
44 namespace pqxx::internal
45 {
47 
50 [[nodiscard]] inline std::string cat2(std::string_view x, std::string_view y)
51 {
52  std::string buf;
53  auto const xs{std::size(x)}, ys{std::size(y)};
54  buf.resize(xs + ys);
55  x.copy(buf.data(), xs);
56  y.copy(buf.data() + xs, ys);
57  return buf;
58 }
59 } // namespace pqxx::internal
60 
61 
62 namespace pqxx
63 {
64 using namespace std::literals;
65 
67 template<typename... T> inline void ignore_unused(T &&...) {}
68 
69 
71 
74 template<typename TO, typename FROM>
75 inline TO check_cast(FROM value, std::string_view description)
76 {
77  static_assert(std::is_arithmetic_v<FROM>);
78  static_assert(std::is_arithmetic_v<TO>);
79  static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);
80 
81  // The rest of this code won't quite work for bool, but bool is trivially
82  // convertible to other arithmetic types as far as I can see.
83  if constexpr (std::is_same_v<FROM, bool>)
84  return static_cast<TO>(value);
85 
86  // Depending on our "if constexpr" conditions, this parameter may not be
87  // needed. Some compilers will warn.
88  ignore_unused(description);
89 
90  using from_limits = std::numeric_limits<decltype(value)>;
91  using to_limits = std::numeric_limits<TO>;
92  if constexpr (std::is_signed_v<FROM>)
93  {
94  if constexpr (std::is_signed_v<TO>)
95  {
96  if (value < to_limits::lowest())
97  throw range_error{internal::cat2("Cast underflow: "sv, description)};
98  }
99  else
100  {
101  // FROM is signed, but TO is not. Treat this as a special case, because
102  // there may not be a good broader type in which the compiler can even
103  // perform our check.
104  if (value < 0)
105  {
107  "Casting negative value to unsigned type: "sv, description)};
108  }
109  }
110  }
111  else
112  {
113  // No need to check: the value is unsigned so can't fall below the range
114  // of the TO type.
115  }
116 
117  if constexpr (std::is_integral_v<FROM>)
118  {
119  using unsigned_from = std::make_unsigned_t<FROM>;
120  using unsigned_to = std::make_unsigned_t<TO>;
121  constexpr auto from_max{static_cast<unsigned_from>((from_limits::max)())};
122  constexpr auto to_max{static_cast<unsigned_to>((to_limits::max)())};
123  if constexpr (from_max > to_max)
124  {
125  if (static_cast<unsigned_from>(value) > to_max)
126  throw range_error{internal::cat2("Cast overflow: "sv, description)};
127  }
128  }
129  else if constexpr ((from_limits::max)() > (to_limits::max)())
130  {
131  if (value > (to_limits::max)())
132  throw range_error{internal::cat2("Cast overflow: ", description)};
133  }
134 
135  return static_cast<TO>(value);
136 }
137 
138 
140 
142 template<typename TYPE>
143 using strip_t = std::remove_cv_t<std::remove_reference_t<TYPE>>;
144 
145 
167 inline PQXX_PRIVATE void check_version()
168 {
169  // There is no particular reason to do this here in @c connection, except
170  // to ensure that every meaningful libpqxx client will execute it. The call
171  // must be in the execution path somewhere or the compiler won't try to link
172  // it. We can't use it to initialise a global or class-static variable,
173  // because a smart compiler might resolve it at compile time.
174  //
175  // On the other hand, we don't want to make a useless function call too
176  // often for performance reasons. A local static variable is initialised
177  // only on the definition's first execution. Compilers will be well
178  // optimised for this behaviour, so there's a minimal one-time cost.
179  static auto const version_ok{internal::PQXX_VERSION_CHECK()};
180  ignore_unused(version_ok);
181 }
182 
183 
185 
187 struct PQXX_LIBEXPORT thread_safety_model
188 {
190  bool safe_libpq = false;
191 
193 
199  bool safe_kerberos = false;
200 
202  std::string description;
203 };
204 
205 
207 [[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();
208 
209 
211 constexpr oid oid_none{0};
212 } // namespace pqxx
213 
214 
216 
225 namespace pqxx::internal
226 {
227 using namespace std::literals;
228 
229 
231 
233 [[nodiscard]] std::string
234 describe_object(std::string_view class_name, std::string_view name);
235 
236 
238 
250  void const *old_guest, std::string_view old_class, std::string_view old_name,
251  void const *new_guest, std::string_view new_class,
252  std::string_view new_name);
253 
254 
256 
260  void const *old_guest, std::string_view old_class, std::string_view old_name,
261  void const *new_guest, std::string_view new_class,
262  std::string_view new_name);
263 
264 
266 
269 constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
270 {
271  return 2 + (2 * binary_bytes) + 1;
272 }
273 
274 
276 
278 constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
279 {
280  return (escaped_bytes - 2) / 2;
281 }
282 
283 
285 
290 void PQXX_LIBEXPORT
291 esc_bin(std::string_view binary_data, char buffer[]) noexcept;
292 
293 
295 std::string PQXX_LIBEXPORT esc_bin(std::string_view binary_data);
296 
297 
299 void PQXX_LIBEXPORT
300 unesc_bin(std::string_view escaped_data, std::byte buffer[]);
301 
302 
304 std::string PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data);
305 } // namespace pqxx::internal
306 
307 #include "pqxx/internal/compiler-internal-post.hxx"
308 #endif
TO check_cast(FROM value, std::string_view description)
Cast a numeric value to another type, or throw if it underflows/overflows.
Definition: util.hxx:75
Internal items for libpqxx&#39; own use. Do not use these yourself.
Definition: composite.hxx:73
std::string describe_object(std::string_view class_name, std::string_view name)
Describe an object for humans, based on class name and optional name.
Definition: util.cxx:48
Descriptor of library&#39;s thread-safety model.
Definition: util.hxx:187
void esc_bin(std::string_view binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition: util.cxx:122
void check_unique_register(void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name)
Check validity of registering a new "guest" in a "host.".
Definition: util.cxx:58
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: util.hxx:143
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:211
thread_safety_model describe_thread_safety()
Describe thread safety available in this build.
Definition: util.cxx:30
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition: version.cxx:18
void check_version()
Definition: util.hxx:167
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition: util.hxx:278
std::string cat2(std::string_view x, std::string_view y)
Efficiently concatenate two strings.
Definition: util.hxx:50
std::string description
A human-readable description of any thread-safety issues.
Definition: util.hxx:202
void check_unique_unregister(void const *old_guest, std::string_view old_class, std::string_view old_name, void const *new_guest, std::string_view new_class, std::string_view new_name)
Like check_unique_register, but for un-registering a guest.
Definition: util.cxx:75
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition: util.hxx:269
void ignore_unused(T &&...)
Suppress compiler warning about an unused item.
Definition: util.hxx:67
Something is out of range, similar to std::out_of_range.
Definition: except.hxx:192
void unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition: util.cxx:152