libpqxx  7.2.0
composite.hxx
1 #ifndef PQXX_H_COMPOSITE
2 #define PQXX_H_COMPOSITE
3 
4 #include "pqxx/internal/array-composite.hxx"
5 #include "pqxx/util.hxx"
6 
7 namespace pqxx
8 {
10 
29 template<typename... T>
30 inline void parse_composite(
31  pqxx::internal::encoding_group enc, std::string_view text, T &... fields)
32 {
33  static_assert(sizeof...(fields) > 0);
34 
35  auto const scan{pqxx::internal::get_glyph_scanner(enc)};
36  auto const data{text.data()};
37  auto const size{std::size(text)};
38  if (size == 0)
39  throw conversion_error{"Cannot parse composite value from empty string."};
40 
41  std::size_t here{0}, next{scan(data, size, here)};
42  if (next != 1 or data[here] != '(')
43  throw conversion_error{
44  "Invalid composite value string: " + std::string{data}};
45 
46  here = next;
47 
48  constexpr auto num_fields{sizeof...(fields)};
49  std::size_t index{0};
50  (pqxx::internal::parse_composite_field(
51  index, text, here, fields, scan, num_fields - 1),
52  ...);
53 }
54 
55 
57 
62 template<typename... T>
63 inline void parse_composite(std::string_view text, T &... fields)
64 {
65  parse_composite(pqxx::internal::encoding_group::MONOBYTE, text, fields...);
66 }
67 } // namespace pqxx
68 
69 
70 namespace pqxx::internal
71 {
72 constexpr char empty_composite_str[]{"()"};
73 } // namespace pqxx::internal
74 
75 
76 namespace pqxx
77 {
79 
81 template<typename... T>
82 inline std::size_t composite_size_buffer(T const &... fields) noexcept
83 {
84  constexpr auto num{sizeof...(fields)};
85 
86  // Size for a multi-field composite includes room for...
87  // + opening parenthesis
88  // + field budgets
89  // + separating comma per field
90  // - comma after final field
91  // + closing parenthesis
92  // + terminating zero
93 
94  if constexpr (sizeof...(fields) == 0)
95  return std::size(pqxx::internal::empty_composite_str);
96  else
97  return 1 + (pqxx::internal::size_composite_field_buffer(fields) + ...) +
98  num + 1;
99 }
100 
101 
103 
108 template<typename... T>
109 inline char *composite_into_buf(char *begin, char *end, T const &... fields)
110 {
111  if (std::size_t(end - begin) < composite_size_buffer(fields...))
112  throw conversion_error{
113  "Buffer space may not be enough to represent composite value."};
114 
115  constexpr auto num_fields{sizeof...(fields)};
116  if constexpr (num_fields == 0)
117  {
118  constexpr char empty[]{"()"};
119  std::memcpy(begin, empty, std::size(empty));
120  return begin + std::size(empty);
121  }
122 
123  char *pos{begin};
124  *pos++ = '(';
125 
126  (pqxx::internal::write_composite_field<T>(pos, end, fields), ...);
127 
128  // If we've got multiple fields, "backspace" that last comma.
129  if constexpr (num_fields > 1)
130  --pos;
131  *pos++ = ')';
132  *pos++ = '\0';
133  return pos;
134 }
135 } // namespace pqxx
136 #endif
Private namespace for libpqxx&#39;s internal use; do not access.
Definition: composite.hxx:70
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
PQXX_PURE glyph_scanner_func * get_glyph_scanner(encoding_group enc)
Definition: encodings.cxx:688
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:30
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:82
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:109
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:178
constexpr char empty_composite_str[]
Definition: composite.hxx:72