libpqxx  7.1.2
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/types.hxx"
31 #include "pqxx/version.hxx"
32 
33 
35 namespace pqxx
36 {}
37 
38 #include <pqxx/internal/libpq-forward.hxx>
39 
40 
41 namespace pqxx
42 {
44 template<typename... T> inline void ignore_unused(T &&...) {}
45 
46 
48 
51 template<typename TO, typename FROM>
52 inline TO check_cast(FROM value, char const description[])
53 {
54  static_assert(std::is_arithmetic_v<FROM>);
55  static_assert(std::is_arithmetic_v<TO>);
56  static_assert(std::is_integral_v<FROM> == std::is_integral_v<TO>);
57 
58  // The rest of this code won't quite work for bool, but bool is trivially
59  // convertible to other arithmetic types as far as I can see.
60  if constexpr (std::is_same_v<FROM, bool>)
61  return static_cast<TO>(value);
62 
63  // Depending on our "if constexpr" conditions, this parameter may not be
64  // needed. Some compilers will warn.
65  ignore_unused(description);
66 
67  using from_limits = std::numeric_limits<decltype(value)>;
68  using to_limits = std::numeric_limits<TO>;
69  if constexpr (std::is_signed_v<FROM>)
70  {
71  if constexpr (std::is_signed_v<TO>)
72  {
73  if (value < (to_limits::min)())
74  throw range_error(std::string{"Cast underflow: "} + description);
75  }
76  else
77  {
78  // FROM is signed, but TO is not. Treat this as a special case, because
79  // there may not be a good broader type in which the compiler can even
80  // perform our check.
81  if (value < 0)
82  throw range_error(
83  std::string{"Casting negative value to unsigned type: "} +
84  description);
85  }
86  }
87  else
88  {
89  // No need to check: the value is unsigned so can't fall below the range
90  // of the TO type.
91  }
92 
93  if constexpr (std::is_integral_v<FROM>)
94  {
95  using unsigned_from = std::make_unsigned_t<FROM>;
96  using unsigned_to = std::make_unsigned_t<TO>;
97  constexpr auto from_max{static_cast<unsigned_from>((from_limits::max)())};
98  constexpr auto to_max{static_cast<unsigned_to>((to_limits::max)())};
99  if constexpr (from_max > to_max)
100  {
101  if (static_cast<unsigned_from>(value) > to_max)
102  throw range_error(std::string{"Cast overflow: "} + description);
103  }
104  }
105  else if constexpr ((from_limits::max)() > (to_limits::max)())
106  {
107  if (value > (to_limits::max)())
108  throw range_error(std::string{"Cast overflow: "} + description);
109  }
110 
111  return static_cast<TO>(value);
112 }
113 
114 
116 
118 template<typename TYPE>
119 using strip_t = std::remove_cv_t<std::remove_reference_t<TYPE>>;
120 
121 
143 inline PQXX_PRIVATE void check_version()
144 {
145  // There is no particular reason to do this here in @c connection, except
146  // to ensure that every meaningful libpqxx client will execute it. The call
147  // must be in the execution path somewhere or the compiler won't try to link
148  // it. We can't use it to initialise a global or class-static variable,
149  // because a smart compiler might resolve it at compile time.
150  //
151  // On the other hand, we don't want to make a useless function call too
152  // often for performance reasons. A local static variable is initialised
153  // only on the definition's first execution. Compilers will be well
154  // optimised for this behaviour, so there's a minimal one-time cost.
155  static auto const version_ok{internal::PQXX_VERSION_CHECK()};
156  ignore_unused(version_ok);
157 }
158 
159 
161 
163 struct PQXX_LIBEXPORT thread_safety_model
164 {
166  bool safe_libpq = false;
167 
169 
175  bool safe_kerberos = false;
176 
178  std::string description;
179 };
180 
181 
183 [[nodiscard]] PQXX_LIBEXPORT thread_safety_model describe_thread_safety();
184 
185 
187 constexpr oid oid_none{0};
188 } // namespace pqxx
189 
190 
192 
201 namespace pqxx::internal
202 {
204 
216 class PQXX_LIBEXPORT namedclass
217 {
218 public:
219  explicit namedclass(std::string_view classname) : m_classname{classname} {}
220 
221  namedclass(std::string_view classname, std::string_view name) :
222  m_classname{classname}, m_name{name}
223  {}
224 
225  namedclass(std::string_view classname, char const name[]) :
226  m_classname{classname}, m_name{name}
227  {}
228 
229  namedclass(std::string_view classname, std::string &&name) :
230  m_classname{classname}, m_name{std::move(name)}
231  {}
232 
234  std::string const &name() const noexcept { return m_name; }
235 
237  std::string const &classname() const noexcept { return m_classname; }
238 
240  std::string description() const;
241 
242 private:
243  std::string m_classname, m_name;
244 };
245 
246 
247 PQXX_PRIVATE void check_unique_registration(
248  namedclass const *new_ptr, namedclass const *old_ptr);
249 PQXX_PRIVATE void check_unique_unregistration(
250  namedclass const *new_ptr, namedclass const *old_ptr);
251 
252 
254 
257 template<typename GUEST> class unique
258 {
259 public:
260  constexpr unique() = default;
261  constexpr unique(unique const &) = delete;
262  constexpr unique(unique &&rhs) : m_guest(rhs.m_guest)
263  {
264  rhs.m_guest = nullptr;
265  }
266  constexpr unique &operator=(unique const &) = delete;
267  constexpr unique &operator=(unique &&rhs)
268  {
269  m_guest = rhs.m_guest;
270  rhs.m_guest = nullptr;
271  return *this;
272  }
273 
274  constexpr GUEST *get() const noexcept { return m_guest; }
275 
276  constexpr void register_guest(GUEST *G)
277  {
278  check_unique_registration(G, m_guest);
279  m_guest = G;
280  }
281 
282  constexpr void unregister_guest(GUEST *G)
283  {
284  check_unique_unregistration(G, m_guest);
285  m_guest = nullptr;
286  }
287 
288 private:
289  GUEST *m_guest = nullptr;
290 };
291 } // namespace pqxx::internal
292 
293 #include "pqxx/internal/compiler-internal-post.hxx"
294 #endif
Something is out of range, similar to std::out_of_range.
Definition: except.hxx:193
Private namespace for libpqxx&#39;s internal use; do not access.
Definition: connection.hxx:60
namedclass(std::string_view classname)
Definition: util.hxx:219
constexpr void register_guest(GUEST *G)
Definition: util.hxx:276
void check_unique_unregistration(namedclass const *new_ptr, namedclass const *old_ptr)
Definition: util.cxx:76
constexpr unique & operator=(unique &&rhs)
Definition: util.hxx:267
namedclass(std::string_view classname, std::string &&name)
Definition: util.hxx:229
TO check_cast(FROM value, char const description[])
Cast a numeric value to another type, or throw if it underflows/overflows.
Definition: util.hxx:52
namedclass(std::string_view classname, char const name[])
Definition: util.hxx:225
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: util.hxx:119
std::string const & name() const noexcept
Object name, or the empty string if no name was given.
Definition: util.hxx:234
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
constexpr oid oid_none
The "null" oid.
Definition: util.hxx:187
Helper base class: object descriptions for error messages and such.
Definition: util.hxx:216
void check_unique_registration(namedclass const *new_ptr, namedclass const *old_ptr)
Definition: util.cxx:60
namedclass(std::string_view classname, std::string_view name)
Definition: util.hxx:221
thread_safety_model describe_thread_safety()
Describe thread safety available in this build.
Definition: util.cxx:26
constexpr unique(unique &&rhs)
Definition: util.hxx:262
std::string description
A human-readable description of any thread-safety issues.
Definition: util.hxx:178
int PQXX_VERSION_CHECK() noexcept
Library version check stub.
Definition: version.cxx:18
void check_version()
Definition: util.hxx:143
Descriptor of library&#39;s thread-safety model.
Definition: util.hxx:163
void ignore_unused(T &&...)
Suppress compiler warning about an unused item.
Definition: util.hxx:44
std::string const & classname() const noexcept
Class name.
Definition: util.hxx:237
Ensure proper opening/closing of GUEST objects related to a "host" object.
Definition: util.hxx:257
constexpr void unregister_guest(GUEST *G)
Definition: util.hxx:282