18#include <rapidfuzz/details/type_traits.hpp>
23static inline void assume(
bool b)
27#elif defined(__GNUC__) || defined(__GNUG__)
28 if (!b) __builtin_unreachable();
29#elif defined(_MSC_VER)
34namespace to_begin_detail {
37template <
typename CharT>
38CharT* to_begin(CharT* s)
44auto to_begin(T& x) ->
decltype(begin(x))
51using to_begin_detail::to_begin;
53namespace to_end_detail {
56template <
typename CharT>
57CharT* to_end(CharT* s)
67auto to_end(T& x) ->
decltype(end(x))
73using to_end_detail::to_end;
75template <
typename Iter>
84 using value_type =
typename std::iterator_traits<Iter>::value_type;
85 using iterator = Iter;
86 using reverse_iterator = std::reverse_iterator<iterator>;
88 Range(Iter first, Iter last) : _first(first), _last(last)
90 assert(std::distance(_first, _last) >= 0);
91 _size =
static_cast<size_t>(std::distance(_first, _last));
94 Range(Iter first, Iter last,
size_t size) : _first(first), _last(last), _size(size)
98 Range(T& x) : Range(to_begin(x), to_end(x))
101 iterator begin() const noexcept
105 iterator end() const noexcept
110 reverse_iterator rbegin() const noexcept
112 return reverse_iterator(end());
114 reverse_iterator rend() const noexcept
116 return reverse_iterator(begin());
128 explicit operator bool()
const
133 template <
typename... Dummy,
typename IterCopy = Iter,
134 typename = rapidfuzz::rf_enable_if_t<
135 std::is_base_of<std::random_access_iterator_tag,
136 typename std::iterator_traits<IterCopy>::iterator_category>::value>>
137 auto operator[](
size_t n)
const ->
decltype(*_first)
139 return _first[
static_cast<ptrdiff_t
>(n)];
142 void remove_prefix(
size_t n)
144 std::advance(_first,
static_cast<ptrdiff_t
>(n));
148 void remove_suffix(
size_t n)
150 std::advance(_last, -
static_cast<ptrdiff_t
>(n));
154 Range subseq(
size_t pos = 0,
size_t count = std::numeric_limits<size_t>::max())
156 if (pos > size())
throw std::out_of_range(
"Index out of range in Range::substr");
159 res.remove_prefix(pos);
160 if (count < res.size()) res.remove_suffix(res.size() - count);
165 const value_type& front()
const
170 const value_type& back()
const
175 Range<reverse_iterator> reversed()
const
177 return {rbegin(), rend(), _size};
180 friend std::ostream& operator<<(std::ostream& os,
const Range& seq)
184 os << static_cast<uint64_t>(x) <<
", ";
190template <
typename Iter>
191auto make_range(Iter first, Iter last) -> Range<Iter>
193 return Range<Iter>(first, last);
197auto make_range(T& x) -> Range<
decltype(to_begin(x))>
199 return {to_begin(x), to_end(x)};
202template <
typename InputIt1,
typename InputIt2>
203inline bool operator==(
const Range<InputIt1>& a,
const Range<InputIt2>& b)
205 if (a.size() != b.size())
return false;
207 return std::equal(a.begin(), a.end(), b.begin());
210template <
typename InputIt1,
typename InputIt2>
211inline bool operator!=(
const Range<InputIt1>& a,
const Range<InputIt2>& b)
216template <
typename InputIt1,
typename InputIt2>
217inline bool operator<(
const Range<InputIt1>& a,
const Range<InputIt2>& b)
219 return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()));
222template <
typename InputIt1,
typename InputIt2>
223inline bool operator>(
const Range<InputIt1>& a,
const Range<InputIt2>& b)
228template <
typename InputIt1,
typename InputIt2>
229inline bool operator<=(
const Range<InputIt1>& a,
const Range<InputIt2>& b)
234template <
typename InputIt1,
typename InputIt2>
235inline bool operator>=(
const Range<InputIt1>& a,
const Range<InputIt2>& b)
240template <
typename InputIt>
241using RangeVec = std::vector<Range<InputIt>>;