util.hxx 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /** Various utility definitions for libpqxx.
  2. *
  3. * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
  4. *
  5. * Copyright (c) 2000-2019, 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 mistake,
  9. * or contact the author.
  10. */
  11. #ifndef PQXX_H_UTIL
  12. #define PQXX_H_UTIL
  13. #include "pqxx/compiler-public.hxx"
  14. #include <cstdio>
  15. #include <cctype>
  16. #include <iterator>
  17. #include <memory>
  18. #include <stdexcept>
  19. #include <string>
  20. #include <type_traits>
  21. #include <typeinfo>
  22. #include <vector>
  23. #include "pqxx/strconv.hxx"
  24. /// The home of all libpqxx classes, functions, templates, etc.
  25. namespace pqxx {}
  26. #include <pqxx/internal/libpq-forward.hxx>
  27. namespace pqxx
  28. {
  29. /// Suppress compiler warning about an unused item.
  30. template<typename T> inline void ignore_unused(T) {}
  31. /// Descriptor of library's thread-safety model.
  32. /** This describes what the library knows about various risks to thread-safety.
  33. */
  34. struct PQXX_LIBEXPORT thread_safety_model
  35. {
  36. /// @deprecated Is error reporting thread-safe? Now always true.
  37. bool have_safe_strerror = true;
  38. /// Is the underlying libpq build thread-safe?
  39. bool safe_libpq;
  40. /// @deprecated Query cancel is always thread-safe now.
  41. bool safe_query_cancel = true;
  42. /// @deprecated Always thread-safe to copy a 'result' or 'binarystring' now.
  43. bool safe_result_copy = true;
  44. /// Is Kerberos thread-safe?
  45. /** @warning Is currently always @c false.
  46. *
  47. * If your application uses Kerberos, all accesses to libpqxx or Kerberos must
  48. * be serialized. Confine their use to a single thread, or protect it with a
  49. * global lock.
  50. */
  51. bool safe_kerberos;
  52. /// A human-readable description of any thread-safety issues.
  53. std::string description;
  54. };
  55. /// Describe thread safety available in this build.
  56. PQXX_LIBEXPORT thread_safety_model describe_thread_safety() noexcept;
  57. /// The "null" oid.
  58. constexpr oid oid_none = 0;
  59. /**
  60. * @defgroup utility Utility functions
  61. */
  62. //@{
  63. /// Represent sequence of values as a string, joined by a given separator.
  64. /**
  65. * Use this to turn e.g. the numbers 1, 2, and 3 into a string "1, 2, 3".
  66. *
  67. * @param sep separator string (to be placed between items)
  68. * @param begin beginning of items sequence
  69. * @param end end of items sequence
  70. * @param access functor defining how to dereference sequence elements
  71. */
  72. template<typename ITER, typename ACCESS> inline
  73. std::string separated_list( //[t00]
  74. const std::string &sep,
  75. ITER begin,
  76. ITER end,
  77. ACCESS access)
  78. {
  79. std::string result;
  80. if (begin != end)
  81. {
  82. result = to_string(access(begin));
  83. for (++begin; begin != end; ++begin)
  84. {
  85. result += sep;
  86. result += to_string(access(begin));
  87. }
  88. }
  89. return result;
  90. }
  91. /// Render sequence as a string, using given separator between items.
  92. template<typename ITER> inline std::string
  93. separated_list(const std::string &sep, ITER begin, ITER end) //[t00]
  94. { return separated_list(sep, begin, end, [](ITER i){ return *i; }); }
  95. /// Render items in a container as a string, using given separator.
  96. template<typename CONTAINER> inline auto
  97. separated_list(const std::string &sep, const CONTAINER &c) //[t10]
  98. /*
  99. Always std::string; necessary because SFINAE doesn't work with the
  100. contents of function bodies, so the check for iterability has to be in
  101. the signature.
  102. */
  103. -> typename std::enable_if<
  104. (
  105. not std::is_void<decltype(std::begin(c))>::value
  106. and not std::is_void<decltype(std::end(c))>::value
  107. ),
  108. std::string
  109. >::type
  110. {
  111. return separated_list(sep, std::begin(c), std::end(c));
  112. }
  113. /// Render items in a tuple as a string, using given separator.
  114. template<
  115. typename TUPLE,
  116. std::size_t INDEX=0,
  117. typename ACCESS,
  118. typename std::enable_if<
  119. (INDEX == std::tuple_size<TUPLE>::value-1),
  120. int
  121. >::type=0
  122. >
  123. inline std::string
  124. separated_list(
  125. const std::string & /* sep */,
  126. const TUPLE &t,
  127. const ACCESS& access
  128. )
  129. {
  130. return to_string(access(&std::get<INDEX>(t)));
  131. }
  132. template<
  133. typename TUPLE,
  134. std::size_t INDEX=0,
  135. typename ACCESS,
  136. typename std::enable_if<
  137. (INDEX < std::tuple_size<TUPLE>::value-1),
  138. int
  139. >::type=0
  140. >
  141. inline std::string
  142. separated_list(const std::string &sep, const TUPLE &t, const ACCESS& access)
  143. {
  144. return
  145. to_string(access(&std::get<INDEX>(t))) +
  146. sep +
  147. separated_list<TUPLE, INDEX+1>(sep, t, access);
  148. }
  149. template<
  150. typename TUPLE,
  151. std::size_t INDEX=0,
  152. typename std::enable_if<
  153. (INDEX <= std::tuple_size<TUPLE>::value),
  154. int
  155. >::type=0
  156. >
  157. inline std::string
  158. separated_list(const std::string &sep, const TUPLE &t)
  159. {
  160. return separated_list(sep, t, [](const TUPLE &tup){return *tup;});
  161. }
  162. //@}
  163. /// Private namespace for libpqxx's internal use; do not access.
  164. /** This namespace hides definitions internal to libpqxx. These are not
  165. * supposed to be used by client programs, and they may change at any time
  166. * without notice.
  167. *
  168. * Conversely, if you find something in this namespace tremendously useful, by
  169. * all means do lodge a request for its publication.
  170. *
  171. * @warning Here be dragons!
  172. */
  173. namespace internal
  174. {
  175. PQXX_LIBEXPORT void freepqmem(const void *) noexcept;
  176. template<typename P> inline void freepqmem_templated(P *p) noexcept
  177. {
  178. freepqmem(p);
  179. }
  180. PQXX_LIBEXPORT void freemallocmem(const void *) noexcept;
  181. template<typename P> inline void freemallocmem_templated(P *p) noexcept
  182. {
  183. freemallocmem(p);
  184. }
  185. /// Helper base class: object descriptions for error messages and such.
  186. /**
  187. * Classes derived from namedclass have a class name (such as "transaction"),
  188. * an optional object name (such as "delete-old-logs"), and a description
  189. * generated from the two names (such as "transaction delete-old-logs").
  190. *
  191. * The class name is dynamic here, in order to support inheritance hierarchies
  192. * where the exact class name may not be known statically.
  193. *
  194. * In inheritance hierarchies, make namedclass a virtual base class so that
  195. * each class in the hierarchy can specify its own class name in its
  196. * constructors.
  197. */
  198. class PQXX_LIBEXPORT namedclass
  199. {
  200. public:
  201. explicit namedclass(const std::string &Classname) :
  202. m_classname{Classname},
  203. m_name{}
  204. {
  205. }
  206. namedclass(const std::string &Classname, const std::string &Name) :
  207. m_classname{Classname},
  208. m_name{Name}
  209. {
  210. }
  211. /// Object name, or the empty string if no name was given.
  212. const std::string &name() const noexcept { return m_name; } //[t01]
  213. /// Class name.
  214. const std::string &classname() const noexcept //[t73]
  215. { return m_classname; }
  216. /// Combination of class name and object name; or just class name.
  217. std::string description() const;
  218. private:
  219. std::string m_classname, m_name;
  220. };
  221. PQXX_PRIVATE void CheckUniqueRegistration(
  222. const namedclass *New, const namedclass *Old);
  223. PQXX_PRIVATE void CheckUniqueUnregistration(
  224. const namedclass *New, const namedclass *Old);
  225. /// Ensure proper opening/closing of GUEST objects related to a "host" object
  226. /** Only a single GUEST may exist for a single host at any given time. GUEST
  227. * must be derived from namedclass.
  228. */
  229. template<typename GUEST>
  230. class unique
  231. {
  232. public:
  233. unique() =default;
  234. unique(const unique &) =delete;
  235. unique &operator=(const unique &) =delete;
  236. GUEST *get() const noexcept { return m_guest; }
  237. void register_guest(GUEST *G)
  238. {
  239. CheckUniqueRegistration(G, m_guest);
  240. m_guest = G;
  241. }
  242. void unregister_guest(GUEST *G)
  243. {
  244. CheckUniqueUnregistration(G, m_guest);
  245. m_guest = nullptr;
  246. }
  247. private:
  248. GUEST *m_guest = nullptr;
  249. };
  250. /// Sleep for the given number of seconds
  251. /** May return early, e.g. when interrupted by a signal. Completes instantly if
  252. * a zero or negative sleep time is requested.
  253. */
  254. PQXX_LIBEXPORT void sleep_seconds(int);
  255. } // namespace internal
  256. } // namespace pqxx
  257. #endif