#ifndef _VECTOR_H
#define _VECTOR_H
#include <stdlib.h>
#include <string.h>
#include <SupportDefs.h>
#include <util/kernel_cpp.h>
template<typename Value> class VectorIterator;
#define _VECTOR_TEMPLATE_LIST template<typename Value>
#define _VECTOR_CLASS_NAME Vector<Value>
#define _VECTOR_CLASS_TYPE typename Vector<Value>
template<typename Value>
class Vector {
public:
typedef VectorIterator<Value> Iterator;
typedef VectorIterator<const Value> ConstIterator;
private:
static const size_t kDefaultChunkSize = 10;
static const size_t kMaximalChunkSize = 1024 * 1024;
public:
Vector(size_t chunkSize = kDefaultChunkSize);
~Vector();
status_t PushFront(const Value &value);
status_t PushBack(const Value &value);
void PopFront();
void PopBack();
status_t Add(const Value &value) { return PushBack(value); }
status_t Add(const Value &value, int32 index) { return Insert(value, index); }
status_t Insert(const Value &value, int32 index);
status_t Insert(const Value &value, const Iterator &iterator);
int32 Remove(const Value &value);
Iterator Erase(int32 index);
Iterator Erase(const Iterator &iterator);
inline int32 Count() const;
inline bool IsEmpty() const;
void MakeEmpty();
inline Iterator Begin();
inline ConstIterator Begin() const;
inline Iterator End();
inline ConstIterator End() const;
inline Iterator Null();
inline ConstIterator Null() const;
inline Iterator IteratorForIndex(int32 index);
inline ConstIterator IteratorForIndex(int32 index) const;
inline const Value &ElementAt(int32 index) const;
inline Value &ElementAt(int32 index);
int32 IndexOf(const Value &value, int32 start = 0) const;
Iterator Find(const Value &value);
Iterator Find(const Value &value, const Iterator &start);
ConstIterator Find(const Value &value) const;
ConstIterator Find(const Value &value, const ConstIterator &start) const;
inline Value &operator[](int32 index);
inline const Value &operator[](int32 index) const;
int32 GetCapacity() const { return fCapacity; }
private:
inline static void _MoveItems(Value *values, int32 offset, int32 count);
bool _Resize(size_t count);
inline int32 _IteratorIndex(const Iterator &iterator) const;
inline int32 _IteratorIndex(const ConstIterator &iterator) const;
private:
size_t fCapacity;
size_t fChunkSize;
int32 fItemCount;
Value *fItems;
};
template<typename Value>
class VectorIterator {
private:
typedef VectorIterator<Value> Iterator;
public:
inline VectorIterator()
: fElement(NULL)
{
}
inline VectorIterator(const Iterator &other)
: fElement(other.fElement)
{
}
inline Iterator &operator++()
{
if (fElement)
++fElement;
return *this;
}
inline Iterator operator++(int)
{
Iterator it(*this);
++*this;
return it;
}
inline Iterator &operator--()
{
if (fElement)
--fElement;
return *this;
}
inline Iterator operator--(int)
{
Iterator it(*this);
--*this;
return it;
}
inline Iterator &operator=(const Iterator &other)
{
fElement = other.fElement;
return *this;
}
inline bool operator==(const Iterator &other) const
{
return (fElement == other.fElement);
}
inline bool operator!=(const Iterator &other) const
{
return !(*this == other);
}
inline Value &operator*() const
{
return *fElement;
}
inline Value *operator->() const
{
return fElement;
}
inline operator bool() const
{
return fElement;
}
public:
inline VectorIterator(Value *element)
: fElement(element)
{
}
inline Value *Element() const
{
return fElement;
}
protected:
Value *fElement;
};
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::Vector(size_t chunkSize)
: fCapacity(0),
fChunkSize(chunkSize),
fItemCount(0),
fItems(NULL)
{
if (fChunkSize == 0 || fChunkSize > kMaximalChunkSize)
fChunkSize = kDefaultChunkSize;
_Resize(0);
}
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_NAME::~Vector()
{
MakeEmpty();
free(fItems);
}
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::PushFront(const Value &value)
{
return Insert(value, 0);
}
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::PushBack(const Value &value)
{
return Insert(value, fItemCount);
}
_VECTOR_TEMPLATE_LIST
void
_VECTOR_CLASS_NAME::PopFront()
{
if (fItemCount > 0)
Erase(0);
}
_VECTOR_TEMPLATE_LIST
void
_VECTOR_CLASS_NAME::PopBack()
{
if (fItemCount > 0)
Erase(fItemCount - 1);
}
_VECTOR_TEMPLATE_LIST
inline
void
_VECTOR_CLASS_NAME::_MoveItems(Value* items, int32 offset, int32 count)
{
if (count > 0 && offset != 0)
memmove(items + offset, items, count * sizeof(Value));
}
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::Insert(const Value &value, int32 index)
{
if (index < 0 || index > fItemCount)
return B_BAD_VALUE;
if (!_Resize(fItemCount + 1))
return B_NO_MEMORY;
_MoveItems(fItems + index, 1, fItemCount - index - 1);
new(fItems + index) Value(value);
return B_OK;
}
_VECTOR_TEMPLATE_LIST
status_t
_VECTOR_CLASS_NAME::Insert(const Value &value, const Iterator &iterator)
{
int32 index = _IteratorIndex(iterator);
if (index >= 0)
return Insert(value, index);
return B_BAD_VALUE;
}
_VECTOR_TEMPLATE_LIST
int32
_VECTOR_CLASS_NAME::Remove(const Value &value)
{
int32 count = 0;
for (int32 i = fItemCount - 1; i >= 0; i--) {
if (ElementAt(i) == value) {
Erase(i);
count++;
}
}
return count;
}
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::Erase(int32 index)
{
if (index >= 0 && index < fItemCount) {
fItems[index].~Value();
_MoveItems(fItems + index + 1, -1, fItemCount - index - 1);
_Resize(fItemCount - 1);
return Iterator(fItems + index);
}
return Null();
}
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::Erase(const Iterator &iterator)
{
int32 index = _IteratorIndex(iterator);
if (index >= 0 && index < fItemCount)
return Erase(index);
return Null();
}
_VECTOR_TEMPLATE_LIST
inline
int32
_VECTOR_CLASS_NAME::Count() const
{
return fItemCount;
}
_VECTOR_TEMPLATE_LIST
inline
bool
_VECTOR_CLASS_NAME::IsEmpty() const
{
return (fItemCount == 0);
}
_VECTOR_TEMPLATE_LIST
void
_VECTOR_CLASS_NAME::MakeEmpty()
{
for (int32 i = 0; i < fItemCount; i++)
fItems[i].~Value();
_Resize(0);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::Begin()
{
return Iterator(fItems);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::ConstIterator
_VECTOR_CLASS_NAME::Begin() const
{
return ConstIterator(fItems);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::End()
{
return Iterator(fItems + fItemCount);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::ConstIterator
_VECTOR_CLASS_NAME::End() const
{
return ConstIterator(fItems + fItemCount);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::Null()
{
return Iterator(NULL);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::ConstIterator
_VECTOR_CLASS_NAME::Null() const
{
return ConstIterator(NULL);
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::IteratorForIndex(int32 index)
{
if (index >= 0 && index <= fItemCount)
return Iterator(fItems + index);
return End();
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::ConstIterator
_VECTOR_CLASS_NAME::IteratorForIndex(int32 index) const
{
if (index >= 0 && index <= fItemCount)
return ConstIterator(fItems + index);
return End();
}
_VECTOR_TEMPLATE_LIST
inline
const Value &
_VECTOR_CLASS_NAME::ElementAt(int32 index) const
{
if (index >= 0 && index < fItemCount)
return fItems[index];
return fItems[0];
}
_VECTOR_TEMPLATE_LIST
inline
Value &
_VECTOR_CLASS_NAME::ElementAt(int32 index)
{
if (index >= 0 && index < fItemCount)
return fItems[index];
return fItems[0];
}
_VECTOR_TEMPLATE_LIST
int32
_VECTOR_CLASS_NAME::IndexOf(const Value &value, int32 start) const
{
if (start >= 0) {
for (int32 i = start; i < fItemCount; i++) {
if (fItems[i] == value)
return i;
}
}
return -1;
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::Find(const Value &value)
{
return Find(value, Begin());
}
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_TYPE::Iterator
_VECTOR_CLASS_NAME::Find(const Value &value, const Iterator &start)
{
int32 index = IndexOf(value, _IteratorIndex(start));
if (index >= 0)
return Iterator(fItems + index);
return End();
}
_VECTOR_TEMPLATE_LIST
inline
_VECTOR_CLASS_TYPE::ConstIterator
_VECTOR_CLASS_NAME::Find(const Value &value) const
{
return Find(value, Begin());
}
_VECTOR_TEMPLATE_LIST
_VECTOR_CLASS_TYPE::ConstIterator
_VECTOR_CLASS_NAME::Find(const Value &value, const ConstIterator &start) const
{
int32 index = IndexOf(value, _IteratorIndex(start));
if (index >= 0)
return ConstIterator(fItems + index);
return End();
}
_VECTOR_TEMPLATE_LIST
inline
Value &
_VECTOR_CLASS_NAME::operator[](int32 index)
{
return ElementAt(index);
}
_VECTOR_TEMPLATE_LIST
inline
const Value &
_VECTOR_CLASS_NAME::operator[](int32 index) const
{
return ElementAt(index);
}
_VECTOR_TEMPLATE_LIST
bool
_VECTOR_CLASS_NAME::_Resize(size_t count)
{
bool result = true;
int32 newSize = count;
if (newSize <= 0)
newSize = 1;
newSize = ((newSize - 1) / fChunkSize + 1) * fChunkSize;
if ((size_t)newSize != fCapacity) {
Value* newItems = (Value*)realloc(fItems, newSize * sizeof(Value));
if (newItems) {
fItems = newItems;
fCapacity = newSize;
} else
result = false;
}
if (result)
fItemCount = count;
return result;
}
_VECTOR_TEMPLATE_LIST
inline
int32
_VECTOR_CLASS_NAME::_IteratorIndex(const Iterator &iterator) const
{
if (iterator.Element()) {
int32 index = iterator.Element() - fItems;
if (index >= 0 && index <= fItemCount)
return index;
}
return -1;
}
_VECTOR_TEMPLATE_LIST
inline
int32
_VECTOR_CLASS_NAME::_IteratorIndex(const ConstIterator &iterator) const
{
if (iterator.Element()) {
int32 index = iterator.Element() - fItems;
if (index >= 0 && index <= fItemCount)
return index;
}
return -1;
}
#endif