#ifndef _VECTOR_MAP_H
#define _VECTOR_MAP_H
#include <stdlib.h>
#include <string.h>
#include <SupportDefs.h>
#include <util/kernel_cpp.h>
#include <util/KernelUtilsOrder.h>
#include <util/Vector.h>
namespace VectorMapEntryStrategy {
template<typename Key, typename Value,
typename KeyOrder = KernelUtilsOrder::Ascending<Key> > class Pair;
template<typename Key, typename Value, typename GetKey,
typename KeyOrder = KernelUtilsOrder::Ascending<Key> >
class ImplicitKey;
}
template<typename Entry, typename Parent, typename EntryIterator>
class VectorMapIterator;
template<typename _Key, typename _Value, typename Entry, typename Parent>
class VectorMapEntry;
#define _VECTOR_MAP_TEMPLATE_LIST template<typename Key, typename Value, \
typename EntryStrategy>
#define _VECTOR_MAP_CLASS_NAME VectorMap<Key, Value, EntryStrategy>
#define _VECTOR_MAP_CLASS_TYPE typename VectorMap<Key, Value, EntryStrategy>
template<typename Key, typename Value,
typename EntryStrategy = VectorMapEntryStrategy::Pair<Key, Value> >
class VectorMap {
private:
typedef _VECTOR_MAP_CLASS_NAME Class;
typedef typename EntryStrategy::Entry _Entry;
typedef typename EntryStrategy::KeyReference KeyReference;
typedef Vector<_Entry> ElementVector;
public:
typedef VectorMapEntry<KeyReference, Value, _Entry, Class>
Entry;
typedef VectorMapEntry<KeyReference, const Value, const _Entry,
const Class> ConstEntry;
typedef VectorMapIterator<Entry, Class, typename ElementVector::Iterator>
Iterator;
typedef VectorMapIterator<ConstEntry, const Class, typename ElementVector::ConstIterator>
ConstIterator;
private:
static const size_t kDefaultChunkSize = 10;
static const size_t kMaximalChunkSize = 1024 * 1024;
public:
VectorMap(size_t chunkSize = kDefaultChunkSize);
~VectorMap();
status_t Insert(const Key &key, const Value &value);
status_t Put(const Key &key, const Value &value);
Value &Get(const Key &key);
const Value &Get(const Key &key) const;
int32 Remove(const Key &key);
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;
Iterator Find(const Key &key);
ConstIterator Find(const Key &key) const;
Iterator FindClose(const Key &key, bool less);
ConstIterator FindClose(const Key &key, bool less) const;
private:
int32 _FindInsertionIndex(const Key &key, bool &exists) const;
private:
friend class VectorMapEntry<KeyReference, Value, _Entry, Class>;
friend class VectorMapEntry<KeyReference, const Value, const _Entry,
const Class>;
ElementVector fElements;
EntryStrategy fEntryStrategy;
};
template<typename KeyReference, typename _Value, typename Entry,
typename Parent>
class VectorMapEntry {
private:
typedef VectorMapEntry<KeyReference, _Value, Entry, Parent> Class;
public:
VectorMapEntry()
: fParent(NULL), fEntry(NULL) {}
inline KeyReference Key() const
{
return fParent->fEntryStrategy.GetKey(*fEntry);
}
inline _Value &Value() const
{
return fParent->fEntryStrategy.GetValue(*fEntry);
}
inline const Class *operator->() const
{
return this;
}
public:
VectorMapEntry(Parent *parent, Entry *entry)
: fParent(parent), fEntry(entry) {}
private:
const Parent *fParent;
Entry *fEntry;
};
template<typename Entry, typename Parent, typename EntryIterator>
class VectorMapIterator {
private:
typedef VectorMapIterator<Entry, Parent, EntryIterator> Iterator;
public:
inline VectorMapIterator()
: fParent(NULL),
fIterator()
{
}
inline VectorMapIterator(
const Iterator &other)
: fParent(other.fParent),
fIterator(other.fIterator)
{
}
inline Iterator &operator++()
{
++fIterator;
return *this;
}
inline Iterator operator++(int)
{
Iterator it(*this);
++*this;
return it;
}
inline Iterator &operator--()
{
--fIterator;
return *this;
}
inline Iterator operator--(int)
{
Iterator it(*this);
--*this;
return it;
}
inline Iterator &operator=(const Iterator &other)
{
fParent = other.fParent;
fIterator = other.fIterator;
return *this;
}
inline bool operator==(const Iterator &other) const
{
return (fParent == other.fParent && fIterator == other.fIterator);
}
inline bool operator!=(const Iterator &other) const
{
return !(*this == other);
}
inline Entry operator*() const
{
return Entry(fParent, &*fIterator);
}
inline Entry operator->() const
{
return Entry(fParent, &*fIterator);
}
inline operator bool() const
{
return fIterator;
}
public:
inline VectorMapIterator(Parent *parent, const EntryIterator &iterator)
: fParent(parent),
fIterator(iterator)
{
}
inline EntryIterator &GetIterator()
{
return fIterator;
}
inline const EntryIterator &GetIterator() const
{
return fIterator;
}
protected:
Parent *fParent;
EntryIterator fIterator;
};
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_NAME::VectorMap(size_t chunkSize)
: fElements(chunkSize)
{
}
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_NAME::~VectorMap()
{
}
_VECTOR_MAP_TEMPLATE_LIST
status_t
_VECTOR_MAP_CLASS_NAME::Insert(const Key &key, const Value &value)
{
if (!fEntryStrategy.AreCompatible(key, value))
return B_BAD_VALUE;
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (exists) {
fElements[index] = fEntryStrategy.MakeEntry(key, value);
return B_OK;
}
return fElements.Insert(fEntryStrategy.MakeEntry(key, value), index);
}
_VECTOR_MAP_TEMPLATE_LIST
inline
status_t
_VECTOR_MAP_CLASS_NAME::Put(const Key &key, const Value &value)
{
return Insert(key, value);
}
_VECTOR_MAP_TEMPLATE_LIST
Value &
_VECTOR_MAP_CLASS_NAME::Get(const Key &key)
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (!exists)
return fEntryStrategy.GetValue(fElements[0]);
return fEntryStrategy.GetValue(fElements[index]);
}
_VECTOR_MAP_TEMPLATE_LIST
const Value &
_VECTOR_MAP_CLASS_NAME::Get(const Key &key) const
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (!exists)
return fEntryStrategy.GetValue(fElements[0]);
return fEntryStrategy.GetValue(fElements[index]);
}
_VECTOR_MAP_TEMPLATE_LIST
int32
_VECTOR_MAP_CLASS_NAME::Remove(const Key &key)
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (!exists)
return 0;
fElements.Erase(index);
return 1;
}
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_TYPE::Iterator
_VECTOR_MAP_CLASS_NAME::Erase(const Iterator &iterator)
{
return Iterator(this, fElements.Erase(iterator.GetIterator()));
}
_VECTOR_MAP_TEMPLATE_LIST
inline
int32
_VECTOR_MAP_CLASS_NAME::Count() const
{
return fElements.Count();
}
_VECTOR_MAP_TEMPLATE_LIST
inline
bool
_VECTOR_MAP_CLASS_NAME::IsEmpty() const
{
return fElements.IsEmpty();
}
_VECTOR_MAP_TEMPLATE_LIST
void
_VECTOR_MAP_CLASS_NAME::MakeEmpty()
{
fElements.MakeEmpty();
}
_VECTOR_MAP_TEMPLATE_LIST
inline
_VECTOR_MAP_CLASS_TYPE::Iterator
_VECTOR_MAP_CLASS_NAME::Begin()
{
return Iterator(this, fElements.Begin());
}
_VECTOR_MAP_TEMPLATE_LIST
inline
_VECTOR_MAP_CLASS_TYPE::ConstIterator
_VECTOR_MAP_CLASS_NAME::Begin() const
{
return ConstIterator(this, fElements.Begin());
}
_VECTOR_MAP_TEMPLATE_LIST
inline
_VECTOR_MAP_CLASS_TYPE::Iterator
_VECTOR_MAP_CLASS_NAME::End()
{
return Iterator(this, fElements.End());
}
_VECTOR_MAP_TEMPLATE_LIST
inline
_VECTOR_MAP_CLASS_TYPE::ConstIterator
_VECTOR_MAP_CLASS_NAME::End() const
{
return ConstIterator(this, fElements.End());
}
_VECTOR_MAP_TEMPLATE_LIST
inline
_VECTOR_MAP_CLASS_TYPE::Iterator
_VECTOR_MAP_CLASS_NAME::Null()
{
return Iterator(this, fElements.Null());
}
_VECTOR_MAP_TEMPLATE_LIST
inline
_VECTOR_MAP_CLASS_TYPE::ConstIterator
_VECTOR_MAP_CLASS_NAME::Null() const
{
return ConstIterator(this, fElements.Null());
}
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_TYPE::Iterator
_VECTOR_MAP_CLASS_NAME::Find(const Key &key)
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (!exists)
return End();
return Iterator(this, fElements.IteratorForIndex(index));
}
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_TYPE::ConstIterator
_VECTOR_MAP_CLASS_NAME::Find(const Key &key) const
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (!exists)
return End();
return ConstIterator(this, fElements.IteratorForIndex(index));
}
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_TYPE::Iterator
_VECTOR_MAP_CLASS_NAME::FindClose(const Key &key, bool less)
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (exists || !less)
return Iterator(this, fElements.IteratorForIndex(index));
if (index > 0)
return Iterator(this, fElements.IteratorForIndex(index - 1));
return End();
}
_VECTOR_MAP_TEMPLATE_LIST
_VECTOR_MAP_CLASS_TYPE::ConstIterator
_VECTOR_MAP_CLASS_NAME::FindClose(const Key &key, bool less) const
{
bool exists = false;
int32 index = _FindInsertionIndex(key, exists);
if (exists || !less)
return ConstIterator(this, fElements.IteratorForIndex(index));
if (index > 0)
return ConstIterator(this, fElements.IteratorForIndex(index - 1));
return End();
}
_VECTOR_MAP_TEMPLATE_LIST
int32
_VECTOR_MAP_CLASS_NAME::_FindInsertionIndex(const Key &key,
bool &exists) const
{
int32 lower = 0;
int32 upper = Count();
while (lower < upper) {
int32 mid = (lower + upper) / 2;
int cmp = fEntryStrategy.Compare(fEntryStrategy.GetKey(fElements[mid]),
key);
if (cmp < 0)
lower = mid + 1;
else
upper = mid;
}
exists = (lower < Count() && fEntryStrategy.Compare(key,
fEntryStrategy.GetKey(fElements[lower])) == 0);
return lower;
}
namespace VectorMapEntryStrategy {
template<typename Key, typename Value, typename KeyOrder>
class Pair {
public:
typedef const Key &KeyReference;
class Entry {
public:
Entry(const Key &key, const Value &value)
: key(key), value(value) {}
Key key;
Value value;
};
inline KeyReference GetKey(const Entry &entry) const
{
return entry.key;
}
inline const Value &GetValue(const Entry &entry) const
{
return entry.value;
}
inline Value &GetValue(Entry &entry) const
{
return entry.value;
}
inline Entry MakeEntry(const Key &key, const Value &value) const
{
return Entry(key, value);
}
inline bool AreCompatible(const Key &, const Value &) const
{
return true;
}
inline int Compare(const Key &a, const Key &b) const
{
return fCompare(a, b);
}
private:
KeyOrder fCompare;
};
template<typename Key, typename Value, typename _GetKey, typename KeyOrder>
class ImplicitKey {
public:
typedef Key KeyReference;
typedef Value Entry;
inline KeyReference GetKey(const Entry &entry) const
{
return fGetKey(entry);
}
inline const Value &GetValue(const Entry &entry) const
{
return entry;
}
inline Value &GetValue(Entry &entry) const
{
return entry;
}
inline Entry MakeEntry(const Key &, const Value &value) const
{
return value;
}
inline bool AreCompatible(const Key &key, const Value &value) const
{
return (fGetKey(value) == key);
}
inline int Compare(const Key &a, const Key &b) const
{
return fCompare(a, b);
}
private:
KeyOrder fCompare;
_GetKey fGetKey;
};
}
#endif