#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