MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HashMap.hpp
1 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 
17 #ifndef NDB_HASHMAP_HPP
18 #define NDB_HASHMAP_HPP
19 
20 #include <ndb_global.h>
21 #include <my_sys.h>
22 #include <hash.h>
23 
24 
25 /*
26  Default implementation for extracting key_ptr and
27  key_length from type K. Used when the entire type
28  K should be used as key.
29 
30  NOTE! Optimized inside HashMap so that it's never
31  actually called
32 */
33 
34 inline const void* HashMap__get_key(const void* key_ptr, size_t* key_length)
35 {
36  key_length = key_length;
37  return key_ptr;
38 }
39 
40 
41 /*
42  Hash container for storing key value pairs
43 */
44 
45 template<typename K, typename T,
46  const void* G(const void*, size_t*) = HashMap__get_key >
47 class HashMap {
48  class Entry {
49  public:
50  K m_key;
51  T m_value;
52  Entry(const K& k, const T& v) : m_key(k), m_value(v) {};
53  };
54 
55  HASH m_hash;
56 
57  static void free_element(void * ptr) {
58  Entry* entry = (Entry*)ptr;
59  delete entry;
60  }
61 
62  /*
63  Callback function which is installed into 'my_hash'
64  and thus called once for each key in the hash that need to
65  be compared. Should return a pointer to where the key
66  start and the key's length.
67  */
68  static uchar* _get_key(const uchar* ptr,
69  size_t* key_length, my_bool first) {
70  const Entry * entry = reinterpret_cast<const Entry*>(ptr);
71  const void* key_ptr = G(&entry->m_key, key_length);
72  return (uchar*)key_ptr;
73  }
74 
75  const void* get_key_ptr(const K* key, size_t *key_length) const {
76  if (G == HashMap__get_key)
77  return key;
78  return _get_key((const uchar*)key, key_length, false);
79  }
80 
81 public:
82  HashMap(ulong initial_size = 1024, uint grow_size = 256) {
83 
84  assert(my_init_done);
85 
86  if (my_hash_init2(&m_hash,
87  grow_size,
88  &my_charset_bin, // charset
89  initial_size, // default_array_elements
90  0, // key_offset
91  sizeof(K), // key_length
92  G == HashMap__get_key ? NULL : _get_key, // get_key,
93  free_element, // free_element
94  HASH_UNIQUE // flags
95  ))
96  abort();
97  }
98 
99  ~HashMap() {
100  my_hash_free(&m_hash);
101  }
102 
103  bool insert(const K& k, const T& v, bool replace = false) {
104  Entry* entry = new Entry(k, v);
105  if (my_hash_insert(&m_hash, (const uchar*)entry) != 0) {
106  // An entry already existed
107 
108  delete entry;
109 
110  T* p;
111  if (replace && search(k, &p)) {
112  *p = v;
113  return true;
114  }
115  return false;
116  }
117  return true;
118  }
119 
120  bool search(const K& k, T& v) const {
121  T* p;
122  if (!search(k, &p))
123  return false;
124  v = *p;
125  return true;
126  }
127 
128  bool search(const K& k, T** v) const {
129  size_t key_length = sizeof(K);
130  const void *key = get_key_ptr(&k, &key_length);
131  Entry* entry= (Entry*)my_hash_search(&m_hash,
132  (const uchar*)key, key_length);
133  if (entry == NULL)
134  return false;
135 
136  *v = &(entry->m_value);
137  return true;
138  }
139 
140  bool remove(const K& k) {
141  size_t key_length = sizeof(K);
142  const void *key = get_key_ptr(&k, &key_length);
143  Entry* entry= (Entry*)my_hash_search(&m_hash,
144  (const uchar*)key, key_length);
145  if (entry == NULL)
146  return false;
147 
148  if (my_hash_delete(&m_hash, (uchar*)entry))
149  return false;
150  return true;
151  }
152 
153  bool remove(size_t i) {
154  Entry* entry = (Entry*)my_hash_element(&m_hash, (ulong)i);
155  if (entry == NULL)
156  return false;
157 
158  if (my_hash_delete(&m_hash, (uchar*)entry))
159  return false;
160  return true;
161  }
162 
163  size_t entries(void) const {
164  return m_hash.records;
165  }
166 
167  T* value(size_t i) const {
168  Entry* entry = (Entry*)my_hash_element((HASH*)&m_hash, (ulong)i);
169  if (entry == NULL)
170  return NULL;
171  return &(entry->m_value);
172  }
173 
174 };
175 
176 #endif