libpqxx
The C++ client library for PostgreSQL
Loading...
Searching...
No Matches
strconv.hxx
Go to the documentation of this file.
1/* String conversion definitions.
2 *
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.
4 *
5 * Copyright (c) 2000-2025, 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 <optional>
23#include <sstream>
24#include <stdexcept>
25#include <typeinfo>
26
27// C++20: Assume support.
28#if defined(PQXX_HAVE_RANGES)
29# include <ranges>
30#endif
31
32#include "pqxx/except.hxx"
33#include "pqxx/util.hxx"
34#include "pqxx/zview.hxx"
35
36
37namespace pqxx::internal
38{
40PQXX_LIBEXPORT std::string demangle_type_name(char const[]);
41} // namespace pqxx::internal
42
43
44namespace pqxx
45{
70
72
80template<typename TYPE>
81std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())};
82
83
85
91template<typename TYPE, typename ENABLE = void> struct nullness
92{
94 static bool has_null;
95
97 static bool always_null;
98
100 static bool is_null(TYPE const &value);
101
103
108 [[nodiscard]] static TYPE null();
109};
110
111
113template<typename TYPE> struct no_null
114{
116
126 static constexpr bool has_null = false;
127
129
132 static constexpr bool always_null = false;
133
135
139 [[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept
140 {
141 return false;
142 }
143};
144
145
147
154template<typename TYPE> struct string_traits
155{
157
160 static constexpr bool converts_to_string{false};
161
163
166 static constexpr bool converts_from_string{false};
167
169
188 [[nodiscard]] static inline zview
189 to_buf(char *begin, char *end, TYPE const &value);
190
192 /* @warning A null value has no string representation. Do not pass a null.
193 *
194 * Writes value's string representation into the buffer, starting exactly at
195 * @c begin, and ensuring a trailing zero. Returns the address just beyond
196 * the trailing zero, so the caller could use it as the @c begin for another
197 * call to @c into_buf writing a next value.
198 */
199 static inline char *into_buf(char *begin, char *end, TYPE const &value);
200
202
207 [[nodiscard]] static inline TYPE from_string(std::string_view text);
208
209 // C++20: Can we make these all constexpr?
211
215 [[nodiscard]] static inline std::size_t
216 size_buffer(TYPE const &value) noexcept;
217
218 // TODO: Move is_unquoted_safe into the traits after all?
219};
220
221
223
239template<typename TYPE> [[noreturn]] void oops_forbidden_conversion() noexcept;
240
241
243
248template<typename TYPE> struct forbidden_conversion
249{
250 static constexpr bool converts_to_string{false};
251 static constexpr bool converts_from_string{false};
252 [[noreturn]] static zview to_buf(char *, char *, TYPE const &)
253 {
255 }
256 [[noreturn]] static char *into_buf(char *, char *, TYPE const &)
257 {
259 }
260 [[noreturn]] static TYPE from_string(std::string_view)
261 {
263 }
264 [[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept
265 {
267 }
268};
269
270
272
287template<> struct string_traits<char> : forbidden_conversion<char>
288{};
289
290
292
305template<>
306struct string_traits<unsigned char> : forbidden_conversion<unsigned char>
307{};
308
309
311
324template<>
325struct string_traits<signed char> : forbidden_conversion<signed char>
326{};
327
328
330
335template<> struct string_traits<std::byte> : forbidden_conversion<std::byte>
336{};
337
338
340template<typename ENUM>
341struct nullness<ENUM, std::enable_if_t<std::is_enum_v<ENUM>>> : no_null<ENUM>
342{};
343
344
345// C++20: Concepts for "converts from string" & "converts to string."
346} // namespace pqxx
347
348
349namespace pqxx::internal
350{
352
361template<typename ENUM> struct enum_traits
362{
363 using impl_type = std::underlying_type_t<ENUM>;
365
366 static constexpr bool converts_to_string{true};
367 static constexpr bool converts_from_string{true};
368
369 [[nodiscard]] static constexpr zview
370 to_buf(char *begin, char *end, ENUM const &value)
371 {
372 return impl_traits::to_buf(begin, end, to_underlying(value));
373 }
374
375 static constexpr char *into_buf(char *begin, char *end, ENUM const &value)
376 {
377 return impl_traits::into_buf(begin, end, to_underlying(value));
378 }
379
380 [[nodiscard]] static ENUM from_string(std::string_view text)
381 {
382 return static_cast<ENUM>(impl_traits::from_string(text));
383 }
384
385 [[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept
386 {
387 return impl_traits::size_buffer(to_underlying(value));
388 }
389
390private:
391 // C++23: Replace with std::to_underlying.
392 static constexpr impl_type to_underlying(ENUM const &value) noexcept
393 {
394 return static_cast<impl_type>(value);
395 }
396};
397} // namespace pqxx::internal
398
399
400// We used to inline type_name<ENUM>, but this triggered a "double free" error
401// on program exit, when libpqxx was built as a shared library on Debian with
402// gcc 12.
403
405
416#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \
417 template<> struct string_traits<ENUM> : pqxx::internal::enum_traits<ENUM> \
418 {}; \
419 template<> inline std::string_view const type_name<ENUM> \
420 { \
421 #ENUM \
422 }
423
424
425namespace pqxx
426{
428
440template<typename TYPE>
441[[nodiscard]] inline TYPE from_string(std::string_view text)
442{
444}
445
446
448
454template<>
455[[nodiscard]] inline std::string_view from_string(std::string_view text)
456{
457 return text;
458}
459
460
462
469template<typename T> inline void from_string(std::string_view text, T &value)
470{
471 value = from_string<T>(text);
472}
473
474
476
481template<typename TYPE> inline std::string to_string(TYPE const &value);
482
483
485
492template<typename... TYPE>
493[[nodiscard]] inline std::vector<std::string_view>
494to_buf(char *here, char const *end, TYPE... value)
495{
496 PQXX_ASSUME(here <= end);
497 return {[&here, end](auto v) {
498 auto begin = here;
499 here = string_traits<decltype(v)>::into_buf(begin, end, v);
500 // Exclude the trailing zero out of the string_view.
501 auto len{static_cast<std::size_t>(here - begin) - 1};
502 return std::string_view{begin, len};
503 }(value)...};
504}
505
507
510template<typename TYPE>
511inline void into_string(TYPE const &value, std::string &out);
512
513
515template<typename TYPE>
516[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept
517{
518 return nullness<strip_t<TYPE>>::is_null(value);
519}
520
521
523
526template<typename... TYPE>
527[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept
528{
529 return (string_traits<strip_t<TYPE>>::size_buffer(value) + ...);
530}
531
532
534
540template<typename TYPE> inline constexpr bool is_sql_array{false};
541
542
544
556template<typename TYPE> inline constexpr bool is_unquoted_safe{false};
557
558
560template<typename T> inline constexpr char array_separator{','};
561
562
564
571template<typename TYPE> inline constexpr format param_format(TYPE const &)
572{
573 return format::text;
574}
575
576
578
587template<typename TYPE>
588inline zview generic_to_buf(char *begin, char *end, TYPE const &value)
589{
590 using traits = string_traits<TYPE>;
591 // The trailing zero does not count towards the zview's size, so subtract 1
592 // from the result we get from into_buf().
593 if (is_null(value))
594 return {};
595 else
596 return {begin, traits::into_buf(begin, end, value) - begin - 1};
597}
598
599
600#if defined(PQXX_HAVE_CONCEPTS) && defined(PQXX_HAVE_RANGES)
602
608template<class TYPE>
609concept binary = std::ranges::contiguous_range<TYPE> and
610 std::is_same_v<strip_t<value_type<TYPE>>, std::byte>;
611#endif
613} // namespace pqxx
614
615
617#endif
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
#define PQXX_LIBEXPORT
Definition header-pre.hxx:157
#define PQXX_ASSUME(condition)
Definition header-pre.hxx:189
Internal items for libpqxx' own use. Do not use these yourself.
Definition encodings.cxx:33
std::string demangle_type_name(char const raw[])
Attempt to demangle std::type_info::name() to something human-readable.
Definition strconv.cxx:228
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
std::string const type_name
A human-readable name for a type, used in error messages and such.
Definition strconv.hxx:81
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:494
constexpr char array_separator
Element separator between SQL array elements of this type.
Definition strconv.hxx:560
constexpr format param_format(std::optional< T > const &value)
Definition conversions.hxx:286
std::string to_string(T const &value)
Definition conversions.hxx:1249
constexpr bool is_unquoted_safe
Can we use this type in arrays and composite types without quoting them?
Definition strconv.hxx:556
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:527
void oops_forbidden_conversion() noexcept
Nonexistent function to indicate a disallowed type conversion.
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition types.hxx:80
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition strconv.hxx:516
zview generic_to_buf(char *begin, char *end, TYPE const &value)
Implement string_traits<TYPE>::to_buf by calling into_buf.
Definition strconv.hxx:588
constexpr bool is_sql_array
Does this type translate to an SQL array?
Definition strconv.hxx:540
void into_string(T const &value, std::string &out)
Definition conversions.hxx:1286
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:548
format
Format code: is data text or binary?
Definition types.hxx:70
@ text
Definition types.hxx:71
@ binary
Definition types.hxx:72
String traits for a forbidden type conversion.
Definition strconv.hxx:249
static char * into_buf(char *, char *, TYPE const &)
Definition strconv.hxx:256
static TYPE from_string(std::string_view)
Definition strconv.hxx:260
static std::size_t size_buffer(TYPE const &) noexcept
Definition strconv.hxx:264
static constexpr bool converts_from_string
Definition strconv.hxx:251
static zview to_buf(char *, char *, TYPE const &)
Definition strconv.hxx:252
static constexpr bool converts_to_string
Definition strconv.hxx:250
Helper class for defining enum conversions.
Definition strconv.hxx:362
string_traits< impl_type > impl_traits
Definition strconv.hxx:364
static std::size_t size_buffer(ENUM const &value) noexcept
Definition strconv.hxx:385
static constexpr zview to_buf(char *begin, char *end, ENUM const &value)
Definition strconv.hxx:370
static constexpr bool converts_from_string
Definition strconv.hxx:367
std::underlying_type_t< ENUM > impl_type
Definition strconv.hxx:363
static ENUM from_string(std::string_view text)
Definition strconv.hxx:380
static constexpr char * into_buf(char *begin, char *end, ENUM const &value)
Definition strconv.hxx:375
static constexpr bool converts_to_string
Definition strconv.hxx:366
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:114
static constexpr bool always_null
Are all values of this type null?
Definition strconv.hxx:132
static constexpr bool has_null
Does TYPE have a "built-in null value"?
Definition strconv.hxx:126
static constexpr bool is_null(TYPE const &) noexcept
Does a given value correspond to an SQL null value?
Definition strconv.hxx:139
Traits describing a type's "null value," if any.
Definition strconv.hxx:92
static bool is_null(TYPE const &value)
Is value a null?
static TYPE null()
Return a null value.
static bool has_null
Does this type have a null value?
Definition strconv.hxx:94
static bool always_null
Is this type always null?
Definition strconv.hxx:97
Traits class for use in string conversions.
Definition strconv.hxx:155
static TYPE from_string(std::string_view text)
Parse a string representation of a TYPE value.
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 constexpr bool converts_to_string
Definition strconv.hxx:160
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
Definition strconv.hxx:166