14#if !defined(PQXX_HEADER_PRE)
15# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
26#include "pqxx/connection.hxx"
27#include "pqxx/internal/array-composite.hxx"
28#include "pqxx/internal/encoding_group.hxx"
29#include "pqxx/internal/encodings.hxx"
53 typename ELEMENT, std::size_t DIMENSIONS = 1u,
68 array(std::string_view data, connection
const &
cx) :
90 check_bounds(index...);
91 return m_elts.at(locate(index...));
105 static_assert(
sizeof...(index) ==
DIMENSIONS);
106 return m_elts[locate(index...)];
147 return static_cast<std::ptrdiff_t
>(
size());
170 void check_dims(std::string_view data)
172 auto sz{std::size(data)};
175 "Trying to parse a ",
DIMENSIONS,
"-dimensional array out of '", data,
188 throw conversion_error{
"Malformed array: does not start with '{'."};
192 "Expecting ",
DIMENSIONS,
"-dimensional array, but found ",
i,
".")};
196 "-dimensional array from array data that has more dimensions.")};
198 if (data[
sz - 1 -
i] !=
'}')
199 throw conversion_error{
200 "Malformed array: does not end in the right number of '}'."};
205 friend class ::pqxx::field;
207 array(std::string_view data, pqxx::internal::encoding_group
enc)
209 using group = pqxx::internal::encoding_group;
225 default: PQXX_UNREACHABLE;
break;
233 std::size_t parse_field_end(std::string_view data, std::size_t
here)
const
235 auto const sz{std::size(data)};
242 throw conversion_error{
"Array looks truncated."};
246 throw conversion_error{
"Array contains double separator."};
247 case '}':
throw conversion_error{
"Array contains trailing separator."};
254 "Unexpected character in array: ",
255 static_cast<unsigned>(
static_cast<unsigned char>(data[
here])),
256 " where separator or closing brace expected.")};
267 constexpr std::size_t estimate_elements(std::string_view data)
const noexcept
273 std::count(std::begin(data), std::end(data),
SEPARATOR)};
277 return static_cast<std::size_t
>(
separators + 1);
280 template<pqxx::
internal::encoding_group ENC>
281 void parse(std::string_view data)
283 static_assert(
DIMENSIONS > 0
u,
"Can't create a zero-dimensional array.");
284 auto const sz{std::size(data)};
287 m_elts.reserve(estimate_elements(data));
301 constexpr std::size_t
outer{std::size_t{0
u} - std::size_t{1u}};
310 std::array<std::size_t, DIMENSIONS>
extents{};
317 if (data[
here] ==
'{')
323 throw conversion_error{
324 "Array text representation closed and reopened its outside "
327 PQXX_ASSUME(
here == 0);
332 throw conversion_error{
333 "Array seems to have inconsistent number of dimensions."};
341 else if (data[
here] ==
'}')
344 throw conversion_error{
"Array has spurious '}'."};
355 throw conversion_error{
"Rows in array have inconsistent sizes."};
368 throw conversion_error{
369 "Malformed array: found element where sub-array was expected."};
375 case '\0':
throw conversion_error{
"Unexpected zero byte in array."};
376 case ',':
throw conversion_error{
"Array contains empty field."};
387 end = pqxx::internal::scan_double_quoted_string<ENC>(
388 std::data(data), std::size(data),
here);
390 std::string
const buf{
391 pqxx::internal::parse_double_quoted_string<ENC>(
392 std::data(data), end,
here)};
400 end = pqxx::internal::scan_unquoted_string<ENC, SEPARATOR, '}'>(
401 std::data(data), std::size(data),
here);
402 std::string_view
const field{
403 std::string_view{std::data(data) +
here, end -
here}};
411 ". Consider making it an array of std::optional<",
425 throw conversion_error{
"Malformed array; may be truncated."};
444 template<
typename...
INDEX> std::size_t locate(
INDEX... index)
const noexcept
448 "Indexing array with wrong number of dimensions.");
449 return add_index(index...);
456 if constexpr (
sizeof...(indexes) == 0)
462 static_assert(
sizeof...(indexes) <
DIMENSIONS);
477 static_assert(
sizeof...(indexes) <
DIMENSIONS);
483 "Array index for dimension ",
dimension,
" is out of bounds: ",
first,
487 if constexpr (
sizeof...(indexes) > 0)
492 std::vector<ELEMENT> m_elts;
495 std::array<std::size_t, DIMENSIONS> m_extents;
505 std::array<std::size_t,
DIMENSIONS - 1> m_factors;
553 explicit array_parser(
554 std::string_view input,
555 internal::encoding_group = internal::encoding_group::MONOBYTE);
564 std::pair<juncture, std::string> get_next() {
return (this->*m_impl)(); }
567 std::string_view m_input;
570 std::size_t m_pos = 0u;
578 using implementation = std::pair<juncture, std::string> (array_parser::*)();
581 static implementation
582 specialize_for_encoding(pqxx::internal::encoding_group enc);
585 implementation m_impl;
588 template<pqxx::
internal::encoding_group>
589 std::pair<juncture, std::string> parse_array_step();
591 template<pqxx::
internal::encoding_group>
593 template<pqxx::
internal::encoding_group>
595 template<pqxx::
internal::encoding_group>
597 template<pqxx::
internal::encoding_group>
600 template<pqxx::
internal::encoding_group>
601 std::string::size_type scan_glyph(std::string::size_type pos)
const;
602 template<pqxx::
internal::encoding_group>
603 std::string::size_type
604 scan_glyph(std::string::size_type pos, std::string::size_type end)
const;
An SQL array received from the database.
Definition array.hxx:56
constexpr auto back() const noexcept
Refer to the last element, if any.
Definition array.hxx:158
constexpr auto cend() const noexcept
Return end point of iteration.
Definition array.hxx:117
constexpr auto crbegin() const noexcept
Begin reverse iteration.
Definition array.hxx:119
ELEMENT const & operator[](INDEX... index) const
Access element (without bounds check).
Definition array.hxx:103
constexpr std::size_t size() const noexcept
Number of elements in the array.
Definition array.hxx:127
constexpr auto ssize() const noexcept
Number of elements in the array (as a signed number).
Definition array.hxx:145
constexpr std::size_t dimensions() noexcept
How many dimensions does this array have?
Definition array.hxx:75
constexpr auto cbegin() const noexcept
Begin iteration of individual elements.
Definition array.hxx:115
constexpr auto crend() const noexcept
Return end point of reverse iteration.
Definition array.hxx:121
std::array< std::size_t, DIMENSIONS > const & sizes() noexcept
Return the sizes of this array in each of its dimensions.
Definition array.hxx:82
array(std::string_view data, connection const &cx)
Parse an SQL array, read as text from a pqxx::result or stream.
Definition array.hxx:68
constexpr auto front() const noexcept
Refer to the first element, if any.
Definition array.hxx:153
std::string concat(TYPE... item)
Efficiently combine a bunch of items into one big string.
Definition concat.hxx:31
std::string_view parse_unquoted_string(char const input[], std::size_t end, std::size_t pos)
Parse an unquoted array entry or cfield of a composite-type field.
Definition array-composite.hxx:149
std::size_t scan_double_quoted_string(char const input[], std::size_t size, std::size_t pos)
Definition array-composite.hxx:20
std::size_t scan_unquoted_string(char const input[], std::size_t size, std::size_t pos)
Find the end of an unquoted string in an array or composite-type value.
Definition array-composite.hxx:131
std::string parse_double_quoted_string(char const input[], std::size_t end, std::size_t pos)
Un-quote and un-escape a double-quoted SQL string.
Definition array-composite.hxx:84
The home of all libpqxx classes, functions, templates, etc.
Definition array.cxx:27
constexpr char array_separator
Element separator between SQL array elements of this type.
Definition strconv.hxx:559
static TYPE null()
Return a null value.
static bool has_null
Does this type have a null value?
Definition strconv.hxx:93