libpqxx 7.8.1
composite.hxx
1#ifndef PQXX_H_COMPOSITE
2#define PQXX_H_COMPOSITE
3
4#if !defined(PQXX_HEADER_PRE)
5# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
6#endif
7
8#include "pqxx/internal/array-composite.hxx"
9#include "pqxx/internal/concat.hxx"
10#include "pqxx/util.hxx"
11
12namespace pqxx
13{
15
34template<typename... T>
35inline void parse_composite(
36 pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
37{
38 static_assert(sizeof...(fields) > 0);
39
40 auto const scan{pqxx::internal::get_glyph_scanner(enc)};
41 auto const data{std::data(text)};
42 auto const size{std::size(text)};
43 if (size == 0)
44 throw conversion_error{"Cannot parse composite value from empty string."};
45
46 std::size_t here{0}, next{scan(data, size, here)};
47 if (next != 1 or data[here] != '(')
48 throw conversion_error{
49 internal::concat("Invalid composite value string: ", text)};
50
51 here = next;
52
53 // TODO: Reuse parse_composite_field specialisation across calls.
54 constexpr auto num_fields{sizeof...(fields)};
55 std::size_t index{0};
56 (pqxx::internal::specialize_parse_composite_field<T>(enc)(
57 index, text, here, fields, num_fields - 1),
58 ...);
59 if (here != std::size(text))
60 throw conversion_error{internal::concat(
61 "Composite value did not end at the closing parenthesis: '", text,
62 "'.")};
63 if (text[here - 1] != ')')
64 throw conversion_error{internal::concat(
65 "Composive value did not end in parenthesis: '", text, "'")};
66}
67
68
70
75template<typename... T>
76inline void parse_composite(std::string_view text, T &...fields)
77{
78 parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...);
79}
80} // namespace pqxx
81
82
84{
85constexpr char empty_composite_str[]{"()"};
86} // namespace pqxx::internal
87
88
89namespace pqxx
90{
92
94template<typename... T>
95[[nodiscard]] inline std::size_t
96composite_size_buffer(T const &...fields) noexcept
97{
98 constexpr auto num{sizeof...(fields)};
99
100 // Size for a multi-field composite includes room for...
101 // + opening parenthesis
102 // + field budgets
103 // + separating comma per field
104 // - comma after final field
105 // + closing parenthesis
106 // + terminating zero
107
108 if constexpr (num == 0)
109 return std::size(pqxx::internal::empty_composite_str);
110 else
111 return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) +
112 num + 1;
113}
114
115
117
122template<typename... T>
123inline char *composite_into_buf(char *begin, char *end, T const &...fields)
124{
125 if (std::size_t(end - begin) < composite_size_buffer(fields...))
126 throw conversion_error{
127 "Buffer space may not be enough to represent composite value."};
128
129 constexpr auto num_fields{sizeof...(fields)};
130 if constexpr (num_fields == 0)
131 {
132 constexpr char empty[]{"()"};
133 std::memcpy(begin, empty, std::size(empty));
134 return begin + std::size(empty);
135 }
136
137 char *pos{begin};
138 *pos++ = '(';
139
140 (pqxx::internal::write_composite_field<T>(pos, end, fields), ...);
141
142 // If we've got multiple fields, "backspace" that last comma.
143 if constexpr (num_fields > 1)
144 --pos;
145 *pos++ = ')';
146 *pos++ = '\0';
147 return pos;
148}
149} // namespace pqxx
150#endif
The home of all libpqxx classes, functions, templates, etc.
Definition array.hxx:33
char * composite_into_buf(char *begin, char *end, T const &...fields)
Render a series of values as a single composite SQL value.
Definition composite.hxx:123
std::size_t composite_size_buffer(T const &...fields) noexcept
Estimate the buffer size needed to represent a value of a composite type.
Definition composite.hxx:96
void parse_composite(pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
Parse a string representation of a value of a composite type.
Definition composite.hxx:35
Internal items for libpqxx' own use. Do not use these yourself.
Definition composite.hxx:84
PQXX_PURE glyph_scanner_func * get_glyph_scanner(encoding_group enc)
Definition encodings.cxx:180
constexpr char empty_composite_str[]
Definition composite.hxx:85
Value conversion failed, e.g. when converting "Hello" to int.
Definition except.hxx:283