/* 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 #include #include #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 class HashMap { static inline std::string get_key_string(const K& key) { if (G == HashMap__get_key) return std::string(pointer_cast(&key), sizeof(K)); size_t key_length = sizeof(K); const char* key_ptr = pointer_cast(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 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, 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 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