8#if defined(PQXX_HAVE_SPAN) && __has_include(<span>)
16#include "pqxx/types.hxx"
17#include "pqxx/util.hxx"
29 return static_cast<char>(i +
'0');
44std::string PQXX_LIBEXPORT
48template<
typename HAVE,
typename NEED>
52 static_cast<int>(have_bytes),
static_cast<int>(need_bytes));
57[[noreturn]] PQXX_LIBEXPORT PQXX_COLD
void
62[[noreturn]] PQXX_LIBEXPORT PQXX_COLD
void
78 static constexpr bool converts_to_string{
false};
79 static constexpr bool converts_from_string{
false};
80 static char *into_buf(
char *,
char *, CHAR_TYPE) =
delete;
81 static constexpr zview
82 to_buf(
char *,
char *, CHAR_TYPE
const &)
noexcept =
delete;
84 static constexpr std::size_t
85 size_buffer(CHAR_TYPE
const &)
noexcept =
delete;
86 static CHAR_TYPE from_string(std::string_view) =
delete;
90template<
typename T> PQXX_LIBEXPORT
extern std::string
to_string_float(T);
98 auto const space{end - begin};
100 auto const len = std::size(text) + 1;
103 "Not enough buffer space to insert " + type_name<T> +
". " +
105 std::memmove(begin, text.data(), len);
114 static constexpr bool converts_to_string{
true};
115 static constexpr bool converts_from_string{
true};
116 static PQXX_LIBEXPORT T from_string(std::string_view text);
117 static PQXX_LIBEXPORT
zview to_buf(
char *begin,
char *end, T
const &value);
118 static PQXX_LIBEXPORT
char *into_buf(
char *begin,
char *end, T
const &value);
120 static constexpr std::size_t size_buffer(T
const &)
noexcept
126 return std::is_signed_v<T> + std::numeric_limits<T>::digits10 + 1 + 1;
135 static constexpr bool converts_to_string{
true};
136 static constexpr bool converts_from_string{
true};
137 static PQXX_LIBEXPORT T from_string(std::string_view text);
138 static PQXX_LIBEXPORT
zview to_buf(
char *begin,
char *end, T
const &value);
139 static PQXX_LIBEXPORT
char *into_buf(
char *begin,
char *end, T
const &value);
142 static constexpr std::size_t digits10(std::size_t value)
noexcept
147 return 1 + digits10(value / 10);
150 static constexpr std::size_t size_buffer(T
const &)
noexcept
152 using lims = std::numeric_limits<T>;
176 auto const max_pos_exp{digits10(lims::max_exponent10)};
179 auto const max_neg_exp{
180 digits10(lims::max_digits10 - lims::min_exponent10)};
183 std::numeric_limits<T>::max_digits10 +
188 (std::max)(max_pos_exp, max_neg_exp) +
208template<>
inline constexpr bool is_unquoted_safe<short>{
true};
213template<>
inline constexpr bool is_unquoted_safe<unsigned short>{
true};
216template<>
inline constexpr bool is_unquoted_safe<int>{
true};
219template<>
inline constexpr bool is_unquoted_safe<unsigned>{
true};
222template<>
inline constexpr bool is_unquoted_safe<long>{
true};
226template<>
inline constexpr bool is_unquoted_safe<unsigned long>{
true};
230template<>
inline constexpr bool is_unquoted_safe<long long>{
true};
235template<>
inline constexpr bool is_unquoted_safe<unsigned long long>{
true};
238template<>
inline constexpr bool is_unquoted_safe<float>{
true};
241template<>
inline constexpr bool is_unquoted_safe<double>{
true};
245template<>
inline constexpr bool is_unquoted_safe<long double>{
true};
253 static PQXX_LIBEXPORT
bool from_string(std::string_view text);
255 static constexpr zview to_buf(
char *,
char *,
bool const &value)
noexcept
257 return value ?
"true"_zv :
"false"_zv;
260 static char *
into_buf(
char *begin,
char *end,
bool const &value)
265 static constexpr std::size_t
size_buffer(
bool const &)
noexcept {
return 6; }
269template<>
inline constexpr bool is_unquoted_safe<bool>{
true};
272template<
typename T>
struct nullness<std::optional<T>>
274 static constexpr bool has_null =
true;
277 static constexpr bool is_null(std::optional<T>
const &v)
noexcept
279 return ((not v.has_value()) or pqxx::is_null(*v));
281 static constexpr std::optional<T>
null() {
return {}; }
286inline constexpr format param_format(std::optional<T>
const &value)
288 return param_format(*value);
299 static char *
into_buf(
char *begin,
char *end, std::optional<T>
const &value)
304 static zview to_buf(
char *begin,
char *end, std::optional<T>
const &value)
306 if (value.has_value())
312 static std::optional<T>
from_string(std::string_view text)
314 return std::optional<T>{
318 static std::size_t
size_buffer(std::optional<T>
const &value)
noexcept
320 return pqxx::size_buffer(value.value());
326inline constexpr bool is_unquoted_safe<std::optional<T>>{is_unquoted_safe<T>};
329template<
typename... T>
struct nullness<std::variant<T...>>
333 static constexpr bool is_null(std::variant<T...>
const &value)
noexcept
336 [](
auto const &i)
noexcept {
346 static constexpr std::variant<T...>
null() =
delete;
356 into_buf(
char *begin,
char *end, std::variant<T...>
const &value)
359 [begin, end](
auto const &i) {
364 static zview to_buf(
char *begin,
char *end, std::variant<T...>
const &value)
367 [begin, end](
auto const &i) {
372 static std::size_t
size_buffer(std::variant<T...>
const &value)
noexcept
375 [](
auto const &i)
noexcept {
return pqxx::size_buffer(i); }, value);
386template<
typename... Args>
387inline constexpr format param_format(std::variant<Args...>
const &value)
389 return std::visit([](
auto &v) {
return param_format(v); }, value);
393template<
typename... T>
394inline constexpr bool is_unquoted_safe<std::variant<T...>>{
395 (is_unquoted_safe<T> and ...)};
398template<
typename T>
inline T
from_string(std::stringstream
const &text)
400 return from_string<T>(text.str());
409 static char *
into_buf(
char *,
char *, std::nullptr_t) =
delete;
411 [[deprecated(
"Do not convert nulls.")]]
static constexpr zview
412 to_buf(
char *,
char *, std::nullptr_t
const &)
noexcept
417 [[deprecated(
"Do not convert nulls.")]]
static constexpr std::size_t
422 static std::nullptr_t
from_string(std::string_view) =
delete;
431 static char *
into_buf(
char *,
char *, std::nullopt_t) =
delete;
433 [[deprecated(
"Do not convert nulls.")]]
static constexpr zview
434 to_buf(
char *,
char *, std::nullopt_t
const &)
noexcept
439 [[deprecated(
"Do not convert nulls.")]]
static constexpr std::size_t
444 static std::nullopt_t
from_string(std::string_view) =
delete;
453 static char *
into_buf(
char *,
char *, std::monostate) =
delete;
455 [[deprecated(
"Do not convert nulls.")]]
static constexpr zview
456 to_buf(
char *,
char *, std::monostate
const &)
noexcept
461 [[deprecated(
"Do not convert nulls.")]]
static constexpr std::size_t
466 [[deprecated(
"Do not convert nulls.")]]
static std::monostate
471template<>
inline constexpr bool is_unquoted_safe<std::nullptr_t>{
true};
476 static constexpr bool has_null =
true;
477 static constexpr bool always_null =
false;
478 static constexpr bool is_null(
char const *t)
noexcept
482 static constexpr char const *null()
noexcept {
return nullptr; }
489 static constexpr bool converts_to_string{
true};
490 static constexpr bool converts_from_string{
true};
492 static char const *
from_string(std::string_view text) {
return text.data(); }
494 static zview to_buf(
char *begin,
char *end,
char const *
const &value)
496 return generic_to_buf(begin, end, value);
499 static char *into_buf(
char *begin,
char *end,
char const *
const &value)
501 auto const space{end - begin};
503 auto const len{std::strlen(value) + 1};
504 if (space < ptrdiff_t(len))
506 "Could not copy string: buffer too small. " +
508 std::memmove(begin, value, len);
512 static std::size_t size_buffer(
char const *
const &value)
noexcept
514 return std::strlen(value) + 1;
521 static constexpr bool has_null =
true;
522 static constexpr bool always_null =
false;
523 static constexpr bool is_null(
char const *t)
noexcept
527 static constexpr char const *null() {
return nullptr; }
534 static constexpr bool converts_to_string{
true};
535 static constexpr bool converts_from_string{
false};
537 static char *into_buf(
char *begin,
char *end,
char *
const &value)
541 static zview to_buf(
char *begin,
char *end,
char *
const &value)
545 static std::size_t size_buffer(
char *
const &value)
noexcept
568 static constexpr zview
569 to_buf(
char *,
char *,
char const (&value)[N])
noexcept
571 return zview{value, N - 1};
574 static char *
into_buf(
char *begin,
char *end,
char const (&value)[N])
578 "Could not convert char[] to string: too long for buffer."};
579 std::memcpy(begin, value, N);
582 static constexpr std::size_t
size_buffer(
char const (&)[N])
noexcept
601 static std::string
from_string(std::string_view text)
603 return std::string{text};
606 static char *
into_buf(
char *begin,
char *end, std::string
const &value)
610 "Could not convert string to string: too long for buffer."};
612 value.copy(begin, std::size(value));
613 begin[std::size(value)] =
'\0';
614 return begin + std::size(value) + 1;
617 static zview to_buf(
char *begin,
char *end, std::string
const &value)
619 return generic_to_buf(begin, end, value);
622 static std::size_t
size_buffer(std::string
const &value)
noexcept
624 return std::size(value) + 1;
643 static constexpr std::size_t
644 size_buffer(std::string_view
const &value)
noexcept
646 return std::size(value) + 1;
649 static char *
into_buf(
char *begin,
char *end, std::string_view
const &value)
653 "Could not store string_view: too long for buffer."};
654 value.copy(begin, std::size(value));
655 begin[std::size(value)] =
'\0';
656 return begin + std::size(value) + 1;
659 static zview to_buf(
char *begin,
char *end, std::string_view
const &value)
663 return generic_to_buf(begin, end, value);
681 static constexpr std::size_t
682 size_buffer(std::string_view
const &value)
noexcept
684 return std::size(value) + 1;
687 static char *
into_buf(
char *begin,
char *end,
zview const &value)
689 auto const size{std::size(value)};
692 value.copy(begin, size);
694 return begin + size + 1;
697 static std::string_view
to_buf(
char *begin,
char *end,
zview const &value)
699 char *
const stop{
into_buf(begin, end, value)};
700 return {begin,
static_cast<std::size_t
>(stop - begin - 1)};
717 static std::size_t
size_buffer(std::stringstream
const &) =
delete;
719 static std::stringstream
from_string(std::string_view text)
721 std::stringstream stream;
722 stream.write(text.data(), std::streamsize(std::size(text)));
726 static char *
into_buf(
char *,
char *, std::stringstream
const &) =
delete;
727 static std::string_view
728 to_buf(
char *,
char *, std::stringstream
const &) =
delete;
734 static constexpr bool has_null =
true;
736 static constexpr bool is_null(std::nullptr_t
const &)
noexcept
740 static constexpr std::nullptr_t
null()
noexcept {
return nullptr; }
746 static constexpr bool has_null =
true;
748 static constexpr bool is_null(std::nullopt_t
const &)
noexcept
752 static constexpr std::nullopt_t
null()
noexcept {
return std::nullopt; }
758 static constexpr bool has_null =
true;
760 static constexpr bool is_null(std::monostate
const &)
noexcept
764 static constexpr std::monostate
null()
noexcept {
return {}; }
768template<
typename T>
struct nullness<std::unique_ptr<T>>
770 static constexpr bool has_null =
true;
772 static constexpr bool is_null(std::unique_ptr<T>
const &t)
noexcept
774 return not t or pqxx::is_null(*t);
776 static constexpr std::unique_ptr<T>
null() {
return {}; }
780template<
typename T,
typename... Args>
788 static std::unique_ptr<T>
from_string(std::string_view text)
794 into_buf(
char *begin,
char *end, std::unique_ptr<T, Args...>
const &value)
800 to_buf(
char *begin,
char *end, std::unique_ptr<T, Args...>
const &value)
809 size_buffer(std::unique_ptr<T, Args...>
const &value)
noexcept
811 return pqxx::size_buffer(*value.get());
816template<
typename T,
typename... Args>
817inline format param_format(std::unique_ptr<T, Args...>
const &value)
819 return param_format(*value);
823template<
typename T,
typename... Args>
824inline constexpr bool is_unquoted_safe<std::unique_ptr<T, Args...>>{
825 is_unquoted_safe<T>};
828template<
typename T>
struct nullness<std::shared_ptr<T>>
830 static constexpr bool has_null =
true;
832 static constexpr bool is_null(std::shared_ptr<T>
const &t)
noexcept
834 return not t or pqxx::is_null(*t);
836 static constexpr std::shared_ptr<T>
null() {
return {}; }
847 static std::shared_ptr<T>
from_string(std::string_view text)
852 static zview to_buf(
char *begin,
char *end, std::shared_ptr<T>
const &value)
857 into_buf(
char *begin,
char *end, std::shared_ptr<T>
const &value)
861 static std::size_t
size_buffer(std::shared_ptr<T>
const &value)
noexcept
863 return pqxx::size_buffer(*value);
868template<
typename T>
format param_format(std::shared_ptr<T>
const &value)
870 return param_format(*value);
875inline constexpr bool is_unquoted_safe<std::shared_ptr<T>>{
876 is_unquoted_safe<T>};
883#if defined(PQXX_HAVE_CONCEPTS)
888template<binary DATA>
inline constexpr format param_format(DATA
const &)
890 return format::binary;
894template<binary DATA>
struct string_traits<DATA>
899 static std::size_t
size_buffer(DATA
const &value)
noexcept
904 static zview
to_buf(
char *begin,
char *end, DATA
const &value)
906 return generic_to_buf(begin, end, value);
909 static char *
into_buf(
char *begin,
char *end, DATA
const &value)
913 throw conversion_overrun{
914 "Not enough buffer space to escape binary data."};
916 return begin + budget;
943 return generic_to_buf(begin, end, value);
946 static char *
into_buf(
char *begin,
char *end,
bytes const &value)
951 "Not enough buffer space to escape binary data."};
953 return begin + budget;
967template<>
inline constexpr format param_format(
bytes const &)
969 return format::binary;
989 return generic_to_buf(begin, end, value);
997 "Not enough buffer space to escape binary data."};
999 return begin + budget;
1007 return format::binary;
1020 static constexpr zview s_null{
"NULL"};
1023 static constexpr bool converts_to_string{
true};
1024 static constexpr bool converts_from_string{
false};
1026 static zview to_buf(
char *begin,
char *end, Container
const &value)
1028 return generic_to_buf(begin, end, value);
1031 static char *into_buf(
char *begin,
char *end, Container
const &value)
1033 assert(begin <= end);
1034 std::size_t
const budget{size_buffer(value)};
1037 "Not enough buffer space to convert array to string."};
1042 bool nonempty{
false};
1043 for (
auto const &elt : value)
1047 s_null.copy(here, std::size(s_null));
1048 here += std::size(s_null);
1050 else if constexpr (is_sql_array<elt_type>)
1055 else if constexpr (is_unquoted_safe<elt_type>)
1067 auto const elt_budget{pqxx::size_buffer(elt)};
1068 assert(elt_budget <
static_cast<std::size_t
>(end - here));
1074 if (c ==
'\\' or c ==
'"')
1080 *here++ = array_separator<elt_type>;
1094 static std::size_t size_buffer(Container
const &value)
noexcept
1096 if constexpr (is_unquoted_safe<elt_type>)
1097 return 3 + std::accumulate(
1098 std::begin(value), std::end(value), std::size_t{},
1099 [](std::size_t acc, elt_type
const &elt) {
1101 (pqxx::is_null(elt) ?
1107 return 3 + std::accumulate(
1108 std::begin(value), std::end(value), std::size_t{},
1109 [](std::size_t acc, elt_type
const &elt) {
1112 std::size_t
const elt_size{
1113 pqxx::is_null(elt) ? std::size(s_null) :
1115 return acc + 2 * elt_size + 2;
1127template<
typename T,
typename... Args>
1132template<
typename T,
typename... Args>
1139template<
typename T,
typename... Args>
1140inline constexpr format param_format(std::vector<T, Args...>
const &)
1142 return format::text;
1147template<
typename... Args>
1148inline constexpr format param_format(std::vector<std::byte, Args...>
const &)
1150 return format::binary;
1154template<
typename T>
inline constexpr bool is_sql_array<std::vector<T>>{
true};
1157#if defined(PQXX_HAVE_SPAN) && __has_include(<span>)
1158template<
typename T,
size_t Extent>
1159struct nullness<std::span<T, Extent>> : no_null<std::span<T, Extent>>
1163template<
typename T,
size_t Extent>
1164struct string_traits<std::span<T, Extent>>
1165 : internal::array_string_traits<std::span<T, Extent>>
1169template<
typename T,
size_t Extent>
1170inline constexpr format param_format(std::span<T, Extent>
const &)
1172 return format::text;
1176template<
size_t Extent>
1177inline constexpr format param_format(std::span<std::byte, Extent>
const &)
1179 return format::binary;
1183template<
typename T,
size_t Extent>
1184inline constexpr bool is_sql_array<std::span<T, Extent>>{
true};
1188template<
typename T, std::
size_t N>
1193template<
typename T, std::
size_t N>
1200template<
typename T,
typename... Args, Args... args>
1201inline constexpr format param_format(std::array<T, args...>
const &)
1203 return format::text;
1208template<
typename... Args, Args... args>
1209inline constexpr format param_format(std::array<std::byte, args...>
const &)
1211 return format::binary;
1215template<
typename T, std::
size_t N>
1216inline constexpr bool is_sql_array<std::array<T, N>>{
true};
1222template<
typename T>
inline std::string
to_string(T
const &value)
1225 throw conversion_error{
1226 "Attempt to convert null " + std::string{type_name<T>} +
1232 buf.resize(size_buffer(value));
1233 auto const data{buf.data()};
1236 buf.resize(
static_cast<std::size_t
>(end - data - 1));
1241template<>
inline std::string
to_string(
float const &value)
1245template<>
inline std::string
to_string(
double const &value)
1249template<>
inline std::string
to_string(
long double const &value)
1253template<>
inline std::string
to_string(std::stringstream
const &value)
1259template<
typename T>
inline void into_string(T
const &value, std::string &out)
1262 throw conversion_error{
1263 "Attempt to convert null " + type_name<T> +
" to a string."};
1267 out.resize(size_buffer(value) + 1);
1268 auto const data{out.data()};
1271 out.resize(
static_cast<std::size_t
>(end - data - 1));
An SQL array received from the database.
Definition array.hxx:56
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
Could not convert value to string: not enough buffer space.
Definition except.hxx:313
Internal items for libpqxx' own use. Do not use these yourself.
Definition encodings.cxx:33
void PQXX_LIBEXPORT unesc_bin(std::string_view escaped_data, std::byte buffer[])
Reconstitute binary data from its escaped version.
Definition util.cxx:165
void throw_null_conversion(std::string const &type)
Throw exception for attempt to convert SQL NULL to given type.
Definition strconv.cxx:255
constexpr std::size_t size_esc_bin(std::size_t binary_bytes) noexcept
Compute buffer size needed to escape binary data for use as a BYTEA.
Definition util.hxx:516
constexpr char number_to_digit(int i) noexcept
Convert a number in [0, 9] to its ASCII digit.
Definition conversions.hxx:27
constexpr bool cmp_less(LEFT lhs, RIGHT rhs) noexcept
Same as std::cmp_less, or a workaround where that's not available.
Definition util.hxx:65
constexpr int digit_to_number(char c) noexcept
Compute numeric value of given textual digit (assuming that it is a digit).
Definition conversions.hxx:34
void PQXX_LIBEXPORT esc_bin(bytes_view binary_data, char buffer[]) noexcept
Hex-escape binary data into a buffer.
Definition util.cxx:133
std::string to_string_float(T value)
Floating-point implementations for pqxx::to_string().
Definition strconv.cxx:668
constexpr bool cmp_greater(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_greater, or workaround if not available.
Definition util.hxx:87
std::string state_buffer_overrun(int have_bytes, int need_bytes)
Summarize buffer overrun.
Definition strconv.cxx:267
char * generic_into_buf(char *begin, char *end, T const &value)
Generic implementation for into_buf, on top of to_buf.
Definition conversions.hxx:95
constexpr bool cmp_greater_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_greater_equal, or workaround if not available.
Definition util.hxx:113
constexpr bool cmp_less_equal(LEFT lhs, RIGHT rhs) noexcept
C++20 std::cmp_less_equal, or workaround if not available.
Definition util.hxx:100
constexpr std::size_t size_unesc_bin(std::size_t escaped_bytes) noexcept
Compute binary size from the size of its escaped version.
Definition util.hxx:525
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
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::conditional< has_generic_bytes_char_traits, std::basic_string< std::byte >, std::basic_string< std::byte, byte_char_traits > >::type bytes
Type alias for a container containing bytes.
Definition util.hxx:375
PQXX_LIBEXPORT std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:566
std::conditional< has_generic_bytes_char_traits, std::basic_string_view< std::byte >, std::basic_string_view< std::byte, byte_char_traits > >::type bytes_view
Type alias for a view of bytes.
Definition util.hxx:385
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:532
format
Format code: is data text or binary?
Definition types.hxx:68
String traits for SQL arrays.
Definition conversions.hxx:1016
Deliberately nonfunctional conversion traits for char types.
Definition conversions.hxx:77
String traits for builtin floating-point types.
Definition conversions.hxx:134
static PQXX_LIBEXPORT zview to_buf(char *begin, char *end, T const &value)
Floating-point to_buf implemented in terms of to_string.
Definition strconv.cxx:600
String traits for builtin integral types (though not bool).
Definition conversions.hxx:113
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:113
static constexpr std::variant< T... > null()=delete
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 TYPE null()
Return a null value.
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
static char * from_string(std::string_view)=delete
Don't allow conversion to this type since it breaks const-safety.
static void from_string(std::string_view)=delete
Don't allow conversion to this type.
static std::string_view from_string(std::string_view)=delete
Don't convert to this type; it has nowhere to store its contents.
static std::variant< T... > from_string(std::string_view)=delete
static zview from_string(std::string_view)=delete
Don't convert to this type; it has nowhere to store its contents.
Traits class for use in string conversions.
Definition strconv.hxx:153
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
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