diff --git a/util/HashMap.hh b/util/HashMap.hh deleted file mode 100644 index 8585c591..00000000 --- a/util/HashMap.hh +++ /dev/null @@ -1,568 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2022, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#pragma once - -#include // size_t -#include "Hash.hh" - -namespace sta { - -template class HashMapBucket; - - -template -class PtrHash -{ -public: - size_t operator()(const OBJECT obj) const { return hashPtr(obj); } -}; - -template -class PtrEqual -{ -public: - bool operator()(const OBJECT obj1, - const OBJECT obj2) const - { return obj1 == obj2; } -}; - -template , class EQUAL = PtrEqual > -class HashMap -{ -public: - HashMap(); - explicit HashMap(size_t capacity, - bool auto_resize); - explicit HashMap(size_t capacity, - bool auto_resize, - HASH hash, - EQUAL equal); - ~HashMap(); - // Number of objects in the table. - size_t size() const { return size_; } - // Number of hash buckets. - size_t capacity() const { return capacity_; } - // Multi-threaded findKey is safe during resize. - void resize(size_t capacity); - void insert(KEY key, - VALUE value); - VALUE findKey(KEY key); - VALUE findKey(KEY key) const; - void findKey(KEY key, - VALUE &value, - bool &exists) const; - void findKey(KEY key, - KEY &map_key, - VALUE &value, - bool &exists) const; - bool hasKey(KEY key) const; - void eraseKey(KEY key); - bool empty() const; - void clear(); - void deleteContentsClear(); - void deleteArrayContentsClear(); - int longestBucketLength() const; - size_t longestBucketHash() const; - int bucketLength(size_t hash) const; - - void - deleteContents() - { - Iterator iter(this); - while (iter.hasNext()) - delete iter.next(); - } - - void - deleteArrayContents() - { - Iterator iter(this); - while (iter.hasNext()) - delete [] iter.next(); - } - - // Java style container itererator - // Map::Iterator iter(map); - // while (iter.hasNext()) { - // Value *v = iter.next(); - // } - class Iterator - { - public: - Iterator() : container_(NULL) {} - explicit Iterator(HashMap *container) - { init(container); } - explicit Iterator(HashMap &container) - { init(container); } - void init(HashMap *container) - { container_ = container; - hash_= 0; - next_ = NULL; - if (container_) - findNext(); - } - void init(HashMap &container) - { container_ = &container; - hash_= 0; - next_ = NULL; - if (container_) - findNext(); - } - bool hasNext() { return container_ && next_ != NULL; } - VALUE next() { - HashMapBucket *next = next_; - findNext(); - return next->value(); - } - void next(KEY &key, VALUE &value) { - HashMapBucket *next = next_; - findNext(); - key = next->key(); - value = next->value(); - } - HashMap *container() { return container_; } - - private: - void - findNext() - { - if (next_) - next_ = next_->next(); - while (next_ == NULL - && hash_ < container_->capacity()) - next_ = container_->table_[hash_++]; - } - HashMap *container_; - size_t hash_; - HashMapBucket *next_; - }; - - class ConstIterator - { - public: - ConstIterator() : container_(NULL) {} - explicit ConstIterator(const HashMap *container) - { init(container); } - explicit ConstIterator(const HashMap &container) - { init(container); } - void init(const HashMap *container) - { container_ = container; hash_= 0; next_ = NULL; findNext(); } - void init(HashMap &container) - { container_ = &container; hash_= 0; next_ = NULL; findNext(); } - bool hasNext() { return container_ && next_ != NULL; } - VALUE next() { - HashMapBucket *next = next_; - findNext(); - return next->value(); - } - void next(// Return values. - KEY &key, - VALUE &value) { - HashMapBucket *next = next_; - findNext(); - key = next->key(); - value = next->value(); - } - HashMap *container() { return container_; } - - private: - void - findNext() - { - if (next_) - next_ = next_->next(); - while (next_ == NULL - && hash_ < container_->capacity()) - next_ = container_->table_[hash_++]; - } - const HashMap *container_; - size_t hash_; - HashMapBucket *next_; - }; - -protected: - void initTable(); - static const int default_capacity = (2 << 6) - 1; - - // Table size. - size_t capacity_; - bool auto_resize_; - HASH hash_; - EQUAL equal_; - size_t size_; - HashMapBucket **table_; - HashMap *tmp_; -}; - -template -class HashMapBucket -{ -public: - HashMapBucket(KEY key, - VALUE value, - HashMapBucket *next); - KEY key() const { return key_; } - VALUE &value() { return value_; } - void set(KEY key, VALUE value) { key_ = key; value_ = value; } - HashMapBucket *next() const { return next_; } - void setNext(HashMapBucket *next) { next_ = next; } - -private: - KEY key_; - VALUE value_; - HashMapBucket *next_; -}; - -template -HashMapBucket::HashMapBucket(KEY key, - VALUE value, - HashMapBucket *next) : - key_(key), - value_(value), - next_(next) -{ -} - -//////////////////////////////////////////////////////////////// - -template -HashMap::HashMap() : - capacity_(default_capacity), - auto_resize_(true), - hash_(HASH()), - equal_(EQUAL()) -{ - initTable(); -} - -template -HashMap::HashMap(size_t capacity, - bool auto_resize) : - auto_resize_(auto_resize), - capacity_(capacity), - hash_(HASH()), - equal_(EQUAL()) -{ - initTable(); -} - -template -HashMap::HashMap(size_t capacity, - bool auto_resize, - HASH hash, - EQUAL equal) : - capacity_(capacity), - auto_resize_(auto_resize), - hash_(hash), - equal_(equal) -{ - initTable(); -} - -template -void -HashMap::initTable() -{ - size_ = 0; - tmp_ = NULL; - table_ = new HashMapBucket*[capacity_]; - for (size_t i = 0; i < capacity_; i++) - table_[i] = NULL; -} - -template -HashMap::~HashMap() -{ - for (size_t hash = 0; hash < capacity_; hash++) { - HashMapBucket *next; - for (HashMapBucket *bucket = table_[hash]; - bucket; - bucket = next) { - next = bucket->next(); - delete bucket; - } - } - delete [] table_; - delete tmp_; -} - -template -bool -HashMap::hasKey(KEY key) const -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - if (equal_(bucket->key(), key)) { - return true; - } - } - return false; -} - -template -VALUE -HashMap::findKey(KEY key) -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - KEY bucket_key = bucket->key(); - if (equal_(bucket_key, key)) { - return bucket->value(); - } - } - return NULL; -} - -template -VALUE -HashMap::findKey(KEY key) const -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - KEY bucket_key = bucket->key(); - if (equal_(bucket_key, key)) { - return bucket->value(); - } - } - return NULL; -} - -template -void -HashMap::findKey(KEY key, - VALUE &value, - bool &exists) const -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - KEY bucket_key = bucket->key(); - if (equal_(bucket_key, key)) { - value = bucket->value(); - exists = true; - return; - } - } - exists = false; -} - -template -void -HashMap::findKey(KEY key, - KEY &map_key, - VALUE &value, - bool &exists) const -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - KEY bucket_key = bucket->key(); - if (equal_(bucket_key, key)) { - map_key = bucket->key(); - value = bucket->value(); - exists = true; - return; - } - } - exists = false; -} - -template -void -HashMap::insert(KEY key, - VALUE value) -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - if (equal_(bucket->key(), key)) { - bucket->set(key, value); - return; - } - } - HashMapBucket *bucket = - new HashMapBucket(key, value, head); - table_[hash] = bucket; - size_++; - if (size_ > capacity_ - && auto_resize_) - resize(nextMersenne(capacity_)); -} - -template -void -HashMap::resize(size_t capacity) -{ - if (capacity != capacity_) { - if (size_ == 0) { - // Table is empty. - capacity_ = capacity; - delete [] table_; - delete tmp_; - initTable(); - } - else { - delete tmp_; - // Copy entries to tmp. - tmp_ = new HashMap(capacity, auto_resize_, - hash_, equal_); - for (size_t hash = 0; hash < capacity_; hash++) { - for (HashMapBucket *bucket = table_[hash]; - bucket; - bucket = bucket->next()) - tmp_->insert(bucket->key(), bucket->value()); - } - - size_t prev_capacity = capacity_; - HashMapBucket **prev_table = table_; - - // Switch over. - table_ = tmp_->table_; - capacity_ = capacity; - - tmp_->capacity_ = prev_capacity; - tmp_->table_ = prev_table; - } - } -} - -template -void -HashMap::eraseKey(KEY key) -{ - size_t hash = hash_(key) % capacity_; - HashMapBucket *head = table_[hash]; - HashMapBucket *prev = NULL; - for (HashMapBucket *bucket = head; bucket; bucket = bucket->next()) { - if (equal_(bucket->key(), key)) { - if (prev) - prev->setNext(bucket->next()); - else - table_[hash] = bucket->next(); - delete bucket; - size_--; - break; - } - prev = bucket; - } -} - -template -void -HashMap::deleteContentsClear() -{ - if (size_ > 0) { - for (size_t hash = 0; hash < capacity_; hash++) { - HashMapBucket *next; - for (HashMapBucket *bucket = table_[hash]; - bucket; - bucket = next) { - delete bucket->value(); - next = bucket->next(); - delete bucket; - } - table_[hash] = NULL; - } - size_ = 0; - } -} - -template -void -HashMap::deleteArrayContentsClear() -{ - if (size_ > 0) { - for (size_t hash = 0; hash < capacity_; hash++) { - HashMapBucket *next; - for (HashMapBucket *bucket = table_[hash]; - bucket; - bucket = next) { - delete [] bucket->value(); - next = bucket->next(); - delete bucket; - } - table_[hash] = NULL; - } - size_ = 0; - } -} - -template -void -HashMap::clear() -{ - if (size_ > 0) { - for (size_t hash = 0; hash < capacity_; hash++) { - HashMapBucket *next; - for (HashMapBucket *bucket = table_[hash]; - bucket; - bucket = next) { - next = bucket->next(); - delete bucket; - } - table_[hash] = NULL; - } - size_ = 0; - } -} - -template -bool -HashMap::empty() const -{ - return size_ == 0; -} - -template -int -HashMap::longestBucketLength() const -{ - return bucketLength(longestBucketHash()); -} - -template -size_t -HashMap::longestBucketHash() const -{ - int longest = 0; - size_t longest_hash = 0; - for (size_t hash = 0; hash < capacity_; hash++) { - int length = bucketLength(hash); - if (length > longest) { - longest = length; - longest_hash = hash; - } - } - return longest_hash; -} - -template -int -HashMap::bucketLength(size_t hash) const -{ - int length = 0; - for (HashMapBucket *bucket = table_[hash]; - bucket; - bucket = bucket->next()) - length++; - return length; -} - -} // namespace