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