4 #if !defined(PQXX_HEADER_PRE)
5 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
25 template<
typename TYPE>
30 template<
typename TYPE>
61 TYPE
const &value,
sl loc = sl::current()) :
65 throw argument_error{
"Got null value as an inclusive range bound.", loc};
68 [[nodiscard]] constexpr TYPE
const &
get() const & noexcept
75 noexcept(noexcept(value < m_value))
77 return not(value < m_value);
82 noexcept(noexcept(value < m_value))
84 return not(m_value < value);
102 TYPE
const &value,
sl loc = sl::current()) :
106 throw argument_error{
"Got null value as an exclusive range bound.", loc};
109 [[nodiscard]] constexpr TYPE
const &
get() const & noexcept
116 noexcept(noexcept(m_value < value))
118 return m_value < value;
123 noexcept(noexcept(value < m_value))
125 return value < m_value;
140 static constexpr
bool equal(TYPE
const &lhs, TYPE
const &rhs)
142 if constexpr (
requires { lhs == rhs; })
147 return not((lhs < rhs) or (rhs < lhs));
170 std::declval<inclusive_bound<TYPE>
const &>()}) and
172 std::declval<exclusive_bound<TYPE>
const &>()})) =
default;
189 noexcept(noexcept(*
this == rhs))
191 return not(*
this == rhs);
199 return not std::holds_alternative<no_bound>(m_bound);
205 return std::holds_alternative<inclusive_bound<TYPE>>(m_bound);
211 return std::holds_alternative<exclusive_bound<TYPE>>(m_bound);
218 [&
value](
auto const &bound) noexcept(noexcept(bound.extends_down_to(
219 value))) { return bound.extends_down_to(value); },
227 [&
value](
auto const &bound) noexcept(noexcept(
228 bound.extends_up_to(
value))) { return bound.extends_up_to(value); },
233 [[nodiscard]] constexpr TYPE
const *
value() const & noexcept
236 [](
auto const &bound) noexcept {
237 using bound_t = std::decay_t<decltype(bound)>;
238 if constexpr (std::is_same_v<bound_t, no_bound>)
239 return static_cast<TYPE
const *
>(
nullptr);
267 template<
typename TYPE>
class range final
281 m_lower{lower}, m_upper{upper}
288 "Range's lower bound ({}) is greater than its upper bound ({}).",
299 m_upper{exclusive_bound<TYPE>{TYPE{}}}
305 noexcept(this->lower_bound() == rhs.lower_bound()) and
306 noexcept(this->upper_bound() == rhs.upper_bound()) and
307 noexcept(this->empty()))
309 return (this->lower_bound() == rhs.lower_bound() and
310 this->upper_bound() == rhs.upper_bound()) or
311 (this->empty() and rhs.empty());
315 noexcept(noexcept(*
this == rhs))
317 return not(*
this == rhs);
334 [[nodiscard]] constexpr
bool empty() const noexcept(
335 noexcept(m_lower.is_exclusive()) and noexcept(m_lower.is_limited()) and
336 noexcept(*m_lower.value() < *m_upper.value()))
338 return (m_lower.is_exclusive() or m_upper.is_exclusive()) and
339 m_lower.is_limited() and m_upper.is_limited() and
340 not(*m_lower.value() < *m_upper.value());
344 [[nodiscard]] constexpr
bool contains(TYPE value)
const noexcept(
345 noexcept(m_lower.extends_down_to(value)) and
346 noexcept(m_upper.extends_up_to(value)))
348 return m_lower.extends_down_to(value) and m_upper.extends_up_to(value);
356 noexcept(noexcept((*
this & other) == other))
358 return (*
this & other) == other;
378 if (not this->lower_bound().is_limited())
381 lower = this->lower_bound();
382 else if (*this->lower_bound().value() < *other.
lower_bound().value())
384 else if (*other.
lower_bound().value() < *this->lower_bound().value())
385 lower = this->lower_bound();
386 else if (this->lower_bound().is_exclusive())
387 lower = this->lower_bound();
392 if (not this->upper_bound().is_limited())
395 upper = this->upper_bound();
396 else if (*other.
upper_bound().value() < *this->upper_bound().value())
398 else if (*this->upper_bound().value() < *other.
upper_bound().value())
399 upper = this->upper_bound();
400 else if (this->upper_bound().is_exclusive())
401 upper = this->upper_bound();
406 lower.is_limited() and upper.is_limited() and
407 (*upper.value() < *lower.value()))
410 return {lower, upper};
419 if (lower_bound().is_inclusive())
421 else if (lower_bound().is_exclusive())
424 if (upper_bound().is_inclusive())
426 else if (upper_bound().is_exclusive())
429 return {lower, upper};
441 [[nodiscard]]
static std::string_view
446 if (std::cmp_less_equal(std::size(buf), std::size(s_empty)))
452 if (std::cmp_less(std::size(buf), 4))
453 throw conversion_overrun{s_overrun.c_str(), c.loc};
454 std::span<char> tmp{buf};
457 (
static_cast<char>(value.
lower_bound().is_inclusive() ?
'[' :
'('));
458 tmp = tmp.subspan(1);
461 if (lower !=
nullptr)
465 tmp = tmp.subspan(1);
468 if (upper !=
nullptr)
470 if (std::cmp_less(std::size(tmp), 2))
471 throw conversion_overrun{s_overrun.c_str(), c.loc};
473 static_cast<char>(value.
upper_bound().is_inclusive() ?
']' :
')');
474 tmp = tmp.subspan(1);
477 static_cast<std::size_t
>(std::data(tmp) - std::data(buf))};
481 [[nodiscard]]
static inline range<TYPE>
484 if (std::size(
text) < 3)
494 (std::size(
text) != std::size(s_empty)) or
495 (
text[1] !=
'm' and
text[1] !=
'M') or
496 (
text[2] !=
'p' and
text[2] !=
'P') or
497 (
text[3] !=
't' and
text[3] !=
'T') or
498 (
text[4] !=
'y' and
text[4] !=
'Y'))
510 std::size_t index{0};
512 static constexpr std::size_t last{1};
520 std::optional<TYPE> lower, upper;
522 auto const field_parser{
523 pqxx::internal::specialize_parse_composite_field<std::optional<TYPE>>(
525 field_parser(index,
text, pos, lower, last, loc);
526 field_parser(index,
text, pos, upper, last, loc);
529 if (pos != std::size(
text))
531 char const closing{
text[pos - 1]};
532 if (closing !=
')' and closing !=
']')
538 bool const left_inc{
text[0] ==
'['};
546 bool const right_inc{closing ==
']'};
553 return {lower_bound, upper_bound};
556 [[nodiscard]]
static inline constexpr std::size_t
561 std::size_t
const lsz{
566 return std::size(s_empty) + 1;
568 return 1 + lsz + 1 + usz + 2;
572 static constexpr
zview s_empty{
"empty"_zv};
573 static constexpr
auto s_overrun{
"Not enough space in buffer for range."_zv};
576 static std::string err_bad_input(std::string_view text)
578 return std::format(
"Invalid range input: '{}'.", text);
584 template<
typename TYPE>
An exclusive boundary value to a pqxx::range.
Definition: range.hxx:94
constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as an upper bound, include value?
Definition: range.hxx:122
constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(m_value< value))
Would this bound, as a lower bound, include value?
Definition: range.hxx:115
constexpr exclusive_bound(TYPE const &value, sl loc=sl::current())
Definition: range.hxx:101
constexpr TYPE const & get() const &noexcept
Definition: range.hxx:109
An inclusive boundary value to a pqxx::range.
Definition: range.hxx:53
constexpr bool extends_down_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as a lower bound, include value?
Definition: range.hxx:74
constexpr TYPE const & get() const &noexcept
Definition: range.hxx:68
constexpr inclusive_bound(TYPE const &value, sl loc=sl::current())
Definition: range.hxx:60
constexpr bool extends_up_to(TYPE const &value) const noexcept(noexcept(value< m_value))
Would this bound, as an upper bound, include value?
Definition: range.hxx:81
A range boundary value.
Definition: range.hxx:135
constexpr bool extends_up_to(TYPE const &value) const
Would this bound, as an upper bound, include value?
Definition: range.hxx:224
constexpr range_bound(range_bound const &) noexcept(noexcept(inclusive_bound< TYPE >{ std::declval< inclusive_bound< TYPE > const & >()}) and noexcept(exclusive_bound< TYPE >{ std::declval< exclusive_bound< TYPE > const & >()}))=default
constexpr bool is_exclusive() const noexcept
Is this boundary an exclusive one?
Definition: range.hxx:209
constexpr range_bound(inclusive_bound< TYPE > const &bound) noexcept(noexcept(inclusive_bound< TYPE >{bound}))
Definition: range.hxx:157
constexpr bool is_limited() const noexcept
Is this a finite bound?
Definition: range.hxx:197
constexpr bool operator==(range_bound const &rhs) const
Definition: range.hxx:178
constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept(*this==rhs))
Definition: range.hxx:188
constexpr bool extends_down_to(TYPE const &value) const
Would this bound, as a lower bound, include value?
Definition: range.hxx:215
range_bound & operator=(range_bound &&)=default
constexpr range_bound(no_bound) noexcept
Definition: range.hxx:154
constexpr TYPE const * value() const &noexcept
Return bound value, or nullptr if it's not limited.
Definition: range.hxx:233
constexpr range_bound(exclusive_bound< TYPE > const &bound) noexcept(noexcept(exclusive_bound{bound}))
Definition: range.hxx:163
constexpr bool is_inclusive() const noexcept
Is this boundary an inclusive one?
Definition: range.hxx:203
constexpr range_bound(range_bound &&)=default
range_bound & operator=(range_bound const &)=default
A C++ equivalent to PostgreSQL's range types.
Definition: range.hxx:268
constexpr range(range_bound< TYPE > lower, range_bound< TYPE > upper, sl loc=sl::current())
Create a range.
Definition: range.hxx:279
range & operator=(range const &)=default
constexpr range operator&(range const &other) const
Intersection of two ranges.
Definition: range.hxx:375
constexpr bool operator==(range const &rhs) const noexcept(noexcept(this->lower_bound()==rhs.lower_bound()) and noexcept(this->upper_bound()==rhs.upper_bound()) and noexcept(this->empty()))
Definition: range.hxx:304
constexpr bool contains(TYPE value) const noexcept(noexcept(m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))
Does this range encompass value?
Definition: range.hxx:344
constexpr bool contains(range< TYPE > const &other) const noexcept(noexcept((*this &other)==other))
Does this range encompass all of other?
Definition: range.hxx:355
constexpr bool operator!=(range const &rhs) const noexcept(noexcept(*this==rhs))
Definition: range.hxx:314
range(range const &)=default
constexpr range_bound< TYPE > const & upper_bound() const &noexcept
Definition: range.hxx:367
range & operator=(range &&)=default
constexpr range_bound< TYPE > const & lower_bound() const &noexcept
Definition: range.hxx:362
constexpr bool empty() const noexcept(noexcept(m_lower.is_exclusive()) and noexcept(m_lower.is_limited()) and noexcept(*m_lower.value()< *m_upper.value()))
Is this range clearly empty?
Definition: range.hxx:334
constexpr range() noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))
Create an empty range.
Definition: range.hxx:297
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:55
Invalid argument passed to libpqxx, similar to std::invalid_argument.
Definition: except.hxx:599
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:612
Could not convert value to string: not enough buffer space.
Definition: except.hxx:638
Something is out of range, similar to std::out_of_range.
Definition: except.hxx:651
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:26
std::source_location sl
Convenience alias for std::source_location. It's just too long.
Definition: types.hxx:38
PQXX_LIBEXPORT std::string to_string(field_ref const &value, ctx)
Convert a field_ref to a string.
Definition: field.hxx:891
constexpr std::size_t size_buffer(TYPE const &...value) noexcept
Estimate how much buffer space is needed to represent values as a string.
Definition: strconv.hxx:399
constexpr bool is_null(TYPE const &value) noexcept
Is value a null?
Definition: strconv.hxx:764
requires(pqxx::internal::to_buf_7< TYPE > or pqxx::internal::to_buf_8< TYPE >) const eval bool supports_to_buf_8()
Is the libpqxx 8 version of to_buf() supported for TYPE?
Definition: strconv.hxx:417
std::size_t into_buf(std::span< char > buf, TYPE const &value, ctx c={})
Write an SQL representation of value into buf.
Definition: strconv.hxx:454
concept has_less
Concept: T supports copying, and less-than operator.
Definition: range.hxx:40
concept has_equal
Concept: T supports equality comparison.
Definition: range.hxx:45
conversion_context const & ctx
Convenience alias: const reference to a pqxx::conversion_context.
Definition: strconv.hxx:201
format
Format code: is data text or binary?
Definition: types.hxx:121
Contextual parameters for string conversions implementations.
Definition: strconv.hxx:163
An unlimited boundary value to a pqxx::range.
Definition: range.hxx:24
constexpr bool extends_down_to(TYPE const &) const noexcept
Definition: range.hxx:26
constexpr bool extends_up_to(TYPE const &) const noexcept
Definition: range.hxx:31
Nullness traits describing a type which does not have a null value.
Definition: strconv.hxx:93
Traits describing a type's "null value," if any.
Definition: strconv.hxx:70
static range< TYPE > from_string(std::string_view text, sl loc=sl::current())
Definition: range.hxx:482
static constexpr std::size_t size_buffer(range< TYPE > const &value) noexcept
Definition: range.hxx:557
static std::string_view to_buf(std::span< char > buf, range< TYPE > const &value, ctx c={})
Definition: range.hxx:442
Traits class for use in string conversions.
Definition: strconv.hxx:213