forked from OctaForge/libostd
initial proof-of-concept implementation of ranges and range iterator
This commit is contained in:
parent
e12b221112
commit
c79e5757f9
96
octa/range.h
Normal file
96
octa/range.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* 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"
|
||||
|
||||
namespace octa {
|
||||
template<typename T>
|
||||
struct RangeTraits {
|
||||
typedef typename T::type::difference difference;
|
||||
typedef typename T::type::value value;
|
||||
typedef typename T::type::pointer pointer;
|
||||
typedef typename T::type::reference reference;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct RangeTraits<T *> {
|
||||
typedef ptrdiff_t difference;
|
||||
typedef T value;
|
||||
typedef T *pointer;
|
||||
typedef T &reference;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct RangeTraits<const T *> {
|
||||
typedef ptrdiff_t difference;
|
||||
typedef T value;
|
||||
typedef const T *pointer;
|
||||
typedef const T &reference;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct RangeTraits<void *> {
|
||||
typedef ptrdiff_t difference;
|
||||
typedef uchar value;
|
||||
typedef void *pointer;
|
||||
typedef uchar &reference;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct RangeTraits<const void *> {
|
||||
typedef ptrdiff_t difference;
|
||||
typedef uchar value;
|
||||
typedef const void *pointer;
|
||||
typedef const uchar &reference;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RangeIterator {
|
||||
T p_range;
|
||||
|
||||
public:
|
||||
struct type {
|
||||
typedef typename RangeTraits<T>::difference difference;
|
||||
typedef typename RangeTraits<T>::value value;
|
||||
typedef typename RangeTraits<T>::pointer pointer;
|
||||
typedef typename RangeTraits<T>::reference reference;
|
||||
};
|
||||
|
||||
RangeIterator(): p_range() {}
|
||||
RangeIterator(const T &range): p_range(range) {}
|
||||
|
||||
template<typename U>
|
||||
RangeIterator(const RangeIterator<U> &it): p_range(it.range()) {}
|
||||
|
||||
T range() const { return p_range; }
|
||||
|
||||
RangeIterator &operator++() {
|
||||
p_range.pop_first();
|
||||
return *this;
|
||||
}
|
||||
|
||||
typename type::reference operator*() {
|
||||
return p_range.first();
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend bool operator!=(const RangeIterator &a, const RangeIterator<U> &b) {
|
||||
return a.range() != b.range();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Range {
|
||||
RangeIterator<T> begin() { return RangeIterator<T>((const T &)*this); }
|
||||
RangeIterator<T> end() { return RangeIterator<T>(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -12,8 +12,69 @@
|
|||
#include "octa/new.h"
|
||||
#include "octa/traits.h"
|
||||
#include "octa/utility.h"
|
||||
#include "octa/range.h"
|
||||
|
||||
namespace octa {
|
||||
template<typename T>
|
||||
class VectorRange: public Range<VectorRange<T> > {
|
||||
T *p_beg, *p_end;
|
||||
|
||||
public:
|
||||
struct type {
|
||||
typedef ptrdiff_t difference;
|
||||
typedef T value;
|
||||
typedef T *pointer;
|
||||
typedef T &reference;
|
||||
};
|
||||
|
||||
VectorRange(): p_beg(nullptr), p_end(nullptr) {}
|
||||
VectorRange(const VectorRange &v): p_beg(v.p_beg), p_end(v.p_end) {}
|
||||
VectorRange(T *beg, T *end): p_beg(beg), p_end(end) {}
|
||||
|
||||
/* satisfy InputRange */
|
||||
|
||||
bool empty() const { return p_beg == nullptr; }
|
||||
|
||||
T &first() { return *p_beg; }
|
||||
const T &first() const { return *p_beg; }
|
||||
|
||||
void pop_first() {
|
||||
if (p_beg == nullptr) return;
|
||||
if (++p_beg == p_end) p_beg = p_end = nullptr;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend bool operator==(const VectorRange &a, const VectorRange<U> &b) {
|
||||
return a.p_beg == b.p_beg && a.p_end == b.p_end;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
friend bool operator!=(const VectorRange &a, const VectorRange<U> &b) {
|
||||
return a.p_beg != b.p_beg || a.p_end != b.p_end;
|
||||
}
|
||||
|
||||
/* satisfy ForwardRange */
|
||||
|
||||
VectorRange save() { return *this; }
|
||||
|
||||
/* satisfy BidirectionalRange */
|
||||
|
||||
T &last() { return *(p_end - 1); }
|
||||
const T &last() const { return *(p_end - 1); }
|
||||
|
||||
void pop_last() {
|
||||
if (p_end-- == p_beg) { p_end = nullptr; return; }
|
||||
if (p_end == p_beg) p_beg = p_end = nullptr;
|
||||
}
|
||||
|
||||
/* satisfy RandomAccessRange */
|
||||
|
||||
T &operator[](size_t i) { return p_beg[i]; }
|
||||
const T &operator[](size_t i) const { return p_beg[i]; }
|
||||
|
||||
size_t length() const { return p_end - p_beg; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Vector {
|
||||
T *p_buf;
|
||||
|
@ -221,6 +282,10 @@ namespace octa {
|
|||
for (size_t i = 0; i < n; ++i) p_buf[idx + i] = v[i];
|
||||
return &p_buf[idx];
|
||||
}
|
||||
|
||||
VectorRange<T> each() {
|
||||
return VectorRange<T>(p_buf, p_buf + p_len);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue