libpqxx  7.7.0
composite.hxx
1 #ifndef PQXX_H_COMPOSITE
2 #define PQXX_H_COMPOSITE
3 
4 #include "pqxx/internal/array-composite.hxx"
5 #include "pqxx/internal/concat.hxx"
6 #include "pqxx/util.hxx"
7 
8 namespace pqxx
9 {
11 
30 template<typename... T>
31 inline void parse_composite(
32  pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
33 {
34  static_assert(sizeof...(fields) > 0);
35 
36  auto const scan{pqxx::internal::get_glyph_scanner(enc)};
37  auto const data{std::data(text)};
38  auto const size{std::size(text)};
39  if (size == 0)
40  throw conversion_error{"Cannot parse composite value from empty string."};
41 
42  std::size_t here{0}, next{scan(data, size, here)};
43  if (next != 1 or data[here] != '(')
44  throw conversion_error{
45  internal::concat("Invalid composite value string: ", text)};
46 
47  here = next;
48 
49  // C++20: constinit.
50  constexpr auto num_fields{sizeof...(fields)};
51  std::size_t index{0};
52  (pqxx::internal::parse_composite_field(
53  index, text, here, fields, scan, num_fields - 1),
54  ...);
55  if (here != std::size(text))
56  throw conversion_error{internal::concat(
57  "Composite value did not end at the closing parenthesis: '", text,
58  "'.")};
59  if (text[here - 1] != ')')
60  throw conversion_error{internal::concat(
61  "Composive value did not end in parenthesis: '", text, "'")};
62 }
63 
64 
66 
71 template<typename... T>
72 inline void parse_composite(std::string_view text, T &...fields)
73 {
74  parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...);
75 }
76 } // namespace pqxx
77 
78 
79 namespace pqxx::internal
80 {
81 // C++20: constinit.
82 constexpr char empty_composite_str[]{"()"};
83 } // namespace pqxx::internal
84 
85 
86 namespace pqxx
87 {
89 
91 template<typename... T>
92 [[nodiscard]] inline std::size_t
93 composite_size_buffer(T const &...fields) noexcept
94 {
95  // C++20: constinit.
96  constexpr auto num{sizeof...(fields)};
97 
98  // Size for a multi-field composite includes room for...
99  // + opening parenthesis
100  // + field budgets
101  // + separating comma per field
102  // - comma after final field
103  // + closing parenthesis
104  // + terminating zero
105 
106  if constexpr (num == 0)
107  return std::size(pqxx::internal::empty_composite_str);
108  else
109  return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) +
110  num + 1;
111 }
112 
113 
115 
120 template<typename... T>
121 inline char *composite_into_buf(char *begin, char *end, T const &...fields)
122 {
123  if (std::size_t(end - begin) < composite_size_buffer(fields...))
124  throw conversion_error{
125  "Buffer space may not be enough to represent composite value."};
126 
127  // C++20: constinit.
128  constexpr auto num_fields{sizeof...(fields)};
129  if constexpr (num_fields == 0)
130  {
131  // C++20: constinit.
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
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:93
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:121
constexpr char empty_composite_str[]
Definition: composite.hxx:82
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:31
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:175
Internal items for libpqxx&#39; own use. Do not use these yourself.
Definition: composite.hxx:79
PQXX_PURE glyph_scanner_func * get_glyph_scanner(encoding_group enc)
Definition: encodings.cxx:785
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:22