4 #if !defined(PQXX_HEADER_PRE)
5 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
11 #include "pqxx/internal/array-composite.hxx"
12 #include "pqxx/internal/concat.hxx"
25 template<
typename TYPE>
30 template<
typename TYPE>
53 throw argument_error{
"Got null value as an inclusive range bound."};
56 [[nodiscard]] constexpr TYPE
const &
get() const & noexcept
63 noexcept(noexcept(value < m_value))
65 return not(value < m_value);
70 noexcept(noexcept(value < m_value))
72 return not(m_value < value);
92 throw argument_error{
"Got null value as an exclusive range bound."};
95 [[nodiscard]] constexpr TYPE
const &
get() const & noexcept
102 noexcept(noexcept(m_value < value))
104 return m_value < value;
109 noexcept(noexcept(value < m_value))
111 return value < m_value;
142 std::declval<inclusive_bound<TYPE>
const &>()})
144 std::declval<exclusive_bound<TYPE>
const &>()})) =
default;
149 noexcept(noexcept(*this->
value() == *rhs.value()))
153 rhs.is_limited() and (this->
is_inclusive() == rhs.is_inclusive()) and
154 (*this->
value() == *rhs.value()));
156 return not rhs.is_limited();
160 noexcept(noexcept(*
this == rhs))
162 return not(*
this == rhs);
170 return not std::holds_alternative<no_bound>(m_bound);
176 return std::holds_alternative<inclusive_bound<TYPE>>(m_bound);
182 return std::holds_alternative<exclusive_bound<TYPE>>(m_bound);
189 [&
value](
auto const &bound) noexcept(noexcept(bound.extends_down_to(
190 value))) { return bound.extends_down_to(value); },
198 [&
value](
auto const &bound) noexcept(noexcept(
199 bound.extends_up_to(
value))) { return bound.extends_up_to(value); },
204 [[nodiscard]] constexpr TYPE
const *
value() const & noexcept
207 [](
auto const &bound) noexcept {
208 using bound_t = std::decay_t<decltype(bound)>;
209 if constexpr (std::is_same_v<bound_t, no_bound>)
210 return static_cast<TYPE
const *
>(
nullptr);
252 m_lower{lower}, m_upper{upper}
258 "Range's lower bound (", *lower.
value(),
259 ") is greater than its upper bound (", *upper.
value(),
").")};
268 m_upper{exclusive_bound<TYPE>{TYPE{}}}
272 noexcept(noexcept(this->lower_bound() == rhs.lower_bound()) and noexcept(
273 this->upper_bound() == rhs.upper_bound()) and noexcept(this->empty()))
275 return (this->lower_bound() == rhs.lower_bound() and
276 this->upper_bound() == rhs.upper_bound()) or
277 (this->empty() and rhs.empty());
281 noexcept(noexcept(*
this == rhs))
283 return not(*
this == rhs);
301 noexcept(noexcept(m_lower.is_exclusive()) and noexcept(
302 m_lower.is_limited()) and noexcept(*m_lower.value() < *m_upper.value()))
304 return (m_lower.is_exclusive() or m_upper.is_exclusive()) and
305 m_lower.is_limited() and m_upper.is_limited() and
306 not(*m_lower.value() < *m_upper.value());
310 constexpr
bool contains(TYPE value)
const noexcept(noexcept(
311 m_lower.extends_down_to(value)) and noexcept(m_upper.extends_up_to(value)))
313 return m_lower.extends_down_to(value) and m_upper.extends_up_to(value);
321 noexcept(noexcept((*
this & other) == other))
323 return (*
this & other) == other;
343 if (not this->lower_bound().is_limited())
346 lower = this->lower_bound();
347 else if (*this->lower_bound().value() < *other.
lower_bound().value())
349 else if (*other.
lower_bound().value() < *this->lower_bound().value())
350 lower = this->lower_bound();
351 else if (this->lower_bound().is_exclusive())
352 lower = this->lower_bound();
357 if (not this->upper_bound().is_limited())
360 upper = this->upper_bound();
361 else if (*other.
upper_bound().value() < *this->upper_bound().value())
363 else if (*this->upper_bound().value() < *other.
upper_bound().value())
364 upper = this->upper_bound();
365 else if (this->upper_bound().is_exclusive())
366 upper = this->upper_bound();
371 lower.is_limited() and upper.is_limited() and
372 (*upper.value() < *lower.value()))
375 return {lower, upper};
382 if (lower_bound().is_inclusive())
384 else if (lower_bound().is_exclusive())
387 if (upper_bound().is_inclusive())
389 else if (upper_bound().is_exclusive())
392 return {lower, upper};
403 [[nodiscard]]
static inline zview
414 if ((end - begin) <= internal::ssize(s_empty))
416 char *here = begin + s_empty.copy(begin, std::size(s_empty));
426 (
static_cast<char>(value.
lower_bound().is_inclusive() ?
'[' :
'('));
429 if (lower !=
nullptr)
434 if (upper !=
nullptr)
436 if ((end - here) < 2)
439 static_cast<char>(value.
upper_bound().is_inclusive() ?
']' :
')');
447 if (std::size(
text) < 3)
449 bool left_inc{
false};
452 case '[': left_inc =
true;
break;
459 (std::size(
text) != std::size(s_empty)) or
460 (
text[1] !=
'm' and
text[1] !=
'M') or
461 (
text[2] !=
'p' and
text[2] !=
'P') or
462 (
text[3] !=
't' and
text[3] !=
'T') or
463 (
text[4] !=
'y' and
text[4] !=
'Y'))
473 std::size_t index{0};
475 static constexpr std::size_t last{1};
479 std::optional<TYPE> lower, upper;
481 auto const field_parser{
482 pqxx::internal::specialize_parse_composite_field<std::optional<TYPE>>(
483 pqxx::internal::encoding_group::UTF8)};
484 field_parser(index,
text, pos, lower, last);
485 field_parser(index,
text, pos, upper, last);
488 if (pos != std::size(
text))
490 char const closing{
text[pos - 1]};
491 if (closing !=
')' and closing !=
']')
493 bool const right_inc{closing ==
']'};
511 return {lower_bound, upper_bound};
514 [[nodiscard]]
static inline constexpr std::size_t
517 TYPE
const *lower{value.lower_bound().value()},
518 *upper{value.upper_bound().value()};
519 std::size_t
const lsz{
524 return std::size(s_empty) + 1;
526 return 1 + lsz + 1 + usz + 2;
530 static constexpr
zview s_empty{
"empty"_zv};
531 static constexpr
auto s_overrun{
"Not enough space in buffer for range."_zv};
534 static std::string err_bad_input(std::string_view text)
536 return internal::concat(
"Invalid range input: '", text,
"'");
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:33
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:513
zview generic_to_buf(char *begin, char *end, TYPE const &value)
Implement string_traits<TYPE>::to_buf by calling into_buf.
Definition: strconv.hxx:585
Invalid argument passed to libpqxx, similar to std::invalid_argument.
Definition: except.hxx:266
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:283
Could not convert value to string: not enough buffer space.
Definition: except.hxx:313
Something is out of range, similar to std::out_of_range.
Definition: except.hxx:326
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
An inclusive boundary value to a pqxx::range.
Definition: range.hxx:43
constexpr inclusive_bound(TYPE const &value)
Definition: range.hxx:50
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:62
constexpr TYPE const & get() const &noexcept
Definition: range.hxx:56
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:69
An exclusive boundary value to a pqxx::range.
Definition: range.hxx:82
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:108
constexpr exclusive_bound(TYPE const &value)
Definition: range.hxx:89
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:101
constexpr TYPE const & get() const &noexcept
Definition: range.hxx:95
A range boundary value.
Definition: range.hxx:121
constexpr bool extends_up_to(TYPE const &value) const
Would this bound, as an upper bound, include value?
Definition: range.hxx:195
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:180
constexpr range_bound(inclusive_bound< TYPE > const &bound) noexcept(noexcept(inclusive_bound< TYPE >{bound}))
Definition: range.hxx:130
constexpr bool is_limited() const noexcept
Is this a finite bound?
Definition: range.hxx:168
constexpr bool operator!=(range_bound const &rhs) const noexcept(noexcept(*this==rhs))
Definition: range.hxx:159
constexpr bool extends_down_to(TYPE const &value) const
Would this bound, as a lower bound, include value?
Definition: range.hxx:186
range_bound & operator=(range_bound &&)=default
constexpr range_bound(no_bound) noexcept
Definition: range.hxx:128
constexpr TYPE const * value() const &noexcept
Return bound value, or nullptr if it's not limited.
Definition: range.hxx:204
constexpr bool operator==(range_bound const &rhs) const noexcept(noexcept(*this->value()== *rhs.value()))
Definition: range.hxx:148
constexpr range_bound(exclusive_bound< TYPE > const &bound) noexcept(noexcept(exclusive_bound{bound}))
Definition: range.hxx:135
constexpr bool is_inclusive() const noexcept
Is this boundary an inclusive one?
Definition: range.hxx:174
constexpr range_bound(range_bound &&)=default
range_bound & operator=(range_bound const &)=default
A C++ equivalent to PostgreSQL's range types.
Definition: range.hxx:240
range & operator=(range const &)=default
constexpr range operator&(range const &other) const
Intersection of two ranges.
Definition: range.hxx:340
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:271
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:310
constexpr bool contains(range< TYPE > const &other) const noexcept(noexcept((*this &other)==other))
Does this range encompass all of other?
Definition: range.hxx:320
constexpr bool operator!=(range const &rhs) const noexcept(noexcept(*this==rhs))
Definition: range.hxx:280
range(range const &)=default
constexpr range_bound< TYPE > const & upper_bound() const &noexcept
Definition: range.hxx:332
constexpr range(range_bound< TYPE > lower, range_bound< TYPE > upper)
Create a range.
Definition: range.hxx:251
range & operator=(range &&)=default
constexpr range_bound< TYPE > const & lower_bound() const &noexcept
Definition: range.hxx:327
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:300
constexpr range() noexcept(noexcept(exclusive_bound< TYPE >{TYPE{}}))
Create an empty range.
Definition: range.hxx:266
static range< TYPE > from_string(std::string_view text)
Definition: range.hxx:445
static constexpr std::size_t size_buffer(range< TYPE > const &value) noexcept
Definition: range.hxx:515
static char * into_buf(char *begin, char *end, range< TYPE > const &value)
Definition: range.hxx:410
static zview to_buf(char *begin, char *end, range< TYPE > const &value)
Definition: range.hxx:404
Traits describing a type's "null value," if any.
Definition: strconv.hxx:91
Nullness traits describing a type which does not have a null value.
Definition: strconv.hxx:113
Traits class for use in string conversions.
Definition: strconv.hxx:153
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38