You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.0 KiB
168 lines
4.0 KiB
#ifndef ANDROID_RENDERSCRIPT_MAP_H
|
|
#define ANDROID_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 // ANDROID_RENDERSCRIPT_MAP_H
|