libpqxx  7.7.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 
12 namespace pqxx
13 {
15 
34 template<typename... T>
35 inline 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  constexpr auto num_fields{sizeof...(fields)};
54  std::size_t index{0};
55  (pqxx::internal::parse_composite_field(
56  index, text, here, fields, scan, num_fields - 1),
57  ...);
58  if (here != std::size(text))
59  throw conversion_error{internal::concat(
60  "Composite value did not end at the closing parenthesis: '", text,
61  "'.")};
62  if (text[here - 1] != ')')
63  throw conversion_error{internal::concat(
64  "Composive value did not end in parenthesis: '", text, "'")};
65 }
66 
67 
69 
74 template<typename... T>
75 inline void parse_composite(std::string_view text, T &...fields)
76 {
77  parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...);
78 }
79 } // namespace pqxx
80 
81 
82 namespace pqxx::internal
83 {
84 constexpr char empty_composite_str[]{"()"};
85 } // namespace pqxx::internal
86 
87 
88 namespace pqxx
89 {
91 
93 template<typename... T>
94 [[nodiscard]] inline std::size_t
95 composite_size_buffer(T const &...fields) noexcept
96 {
97  constexpr auto num{sizeof...(fields)};
98 
99  // Size for a multi-field composite includes room for...
100  // + opening parenthesis
101  // + field budgets
102  // + separating comma per field
103  // - comma after final field
104  // + closing parenthesis
105  // + terminating zero
106 
107  if constexpr (num == 0)
108  return std::size(pqxx::internal::empty_composite_str);
109  else
110  return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) +
111  num + 1;
112 }
113 
114 
116 
121 template<typename... T>
122 inline char *composite_into_buf(char *begin, char *end, T const &...fields)
123 {
124  if (std::size_t(end - begin) < composite_size_buffer(fields...))
125  throw conversion_error{
126  "Buffer space may not be enough to represent composite value."};
127 
128  constexpr auto num_fields{sizeof...(fields)};
129  if constexpr (num_fields == 0)
130  {
131  constexpr char empty[]{"()"};
132  std::memcpy(begin, empty, std::size(empty));
133  return begin + std::size(empty);
134  }
135 
136  char *pos{begin};
137  *pos++ = '(';
138 
139  (pqxx::internal::write_composite_field<T>(pos, end, fields), ...);
140 
141  // If we've got multiple fields, "backspace" that last comma.
142  if constexpr (num_fields > 1)
143  --pos;
144  *pos++ = ')';
145  *pos++ = '\0';
146  return pos;
147 }
148 } // namespace pqxx
149 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:26
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
constexpr char empty_composite_str[]
Definition: composite.hxx:84
PQXX_PURE glyph_scanner_func * get_glyph_scanner(encoding_group enc)
Definition: encodings.cxx:796
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:95
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:122
Internal items for libpqxx&#39; own use. Do not use these yourself.
Definition: composite.hxx:82
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:187