From c79e5757f99958ad9ccb5cea7897608a82b6c0b3 Mon Sep 17 00:00:00 2001 From: q66 Date: Thu, 16 Apr 2015 00:18:00 +0100 Subject: [PATCH] initial proof-of-concept implementation of ranges and range iterator --- octa/range.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ octa/vector.h | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 octa/range.h diff --git a/octa/range.h b/octa/range.h new file mode 100644 index 0000000..dc62dc9 --- /dev/null +++ b/octa/range.h @@ -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 + +#include "octa/types.h" + +namespace octa { + template + 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 + struct RangeTraits { + typedef ptrdiff_t difference; + typedef T value; + typedef T *pointer; + typedef T &reference; + }; + + template + struct RangeTraits { + typedef ptrdiff_t difference; + typedef T value; + typedef const T *pointer; + typedef const T &reference; + }; + + template<> + struct RangeTraits { + typedef ptrdiff_t difference; + typedef uchar value; + typedef void *pointer; + typedef uchar &reference; + }; + + template<> + struct RangeTraits { + typedef ptrdiff_t difference; + typedef uchar value; + typedef const void *pointer; + typedef const uchar &reference; + }; + + template + class RangeIterator { + T p_range; + + public: + struct type { + typedef typename RangeTraits::difference difference; + typedef typename RangeTraits::value value; + typedef typename RangeTraits::pointer pointer; + typedef typename RangeTraits::reference reference; + }; + + RangeIterator(): p_range() {} + RangeIterator(const T &range): p_range(range) {} + + template + RangeIterator(const RangeIterator &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 + friend bool operator!=(const RangeIterator &a, const RangeIterator &b) { + return a.range() != b.range(); + } + }; + + template + struct Range { + RangeIterator begin() { return RangeIterator((const T &)*this); } + RangeIterator end() { return RangeIterator(); } + }; +} + +#endif \ No newline at end of file diff --git a/octa/vector.h b/octa/vector.h index 05d61fe..cd2f7f4 100644 --- a/octa/vector.h +++ b/octa/vector.h @@ -12,8 +12,69 @@ #include "octa/new.h" #include "octa/traits.h" #include "octa/utility.h" +#include "octa/range.h" namespace octa { + template + class VectorRange: public Range > { + 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 + friend bool operator==(const VectorRange &a, const VectorRange &b) { + return a.p_beg == b.p_beg && a.p_end == b.p_end; + } + + template + friend bool operator!=(const VectorRange &a, const VectorRange &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 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 each() { + return VectorRange(p_buf, p_buf + p_len); + } }; }