libpqxx  7.9.0
strconv.hxx
1 /* String conversion definitions.
2  *
3  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.
4  *
5  * Copyright (c) 2000-2024, 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_STRCONV
12 #define PQXX_H_STRCONV
13 
14 #if !defined(PQXX_HEADER_PRE)
15 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
16 #endif
17 
18 #include <algorithm>
19 #include <charconv>
20 #include <cstring>
21 #include <limits>
22 #include <sstream>
23 #include <stdexcept>
24 #include <typeinfo>
25 
26 // C++20: Assume support.
27 #if __has_include(<ranges>)
28 # include <ranges>
29 #endif
30 
31 #include "pqxx/except.hxx"
32 #include "pqxx/util.hxx"
33 #include "pqxx/zview.hxx"
34 
35 
36 namespace pqxx::internal
37 {
39 PQXX_LIBEXPORT std::string demangle_type_name(char const[]);
40 } // namespace pqxx::internal
41 
42 
43 namespace pqxx
44 {
69 
71 
79 template<typename TYPE>
80 std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())};
81 
82 
84 
90 template<typename TYPE, typename ENABLE = void> struct nullness
91 {
93  static bool has_null;
94 
96  static bool always_null;
97 
99  static bool is_null(TYPE const &value);
100 
102 
107  [[nodiscard]] static TYPE null();
108 };
109 
110 
112 template<typename TYPE> struct no_null
113 {
115 
125  static constexpr bool has_null = false;
126 
128 
131  static constexpr bool always_null = false;
132 
134 
138  [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept
139  {
140  return false;
141  }
142 };
143 
144 
146 
152 template<typename TYPE> struct string_traits
153 {
155 
158  static constexpr bool converts_to_string{false};
159 
161 
164  static constexpr bool converts_from_string{false};
165 
167 
186  [[nodiscard]] static inline zview
187  to_buf(char *begin, char *end, TYPE const &value);
188 
190  /* @warning A null value has no string representation. Do not pass a null.
191  *
192  * Writes value's string representation into the buffer, starting exactly at
193  * @c begin, and ensuring a trailing zero. Returns the address just beyond
194  * the trailing zero, so the caller could use it as the @c begin for another
195  * call to @c into_buf writing a next value.
196  */
197  static inline char *into_buf(char *begin, char *end, TYPE const &value);
198 
200 
205  [[nodiscard]] static inline TYPE from_string(std::string_view text);
206 
207  // C++20: Can we make these all constexpr?
209 
213  [[nodiscard]] static inline std::size_t
214  size_buffer(TYPE const &value) noexcept;
215 
216  // TODO: Move is_unquoted_string into the traits after all?
217 };
218 
219 
221 
237 template<typename TYPE> [[noreturn]] void oops_forbidden_conversion() noexcept;
238 
239 
241 
246 template<typename TYPE> struct forbidden_conversion
247 {
248  static constexpr bool converts_to_string{false};
249  static constexpr bool converts_from_string{false};
250  [[noreturn]] static zview to_buf(char *, char *, TYPE const &)
251  {
252  oops_forbidden_conversion<TYPE>();
253  }
254  [[noreturn]] static char *into_buf(char *, char *, TYPE const &)
255  {
256  oops_forbidden_conversion<TYPE>();
257  }
258  [[noreturn]] static TYPE from_string(std::string_view)
259  {
260  oops_forbidden_conversion<TYPE>();
261  }
262  [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept
263  {
264  oops_forbidden_conversion<TYPE>();
265  }
266 };
267 
268 
270 
285 template<> struct string_traits<char> : forbidden_conversion<char>
286 {};
287 
288 
290 
303 template<>
304 struct string_traits<unsigned char> : forbidden_conversion<unsigned char>
305 {};
306 
307 
309 
322 template<>
323 struct string_traits<signed char> : forbidden_conversion<signed char>
324 {};
325 
326 
328 
333 template<> struct string_traits<std::byte> : forbidden_conversion<std::byte>
334 {};
335 
336 
338 template<typename ENUM>
339 struct nullness<ENUM, std::enable_if_t<std::is_enum_v<ENUM>>> : no_null<ENUM>
340 {};
341 
342 
343 // C++20: Concepts for "converts from string" & "converts to string."
344 } // namespace pqxx
345 
346 
347 namespace pqxx::internal
348 {
350 
359 template<typename ENUM> struct enum_traits
360 {
361  using impl_type = std::underlying_type_t<ENUM>;
363 
364  static constexpr bool converts_to_string{true};
365  static constexpr bool converts_from_string{true};
366 
367  [[nodiscard]] static constexpr zview
368  to_buf(char *begin, char *end, ENUM const &value)
369  {
370  return impl_traits::to_buf(begin, end, to_underlying(value));
371  }
372 
373  static constexpr char *into_buf(char *begin, char *end, ENUM const &value)
374  {
375  return impl_traits::into_buf(begin, end, to_underlying(value));
376  }
377 
378  [[nodiscard]] static ENUM from_string(std::string_view text)
379  {
380  return static_cast<ENUM>(impl_traits::from_string(text));
381  }
382 
383  [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept
384  {
385  return impl_traits::size_buffer(to_underlying(value));
386  }
387 
388 private:
389  // C++23: Replace with std::to_underlying.
390  static constexpr impl_type to_underlying(ENUM const &value) noexcept
391  {
392  return static_cast<impl_type>(value);
393  }
394 };
395 } // namespace pqxx::internal
396 
397 
398 // We used to inline type_name<ENUM>, but this triggered a "double free" error
399 // on program exit, when libpqxx was built as a shared library on Debian with
400 // gcc 12.
401 
403 
414 #define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \
415  template<> struct string_traits<ENUM> : pqxx::internal::enum_traits<ENUM> \
416  {}; \
417  template<> inline std::string_view const type_name<ENUM> \
418  { \
419  #ENUM \
420  }
421 
422 
423 namespace pqxx
424 {
426 
438 template<typename TYPE>
439 [[nodiscard]] inline TYPE from_string(std::string_view text)
440 {
442 }
443 
444 
446 
452 template<>
453 [[nodiscard]] inline std::string_view from_string(std::string_view text)
454 {
455  return text;
456 }
457 
458 
460 
467 template<typename T> inline void from_string(std::string_view text, T &value)
468 {
469  value = from_string<T>(text);
470 }
471 
472 
474 
479 template<typename TYPE> inline std::string to_string(TYPE const &value);
480 
481 
483 
490 template<typename... TYPE>
491 [[nodiscard]] inline std::vector<std::string_view>
492 to_buf(char *here, char const *end, TYPE... value)
493 {
494  return {[&here, end](auto v) {
495  auto begin = here;
496  here = string_traits<decltype(v)>::into_buf(begin, end, v);
497  // Exclude the trailing zero out of the string_view.
498  auto len{static_cast<std::size_t>(here - begin) - 1};
499  return std::string_view{begin, len};
500  }(value)...};
501 }
502 
504 
507 template<typename TYPE>
508 inline void into_string(TYPE const &value, std::string &out);
509 
510 
512 template<typename TYPE>
513 [[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept
514 {
515  return nullness<strip_t<TYPE>>::is_null(value);
516 }
517 
518 
520 
523 template<typename... TYPE>
524 [[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept
525 {
526  return (string_traits<strip_t<TYPE>>::size_buffer(value) + ...);
527 }
528 
529 
531 
537 template<typename TYPE> inline constexpr bool is_sql_array{false};
538 
539 
541 
553 template<typename TYPE> inline constexpr bool is_unquoted_safe{false};
554 
555 
557 template<typename T> inline constexpr char array_separator{','};
558 
559 
561 
568 template<typename TYPE> inline constexpr format param_format(TYPE const &)
569 {
570  return format::text;
571 }
572 
573 
575 
584 template<typename TYPE>
585 inline zview generic_to_buf(char *begin, char *end, TYPE const &value)
586 {
587  using traits = string_traits<TYPE>;
588  // The trailing zero does not count towards the zview's size, so subtract 1
589  // from the result we get from into_buf().
590  if (is_null(value))
591  return {};
592  else
593  return {begin, traits::into_buf(begin, end, value) - begin - 1};
594 }
595 
596 
597 #if defined(PQXX_HAVE_CONCEPTS)
599 
605 template<class TYPE>
606 concept binary = std::ranges::contiguous_range<TYPE> and
607  std::is_same_v<strip_t<value_type<TYPE>>, std::byte>;
608 #endif
610 } // namespace pqxx
611 
612 
613 #include "pqxx/internal/conversions.hxx"
614 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:33
std::string const type_name
A human-readable name for a type, used in error messages and such.
Definition: strconv.hxx:80
void into_string(TYPE const &value, std::string &out)
Convert a value to a readable string that PostgreSQL will understand.
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: types.hxx:78
std::vector< std::string_view > to_buf(char *here, char const *end, TYPE... value)
Convert multiple values to strings inside a single buffer.
Definition: strconv.hxx:492
constexpr char array_separator
Element separator between SQL array elements of this type.
Definition: strconv.hxx:557
constexpr bool is_unquoted_safe
Can we use this type in arrays and composite types without quoting them?
Definition: strconv.hxx:553
std::size_t size_buffer(TYPE const &...value) noexcept
Estimate how much buffer space is needed to represent values as a string.
Definition: strconv.hxx:524
void oops_forbidden_conversion() noexcept
Nonexistent function to indicate a disallowed type conversion.
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:513
zview generic_to_buf(char *begin, char *end, TYPE const &value)
Implement string_traits<TYPE>::to_buf by calling into_buf.
Definition: strconv.hxx:585
constexpr format param_format(TYPE const &)
What's the preferred format for passing non-null parameters of this type?
Definition: strconv.hxx:568
constexpr bool is_sql_array
Does this type translate to an SQL array?
Definition: strconv.hxx:537
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:566
T from_string(field const &value)
Convert a field's value to type T.
Definition: field.hxx:531
format
Format code: is data text or binary?
Definition: types.hxx:68
Internal items for libpqxx' own use. Do not use these yourself.
Definition: composite.hxx:84
std::string demangle_type_name(char const[])
Attempt to demangle std::type_info::name() to something human-readable.
Definition: strconv.cxx:233
Traits describing a type's "null value," if any.
Definition: strconv.hxx:91
static bool is_null(TYPE const &value)
Is value a null?
static bool has_null
Does this type have a null value?
Definition: strconv.hxx:93
static bool always_null
Is this type always null?
Definition: strconv.hxx:96
Nullness traits describing a type which does not have a null value.
Definition: strconv.hxx:113
static constexpr bool always_null
Are all values of this type null?
Definition: strconv.hxx:131
static constexpr bool has_null
Does TYPE have a "built-in null value"?
Definition: strconv.hxx:125
static constexpr bool is_null(TYPE const &) noexcept
Does a given value correspond to an SQL null value?
Definition: strconv.hxx:138
Traits class for use in string conversions.
Definition: strconv.hxx:153
static std::size_t size_buffer(TYPE const &value) noexcept
Estimate how much buffer space is needed to represent value.
static zview to_buf(char *begin, char *end, TYPE const &value)
Return a string_view representing value, plus terminating zero.
static TYPE from_string(std::string_view text)
Parse a string representation of a TYPE value.
Definition: strconv.cxx:738
static constexpr bool converts_to_string
Is conversion from TYPE to strings supported?
Definition: strconv.hxx:158
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
static constexpr bool converts_from_string
Is conversion from string_view to TYPE supported?
Definition: strconv.hxx:164
String traits for a forbidden type conversion.
Definition: strconv.hxx:247
static TYPE from_string(std::string_view)
Definition: strconv.hxx:258
static std::size_t size_buffer(TYPE const &) noexcept
Definition: strconv.hxx:262
static zview to_buf(char *, char *, TYPE const &)
Definition: strconv.hxx:250
static char * into_buf(char *, char *, TYPE const &)
Definition: strconv.hxx:254
Helper class for defining enum conversions.
Definition: strconv.hxx:360
static std::size_t size_buffer(ENUM const &value) noexcept
Definition: strconv.hxx:383
static constexpr zview to_buf(char *begin, char *end, ENUM const &value)
Definition: strconv.hxx:368
static constexpr char * into_buf(char *begin, char *end, ENUM const &value)
Definition: strconv.hxx:373
static constexpr bool converts_from_string
Definition: strconv.hxx:365
std::underlying_type_t< ENUM > impl_type
Definition: strconv.hxx:361
static ENUM from_string(std::string_view text)
Definition: strconv.hxx:378
static constexpr bool converts_to_string
Definition: strconv.hxx:364
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38