#ifndef __DArray__
#define __DArray__
#include "Forwards.hpp"
#include "Debug/Assertion.hpp"
#include "Allocator.hpp"
#include "Comparison.hpp"
#include "Random.hpp"
#include "Reflection.hpp"
#include "VirtualIterator.hpp"
namespace Lib {
template<typename C>
class DArray
{
public:
USE_ALLOCATOR(DArray<C>);
class Iterator;
DECL_ELEMENT_TYPE(C);
DECL_ITERATOR_TYPE(Iterator);
inline
DArray (size_t size=0)
: _size(size), _capacity(size)
{
if(size>0) {
void* mem = ALLOC_KNOWN(sizeof(C)*_capacity,"DArray<>");
_array = array_new<C>(mem, _capacity);
} else {
_array=0;
}
}
explicit DArray(const DArray& o)
: _size(o.size()), _capacity(o.size())
{
if(_size==0) {
_array=0;
return;
}
void* mem = ALLOC_KNOWN(sizeof(C)*_capacity,"DArray<>");
_array = static_cast<C*>(mem);
for(size_t i=0; i<_size; i++) {
::new (&_array[i]) C(o[i]);
}
}
DArray clone() const { return DArray(*this); }
void swap(DArray& other) {
std::swap(other._size, _size);
std::swap(other._capacity, _capacity);
std::swap(other._array, _array);
}
bool keepRecycled() const { return _capacity > 0; }
DArray(DArray&& other) : DArray() { swap(other); }
DArray& operator=(DArray&& other) { swap(other); return *this; }
inline ~DArray()
{
if(_array) {
array_delete(_array, _capacity);
DEALLOC_KNOWN(_array,sizeof(C)*_capacity,"DArray<>");
}
}
inline C& operator[] (size_t n)
{
ASS_L(n,_size);
return _array[n];
}
inline const C& operator[](size_t n) const
{
ASS_L(n,_size);
return _array[n];
}
inline void shrink(size_t s)
{
ASS_LE(s,_size);
_size = s;
}
inline bool operator==(const DArray& o) const
{
if(size()!=o.size()) { return false; }
size_t sz = size();
for(size_t i=0; i<sz; i++) {
if(!((*this)[i]==o[i])) { return false; }
}
return true;
}
inline bool operator!=(const DArray& o) const { return !(*this==o); }
inline C* array() { return _array; }
inline const C* array() const { return _array; }
inline C* begin() { return _array; }
inline C* end() { return _array+_size; }
inline bool ensure(size_t s)
{
if (_capacity >= s) {
_size = s;
return true;
}
size_t newCapacity = std::max(s, _capacity*2);
void* mem = ALLOC_KNOWN(sizeof(C)*newCapacity,"DArray<>");
C* newArray=array_new<C>(mem, newCapacity);
if(_array) {
array_delete(_array, _capacity);
DEALLOC_KNOWN(_array,sizeof(C)*_capacity,"DArray<>");
}
_size = s;
_capacity = newCapacity;
_array = newArray;
return false;
}
void reset() { ensure(0); }
void expand(size_t s)
{
if (_capacity >= s) {
_size = s;
return;
}
size_t oldCapacity=_capacity;
size_t newCapacity=std::max(s, oldCapacity*2);
void* mem = ALLOC_KNOWN(sizeof(C)*newCapacity,"DArray<>");
C* oldArr = _array;
_capacity = newCapacity;
_array = static_cast<C*>(mem);
C* optr=oldArr;
C* nptr=_array;
C* firstEmpty=_array+_size;
C* afterLast=_array+_capacity;
while(nptr!=firstEmpty) {
C *oldAddr = optr++, *newAddr = nptr++;
::new (newAddr) C(std::move(*oldAddr));
oldAddr->~C();
}
while(nptr!=afterLast) {
::new (nptr++) C();
}
_size = s;
if(oldArr) {
DEALLOC_KNOWN(oldArr,sizeof(C)*oldCapacity,"DArray<>");
}
}
void expand(size_t s, C defVal)
{
size_t oldSize = _size;
expand(s);
if(s<=oldSize) {
return;
}
for(size_t i=oldSize; i<s; i++) {
(*this)[i] = defVal;
}
}
inline size_t size() const { return _size; }
static DArray initialized(size_t count, const C& value=C()) {
DArray out(count);
out.init(count, value);
return out;
}
void init(size_t count, const C& value=C()) {
ensure(count);
C* ptr=_array+count;
while(ptr!=_array) {
*(--ptr)=value;
}
}
template<typename Arr>
void initFromArray(size_t count, const Arr& src) {
ensure(count);
C* ptr=_array+count;
while(count) {
*(--ptr)=src[--count];
}
}
void initFromArray(size_t count, const C* src) {
ensure(count);
C* ptr=_array+count;
while(count) {
*(--ptr)=src[--count];
}
}
template<class It>
void initFromIterator(It it, size_t count=0) {
if(count) {
ensure(count);
C* ptr=_array;
while(it.hasNext()) {
*(ptr++)=it.next();
}
} else {
ensure(0);
count=0;
while(it.hasNext()) {
expand(++count);
(*this)[count-1]=it.next();
}
}
}
template<class It>
static DArray fromIterator(It it, size_t count=0) {
DArray out;
if (count != 0) {
out.initFromIterator(it, count);
} else if (it.knowsSize()) {
out.initFromIterator(it, it.size());
} else {
out.initFromIterator(it);
}
return out;
}
template<typename Comparator>
inline void sort(Comparator comp)
{
sortGen<false>(comp);
}
template<typename Comparator>
inline void sortInversed(Comparator comp)
{
sortGen<true>(comp);
}
template<bool Inversed, typename Comparator>
void sortGen(Comparator comp)
{
if(_size <= 1) {
return;
}
static DArray<size_t> ft(32);
size_t from = 0;
size_t to=size()-1;
ft.ensure(to);
size_t p = 0; for (;;) {
ASS(from<size() && to<size()); ASS(from<to);
size_t m = from + Random::getInteger(to-from+1);
C mid = (*this)[m];
size_t l = from;
size_t r = to;
while (l < m) {
switch ((Inversed?-1:1)*comp.compare((*this)[l],mid))
{
case EQUAL:
case LESS:
l++;
break;
case GREATER:
if (m == r) {
(*this)[m] = (*this)[l];
(*this)[l] = (*this)[m-1];
(*this)[m-1] = mid;
m--;
r--;
}
else {
ASS(m < r);
C aux = (*this)[l];
(*this)[l] = (*this)[r];
(*this)[r] = aux;
r--;
}
break;
}
}
while (m < r) {
switch ((Inversed?-1:1)*comp.compare(mid,(*this)[m+1]))
{
case LESS:
{
C aux = (*this)[r];
(*this)[r] = (*this)[m+1];
(*this)[m+1] = aux;
r--;
}
break;
case EQUAL:
case GREATER:
(*this)[m] = (*this)[m+1];
(*this)[m+1] = mid;
m++;
}
}
if (m+1 < to) {
ft[p++] = m+1;
ft[p++] = to;
}
to = m-1;
if (m!=0 && from < to) {
continue;
}
if (p != 0) {
p -= 2;
ASS(p >= 0);
from = ft[p];
to = ft[p+1];
continue;
}
return;
}
}
protected:
size_t _size;
size_t _capacity;
C* _array;
public:
class Iterator
{
public:
DECL_ELEMENT_TYPE(C);
inline Iterator() : _next(0), _afterLast(0) {}
inline Iterator(DArray& arr) : _next(arr._array),
_afterLast(arr._array+arr._size) {}
inline bool hasNext() { return _next!=_afterLast; }
inline C next() { return *(_next++); }
private:
C* _next;
C* _afterLast;
};
class ConstIterator
{
public:
DECL_ELEMENT_TYPE(C);
inline ConstIterator() : _next(0), _afterLast(0) {}
inline ConstIterator(const DArray& arr) : _next(arr._array),
_afterLast(arr._array+arr._size) {}
inline bool hasNext() { return _next!=_afterLast; }
inline const C& next() { return *(_next++); }
private:
const C* _next;
const C* _afterLast;
};
class ReversedIterator
{
public:
DECL_ELEMENT_TYPE(C);
inline ReversedIterator(DArray& arr) : _curr(arr._array+arr._size),
_first(arr._array) {}
inline bool hasNext() { return _curr!=_first; }
inline C next() { return *(--_curr); }
private:
C* _curr;
C* _first;
};
friend std::ostream& operator<<(std::ostream& out, DArray const& self)
{
ConstIterator iter(self);
out << "[ ";
if (iter.hasNext()) {
out << iter.next();
while (iter.hasNext()) {
out << ", ";
out << iter.next();
}
}
out << " ]";
return out;
}
};
template<typename T>
VirtualIterator<T> getContentIterator(DArray<T>& arr)
{
return pvi( typename DArray<T>::Iterator(arr) );
}
}
#endif