153 lines
4.0 KiB
C++
153 lines
4.0 KiB
C++
/* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
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, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
|
|
#ifndef NDB_HASHMAP_HPP
|
|
#define NDB_HASHMAP_HPP
|
|
|
|
#include <ndb_global.h>
|
|
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
|
|
#include "template_utils.h"
|
|
|
|
/*
|
|
Default implementation for extracting key_ptr and
|
|
key_length from type K. Used when the entire type
|
|
K should be used as key.
|
|
|
|
NOTE! Optimized inside HashMap so that it's never
|
|
actually called
|
|
*/
|
|
|
|
inline const void* HashMap__get_key(const void* key_ptr, size_t* key_length)
|
|
{
|
|
(void)key_length;
|
|
return key_ptr;
|
|
}
|
|
|
|
|
|
/*
|
|
Hash container for storing key value pairs
|
|
*/
|
|
|
|
template<typename K, typename T,
|
|
const void* G(const void*, size_t*) = HashMap__get_key >
|
|
class HashMap {
|
|
static inline std::string get_key_string(const K& key)
|
|
{
|
|
if (G == HashMap__get_key)
|
|
return std::string(pointer_cast<const char *>(&key), sizeof(K));
|
|
|
|
size_t key_length = sizeof(K);
|
|
const char* key_ptr = pointer_cast<const char *>(G(&key, &key_length));
|
|
return std::string(key_ptr, key_length);
|
|
}
|
|
|
|
struct HashMap__hash {
|
|
size_t operator() (const K& key) const {
|
|
return hasher(get_key_string(key));
|
|
}
|
|
std::hash<std::string> hasher;
|
|
};
|
|
|
|
struct HashMap__equal_to {
|
|
bool operator() (const K& key1, const K& key2) const {
|
|
return get_key_string(key1) == get_key_string(key2);
|
|
}
|
|
};
|
|
|
|
typedef
|
|
std::unordered_map<K, std::unique_ptr<T>,
|
|
HashMap__hash, HashMap__equal_to>
|
|
InternalHash;
|
|
|
|
InternalHash m_hash;
|
|
|
|
public:
|
|
HashMap(ulong initial_size = 1024)
|
|
: m_hash(initial_size, HashMap__hash(), HashMap__equal_to())
|
|
{
|
|
}
|
|
|
|
bool insert(const K& k, const T& v, bool replace = false) {
|
|
// Note: This can be written simpler with try_emplace once we get to C++17.
|
|
std::unique_ptr<T> v_ptr(new T(v));
|
|
if (replace) {
|
|
auto it = m_hash.find(k);
|
|
if (it != m_hash.end()) {
|
|
it->second = std::move(v_ptr);
|
|
return true;
|
|
}
|
|
// Did not already exist, fall through to below.
|
|
}
|
|
return m_hash.emplace(k, std::move(v_ptr)).second;
|
|
}
|
|
|
|
bool search(const K& k, T& v) const {
|
|
const auto it = m_hash.find(k);
|
|
if (it == m_hash.end())
|
|
return false;
|
|
v = *it->second.get();
|
|
return true;
|
|
}
|
|
|
|
bool search(const K& k, const T** v) const {
|
|
auto it = m_hash.find(k);
|
|
if (it == m_hash.end())
|
|
return false;
|
|
|
|
*v = it->second.get();
|
|
return true;
|
|
}
|
|
|
|
bool search(const K& k, T** v) {
|
|
auto it = m_hash.find(k);
|
|
if (it == m_hash.end())
|
|
return false;
|
|
|
|
*v = it->second.get();
|
|
return true;
|
|
}
|
|
|
|
bool remove(const K& k) {
|
|
return m_hash.erase(k) != 0;
|
|
}
|
|
|
|
size_t entries(void) const {
|
|
return m_hash.size();
|
|
}
|
|
|
|
// Forwarders to the underlying map.
|
|
|
|
typename InternalHash::iterator begin() { return m_hash.begin(); }
|
|
typename InternalHash::iterator end() { return m_hash.end(); }
|
|
typename InternalHash::iterator
|
|
erase(typename InternalHash::const_iterator pos) {
|
|
return m_hash.erase(pos);
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|