1 #ifndef SQL_HSET_INCLUDED
2 #define SQL_HSET_INCLUDED
3 /* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; version 2 of the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA */
17 
18 #include "hash.h"
19 
20 
21 /**
22   A type-safe wrapper around mysys HASH.
23 */
24 
25 template <typename T>
26 class Hash_set
27 {
28 public:
29   enum { START_SIZE= 8 };
30   /**
31     Constructs an empty hash. Does not allocate memory, it is done upon
32     the first insert. Thus does not cause or return errors.
33   */
34   Hash_set(uchar *(*K)(const T *, size_t *, my_bool),
35            CHARSET_INFO *cs= &my_charset_bin)
36   {
37     my_hash_clear(&m_hash);
38     m_hash.get_key= (my_hash_get_key)K;
39     m_hash.charset= cs;
40   }
41   /**
42     Destroy the hash by freeing the buckets table. Does
43     not call destructors for the elements.
44   */
~Hash_set()45   ~Hash_set()
46   {
47     my_hash_free(&m_hash);
48   }
49   /**
50     Insert a single value into a hash. Does not tell whether
51     the value was inserted -- if an identical value existed,
52     it is not replaced.
53 
54     @retval TRUE  Out of memory.
55     @retval FALSE OK. The value either was inserted or existed
56                   in the hash.
57   */
insert(T * value)58   bool insert(T *value)
59   {
60     my_hash_init_opt(&m_hash, m_hash.charset, START_SIZE, 0, 0,
61                      m_hash.get_key, 0, MYF(0));
62     size_t key_len;
63     uchar *v= reinterpret_cast<uchar *>(value);
64     const uchar *key= m_hash.get_key(v, &key_len, FALSE);
65     if (find(key, key_len) == NULL)
66       return my_hash_insert(&m_hash, v);
67     return FALSE;
68   }
remove(T * value)69   bool remove(T *value)
70   {
71     return my_hash_delete(&m_hash, reinterpret_cast<uchar*>(value));
72   }
find(const void * key,size_t klen)73   T *find(const void *key, size_t klen) const
74   {
75     return (T*)my_hash_search(&m_hash, reinterpret_cast<const uchar *>(key), klen);
76   }
77   /** Is this hash set empty? */
is_empty()78   bool is_empty() const { return m_hash.records == 0; }
79   /** Returns the number of unique elements. */
size()80   size_t size() const { return static_cast<size_t>(m_hash.records); }
at(size_t i)81   const T* at(size_t i) const
82   {
83     return reinterpret_cast<T*>(my_hash_element(const_cast<HASH*>(&m_hash), i));
84   }
85   /** An iterator over hash elements. Is not insert-stable. */
86   class Iterator
87   {
88   public:
Iterator(Hash_set & hash_set)89     Iterator(Hash_set &hash_set)
90       : m_hash(&hash_set.m_hash),
91         m_idx(0)
92     {}
93     /**
94       Return the current element and reposition the iterator to the next
95       element.
96     */
97     inline T *operator++(int)
98     {
99       if (m_idx < m_hash->records)
100         return reinterpret_cast<T*>(my_hash_element(m_hash, m_idx++));
101       return NULL;
102     }
rewind()103     void rewind() { m_idx= 0; }
104   private:
105     HASH *m_hash;
106     uint m_idx;
107   };
108 private:
109   HASH m_hash;
110 };
111 
112 #endif // SQL_HSET_INCLUDED
113