Loading...
Searching...
No Matches
strconv.hxx
/* String conversion definitions.
*
* DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/stringconv instead.
*
* Copyright (c) 2000-2024, Jeroen T. Vermeulen.
*
* See COPYING for copyright license. If you did not receive a file called
* COPYING with this source code, please notify the distributor of this
* mistake, or contact the author.
*/
#ifndef PQXX_H_STRCONV
#define PQXX_H_STRCONV
#if !defined(PQXX_HEADER_PRE)
# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
#endif
#include <algorithm>
#include <charconv>
#include <cstring>
#include <limits>
#include <sstream>
#include <stdexcept>
#include <typeinfo>
// C++20: Assume support.
#if __has_include(<ranges>)
# include <ranges>
#endif
#include "pqxx/except.hxx"
#include "pqxx/util.hxx"
#include "pqxx/zview.hxx"
namespace pqxx::internal
{
PQXX_LIBEXPORT std::string demangle_type_name(char const[]);
} // namespace pqxx::internal
namespace pqxx
{
template<typename TYPE>
std::string const type_name{internal::demangle_type_name(typeid(TYPE).name())};
template<typename TYPE, typename ENABLE = void> struct nullness
{
static bool has_null;
static bool always_null;
static bool is_null(TYPE const &value);
[[nodiscard]] static TYPE null();
};
template<typename TYPE> struct no_null
{
static constexpr bool has_null = false;
static constexpr bool always_null = false;
[[nodiscard]] static constexpr bool is_null(TYPE const &) noexcept
{
return false;
}
};
template<typename TYPE> struct string_traits
{
static constexpr bool converts_to_string{false};
static constexpr bool converts_from_string{false};
[[nodiscard]] static inline zview
to_buf(char *begin, char *end, TYPE const &value);
/* @warning A null value has no string representation. Do not pass a null.
*
* Writes value's string representation into the buffer, starting exactly at
* @c begin, and ensuring a trailing zero. Returns the address just beyond
* the trailing zero, so the caller could use it as the @c begin for another
* call to @c into_buf writing a next value.
*/
static inline char *into_buf(char *begin, char *end, TYPE const &value);
[[nodiscard]] static inline TYPE from_string(std::string_view text);
// C++20: Can we make these all constexpr?
[[nodiscard]] static inline std::size_t
size_buffer(TYPE const &value) noexcept;
// TODO: Move is_unquoted_safe into the traits after all?
};
template<typename TYPE> [[noreturn]] void oops_forbidden_conversion() noexcept;
template<typename TYPE> struct forbidden_conversion
{
static constexpr bool converts_to_string{false};
static constexpr bool converts_from_string{false};
[[noreturn]] static zview to_buf(char *, char *, TYPE const &)
{
oops_forbidden_conversion<TYPE>();
}
[[noreturn]] static char *into_buf(char *, char *, TYPE const &)
{
oops_forbidden_conversion<TYPE>();
}
[[noreturn]] static TYPE from_string(std::string_view)
{
oops_forbidden_conversion<TYPE>();
}
[[noreturn]] static std::size_t size_buffer(TYPE const &) noexcept
{
oops_forbidden_conversion<TYPE>();
}
};
template<> struct string_traits<char> : forbidden_conversion<char>
{};
template<>
struct string_traits<unsigned char> : forbidden_conversion<unsigned char>
{};
template<>
struct string_traits<signed char> : forbidden_conversion<signed char>
{};
template<> struct string_traits<std::byte> : forbidden_conversion<std::byte>
{};
template<typename ENUM>
struct nullness<ENUM, std::enable_if_t<std::is_enum_v<ENUM>>> : no_null<ENUM>
{};
// C++20: Concepts for "converts from string" & "converts to string."
} // namespace pqxx
namespace pqxx::internal
{
template<typename ENUM> struct enum_traits
{
using impl_type = std::underlying_type_t<ENUM>;
using impl_traits = string_traits<impl_type>;
static constexpr bool converts_to_string{true};
static constexpr bool converts_from_string{true};
[[nodiscard]] static constexpr zview
to_buf(char *begin, char *end, ENUM const &value)
{
return impl_traits::to_buf(begin, end, to_underlying(value));
}
static constexpr char *into_buf(char *begin, char *end, ENUM const &value)
{
return impl_traits::into_buf(begin, end, to_underlying(value));
}
[[nodiscard]] static ENUM from_string(std::string_view text)
{
return static_cast<ENUM>(impl_traits::from_string(text));
}
[[nodiscard]] static std::size_t size_buffer(ENUM const &value) noexcept
{
return impl_traits::size_buffer(to_underlying(value));
}
private:
// C++23: Replace with std::to_underlying.
static constexpr impl_type to_underlying(ENUM const &value) noexcept
{
return static_cast<impl_type>(value);
}
};
} // namespace pqxx::internal
// We used to inline type_name<ENUM>, but this triggered a "double free" error
// on program exit, when libpqxx was built as a shared library on Debian with
// gcc 12.
#define PQXX_DECLARE_ENUM_CONVERSION(ENUM) \
template<> struct string_traits<ENUM> : pqxx::internal::enum_traits<ENUM> \
{}; \
template<> inline std::string_view const type_name<ENUM> \
{ \
#ENUM \
}
namespace pqxx
{
template<typename TYPE>
[[nodiscard]] inline TYPE from_string(std::string_view text)
{
return string_traits<TYPE>::from_string(text);
}
template<>
[[nodiscard]] inline std::string_view from_string(std::string_view text)
{
return text;
}
template<typename T> inline void from_string(std::string_view text, T &value)
{
value = from_string<T>(text);
}
template<typename TYPE> inline std::string to_string(TYPE const &value);
template<typename... TYPE>
[[nodiscard]] inline std::vector<std::string_view>
to_buf(char *here, char const *end, TYPE... value)
{
PQXX_ASSUME(here <= end);
return {[&here, end](auto v) {
auto begin = here;
here = string_traits<decltype(v)>::into_buf(begin, end, v);
// Exclude the trailing zero out of the string_view.
auto len{static_cast<std::size_t>(here - begin) - 1};
return std::string_view{begin, len};
}(value)...};
}
template<typename TYPE>
inline void into_string(TYPE const &value, std::string &out);
template<typename TYPE>
[[nodiscard]] inline constexpr bool is_null(TYPE const &value) noexcept
{
return nullness<strip_t<TYPE>>::is_null(value);
}
template<typename... TYPE>
[[nodiscard]] inline std::size_t size_buffer(TYPE const &...value) noexcept
{
return (string_traits<strip_t<TYPE>>::size_buffer(value) + ...);
}
template<typename TYPE> inline constexpr bool is_sql_array{false};
template<typename TYPE> inline constexpr bool is_unquoted_safe{false};
template<typename T> inline constexpr char array_separator{','};
template<typename TYPE> inline constexpr format param_format(TYPE const &)
{
return format::text;
}
template<typename TYPE>
inline zview generic_to_buf(char *begin, char *end, TYPE const &value)
{
using traits = string_traits<TYPE>;
// The trailing zero does not count towards the zview's size, so subtract 1
// from the result we get from into_buf().
if (is_null(value))
return {};
else
return {begin, traits::into_buf(begin, end, value) - begin - 1};
}
#if defined(PQXX_HAVE_CONCEPTS)
template<class TYPE>
concept binary = std::ranges::contiguous_range<TYPE> and
std::is_same_v<strip_t<value_type<TYPE>>, std::byte>;
#endif
} // namespace pqxx
#include "pqxx/internal/conversions.hxx"
#endif
pqxx::zview
Marker-type wrapper: zero-terminated std::string_view.
Definition zview.hxx:38
pqxx::internal
Internal items for libpqxx' own use. Do not use these yourself.
Definition encodings.cxx:33
pqxx::internal::demangle_type_name
std::string demangle_type_name(char const raw[])
Attempt to demangle std::type_info::name() to something human-readable.
Definition strconv.cxx:226
pqxx
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
pqxx::type_name
std::string const type_name
A human-readable name for a type, used in error messages and such.
Definition strconv.hxx:80
pqxx::oops_forbidden_conversion
void oops_forbidden_conversion() noexcept
Nonexistent function to indicate a disallowed type conversion.
pqxx::to_string
PQXX_LIBEXPORT std::string to_string(field const &value)
Convert a field to a string.
Definition result.cxx:628
pqxx::from_string
T from_string(field const &value)
Convert a field's value to type T.
Definition field.hxx:548
pqxx::format
format
Format code: is data text or binary?
Definition types.hxx:70
pqxx::forbidden_conversion
String traits for a forbidden type conversion.
Definition strconv.hxx:248
pqxx::internal::enum_traits
Helper class for defining enum conversions.
Definition strconv.hxx:361
pqxx::no_null
Nullness traits describing a type which does not have a null value.
Definition strconv.hxx:113
pqxx::no_null::always_null
static constexpr bool always_null
Are all values of this type null?
Definition strconv.hxx:131
pqxx::no_null::has_null
static constexpr bool has_null
Does TYPE have a "built-in null value"?
Definition strconv.hxx:125
pqxx::no_null::is_null
static constexpr bool is_null(TYPE const &) noexcept
Does a given value correspond to an SQL null value?
Definition strconv.hxx:138
pqxx::nullness
Traits describing a type's "null value," if any.
Definition strconv.hxx:91
pqxx::nullness::is_null
static bool is_null(TYPE const &value)
Is value a null?
pqxx::nullness::null
static TYPE null()
Return a null value.
pqxx::nullness::has_null
static bool has_null
Does this type have a null value?
Definition strconv.hxx:93
pqxx::nullness::always_null
static bool always_null
Is this type always null?
Definition strconv.hxx:96
pqxx::string_traits
Traits class for use in string conversions.
Definition strconv.hxx:154
pqxx::string_traits::from_string
static TYPE from_string(std::string_view text)
Parse a string representation of a TYPE value.
pqxx::string_traits::size_buffer
static std::size_t size_buffer(TYPE const &value) noexcept
Estimate how much buffer space is needed to represent value.
pqxx::string_traits::to_buf
static zview to_buf(char *begin, char *end, TYPE const &value)
Return a string_view representing value, plus terminating zero.
pqxx::string_traits::converts_to_string
static constexpr bool converts_to_string
Is conversion from TYPE to strings supported?
Definition strconv.hxx:159
pqxx::string_traits::into_buf
static char * into_buf(char *begin, char *end, TYPE const &value)
Write value's string representation into buffer at begin.
pqxx::string_traits::converts_from_string
static constexpr bool converts_from_string
Is conversion from string_view to TYPE supported?
Definition strconv.hxx:165