libpqxx  7.2.1
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 <iterator>
20 #include <limits>
21 #include <memory>
22 #include <stdexcept>
23 #include <string>
24 #include <string_view>
25 #include <type_traits>
26 #include <typeinfo>
27 #include <vector>
28 
29 #include "pqxx/except.hxx"
30 #include "pqxx/internal/encodings.hxx"
31 #include "pqxx/types.hxx"
32 #include "pqxx/version.hxx"
33 
34 
36 namespace pqxx
37 {}
38 
39 #include <pqxx/internal/libpq-forward.hxx>
40 
41 
42 namespace pqxx
43 {
45 template<typename... T> inline void ignore_unused(T &&...) {}
46 
47 
49 
52 template<typename TO, typename FROM>
53 inline TO check_cast(FROM value, char const description[])
54 {
55  static_assert(std::is_arithmetic_v<FROM>);
56  static_assert(std::is_arithmetic_v<TO>);
57  static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);
58 
59  // The rest of this code won't quite work for bool, but bool is trivially
60  // convertible to other arithmetic types as far as I can see.
61  if constexpr (std::is_same_v<FROM, bool>)
62  return static_cast<TO>(value);
63 
64  // Depending on our "if constexpr" conditions, this parameter may not be
65  // needed. Some compilers will warn.
66  ignore_unused(description);
67 
68  using from_limits = std::numeric_limits<decltype(value)>;
69  using to_limits = std::numeric_limits<TO>;
70  if constexpr (std::is_signed_v<FROM>)
71  {
72  if constexpr (std::is_signed_v<TO>)
73  {
74  if (value < to_limits::lowest())
75  throw range_error(std::string{"Cast underflow: "} + description);
76  }
77  else
78  {
79  // FROM is signed, but TO is not. Treat this as a special case, because
80  // there may not be a good broader type in which the compiler can even
81  // perform our check.
82  if (value < 0)
83  throw range_error(
84  std::string{"Casting negative value to unsigned type: "} +
85  description);
86  }
87  }
88  else
89  {
90  // No need to check: the value is unsigned so can't fall below the range
91  // of the TO type.
92  }
93 
94  if constexpr (std::is_integral_v<FROM>)
95  {
96  using unsigned_from = std::make_unsigned_t<FROM>;
97  using unsigned_to = std::make_unsigned_t<TO>;
98  constexpr auto from_max{static_cast<unsigned_from>((from_limits::max)())};
99  constexpr auto to_max{static_cast<unsigned_to>((to_limits::max)())};
100  if constexpr (from_max > to_max)
101  {
102  if (static_cast<unsigned_from>(value) > to_max)
103  throw range_error(std::string{"Cast overflow: "} + description);
104  }
105  }
106  else if constexpr ((from_limits::max)() > (to_limits::max)())
107  {
108  if (value > (to_limits::max)())
109  throw range_error(std::string{"Cast overflow: "} + description);
110  }
111 
112  return static_cast<TO>(value);
113 }
114 
115 
117 
119 template<typename TYPE>
120 using strip_t = std::remove_cv_t<std::remove_reference_t<TYPE>>;
121 
122 
144 inline PQXX_PRIVATE void check_version()
145 {
146  // There is no particular reason to do this here in @c connection, except
147  // to ensure that every meaningful libpqxx client will execute it. The call
148  // must be in the execution path somewhere or the compiler won't try to link
149  // it. We can't use it to initialise a global or class-static variable,
150  // because a smart compiler might resolve it at compile time.
151  //
152  // On the other hand, we don't want to make a useless function call too
153  // often for performance reasons. A local static variable is initialised
154  // only on the definition's first execution. Compilers will be well
155  // optimised for this behaviour, so there's a minimal one-time cost.
156  static auto const version_ok{internal::PQXX_VERSION_CHECK()};
157  ignore_unused(version_ok);
158 }
159 
160 
162 
164 struct PQXX_LIBEXPORT thread_safety_model
165 {
167  bool safe_libpq = false;
168 
170 
176  bool safe_kerberos = false;
177 
179  std::string description;
180 };
181 
182 
184 [[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();
185 
186 
188 constexpr oid oid_none{0};
189 } // namespace pqxx
190 
191 
193 
202 namespace pqxx::internal
203 {
205 
218 class PQXX_LIBEXPORT namedclass
219 {
220 public:
221  explicit namedclass(std::string_view classname) : m_classname{classname} {}
222 
223  namedclass(std::string_view classname, std::string_view name) :
224  m_classname{classname}, m_name{name}
225  {}
226 
227  namedclass(std::string_view classname, char const name[]) :
228  m_classname{classname}, m_name{name}
229  {}
230 
231  namedclass(std::string_view classname, std::string &&name) :
232  m_classname{classname}, m_name{std::move(name)}
233  {}
234 
236  std::string const &name() const noexcept { return m_name; }
237 
239  std::string const &classname() const noexcept { return m_classname; }
240 
242  std::string description() const;
243 
244 private:
245  std::string m_classname, m_name;
246 };
247 
248 
249 PQXX_PRIVATE void check_unique_registration(
250  namedclass const *new_ptr, namedclass const *old_ptr);
251 PQXX_PRIVATE void check_unique_unregistration(
252  namedclass const *new_ptr, namedclass const *old_ptr);
253 
254 
256 
259 template<typename GUEST> class unique
260 {
261 public:
262  constexpr unique() = default;
263  constexpr unique(unique const &) = delete;
264  constexpr unique(unique &&rhs) : m_guest(rhs.m_guest)
265  {
266  rhs.m_guest = nullptr;
267  }
268  constexpr unique &operator=(unique const &) = delete;
269  constexpr unique &operator=(unique &&rhs)
270  {
271  m_guest = rhs.m_guest;
272  rhs.m_guest = nullptr;
273  return *this;
274  }
275 
276  constexpr GUEST *get() const noexcept { return m_guest; }
277 
278  constexpr void register_guest(GUEST *G)
279  {
280  check_unique_registration(G, m_guest);
281  m_guest = G;
282  }
283 
284  constexpr void unregister_guest(GUEST *G)
285  {
286  check_unique_unregistration(G, m_guest);
287  m_guest = nullptr;
288  }
289 
290 private:
291  GUEST *m_guest = nullptr;
292 };
293 
294 
296 
299 constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
300 {
301  return 2 + (2 * binary_bytes) + 1;
302 }
303 
304 
306 
308 constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
309 {
310  return (escaped_bytes - 2) / 2;
311 }
312 
313 
315 
320 void PQXX_LIBEXPORT
321 esc_bin(std::string_view binary_data, char buffer[]) noexcept;
322 
323 
325 std::string PQXX_LIBEXPORT esc_bin(std::string_view binary_data);
326 
327 
329 void PQXX_LIBEXPORT
330 unesc_bin(std::string_view escaped_data, std::byte buffer[]);
331 
332 
334 std::string PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data);
335 } // namespace pqxx::internal
336 
337 #include "pqxx/internal/compiler-internal-post.hxx"
338 #endif
Private namespace for libpqxx&#39;s internal use; do not access.
Definition: composite.hxx:70
void check_unique_unregistration(namedclass const *new_ptr, namedclass const *old_ptr)
Definition: util.cxx:88
std::string const & classname() const noexcept
Class name.
Definition: util.hxx:239
void esc_bin(std::string_view binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition: util.cxx:135
namedclass(std::string_view classname, std::string_view name)
Definition: util.hxx:223
TO check_cast(FROM value, char const description[])
Cast a numeric value to another type, or throw if it underflows/overflows.
Definition: util.hxx:53
constexpr unique & operator=(unique &&rhs)
Definition: util.hxx:269
constexpr void register_guest(GUEST *G)
Definition: util.hxx:278
Helper base class: object descriptions for error messages and such.
Definition: util.hxx:218
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: util.hxx:120
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:188
namedclass(std::string_view classname)
Definition: util.hxx:221
void check_unique_registration(namedclass const *new_ptr, namedclass const *old_ptr)
Definition: util.cxx:72
namedclass(std::string_view classname, char const name[])
Definition: util.hxx:227
thread_safety_model describe_thread_safety()
Describe thread safety available in this build.
Definition: util.cxx:26
std::string description
A human-readable description of any thread-safety issues.
Definition: util.hxx:179
namedclass(std::string_view classname, std::string &&name)
Definition: util.hxx:231
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition: version.cxx:18
Descriptor of library&#39;s thread-safety model.
Definition: util.hxx:164
void check_version()
Definition: util.hxx:144
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:308
constexpr unique(unique &&rhs)
Definition: util.hxx:264
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:299
constexpr void unregister_guest(GUEST *G)
Definition: util.hxx:284
Ensure proper opening/closing of GUEST objects related to a "host" object.
Definition: util.hxx:259
std::string const & name() const noexcept
Object name, or the empty string if no name was given.
Definition: util.hxx:236
void ignore_unused(T &&...)
Suppress compiler warning about an unused item.
Definition: util.hxx:45
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:165