2015-04-15 23:18:00 +00:00
|
|
|
/* Ranges for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OCTA_RANGE_H
|
|
|
|
#define OCTA_RANGE_H
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include "octa/types.h"
|
2015-04-17 23:11:16 +00:00
|
|
|
#include "octa/utility.h"
|
2015-04-28 17:48:58 +00:00
|
|
|
#include "octa/type_traits.h"
|
2015-04-15 23:18:00 +00:00
|
|
|
|
|
|
|
namespace octa {
|
2015-04-27 18:56:06 +00:00
|
|
|
struct InputRangeTag {};
|
|
|
|
struct OutputRangeTag {};
|
2015-05-23 19:33:08 +00:00
|
|
|
struct ForwardRangeTag: InputRangeTag {};
|
|
|
|
struct BidirectionalRangeTag: ForwardRangeTag {};
|
|
|
|
struct RandomAccessRangeTag: BidirectionalRangeTag {};
|
2015-05-23 19:00:03 +00:00
|
|
|
struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {};
|
2015-04-16 20:50:53 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> struct RangeHalf;
|
2015-05-29 22:48:05 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
#define __OCTA_RANGE_TRAIT(_Name, _TypeName) \
|
|
|
|
template<typename _T> \
|
|
|
|
struct __OctaRange##_Name { \
|
|
|
|
typedef typename _T::_TypeName Type; \
|
2015-05-29 22:48:05 +00:00
|
|
|
}; \
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> \
|
|
|
|
struct __OctaRange##_Name<RangeHalf<_T>> { \
|
|
|
|
typedef typename _T::_TypeName Type; \
|
2015-05-29 22:48:05 +00:00
|
|
|
}; \
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> \
|
|
|
|
using Range##_Name = typename __OctaRange##_Name<_T>::Type;
|
2015-05-29 22:48:05 +00:00
|
|
|
|
|
|
|
__OCTA_RANGE_TRAIT(Category, Category)
|
2015-06-03 18:52:20 +00:00
|
|
|
__OCTA_RANGE_TRAIT(Size, Size)
|
|
|
|
__OCTA_RANGE_TRAIT(Value, Value)
|
|
|
|
__OCTA_RANGE_TRAIT(Reference, Reference)
|
|
|
|
__OCTA_RANGE_TRAIT(Difference, Difference)
|
2015-05-29 22:48:05 +00:00
|
|
|
|
|
|
|
#undef __OCTA_RANGE_TRAIT
|
2015-04-15 23:18:00 +00:00
|
|
|
|
2015-05-23 19:33:08 +00:00
|
|
|
// is input range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, bool = octa::IsConvertible<
|
|
|
|
RangeCategory<_T>, InputRangeTag
|
2015-05-23 19:33:08 +00:00
|
|
|
>::value> struct IsInputRange: False {};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct IsInputRange<_T, true>: True {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
|
|
|
// is forward range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, bool = octa::IsConvertible<
|
|
|
|
RangeCategory<_T>, ForwardRangeTag
|
2015-05-23 19:33:08 +00:00
|
|
|
>::value> struct IsForwardRange: False {};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct IsForwardRange<_T, true>: True {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
|
|
|
// is bidirectional range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, bool = octa::IsConvertible<
|
|
|
|
RangeCategory<_T>, BidirectionalRangeTag
|
2015-05-23 19:33:08 +00:00
|
|
|
>::value> struct IsBidirectionalRange: False {};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct IsBidirectionalRange<_T, true>: True {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
|
|
|
// is random access range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, bool = octa::IsConvertible<
|
|
|
|
RangeCategory<_T>, RandomAccessRangeTag
|
2015-05-23 19:33:08 +00:00
|
|
|
>::value> struct IsRandomAccessRange: False {};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct IsRandomAccessRange<_T, true>: True {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
|
|
|
// is finite random access range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, bool = octa::IsConvertible<
|
|
|
|
RangeCategory<_T>, FiniteRandomAccessRangeTag
|
2015-05-23 19:33:08 +00:00
|
|
|
>::value> struct IsFiniteRandomAccessRange: False {};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct IsFiniteRandomAccessRange<_T, true>: True {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
|
|
|
// is infinite random access range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-05-23 19:33:08 +00:00
|
|
|
struct IsInfiniteRandomAccessRange: IntegralConstant<bool,
|
2015-06-01 23:57:34 +00:00
|
|
|
(IsRandomAccessRange<_T>::value && !IsFiniteRandomAccessRange<_T>::value)
|
2015-05-23 19:33:08 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
// is output range
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _P>
|
2015-05-23 21:24:12 +00:00
|
|
|
struct __OctaOutputRangeTest {
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _U, void (_U::*)(_P)> struct __Test {};
|
|
|
|
template<typename _U> static char __test(__Test<_U, &_U::put> *);
|
|
|
|
template<typename _U> static int __test(...);
|
|
|
|
static constexpr bool value = (sizeof(__test<_T>(0)) == sizeof(char));
|
2015-05-23 21:24:12 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, bool = (octa::IsConvertible<
|
|
|
|
RangeCategory<_T>, OutputRangeTag
|
|
|
|
>::value || (IsInputRange<_T>::value &&
|
|
|
|
(__OctaOutputRangeTest<_T, const RangeValue<_T> &>::value ||
|
|
|
|
__OctaOutputRangeTest<_T, RangeValue<_T> &&>::value)
|
2015-05-23 21:27:57 +00:00
|
|
|
))> struct IsOutputRange: False {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct IsOutputRange<_T, true>: True {};
|
2015-05-23 19:33:08 +00:00
|
|
|
|
|
|
|
// range iterator
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-04-24 17:16:35 +00:00
|
|
|
struct __OctaRangeIterator {
|
2015-06-01 23:57:34 +00:00
|
|
|
__OctaRangeIterator(): __range() {}
|
|
|
|
explicit __OctaRangeIterator(const _T &__range): __range(__range) {}
|
2015-04-24 17:16:35 +00:00
|
|
|
__OctaRangeIterator &operator++() {
|
2015-06-01 23:57:34 +00:00
|
|
|
__range.pop_front();
|
2015-04-24 17:16:35 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> operator*() const {
|
|
|
|
return __range.front();
|
2015-04-24 17:16:35 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
bool operator!=(__OctaRangeIterator) const { return !__range.empty(); }
|
2015-04-24 17:16:35 +00:00
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
2015-04-24 17:16:35 +00:00
|
|
|
};
|
2015-04-15 23:18:00 +00:00
|
|
|
|
2015-05-29 22:32:25 +00:00
|
|
|
// range half
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-05-29 22:32:25 +00:00
|
|
|
struct RangeHalf {
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
2015-05-29 22:32:25 +00:00
|
|
|
public:
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef _T Range;
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf(): __range() {}
|
|
|
|
RangeHalf(const _T &__range): __range(__range) {}
|
|
|
|
RangeHalf(const RangeHalf &__half): __range(__half.__range) {}
|
|
|
|
RangeHalf(RangeHalf &&__half): __range(octa::move(__half.__range)) {}
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf &operator=(const RangeHalf &__half) {
|
|
|
|
__range = __half.__range;
|
2015-05-29 22:32:25 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf &operator=(RangeHalf &&__half) {
|
|
|
|
__range = octa::move(__half.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T range() const { return __range; }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool next() { return __range.pop_front(); }
|
|
|
|
bool prev() { return __range.push_front(); }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeSize<_T> next_n(RangeSize<_T> __n) {
|
|
|
|
return __range.pop_front_n(__n);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeSize<_T> prev_n(RangeSize<_T> __n) {
|
|
|
|
return __range.push_front_n(__n);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> get() const {
|
|
|
|
return __range.front();
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance(const RangeHalf &__half) const {
|
|
|
|
return __range.distance_front(__half.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals(const RangeHalf &__half) const {
|
|
|
|
return __range.equals_front(__half.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool operator==(const RangeHalf &__half) const {
|
|
|
|
return equals(__half);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
bool operator!=(const RangeHalf &__half) const {
|
|
|
|
return !equals(__half);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* iterator like interface */
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> operator*() const {
|
2015-05-29 22:32:25 +00:00
|
|
|
return get();
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> operator[](RangeSize<_T> __idx) const {
|
|
|
|
return __range[__idx];
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RangeHalf &operator++() {
|
|
|
|
next();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
RangeHalf operator++(int) {
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf __tmp(*this);
|
2015-05-29 22:32:25 +00:00
|
|
|
next();
|
2015-06-01 23:57:34 +00:00
|
|
|
return octa::move(__tmp);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RangeHalf &operator--() {
|
|
|
|
prev();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
RangeHalf operator--(int) {
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf __tmp(*this);
|
2015-05-29 22:32:25 +00:00
|
|
|
prev();
|
2015-06-01 23:57:34 +00:00
|
|
|
return octa::move(__tmp);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf operator+(RangeDifference<_T> __n) {
|
|
|
|
RangeHalf __tmp(*this);
|
|
|
|
if (__n < 0) __tmp.prev_n(-__n);
|
|
|
|
else __tmp.next_n(__n);
|
|
|
|
return octa::move(__tmp);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf operator-(RangeDifference<_T> __n) {
|
|
|
|
RangeHalf __tmp(*this);
|
|
|
|
if (__n < 0) __tmp.next_n(-__n);
|
|
|
|
else __tmp.prev_n(__n);
|
|
|
|
return octa::move(__tmp);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf &operator+=(RangeDifference<_T> __n) {
|
|
|
|
if (__n < 0) prev_n(-__n);
|
|
|
|
else next_n(__n);
|
2015-05-29 22:32:25 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf &operator-=(RangeDifference<_T> __n) {
|
|
|
|
if (__n < 0) next_n(-__n);
|
|
|
|
else prev_n(__n);
|
2015-05-29 22:32:25 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R>
|
|
|
|
RangeDifference<_R> operator-(const _R &__lhs, const _R &__rhs) {
|
|
|
|
return __rhs.distance(__lhs);
|
2015-05-30 00:46:50 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R>
|
|
|
|
RangeSize<_R> __octa_pop_front_n(_R &__range, RangeSize<_R> __n) {
|
|
|
|
for (RangeSize<_R> __i = 0; __i < __n; ++__i)
|
|
|
|
if (!__range.pop_front()) return __i;
|
|
|
|
return __n;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R>
|
|
|
|
RangeSize<_R> __octa_pop_back_n(_R &__range, RangeSize<_R> __n) {
|
|
|
|
for (RangeSize<_R> __i = 0; __i < __n; ++__i)
|
|
|
|
if (!__range.pop_back()) return __i;
|
|
|
|
return __n;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R>
|
|
|
|
RangeSize<_R> __octa_push_front_n(_R &__range, RangeSize<_R> __n) {
|
|
|
|
for (RangeSize<_R> __i = 0; __i < __n; ++__i)
|
|
|
|
if (!__range.push_front()) return __i;
|
|
|
|
return __n;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _R>
|
|
|
|
RangeSize<_R> __octa_push_back_n(_R &__range, RangeSize<_R> __n) {
|
|
|
|
for (RangeSize<_R> __i = 0; __i < __n; ++__i)
|
|
|
|
if (!__range.push_back()) return __i;
|
|
|
|
return __n;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _B, typename _C, typename _V, typename _R = _V &,
|
|
|
|
typename _S = size_t, typename _D = ptrdiff_t
|
2015-04-27 18:56:06 +00:00
|
|
|
> struct InputRange {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _C Category;
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef _S Size;
|
|
|
|
typedef _D Difference;
|
|
|
|
typedef _V Value;
|
|
|
|
typedef _R Reference;
|
2015-04-16 01:07:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
__OctaRangeIterator<_B> begin() const {
|
|
|
|
return __OctaRangeIterator<_B>((const _B &)*this);
|
2015-04-17 19:14:43 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
__OctaRangeIterator<_B> end() const {
|
|
|
|
return __OctaRangeIterator<_B>();
|
2015-04-17 19:14:43 +00:00
|
|
|
}
|
2015-05-23 16:36:26 +00:00
|
|
|
|
2015-06-03 18:52:20 +00:00
|
|
|
Size pop_front_n(Size __n) {
|
2015-06-01 23:57:34 +00:00
|
|
|
return __octa_pop_front_n<_B>(*((_B *)this), __n);
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-03 18:52:20 +00:00
|
|
|
Size pop_back_n(Size __n) {
|
2015-06-01 23:57:34 +00:00
|
|
|
return __octa_pop_back_n<_B>(*((_B *)this), __n);
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
2015-05-28 01:38:52 +00:00
|
|
|
|
2015-06-03 18:52:20 +00:00
|
|
|
Size push_front_n(Size __n) {
|
2015-06-01 23:57:34 +00:00
|
|
|
return __octa_push_front_n<_B>(*((_B *)this), __n);
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-03 18:52:20 +00:00
|
|
|
Size push_back_n(Size __n) {
|
2015-06-01 23:57:34 +00:00
|
|
|
return __octa_push_back_n<_B>(*((_B *)this), __n);
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_B each() const {
|
|
|
|
return _B(*((_B *)this));
|
2015-05-28 01:38:52 +00:00
|
|
|
}
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeHalf<_B> half() const {
|
|
|
|
return RangeHalf<_B>(*((_B *)this));
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-04-17 19:14:43 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _V, typename _R = _V &, typename _S = size_t,
|
|
|
|
typename _D = ptrdiff_t
|
2015-05-29 22:32:25 +00:00
|
|
|
> struct OutputRange {
|
2015-05-03 22:44:48 +00:00
|
|
|
typedef OutputRangeTag Category;
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef _S Size;
|
|
|
|
typedef _D Difference;
|
|
|
|
typedef _V Value;
|
|
|
|
typedef _R Reference;
|
2015-04-17 20:33:01 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct ReverseRange: InputRange<ReverseRange<_T>,
|
|
|
|
RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>,
|
|
|
|
RangeDifference<_T>
|
2015-04-17 19:14:43 +00:00
|
|
|
> {
|
2015-04-27 18:53:48 +00:00
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef RangeReference<_T> _r_ref;
|
|
|
|
typedef RangeSize<_T> _r_size;
|
2015-04-27 18:53:48 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-04-27 18:53:48 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange(): __range() {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange(const _T &__range): __range(__range) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange(const ReverseRange &__it): __range(__it.__range) {}
|
2015-04-16 01:07:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange(ReverseRange &&__it): __range(octa::move(__it.__range)) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange &operator=(const ReverseRange &__v) {
|
|
|
|
__range = __v.__range;
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange &operator=(ReverseRange &&__v) {
|
|
|
|
__range = octa::move(__v.__range);
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange &operator=(const _T &__v) {
|
|
|
|
__range = __v;
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange &operator=(_T &&__v) {
|
|
|
|
__range = octa::move(__v);
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __range.empty(); }
|
|
|
|
_r_size size() const { return __range.size(); }
|
2015-04-27 18:53:48 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const ReverseRange &__r) const {
|
|
|
|
return __range.equals_back(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_back(const ReverseRange &__r) const {
|
|
|
|
return __range.equals_front(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_front(const ReverseRange &__r) const {
|
|
|
|
return -__range.distance_back(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_back(const ReverseRange &__r) const {
|
|
|
|
return -__range.distance_front(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool pop_front() { return __range.pop_back(); }
|
|
|
|
bool pop_back() { return __range.pop_front(); }
|
2015-04-16 01:07:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool push_front() { return __range.push_back(); }
|
|
|
|
bool push_back() { return __range.push_front(); }
|
2015-04-16 01:07:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_size pop_front_n(_r_size __n) { return __range.pop_front_n(__n); }
|
|
|
|
_r_size pop_back_n(_r_size __n) { return __range.pop_back_n(__n); }
|
2015-05-29 18:52:20 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_size push_front_n(_r_size __n) { return __range.push_front_n(__n); }
|
|
|
|
_r_size push_back_n(_r_size __n) { return __range.push_back_n(__n); }
|
2015-05-23 16:36:26 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_ref front() const { return __range.back(); }
|
|
|
|
_r_ref back() const { return __range.front(); }
|
2015-04-16 01:07:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_ref operator[](_r_size __i) const { return __range[size() - __i - 1]; }
|
2015-04-16 01:07:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ReverseRange<_T> slice(_r_size __start, _r_size __end) const {
|
|
|
|
_r_size __len = __range.size();
|
|
|
|
return ReverseRange<_T>(__range.slice(__len - __end, __len - __start));
|
2015-04-18 21:05:24 +00:00
|
|
|
}
|
2015-04-16 01:07:32 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
ReverseRange<_T> make_reverse_range(const _T &__it) {
|
|
|
|
return ReverseRange<_T>(__it);
|
2015-04-16 01:07:32 +00:00
|
|
|
}
|
2015-04-16 22:06:39 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct MoveRange: InputRange<MoveRange<_T>,
|
|
|
|
RangeCategory<_T>, RangeValue<_T>, RangeValue<_T> &&, RangeSize<_T>,
|
|
|
|
RangeDifference<_T>
|
2015-04-17 19:14:43 +00:00
|
|
|
> {
|
2015-04-27 18:53:48 +00:00
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef RangeValue<_T> _r_val;
|
|
|
|
typedef RangeValue<_T> &&_r_ref;
|
|
|
|
typedef RangeSize<_T> _r_size;
|
2015-04-27 18:53:48 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-04-27 18:53:48 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange(): __range() {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange(const _T &__range): __range(__range) {}
|
2015-04-16 22:06:39 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange(const MoveRange &__it): __range(__it.__range) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange(MoveRange &&__it): __range(octa::move(__it.__range)) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange &operator=(const MoveRange &__v) {
|
|
|
|
__range = __v.__range;
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange &operator=(MoveRange &&__v) {
|
|
|
|
__range = octa::move(__v.__range);
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange &operator=(const _T &__v) {
|
|
|
|
__range = __v;
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange &operator=(_T &&__v) {
|
|
|
|
__range = octa::move(__v);
|
2015-04-18 19:31:07 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __range.empty(); }
|
|
|
|
_r_size size() const { return __range.size(); }
|
2015-04-16 22:06:39 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const MoveRange &__r) const {
|
|
|
|
return __range.equals_front(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_back(const MoveRange &__r) const {
|
|
|
|
return __range.equals_back(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_front(const MoveRange &__r) const {
|
|
|
|
return __range.distance_front(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_back(const MoveRange &__r) const {
|
|
|
|
return __range.distance_back(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool pop_front() { return __range.pop_front(); }
|
|
|
|
bool pop_back() { return __range.pop_back(); }
|
2015-04-16 22:06:39 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool push_front() { return __range.push_front(); }
|
|
|
|
bool push_back() { return __range.push_back(); }
|
2015-05-29 18:52:20 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_size pop_front_n(_r_size __n) { return __range.pop_front_n(__n); }
|
|
|
|
_r_size pop_back_n(_r_size __n) { return __range.pop_back_n(__n); }
|
2015-05-29 18:52:20 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_size push_front_n(_r_size __n) { return __range.push_front_n(__n); }
|
|
|
|
_r_size push_back_n(_r_size __n) { return __range.push_back_n(__n); }
|
2015-05-23 16:36:26 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_ref front() const { return octa::move(__range.front()); }
|
|
|
|
_r_ref back() const { return octa::move(__range.back()); }
|
2015-04-16 22:06:39 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_ref operator[](_r_size __i) const { return octa::move(__range[__i]); }
|
2015-04-16 22:06:39 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
MoveRange<_T> slice(_r_size __start, _r_size __end) const {
|
|
|
|
return MoveRange<_T>(__range.slice(__start, __end));
|
2015-04-18 21:05:24 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
void put(const _r_val &__v) { __range.put(__v); }
|
|
|
|
void put(_r_val &&__v) { __range.put(octa::move(__v)); }
|
2015-04-16 22:06:39 +00:00
|
|
|
};
|
2015-04-16 22:26:10 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
MoveRange<_T> make_move_range(const _T &__it) {
|
|
|
|
return MoveRange<_T>(__it);
|
2015-04-16 22:26:10 +00:00
|
|
|
}
|
2015-04-16 23:55:50 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct NumberRange: InputRange<NumberRange<_T>, ForwardRangeTag, _T, _T> {
|
|
|
|
NumberRange(): __a(0), __b(0), __step(0) {}
|
|
|
|
NumberRange(const NumberRange &__it): __a(__it.__a), __b(__it.__b),
|
|
|
|
__step(__it.__step) {}
|
|
|
|
NumberRange(_T __a, _T __b, _T __step = _T(1)): __a(__a), __b(__b),
|
|
|
|
__step(__step) {}
|
|
|
|
NumberRange(_T __v): __a(0), __b(__v), __step(1) {}
|
2015-04-16 23:55:50 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __a * __step >= __b * __step; }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const NumberRange &__range) const {
|
|
|
|
return __a == __range.__a;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool pop_front() { __a += __step; return true; }
|
|
|
|
bool push_front() { __a -= __step; return true; }
|
|
|
|
_T front() const { return __a; }
|
2015-04-16 23:55:50 +00:00
|
|
|
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __a, __b, __step;
|
2015-04-16 23:55:50 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
NumberRange<_T> range(_T __a, _T __b, _T __step = _T(1)) {
|
|
|
|
return NumberRange<_T>(__a, __b, __step);
|
2015-04-16 23:55:50 +00:00
|
|
|
}
|
2015-04-17 19:33:36 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
NumberRange<_T> range(_T __v) {
|
|
|
|
return NumberRange<_T>(__v);
|
2015-04-17 19:33:36 +00:00
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct PointerRange: InputRange<PointerRange<_T>, FiniteRandomAccessRangeTag, _T> {
|
|
|
|
PointerRange(): __beg(nullptr), __end(nullptr) {}
|
|
|
|
PointerRange(const PointerRange &__v): __beg(__v.__beg),
|
|
|
|
__end(__v.__end) {}
|
|
|
|
PointerRange(_T *__beg, _T *__end): __beg(__beg), __end(__end) {}
|
|
|
|
PointerRange(_T *__beg, size_t __n): __beg(__beg), __end(__beg + __n) {}
|
|
|
|
|
|
|
|
PointerRange &operator=(const PointerRange &__v) {
|
|
|
|
__beg = __v.__beg;
|
|
|
|
__end = __v.__end;
|
2015-05-08 01:03:48 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-04-18 23:02:38 +00:00
|
|
|
/* satisfy InputRange / ForwardRange */
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __beg == __end; }
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 00:13:37 +00:00
|
|
|
bool pop_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
if (__beg == __end) return false;
|
|
|
|
++__beg;
|
2015-05-29 19:02:40 +00:00
|
|
|
return true;
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
2015-06-01 00:13:37 +00:00
|
|
|
bool push_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
--__beg; return true;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t pop_front_n(size_t __n) {
|
|
|
|
size_t __olen = __end - __beg;
|
|
|
|
__beg += __n;
|
|
|
|
if (__beg > __end) {
|
|
|
|
__beg = __end;
|
|
|
|
return __olen;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
return __n;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t push_front_n(size_t __n) {
|
|
|
|
__beg -= __n; return true;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T &front() const { return *__beg; }
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const PointerRange &__range) const {
|
|
|
|
return __beg == __range.__beg;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ptrdiff_t distance_front(const PointerRange &__range) const {
|
|
|
|
return __range.__beg - __beg;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-04-18 23:02:38 +00:00
|
|
|
/* satisfy BidirectionalRange */
|
2015-06-01 00:13:37 +00:00
|
|
|
bool pop_back() {
|
2015-06-01 23:57:34 +00:00
|
|
|
if (__end == __beg) return false;
|
|
|
|
--__end;
|
2015-05-29 19:02:40 +00:00
|
|
|
return true;
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
2015-06-01 00:13:37 +00:00
|
|
|
bool push_back() {
|
2015-06-01 23:57:34 +00:00
|
|
|
++__end; return true;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t pop_back_n(size_t __n) {
|
|
|
|
size_t __olen = __end - __beg;
|
|
|
|
__end -= __n;
|
|
|
|
if (__end < __beg) {
|
|
|
|
__end = __beg;
|
|
|
|
return __olen;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
return __n;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t push_back_n(size_t __n) {
|
|
|
|
__end += __n; return true;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T &back() const { return *(__end - 1); }
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_back(const PointerRange &__range) const {
|
|
|
|
return __end == __range.__end;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
ptrdiff_t distance_back(const PointerRange &__range) const {
|
|
|
|
return __range.__end - __end;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-05-23 19:00:03 +00:00
|
|
|
/* satisfy FiniteRandomAccessRange */
|
2015-06-01 23:57:34 +00:00
|
|
|
size_t size() const { return __end - __beg; }
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
PointerRange slice(size_t __start, size_t __end) const {
|
|
|
|
return PointerRange(__beg + __start, __beg + __end);
|
2015-04-18 23:02:38 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T &operator[](size_t __i) const { return __beg[__i]; }
|
2015-04-18 23:02:38 +00:00
|
|
|
|
2015-04-21 16:56:36 +00:00
|
|
|
/* satisfy OutputRange */
|
2015-06-01 23:57:34 +00:00
|
|
|
void put(const _T &__v) {
|
|
|
|
*(__beg++) = __v;
|
2015-04-28 17:48:58 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
void put(_T &&__v) {
|
|
|
|
*(__beg++) = octa::move(__v);
|
2015-05-08 01:03:48 +00:00
|
|
|
}
|
2015-04-21 16:56:36 +00:00
|
|
|
|
2015-04-18 23:02:38 +00:00
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T *__beg, *__end;
|
2015-04-18 23:02:38 +00:00
|
|
|
};
|
2015-04-21 16:58:36 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _S>
|
2015-04-21 16:58:36 +00:00
|
|
|
struct EnumeratedValue {
|
2015-06-01 23:57:34 +00:00
|
|
|
_S index;
|
|
|
|
_T value;
|
2015-04-21 16:58:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct EnumeratedRange: InputRange<EnumeratedRange<_T>,
|
|
|
|
CommonType<RangeCategory<_T>, ForwardRangeTag>, RangeValue<_T>,
|
|
|
|
EnumeratedValue<RangeReference<_T>, RangeSize<_T>>,
|
|
|
|
RangeSize<_T>
|
2015-04-21 16:58:36 +00:00
|
|
|
> {
|
2015-04-27 18:53:48 +00:00
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef RangeReference<_T> _r_ref;
|
|
|
|
typedef RangeSize<_T> _r_size;
|
2015-04-27 18:53:48 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
|
|
|
_r_size __index;
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-04-27 18:53:48 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange(): __range(), __index(0) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange(const _T &__range): __range(__range), __index(0) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange(const EnumeratedRange &__it):
|
|
|
|
__range(__it.__range), __index(__it.__index) {}
|
2015-04-21 16:58:36 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange(EnumeratedRange &&__it):
|
|
|
|
__range(octa::move(__it.__range)), __index(__it.__index) {}
|
2015-04-28 17:48:58 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange &operator=(const EnumeratedRange &__v) {
|
|
|
|
__range = __v.__range;
|
|
|
|
__index = __v.__index;
|
2015-04-21 16:58:36 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange &operator=(EnumeratedRange &&__v) {
|
|
|
|
__range = octa::move(__v.__range);
|
|
|
|
__index = __v.__index;
|
2015-04-21 16:58:36 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange &operator=(const _T &__v) {
|
|
|
|
__range = __v;
|
|
|
|
__index = 0;
|
2015-04-21 16:58:36 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedRange &operator=(_T &&__v) {
|
|
|
|
__range = octa::move(__v);
|
|
|
|
__index = 0;
|
2015-04-21 16:58:36 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __range.empty(); }
|
2015-04-21 16:58:36 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const EnumeratedRange &__r) const {
|
|
|
|
return __range.equals_front(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 00:13:37 +00:00
|
|
|
bool pop_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
if (__range.pop_front()) {
|
|
|
|
++__index;
|
2015-05-29 19:02:40 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2015-04-21 16:58:36 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_r_size pop_front_n(_r_size __n) {
|
|
|
|
_r_size __ret = __range.pop_front_n(__n);
|
|
|
|
__index += __ret;
|
|
|
|
return __ret;
|
2015-05-23 16:36:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
EnumeratedValue<_r_ref, _r_size> front() const {
|
|
|
|
return EnumeratedValue<_r_ref, _r_size> { __index, __range.front() };
|
2015-04-21 16:58:36 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
EnumeratedRange<_T> enumerate(const _T &__it) {
|
|
|
|
return EnumeratedRange<_T>(__it);
|
2015-04-21 16:58:36 +00:00
|
|
|
}
|
2015-05-26 18:25:20 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct TakeRange: InputRange<TakeRange<_T>,
|
|
|
|
CommonType<RangeCategory<_T>, ForwardRangeTag>,
|
|
|
|
RangeValue<_T>, RangeReference<_T>, RangeSize<_T>
|
2015-05-27 19:45:34 +00:00
|
|
|
> {
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
|
|
|
RangeSize<_T> __remaining;
|
2015-05-27 19:45:34 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
TakeRange(): __range(), __remaining(0) {}
|
|
|
|
TakeRange(const _T &__range, RangeSize<_T> __rem): __range(__range),
|
|
|
|
__remaining(__rem) {}
|
|
|
|
TakeRange(const TakeRange &__it): __range(__it.__range),
|
|
|
|
__remaining(__it.__remaining) {}
|
|
|
|
TakeRange(TakeRange &&__it): __range(octa::move(__it.__range)),
|
|
|
|
__remaining(__it.__remaining) {}
|
|
|
|
|
|
|
|
TakeRange &operator=(const TakeRange &__v) {
|
|
|
|
__range = __v.__range; __remaining = __v.__remaining; return *this;
|
|
|
|
}
|
|
|
|
TakeRange &operator=(TakeRange &&__v) {
|
|
|
|
__range = octa::move(__v.__range);
|
|
|
|
__remaining = __v.__remaining;
|
|
|
|
return *this;
|
2015-05-27 19:45:34 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return (__remaining <= 0) || __range.empty(); }
|
2015-05-27 19:45:34 +00:00
|
|
|
|
2015-06-01 00:13:37 +00:00
|
|
|
bool pop_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
if (__range.pop_front()) {
|
|
|
|
--__remaining;
|
2015-05-29 19:02:40 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2015-06-01 00:13:37 +00:00
|
|
|
bool push_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
if (__range.push_front()) {
|
|
|
|
++__remaining;
|
2015-05-29 18:52:20 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeSize<_T> pop_front_n(RangeSize<_T> __n) {
|
|
|
|
RangeSize<_T> __ret = __range.pop_front_n(__n);
|
|
|
|
__remaining -= __ret;
|
|
|
|
return __ret;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeSize<_T> push_front_n(RangeSize<_T> __n) {
|
|
|
|
RangeSize<_T> __ret = __range.push_front_n(__n);
|
|
|
|
__remaining += __ret;
|
|
|
|
return __ret;
|
2015-05-27 19:45:34 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> front() const { return __range.front(); }
|
2015-05-27 19:45:34 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const TakeRange &__r) const {
|
|
|
|
return __range.equals_front(__r.__range);
|
2015-05-27 19:45:34 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_front(const TakeRange &__r) const {
|
|
|
|
return __range.distance_front(__r.__range);
|
2015-05-27 19:45:34 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
TakeRange<_T> take(const _T &__it, RangeSize<_T> __n) {
|
|
|
|
return TakeRange<_T>(__it, __n);
|
2015-05-27 19:45:34 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct ChunksRange: InputRange<ChunksRange<_T>,
|
|
|
|
CommonType<RangeCategory<_T>, ForwardRangeTag>,
|
|
|
|
TakeRange<_T>, TakeRange<_T>, RangeSize<_T>
|
2015-05-27 19:56:44 +00:00
|
|
|
> {
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __range;
|
|
|
|
RangeSize<_T> __chunksize;
|
2015-05-27 19:56:44 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
ChunksRange(): __range(), __chunksize(0) {}
|
|
|
|
ChunksRange(const _T &__range, RangeSize<_T> __chs): __range(__range),
|
|
|
|
__chunksize(__chs) {}
|
|
|
|
ChunksRange(const ChunksRange &__it): __range(__it.__range),
|
|
|
|
__chunksize(__it.__chunksize) {}
|
|
|
|
ChunksRange(ChunksRange &&__it): __range(octa::move(__it.__range)),
|
|
|
|
__chunksize(__it.__chunksize) {}
|
|
|
|
|
|
|
|
ChunksRange &operator=(const ChunksRange &__v) {
|
|
|
|
__range = __v.__range; __chunksize = __v.p_chunksize; return *this;
|
|
|
|
}
|
|
|
|
ChunksRange &operator=(ChunksRange &&__v) {
|
|
|
|
__range = octa::move(__v.__range);
|
|
|
|
__chunksize = __v.__chunksize;
|
|
|
|
return *this;
|
2015-05-27 19:56:44 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __range.empty(); }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const ChunksRange &__r) const {
|
|
|
|
return __range.equals_front(__r.__range);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool pop_front() { return __range.pop_front_n(__chunksize) > 0; }
|
2015-06-01 00:13:37 +00:00
|
|
|
bool push_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __tmp = __range;
|
|
|
|
RangeSize<_T> __an = __tmp.push_front_n(__chunksize);
|
|
|
|
if (__an != __chunksize) return false;
|
|
|
|
__range = __tmp;
|
2015-05-29 18:52:20 +00:00
|
|
|
return true;
|
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeSize<_T> pop_front_n(RangeSize<_T> __n) {
|
|
|
|
return __range.pop_front_n(__chunksize * __n) / __chunksize;
|
|
|
|
}
|
|
|
|
RangeSize<_T> push_front_n(RangeSize<_T> __n) {
|
|
|
|
_T __tmp = __range;
|
|
|
|
RangeSize<_T> __an = __tmp.push_front_n(__chunksize * __n);
|
|
|
|
RangeSize<_T> __pn = __an / __chunksize;
|
|
|
|
if (!__pn) return 0;
|
|
|
|
if (__pn == __n) {
|
|
|
|
__range = __tmp;
|
|
|
|
return __pn;
|
2015-05-29 18:52:20 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
return __range.push_front_n(__chunksize * __an) / __chunksize;
|
2015-05-27 19:56:44 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
TakeRange<_T> front() const { return take(__range, __chunksize); }
|
2015-05-27 19:56:44 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
ChunksRange<_T> chunks(const _T &__it, RangeSize<_T> __chs) {
|
|
|
|
return ChunksRange<_T>(__it, __chs);
|
2015-05-27 19:56:44 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
auto each(_T &__r) -> decltype(__r.each()) {
|
|
|
|
return __r.each();
|
2015-05-26 18:25:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
auto each(const _T &__r) -> decltype(__r.each()) {
|
|
|
|
return __r.each();
|
2015-05-26 18:25:20 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, size_t _N>
|
|
|
|
PointerRange<_T> each(_T (&__array)[_N]) {
|
|
|
|
return PointerRange<_T>(__array, _N);
|
2015-05-26 18:25:20 +00:00
|
|
|
}
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-05-31 23:33:59 +00:00
|
|
|
// range of
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T> using RangeOf = decltype(octa::each(octa::declval<_T>()));
|
2015-05-31 23:33:59 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct HalfRange: InputRange<HalfRange<_T>,
|
|
|
|
RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>,
|
|
|
|
RangeDifference<_T>
|
2015-05-29 22:32:25 +00:00
|
|
|
> {
|
|
|
|
private:
|
2015-06-01 23:57:34 +00:00
|
|
|
_T __beg;
|
|
|
|
_T __end;
|
2015-05-29 22:32:25 +00:00
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
HalfRange(): __beg(), __end() {}
|
|
|
|
HalfRange(const HalfRange &__range): __beg(__range.__beg),
|
|
|
|
__end(__range.__end) {}
|
|
|
|
HalfRange(HalfRange &&__range): __beg(octa::move(__range.__beg)),
|
|
|
|
__end(octa::move(__range.__end)) {}
|
|
|
|
HalfRange(const _T &__beg, const _T &__end): __beg(__beg),
|
|
|
|
__end(__end) {}
|
|
|
|
HalfRange(_T &&__beg, _T &&__end): __beg(octa::move(__beg)),
|
|
|
|
__end(octa::move(__end)) {}
|
|
|
|
|
|
|
|
HalfRange &operator=(const HalfRange &__range) {
|
|
|
|
__beg = __range.p_beg;
|
|
|
|
__end = __range.p_end;
|
2015-05-29 22:32:25 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
HalfRange &operator=(HalfRange &&__range) {
|
|
|
|
__beg = octa::move(__range.p_beg);
|
|
|
|
__end = octa::move(__range.p_end);
|
2015-05-29 22:32:25 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool empty() const { return __beg == __end; }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 00:13:37 +00:00
|
|
|
bool pop_front() {
|
2015-05-29 22:32:25 +00:00
|
|
|
if (empty()) return false;
|
2015-06-01 23:57:34 +00:00
|
|
|
return __beg.next();
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 00:13:37 +00:00
|
|
|
bool push_front() {
|
2015-06-01 23:57:34 +00:00
|
|
|
return __beg.prev();
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 00:13:37 +00:00
|
|
|
bool pop_back() {
|
2015-05-29 22:32:25 +00:00
|
|
|
if (empty()) return false;
|
2015-06-01 23:57:34 +00:00
|
|
|
return __end.prev();
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 00:13:37 +00:00
|
|
|
bool push_back() {
|
2015-06-01 23:57:34 +00:00
|
|
|
return __end.next();
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> front() const { return *__beg; }
|
|
|
|
RangeReference<_T> back() const { return *(__end - 1); }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_front(const HalfRange &__range) const {
|
|
|
|
return __beg == __range.__beg;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
bool equals_back(const HalfRange &__range) const {
|
|
|
|
return __end == __range.__end;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_front(const HalfRange &__range) const {
|
|
|
|
return __range.__beg - __beg;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeDifference<_T> distance_back(const HalfRange &__range) const {
|
|
|
|
return __range.__end - __end;
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeSize<_T> size() const { return __end - __beg; }
|
2015-05-29 22:32:25 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
HalfRange<_T> slice(RangeSize<_T> __start, RangeSize<_T> __end) const {
|
|
|
|
return HalfRange<_T>(__beg + __start, __beg + __end);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
RangeReference<_T> operator[](RangeSize<_T> __idx) const {
|
|
|
|
return __beg[__idx];
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
void put(const RangeValue<_T> &__v) {
|
|
|
|
__beg.range().put(__v);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-06-01 23:57:34 +00:00
|
|
|
void put(RangeValue<_T> &&__v) {
|
|
|
|
__beg.range().put(octa::move(__v));
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
|
|
|
HalfRange<RangeHalf<_T>>
|
|
|
|
make_half_range(const RangeHalf<_T> &__a, const RangeHalf<_T> &__b) {
|
|
|
|
return HalfRange<RangeHalf<_T>>(__a, __b);
|
2015-05-29 22:32:25 +00:00
|
|
|
}
|
2015-04-15 23:18:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|