1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 *   Copyright (C) 1997-2014, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 ******************************************************************************
8 *   Date        Name        Description
9 *   03/28/00    aliu        Creation.
10 ******************************************************************************
11 */
12 
13 #ifndef HASH_H
14 #define HASH_H
15 
16 #include "unicode/unistr.h"
17 #include "unicode/uobject.h"
18 #include "cmemory.h"
19 #include "uhash.h"
20 
21 U_NAMESPACE_BEGIN
22 
23 /**
24  * Hashtable is a thin C++ wrapper around UHashtable, a general-purpose void*
25  * hashtable implemented in C.  Hashtable is designed to be idiomatic and
26  * easy-to-use in C++.
27  *
28  * Hashtable is an INTERNAL CLASS.
29  */
30 class U_COMMON_API Hashtable : public UMemory {
31     UHashtable* hash;
32     UHashtable hashObj;
33 
34     inline void init(UHashFunction *keyHash, UKeyComparator *keyComp, UValueComparator *valueComp, UErrorCode& status);
35 
36     inline void initSize(UHashFunction *keyHash, UKeyComparator *keyComp, UValueComparator *valueComp, int32_t size, UErrorCode& status);
37 
38 public:
39     /**
40      * Construct a hashtable
41      * @param ignoreKeyCase If true, keys are case insensitive.
42      * @param status Error code
43     */
44     inline Hashtable(UBool ignoreKeyCase, UErrorCode& status);
45 
46     /**
47      * Construct a hashtable
48      * @param ignoreKeyCase If true, keys are case insensitive.
49      * @param size initial size allocation
50      * @param status Error code
51     */
52     inline Hashtable(UBool ignoreKeyCase, int32_t size, UErrorCode& status);
53 
54     /**
55      * Construct a hashtable
56      * @param keyComp Comparator for comparing the keys
57      * @param valueComp Comparator for comparing the values
58      * @param status Error code
59     */
60     inline Hashtable(UKeyComparator *keyComp, UValueComparator *valueComp, UErrorCode& status);
61 
62     /**
63      * Construct a hashtable
64      * @param status Error code
65     */
66     inline Hashtable(UErrorCode& status);
67 
68     /**
69      * Construct a hashtable, _disregarding any error_.  Use this constructor
70      * with caution.
71      */
72     inline Hashtable();
73 
74     /**
75      * Non-virtual destructor; make this virtual if Hashtable is subclassed
76      * in the future.
77      */
78     inline ~Hashtable();
79 
80     inline UObjectDeleter *setValueDeleter(UObjectDeleter *fn);
81 
82     inline int32_t count() const;
83 
84     inline void* put(const UnicodeString& key, void* value, UErrorCode& status);
85 
86     inline int32_t puti(const UnicodeString& key, int32_t value, UErrorCode& status);
87 
88     inline int32_t putiAllowZero(const UnicodeString& key, int32_t value, UErrorCode& status);
89 
90     inline void* get(const UnicodeString& key) const;
91 
92     inline int32_t geti(const UnicodeString& key) const;
93 
94     inline int32_t getiAndFound(const UnicodeString& key, UBool &found) const;
95 
96     inline void* remove(const UnicodeString& key);
97 
98     inline int32_t removei(const UnicodeString& key);
99 
100     inline void removeAll(void);
101 
102     inline UBool containsKey(const UnicodeString& key) const;
103 
104     inline const UHashElement* find(const UnicodeString& key) const;
105 
106     /**
107      * @param pos - must be UHASH_FIRST on first call, and untouched afterwards.
108      * @see uhash_nextElement
109      */
110     inline const UHashElement* nextElement(int32_t& pos) const;
111 
112     inline UKeyComparator* setKeyComparator(UKeyComparator*keyComp);
113 
114     inline UValueComparator* setValueComparator(UValueComparator* valueComp);
115 
116     inline UBool equals(const Hashtable& that) const;
117 private:
118     Hashtable(const Hashtable &other); // forbid copying of this class
119     Hashtable &operator=(const Hashtable &other); // forbid copying of this class
120 };
121 
122 /*********************************************************************
123  * Implementation
124  ********************************************************************/
125 
init(UHashFunction * keyHash,UKeyComparator * keyComp,UValueComparator * valueComp,UErrorCode & status)126 inline void Hashtable::init(UHashFunction *keyHash, UKeyComparator *keyComp,
127                             UValueComparator *valueComp, UErrorCode& status) {
128     if (U_FAILURE(status)) {
129         return;
130     }
131     uhash_init(&hashObj, keyHash, keyComp, valueComp, &status);
132     if (U_SUCCESS(status)) {
133         hash = &hashObj;
134         uhash_setKeyDeleter(hash, uprv_deleteUObject);
135     }
136 }
137 
initSize(UHashFunction * keyHash,UKeyComparator * keyComp,UValueComparator * valueComp,int32_t size,UErrorCode & status)138 inline void Hashtable::initSize(UHashFunction *keyHash, UKeyComparator *keyComp,
139                                 UValueComparator *valueComp, int32_t size, UErrorCode& status) {
140     if (U_FAILURE(status)) {
141         return;
142     }
143     uhash_initSize(&hashObj, keyHash, keyComp, valueComp, size, &status);
144     if (U_SUCCESS(status)) {
145         hash = &hashObj;
146         uhash_setKeyDeleter(hash, uprv_deleteUObject);
147     }
148 }
149 
Hashtable(UKeyComparator * keyComp,UValueComparator * valueComp,UErrorCode & status)150 inline Hashtable::Hashtable(UKeyComparator *keyComp, UValueComparator *valueComp,
151                  UErrorCode& status) : hash(0) {
152     init( uhash_hashUnicodeString, keyComp, valueComp, status);
153 }
154 
Hashtable(UBool ignoreKeyCase,UErrorCode & status)155 inline Hashtable::Hashtable(UBool ignoreKeyCase, UErrorCode& status)
156  : hash(0)
157 {
158     init(ignoreKeyCase ? uhash_hashCaselessUnicodeString
159                         : uhash_hashUnicodeString,
160             ignoreKeyCase ? uhash_compareCaselessUnicodeString
161                         : uhash_compareUnicodeString,
162             NULL,
163             status);
164 }
165 
Hashtable(UBool ignoreKeyCase,int32_t size,UErrorCode & status)166 inline Hashtable::Hashtable(UBool ignoreKeyCase, int32_t size, UErrorCode& status)
167  : hash(0)
168 {
169     initSize(ignoreKeyCase ? uhash_hashCaselessUnicodeString
170                         : uhash_hashUnicodeString,
171             ignoreKeyCase ? uhash_compareCaselessUnicodeString
172                         : uhash_compareUnicodeString,
173             NULL, size,
174             status);
175 }
176 
Hashtable(UErrorCode & status)177 inline Hashtable::Hashtable(UErrorCode& status)
178  : hash(0)
179 {
180     init(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, status);
181 }
182 
Hashtable()183 inline Hashtable::Hashtable()
184  : hash(0)
185 {
186     UErrorCode status = U_ZERO_ERROR;
187     init(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, status);
188 }
189 
~Hashtable()190 inline Hashtable::~Hashtable() {
191     if (hash != NULL) {
192         uhash_close(hash);
193     }
194 }
195 
setValueDeleter(UObjectDeleter * fn)196 inline UObjectDeleter *Hashtable::setValueDeleter(UObjectDeleter *fn) {
197     return uhash_setValueDeleter(hash, fn);
198 }
199 
count()200 inline int32_t Hashtable::count() const {
201     return uhash_count(hash);
202 }
203 
put(const UnicodeString & key,void * value,UErrorCode & status)204 inline void* Hashtable::put(const UnicodeString& key, void* value, UErrorCode& status) {
205     return uhash_put(hash, new UnicodeString(key), value, &status);
206 }
207 
puti(const UnicodeString & key,int32_t value,UErrorCode & status)208 inline int32_t Hashtable::puti(const UnicodeString& key, int32_t value, UErrorCode& status) {
209     return uhash_puti(hash, new UnicodeString(key), value, &status);
210 }
211 
putiAllowZero(const UnicodeString & key,int32_t value,UErrorCode & status)212 inline int32_t Hashtable::putiAllowZero(const UnicodeString& key, int32_t value,
213                                         UErrorCode& status) {
214     return uhash_putiAllowZero(hash, new UnicodeString(key), value, &status);
215 }
216 
get(const UnicodeString & key)217 inline void* Hashtable::get(const UnicodeString& key) const {
218     return uhash_get(hash, &key);
219 }
220 
geti(const UnicodeString & key)221 inline int32_t Hashtable::geti(const UnicodeString& key) const {
222     return uhash_geti(hash, &key);
223 }
224 
getiAndFound(const UnicodeString & key,UBool & found)225 inline int32_t Hashtable::getiAndFound(const UnicodeString& key, UBool &found) const {
226     return uhash_getiAndFound(hash, &key, &found);
227 }
228 
remove(const UnicodeString & key)229 inline void* Hashtable::remove(const UnicodeString& key) {
230     return uhash_remove(hash, &key);
231 }
232 
removei(const UnicodeString & key)233 inline int32_t Hashtable::removei(const UnicodeString& key) {
234     return uhash_removei(hash, &key);
235 }
236 
containsKey(const UnicodeString & key)237 inline UBool Hashtable::containsKey(const UnicodeString& key) const {
238     return uhash_containsKey(hash, &key);
239 }
240 
find(const UnicodeString & key)241 inline const UHashElement* Hashtable::find(const UnicodeString& key) const {
242     return uhash_find(hash, &key);
243 }
244 
nextElement(int32_t & pos)245 inline const UHashElement* Hashtable::nextElement(int32_t& pos) const {
246     return uhash_nextElement(hash, &pos);
247 }
248 
removeAll(void)249 inline void Hashtable::removeAll(void) {
250     uhash_removeAll(hash);
251 }
252 
setKeyComparator(UKeyComparator * keyComp)253 inline UKeyComparator* Hashtable::setKeyComparator(UKeyComparator*keyComp){
254     return uhash_setKeyComparator(hash, keyComp);
255 }
256 
setValueComparator(UValueComparator * valueComp)257 inline UValueComparator* Hashtable::setValueComparator(UValueComparator* valueComp){
258     return uhash_setValueComparator(hash, valueComp);
259 }
260 
equals(const Hashtable & that)261 inline UBool Hashtable::equals(const Hashtable& that)const{
262    return uhash_equals(hash, that.hash);
263 }
264 U_NAMESPACE_END
265 
266 #endif
267 
268