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