#ifndef ANDOID_RENDERSCRIPT_MAP_H
#define ANDOID_RENDERSCRIPT_MAP_H
#include <stddef.h>
namespace android {
namespace renderscript {
template <class T1, class T2>
class Pair {
public:
Pair() {}
Pair(T1 f1, T2 f2) : first(f1), second(f2) {}
T1 first;
T2 second;
};
template <class T1, class T2>
Pair<T1, T2> make_pair(T1 first, T2 second) {
return Pair<T1, T2>(first, second);
}
#define MAP_LOG_NUM_BUCKET 8
#define MAP_NUM_BUCKET (1 << MAP_LOG_NUM_BUCKET)
#define MAP_NUM_BUCKET_MASK (MAP_NUM_BUCKET - 1)
template <class KeyType, class ValueType>
class Map {
private:
typedef Pair<KeyType, ValueType> MapEntry;
struct LinkNode {
MapEntry entry;
LinkNode* next;
};
public:
Map() : endIterator(MAP_NUM_BUCKET, nullptr, this) {
for (size_t i = 0; i < MAP_NUM_BUCKET; i++) { bucket[i] = nullptr; }
}
~Map() {
for (size_t i = 0; i < MAP_NUM_BUCKET; i++) {
LinkNode* p = bucket[i];
LinkNode* next;
while (p != nullptr) {
next = p->next;
delete p;
p = next;
}
}
}
ValueType& operator[](const KeyType& key) {
const size_t index = hash(key) & MAP_NUM_BUCKET_MASK;
LinkNode* node = bucket[index];
LinkNode* prev = nullptr;
while (node != nullptr) {
if (node->entry.first == key) {
return node->entry.second;
}
prev = node;
node = node->next;
}
node = new LinkNode();
node->entry.first = key;
node->next = nullptr;
if (prev == nullptr) {
bucket[index] = node;
} else {
prev->next = node;
}
return node->entry.second;
}
class iterator {
friend class Map;
public:
iterator& operator++() {
LinkNode* next;
next = node->next;
if (next != nullptr) {
node = next;
return *this;
}
while (++bucket_index < MAP_NUM_BUCKET) {
next = map->bucket[bucket_index];
if (next != nullptr) {
node = next;
return *this;
}
}
node = nullptr;
return *this;
}
bool operator==(const iterator& other) const {
return node == other.node && bucket_index == other.bucket_index &&
map == other.map;
}
bool operator!=(const iterator& other) const {
return node != other.node || bucket_index != other.bucket_index ||
map != other.map;
}
const MapEntry& operator*() const {
return node->entry;
}
protected:
iterator(size_t index, LinkNode* n, const Map* m) : bucket_index(index), node(n), map(m) {}
private:
size_t bucket_index;
LinkNode* node;
const Map* map;
};
iterator begin() const {
for (size_t i = 0; i < MAP_NUM_BUCKET; i++) {
LinkNode* node = bucket[i];
if (node != nullptr) {
return iterator(i, node, this);
}
}
return end();
}
const iterator& end() const { return endIterator; }
iterator begin() { return ((const Map*)this)->begin(); }
const iterator& end() { return endIterator; }
iterator find(const KeyType& key) const {
const size_t index = hash(key) & MAP_NUM_BUCKET_MASK;
LinkNode* node = bucket[index];
while (node != nullptr) {
if (node->entry.first == key) {
return iterator(index, node, this);
}
node = node->next;
}
return end();
}
private:
size_t hash(const KeyType& key) const { return ((size_t)key) >> 4; }
LinkNode* bucket[MAP_NUM_BUCKET];
const iterator endIterator;
};
} // namespace renderscript
} // namespace android
#endif // ANDOID_RENDERSCRIPT_MAP_H