#ifndef __DEQUE_AMV
#define __DEQUE_AMV
#include "exception.h"
#include "allocator.h"
#include "iterator.h"
#include "algorithm.h"
#include "memoryAMV.h"
namespace amv {
#define PAGE_SIZE 4096
#define OBJECTS_FOR_BLOCK (PAGE_SIZE<sizeof(type)? 1: PAGE_SIZE/sizeof(type))
template <class type, class A=allocator<type> >
class deque {
public:
typedef A allocator_type;
typedef A::size_type size_type;
typedef A::difference_type difference_type;
typedef A::pointer pointer;
typedef A::const_pointer const_pointer;
typedef A::reference reference;
typedef A::const_reference const_reference;
typedef A::value_type value_type;
class const_iterator;
class iterator: public
RanIt<value_type,difference_type,pointer,reference> {
friend class deque<type,A>;
friend class const_iterator;
type *pObject, *blockBegin, *blockEnd;
type **pBlocks;
iterator(type **newPBlocks):
pObject(*newPBlocks),
blockBegin(pObject),
blockEnd(blockBegin+OBJECTS_FOR_BLOCK),
pBlocks(newPBlocks)
{
}
iterator(type *pSourceObject, type **newPBlocks):
pObject(pSourceObject),
blockBegin(*newPBlocks),
blockEnd(blockBegin+OBJECTS_FOR_BLOCK),
pBlocks(newPBlocks)
{
}
public:
iterator(): pObject(0),
blockBegin(0), blockEnd(0), pBlocks(0)
{
}
type &operator *() const
{
return *pObject;
}
type *operator->() const
{
return pObject;
}
iterator &operator ++()
{
if(++pObject==blockEnd)
{
pObject=blockBegin=*++pBlocks;
blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
}
return *this;
}
iterator operator ++(int i)
{
iterator temp(*this);
++(*this);
return temp;
}
iterator &operator --()
{
if(pObject==blockBegin)
{
blockBegin=*--pBlocks;
pObject=blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
}
--pObject;
return *this;
}
iterator operator --(int i)
{
iterator temp(*this);
--(*this);
return temp;
}
iterator &operator+=(difference_type n)
{ type *p=pObject+n;
if(p>=blockEnd)
{
difference_type blocksDifference=((p-blockBegin)/OBJECTS_FOR_BLOCK);
difference_type offset=(p-blockBegin)%OBJECTS_FOR_BLOCK;
pBlocks+=blocksDifference;
blockBegin=*pBlocks;
blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
pObject=blockBegin+offset;
}
else
pObject=p;
return *this;
}
iterator &operator-=(difference_type n)
{ type *p=pObject-n;
if(p<blockBegin)
{
difference_type m=(blockBegin-p)%OBJECTS_FOR_BLOCK;
difference_type blocksDifference=((blockBegin-p)/OBJECTS_FOR_BLOCK)+(m? 1: 0);
difference_type offset=m? OBJECTS_FOR_BLOCK-m: 0;
pBlocks-=blocksDifference;
blockBegin=*pBlocks;
blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
pObject=blockBegin+offset;
}
else
pObject=p;
return *this;
}
iterator operator+(difference_type n) const
{
iterator it(*this);
return (it+=n);
}
iterator operator-(difference_type n) const
{
iterator it(*this);
return (it-=n);
}
difference_type operator-(const iterator &it) const
{
return (pBlocks==it.pBlocks? pObject-it.pObject:
OBJECTS_FOR_BLOCK*(pBlocks-it.pBlocks-1)+
(pObject-blockBegin)+(it.blockEnd-it.pObject));
}
reference operator[](difference_type n) const
{
return (*(*this+n));
}
operator bool() const
{
return pObject;
}
bool operator==(const iterator & Iterator) const
{
return (pObject==Iterator.pObject);
}
bool operator!=(const iterator & Iterator) const
{
return !(*this==Iterator);
}
bool operator<(const iterator &Iterator) const
{
return (pBlocks<Iterator.pBlocks ||
pBlocks==Iterator.pBlocks && pObject<Iterator.pObject);
}
bool operator<=(const iterator &Iterator) const
{
return !(Iterator<*this);
}
bool operator>(const iterator &Iterator) const
{
return (Iterator<*this);
}
bool operator>=(const iterator &Iterator) const
{
return !(*this<Iterator);
}
};
class const_iterator: public
RanIt<value_type,difference_type,const_pointer,const_reference> {
friend class deque<type,A>;
friend class iterator;
const type *pObject, *blockBegin, *blockEnd;
const type **pBlocks;
const_iterator(const type **newPBlocks):
pObject(*newPBlocks),
blockBegin(pObject),
blockEnd(blockBegin+OBJECTS_FOR_BLOCK),
pBlocks(newPBlocks)
{
}
public:
const_iterator(): pObject(0),
blockBegin(0), blockEnd(0), pBlocks(0)
{
}
const_iterator(const iterator &Iterator):
pObject(Iterator.pObject),
blockBegin(Iterator.blockBegin),
blockEnd(Iterator.blockEnd),
pBlocks(const_cast<const type **>(Iterator.pBlocks))
{
}
const_iterator &operator=(const iterator &Iterator)
{
pObject=Iterator.pObject;
blockBegin=Iterator.blockBegin;
blockEnd=Iterator.blockEnd;
pBlocks=const_cast<const type **>(Iterator.pBlocks);
return *this;
}
const type &operator *() const
{
return *pObject;
}
const type *operator->() const
{
return pObject;
}
const_iterator &operator ++()
{
if(++pObject==blockEnd)
{
pObject=blockBegin=*++pBlocks;
blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
}
return *this;
}
const_iterator operator ++(int i)
{
const_iterator temp(*this);
++(*this);
return temp;
}
const_iterator &operator --()
{
if(pObject==blockBegin)
{
blockBegin=*--pBlocks;
pObject=blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
}
--pObject;
return *this;
}
const_iterator operator --(int i)
{
const_iterator temp(*this);
--(*this);
return temp;
}
const_iterator &operator+=(difference_type n)
{ const type *p=pObject+n;
if(p>=blockEnd)
{
difference_type blocksDifference=((p-blockBegin)/OBJECTS_FOR_BLOCK);
difference_type offset=(p-blockBegin)%OBJECTS_FOR_BLOCK;
pBlocks+=blocksDifference;
blockBegin=*pBlocks;
blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
pObject=blockBegin+offset;
}
else
pObject=p;
return *this;
}
const_iterator &operator-=(difference_type n)
{ const type *p=pObject-n;
if(p<blockBegin)
{
difference_type m=(blockBegin-p)%OBJECTS_FOR_BLOCK;
difference_type blocksDifference=((blockBegin-p)/OBJECTS_FOR_BLOCK)+(m? 1: 0);
difference_type offset=m? OBJECTS_FOR_BLOCK-m: 0;
pBlocks-=blocksDifference;
blockBegin=*pBlocks;
blockEnd=blockBegin+OBJECTS_FOR_BLOCK;
pObject=blockBegin+offset;
}
else
pObject=p;
return *this;
}
const_iterator operator+(difference_type n) const
{
const_iterator it(*this);
return (it+=n);
}
const_iterator operator-(difference_type n) const
{
const_iterator it(*this);
return (it-=n);
}
difference_type operator-(const const_iterator &it) const
{
return (pBlocks==it.pBlocks? pObject-it.pObject:
OBJECTS_FOR_BLOCK*(pBlocks-it.pBlocks-1)+
(pObject-blockBegin)+(it.blockEnd-it.pObject));
}
const_reference operator[](difference_type n) const
{
return (*(*this+n));
}
operator bool() const
{
return pObject;
}
bool operator==(const const_iterator & Iterator) const
{
return (pObject==Iterator.pObject);
}
bool operator!=(const const_iterator & Iterator) const
{
return !(*this==Iterator);
}
bool operator<(const const_iterator &Iterator) const
{
return (pBlocks<Iterator.pBlocks ||
pBlocks==Iterator.pBlocks && pObject<Iterator.pObject);
}
bool operator<=(const const_iterator &Iterator) const
{
return !(Iterator<*this);
}
bool operator>(const const_iterator &Iterator) const
{
return (Iterator<*this);
}
bool operator>=(const const_iterator &Iterator) const
{
return !(*this<Iterator);
}
};
typedef reverse_iterator<const_iterator> const_reverse_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
reference operator[](size_type subscript);
const_reference operator[](size_type subscript) const;
reference at(size_type subscript);
const_reference at(size_type subscript) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
deque(const A &sourceAllocator=A());
deque(size_type sourceSize, const type &sourceValue=type(), const A &sourceAllocator=A());
deque(const deque<type,A> &d);
~deque();
deque<type,A> &operator=(const deque<type,A> &op2);
void clear();
void push_front(const type &newObject);
void pop_front();
void push_back(const type &newObject);
void pop_back();
size_type size() const;
bool empty() const;
operator bool() const;
bool operator==(const deque<type,A> &d) const;
protected:
A alloc;
iterator itBegin;
iterator itEnd;
size_type m_size;
size_type initialPos;
size_type nBlocks;
type **pBlocks;
size_type realSize;
void addBlockBack();
void addBlockFront();
void removeBlockBack();
void removeBlockFront();
};
template <class type, class A>
inline deque<type,A>::iterator deque<type,A>::begin()
{
return itBegin;
}
template <class type, class A>
inline deque<type,A>::const_iterator deque<type,A>::begin() const
{
return itBegin;
}
template <class type, class A>
inline deque<type,A>::iterator deque<type,A>::end()
{
return itEnd;
}
template <class type, class A>
inline deque<type,A>::const_iterator deque<type,A>::end() const
{
return itEnd;
}
template <class type, class A>
inline deque<type,A>::reverse_iterator deque<type,A>::rbegin()
{
return itEnd;
}
template <class type, class A>
inline deque<type,A>::const_reverse_iterator deque<type,A>::rbegin() const
{
return itEnd;
}
template <class type, class A>
inline deque<type,A>::reverse_iterator deque<type,A>::rend()
{
return itBegin;
}
template <class type, class A>
inline deque<type,A>::const_reverse_iterator deque<type,A>::rend() const
{
return itBegin;
}
template <class type, class A>
inline deque<type,A>::reference deque<type,A>::operator[](size_type subscript)
{
subscript+=initialPos;
return pBlocks[subscript/OBJECTS_FOR_BLOCK][subscript%OBJECTS_FOR_BLOCK];
}
template <class type, class A>
inline deque<type,A>::const_reference deque<type,A>::operator[](size_type subscript) const
{
subscript+=initialPos;
return pBlocks[subscript/OBJECTS_FOR_BLOCK][subscript%OBJECTS_FOR_BLOCK];
}
template <class type, class A>
inline deque<type,A>::reference deque<type,A>::at(size_type subscript)
{
if(subscript>=m_size)
throw out_of_range();
return (*this)[subscript];
}
template <class type, class A>
inline deque<type,A>::const_reference deque<type,A>::at(size_type subscript) const
{
if(subscript>=m_size)
throw out_of_range();
return (*this)[subscript];
}
template <class type, class A>
inline deque<type,A>::reference deque<type,A>::front()
{
return *itBegin;
}
template <class type, class A>
inline deque<type,A>::const_reference deque<type,A>::front() const
{
return *itBegin;
}
template <class type, class A>
inline deque<type,A>::reference deque<type,A>::back()
{
iterator temp(itEnd);
return *(--temp);
}
template <class type, class A>
inline deque<type,A>::const_reference deque<type,A>::back() const
{
const_iterator temp(itEnd);
return *(--temp);
}
template <class type, class A>
inline deque<type,A>::deque(const A &sourceAllocator):
alloc(sourceAllocator), m_size(0), initialPos(0), nBlocks(0), pBlocks(0),
realSize(0), itBegin(), itEnd()
{
}
template <class type, class A>
inline deque<type,A>::deque(size_type sourceSize, const type &sourceValue, const A &sourceAllocator):
alloc(sourceAllocator), m_size(sourceSize), initialPos(0), nBlocks(0), pBlocks(0), realSize(0),
itBegin(), itEnd()
{
int module;
if(module=(m_size%OBJECTS_FOR_BLOCK))
nBlocks=(m_size/OBJECTS_FOR_BLOCK)+1;
else
nBlocks=m_size/OBJECTS_FOR_BLOCK;
realSize=nBlocks*OBJECTS_FOR_BLOCK;
pBlocks=static_cast<type **>(alloc.allocateBytes((nBlocks+1)*sizeof(type *)));
type *pB, *pE;
size_type nFullBlocks=nBlocks-1,i;
for(i=0; i<nFullBlocks; ++i)
{
pB=pBlocks[i]=alloc.allocate(OBJECTS_FOR_BLOCK);
pE=pB+OBJECTS_FOR_BLOCK;
while(pB!=pE)
{
alloc.construct(pB,sourceValue);
++pB;
}
}
pB=pBlocks[i]=alloc.allocate(OBJECTS_FOR_BLOCK);
pE=pB+(module? module: OBJECTS_FOR_BLOCK);
while(pB!=pE)
{
alloc.construct(pB,sourceValue);
++pB;
}
pBlocks[nBlocks]=0;
itBegin=iterator(pBlocks);
if(module)
itEnd=iterator(pE,pBlocks+nBlocks-1);
else
itEnd=iterator(pBlocks+nBlocks);
}
template <class type, class A>
inline deque<type,A>::deque(const deque<type,A> &d):
alloc(d.alloc), itBegin(), itEnd(),
m_size(d.m_size), initialPos(d.initialPos),
nBlocks(d.nBlocks), pBlocks(0), realSize(d.realSize)
{
if(m_size)
{
type **pTemp, **pEnd;
pTemp=pBlocks=static_cast<type **>(alloc.allocateBytes((nBlocks+1)*sizeof(type *)));
pEnd=pTemp+nBlocks;
while(pTemp!=pEnd)
{
*pTemp=alloc.allocate(OBJECTS_FOR_BLOCK);
++pTemp;
}
pBlocks[nBlocks]=0;
itBegin=iterator((*pBlocks)+initialPos,pBlocks);
if(d.itEnd)
{
difference_type offset=d.itEnd.pObject-d.itEnd.blockBegin;
itEnd=iterator(pBlocks+nBlocks-1);
itEnd.pObject+=offset;
}
else
itEnd=iterator(pBlocks+nBlocks);
uninitialized_copy(d.itBegin,d.itEnd,itBegin,type());
}
}
template <class type, class A>
inline deque<type,A>::~deque()
{
size_type i;
for(i=0; i<m_size; ++i)
alloc.destroy(&((*this)[i]));
for(i=0; i<nBlocks; ++i)
alloc.deallocate(pBlocks[i]);
alloc.deallocate(pBlocks);
}
template <class type, class A>
inline deque<type,A> &deque<type,A>::operator=(const deque<type,A> &op2)
{
this->~deque<type,A>();
m_size=op2.m_size;
initialPos=op2.initialPos;
nBlocks=op2.nBlocks;
realSize=op2.realSize;
if(m_size)
{
type **pTemp, **pEnd;
pTemp=pBlocks=static_cast<type **>(alloc.allocateBytes((nBlocks+1)*sizeof(type *)));
pEnd=pTemp+nBlocks;
while(pTemp!=pEnd)
{
*pTemp=alloc.allocate(OBJECTS_FOR_BLOCK);
++pTemp;
}
pBlocks[nBlocks]=0;
itBegin=iterator((*pBlocks)+initialPos,pBlocks);
if(op2.itEnd)
{
difference_type offset=op2.itEnd.pObject-op2.itEnd.blockBegin;
itEnd=iterator(pBlocks+nBlocks-1);
itEnd.pObject+=offset;
}
else
itEnd=iterator(pBlocks+nBlocks);
copy(op2.itBegin,op2.itEnd,itBegin);
}
else
{
pBlocks=0;
itBegin=iterator();
itEnd=iterator();
}
return *this;
}
template <class type, class A>
inline void deque<type,A>::clear()
{
this->~deque<type,A>();
m_size=0;
initialPos=0;
nBlocks=0;
pBlocks=0;
realSize=0;
itBegin=iterator();
itEnd=iterator();
}
template <class type, class A>
inline void deque<type,A>::push_front(const type &newObject)
{
if(initialPos>=1)
{
--initialPos;
++m_size;
pBlocks[0][initialPos]=newObject;
--itBegin;
}
else
{
addBlockFront();
initialPos=OBJECTS_FOR_BLOCK-1;
++m_size;
pBlocks[0][initialPos]=newObject;
}
}
template <class type, class A>
inline void deque<type,A>::pop_front()
{
if(--m_size)
{
if(initialPos<(OBJECTS_FOR_BLOCK-1))
{
++initialPos;
++itBegin;
}
else
{
removeBlockFront();
initialPos=0;
}
}
else
{
alloc.destroy(itBegin.pObject);
clear();
}
}
template <class type, class A>
inline void deque<type,A>::push_back(const type &newObject)
{
size_type realSubscript=initialPos+m_size;
if((realSubscript)<realSize)
{
alloc.construct(itEnd.pObject,newObject);
++itEnd;
++m_size;
}
else
{
addBlockBack();
alloc.construct(itEnd.blockBegin,newObject);
++m_size;
}
}
template <class type, class A>
inline void deque<type,A>::pop_back()
{
if(--m_size)
{
if(!((initialPos+m_size)%OBJECTS_FOR_BLOCK))
{
alloc.destroy(itEnd.blockBegin);
removeBlockBack();
}
else
{
--itEnd;
alloc.destroy(itEnd.pObject);
}
}
else
{
alloc.destroy(itBegin.pObject);
clear();
}
}
template <class type, class A>
inline deque<type,A>::size_type deque<type,A>::size() const
{
return m_size;
}
template <class type, class A>
inline bool deque<type,A>::empty() const
{
return size()==0;
}
template <class type, class A>
inline deque<type,A>::operator bool() const
{
return m_size;
}
template <class type, class A>
inline bool deque<type,A>::operator==(const deque<type,A> &d) const
{
if(m_size!=d.size())
return false;
for(size_type i=0; i<m_size; ++i)
{
if(!((*this)[i]==d[i]))
return false;
}
return true;
}
template <class type, class A>
inline void deque<type,A>::addBlockBack()
{
type **newPBlocks;
newPBlocks=static_cast<type **>(alloc.allocateBytes((nBlocks+2)*sizeof(type *)));
copy(pBlocks,pBlocks+nBlocks,newPBlocks);
newPBlocks[nBlocks++]=alloc.allocate(OBJECTS_FOR_BLOCK);
newPBlocks[nBlocks]=0;
alloc.deallocate(pBlocks);
pBlocks=newPBlocks;
realSize=nBlocks*OBJECTS_FOR_BLOCK;
if(itBegin.pObject==itBegin.blockBegin)
itBegin=iterator(pBlocks);
else
{
difference_type offset=itBegin.pObject-itBegin.blockBegin;
itBegin=iterator(pBlocks);
itBegin.pObject+=offset;
}
itEnd=iterator(pBlocks+nBlocks-1);
++itEnd;
}
template <class type, class A>
inline void deque<type,A>::addBlockFront()
{
type **newPBlocks;
newPBlocks=static_cast<type **>(alloc.allocateBytes((++nBlocks+1)*sizeof(type *)));
newPBlocks[0]=alloc.allocate(OBJECTS_FOR_BLOCK);
copy(pBlocks,pBlocks+nBlocks-1,newPBlocks+1);
newPBlocks[nBlocks]=0;
alloc.deallocate(pBlocks);
pBlocks=newPBlocks;
realSize=nBlocks*OBJECTS_FOR_BLOCK;
itBegin=iterator(pBlocks);
itBegin.pObject+=OBJECTS_FOR_BLOCK-1;
if(itEnd)
{
difference_type offset=itEnd.pObject-itEnd.blockBegin;
itEnd=iterator(pBlocks+nBlocks-1);
itEnd.pObject+=offset;
}
else
itEnd=iterator(pBlocks+nBlocks);
}
template <class type, class A>
inline void deque<type,A>::removeBlockBack()
{
type **newPBlocks;
newPBlocks=static_cast<type **>(alloc.allocateBytes((--nBlocks+1)*sizeof(type *)));
copy(pBlocks,pBlocks+nBlocks,newPBlocks);
alloc.deallocate(pBlocks[nBlocks]);
newPBlocks[nBlocks]=0;
alloc.deallocate(pBlocks);
pBlocks=newPBlocks;
realSize=nBlocks*OBJECTS_FOR_BLOCK;
if(itBegin.pObject==itBegin.blockBegin)
itBegin=iterator(pBlocks);
else
{
difference_type offset=itBegin.pObject-itBegin.blockBegin;
itBegin=iterator(pBlocks);
itBegin.pObject+=offset;
}
itEnd=iterator(pBlocks+nBlocks);
}
template <class type, class A>
inline void deque<type,A>::removeBlockFront()
{
type **newPBlocks;
newPBlocks=static_cast<type **>(alloc.allocateBytes((--nBlocks+1)*sizeof(type *)));
copy(pBlocks+1,pBlocks+nBlocks+1,newPBlocks);
alloc.deallocate(pBlocks[0]);
newPBlocks[nBlocks]=0;
alloc.deallocate(pBlocks);
pBlocks=newPBlocks;
realSize=nBlocks*OBJECTS_FOR_BLOCK;
itBegin=iterator(pBlocks);
if(itEnd)
{
difference_type offset=itEnd.pObject-itEnd.blockBegin;
itEnd=iterator(pBlocks+nBlocks-1);
itEnd.pObject+=offset;
}
else
itEnd=iterator(pBlocks+nBlocks);
}
}
#endif