|
@@ -35,17 +35,29 @@ class HashMap final {
|
|
return reinterpret_cast<const V*> (values)[index];
|
|
return reinterpret_cast<const V*> (values)[index];
|
|
}
|
|
}
|
|
|
|
|
|
- int searchIndex(const K& key) const {
|
|
|
|
|
|
+ enum SearchResult {
|
|
|
|
+ FREE_INDEX_FOUND, KEY_FOUND, NOTHING_FOUND
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ struct Search {
|
|
|
|
+ int index;
|
|
|
|
+ SearchResult result;
|
|
|
|
+
|
|
|
|
+ Search(int index, SearchResult result) : index(index), result(result) {
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Search searchIndex(const K& key) const {
|
|
int base = hash(key);
|
|
int base = hash(key);
|
|
for(int i = 0; i < CAPACITY; i++) {
|
|
for(int i = 0; i < CAPACITY; i++) {
|
|
int h = (base + i) & MASK;
|
|
int h = (base + i) & MASK;
|
|
if(!used[h]) {
|
|
if(!used[h]) {
|
|
- return -h;
|
|
|
|
|
|
+ return Search(h, FREE_INDEX_FOUND);
|
|
} else if(getKey(h) == key) {
|
|
} else if(getKey(h) == key) {
|
|
- return h;
|
|
|
|
|
|
+ return Search(h, KEY_FOUND);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return -CAPACITY;
|
|
|
|
|
|
+ return Search(-1, NOTHING_FOUND);
|
|
}
|
|
}
|
|
|
|
|
|
void copy(const HashMap& other) {
|
|
void copy(const HashMap& other) {
|
|
@@ -57,7 +69,7 @@ class HashMap final {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
void move(HashMap& other) {
|
|
void move(HashMap& other) {
|
|
for(int i = 0; i < other.CAPACITY; i++) {
|
|
for(int i = 0; i < other.CAPACITY; i++) {
|
|
if(other.used[i]) {
|
|
if(other.used[i]) {
|
|
@@ -87,53 +99,63 @@ public:
|
|
copy(other);
|
|
copy(other);
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
HashMap(HashMap&& other) : used(false) {
|
|
HashMap(HashMap&& other) : used(false) {
|
|
move(other);
|
|
move(other);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
HashMap& operator=(HashMap&& other) {
|
|
HashMap& operator=(HashMap&& other) {
|
|
clear();
|
|
clear();
|
|
move(other);
|
|
move(other);
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
+ bool tryEmplace(const K& key, Args&&... args) {
|
|
|
|
+ Search s = searchIndex(key);
|
|
|
|
+ if(s.result == FREE_INDEX_FOUND) {
|
|
|
|
+ used[s.index] = true;
|
|
|
|
+ new (reinterpret_cast<K*> (keys) + s.index) K(key);
|
|
|
|
+ new (reinterpret_cast<V*> (values) + s.index) V(args...);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
void add(const K& key, const V& value) {
|
|
void add(const K& key, const V& value) {
|
|
- int index = searchIndex(key);
|
|
|
|
- if(index >= 0) {
|
|
|
|
- getValue(index) = value;
|
|
|
|
- } else if(index > -CAPACITY) {
|
|
|
|
- index = -index;
|
|
|
|
- used[index] = true;
|
|
|
|
- new (reinterpret_cast<K*> (keys) + index) K(key);
|
|
|
|
- new (reinterpret_cast<V*> (values) + index) V(value);
|
|
|
|
|
|
+ Search s = searchIndex(key);
|
|
|
|
+ if(s.result == KEY_FOUND) {
|
|
|
|
+ getValue(s.index) = value;
|
|
|
|
+ } else if(s.result == FREE_INDEX_FOUND) {
|
|
|
|
+ used[s.index] = true;
|
|
|
|
+ new (reinterpret_cast<K*> (keys) + s.index) K(key);
|
|
|
|
+ new (reinterpret_cast<V*> (values) + s.index) V(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void add(const K& key, const V&& value) {
|
|
void add(const K& key, const V&& value) {
|
|
- int index = searchIndex(key);
|
|
|
|
- if(index >= 0) {
|
|
|
|
- getValue(index) = std::move(value);
|
|
|
|
- } else if(index > -CAPACITY) {
|
|
|
|
- index = -index;
|
|
|
|
- used[index] = true;
|
|
|
|
- new (reinterpret_cast<K*> (keys) + index) K(key);
|
|
|
|
- new (reinterpret_cast<V*> (values) + index) V(std::move(value));
|
|
|
|
|
|
+ Search s = searchIndex(key);
|
|
|
|
+ if(s.result == KEY_FOUND) {
|
|
|
|
+ getValue(s.index) = std::move(value);
|
|
|
|
+ } else if(s.result == FREE_INDEX_FOUND) {
|
|
|
|
+ used[s.index] = true;
|
|
|
|
+ new (reinterpret_cast<K*> (keys) + s.index) K(key);
|
|
|
|
+ new (reinterpret_cast<V*> (values) + s.index) V(std::move(value));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const V& search(const K& key, const V& notFound) const {
|
|
const V& search(const K& key, const V& notFound) const {
|
|
- int index = searchIndex(key);
|
|
|
|
- return index < 0 ? notFound : getValue(index);
|
|
|
|
|
|
+ Search s = searchIndex(key);
|
|
|
|
+ return s.result == KEY_FOUND ? getValue(s.index) : notFound;
|
|
}
|
|
}
|
|
|
|
|
|
V& search(const K& key, V& notFound) {
|
|
V& search(const K& key, V& notFound) {
|
|
- int index = searchIndex(key);
|
|
|
|
- return index < 0 ? notFound : getValue(index);
|
|
|
|
|
|
+ Search s = searchIndex(key);
|
|
|
|
+ return s.result == KEY_FOUND ? getValue(s.index) : notFound;
|
|
}
|
|
}
|
|
|
|
|
|
bool contains(const K& key) const {
|
|
bool contains(const K& key) const {
|
|
- return searchIndex(key) >= 0;
|
|
|
|
|
|
+ return searchIndex(key).result == KEY_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
void clear() {
|
|
void clear() {
|