|
1 // stringhash.h |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 #ifndef FSHELL_STRINGHASH_H |
|
13 #define FSHELL_STRINGHASH_H |
|
14 |
|
15 #include <e32hashtab.h> |
|
16 |
|
17 namespace LtkUtils |
|
18 { |
|
19 template <typename T> class TStringHashIter; |
|
20 template <typename T> struct SHashVal { HBufC* iKey; T iValue; }; |
|
21 |
|
22 template <typename T> |
|
23 class RStringHash |
|
24 { |
|
25 public: // RHashMap-style |
|
26 inline RStringHash(); |
|
27 inline T* Find(const TDesC& aKey); |
|
28 inline T FindPtr(const TDesC& aKey); // Only use if T is a pointer |
|
29 inline T& FindL(const TDesC& aKey); |
|
30 inline T const* Find(const TDesC& aKey) const; |
|
31 inline T const FindPtr(const TDesC& aKey) const; // Only use if T is a pointer |
|
32 inline T const& FindL(const TDesC& aKey) const; |
|
33 inline TInt Insert(const TDesC& aKey, const T& aValue); |
|
34 inline void InsertL(const TDesC& aKey, const T& aValue); |
|
35 inline TInt Remove(const TDesC& aKey); |
|
36 |
|
37 inline TInt Count() const; |
|
38 inline TInt Reserve(TInt aCount); |
|
39 inline void ReserveL(TInt aCount); |
|
40 inline void Close(); |
|
41 |
|
42 protected: |
|
43 inline SHashVal<T>* DoFind(const TDesC& aKey); |
|
44 inline SHashVal<T> const* DoFind(const TDesC& aKey) const; |
|
45 friend class TStringHashIter<T>; |
|
46 |
|
47 RHashMap<TDesC*, SHashVal<T> > iHash; |
|
48 TAny* iSpare; |
|
49 TAny* iSpare2; |
|
50 }; |
|
51 |
|
52 template <typename T> |
|
53 class TStringHashIter |
|
54 { |
|
55 public: |
|
56 inline TStringHashIter(const RStringHash<T>& aHash); |
|
57 inline const TDesC* CurrentKey() const; |
|
58 inline const TDesC* NextKey(); |
|
59 inline T* CurrentValue(); |
|
60 inline const T* NextValue(); |
|
61 inline void RemoveCurrent(); |
|
62 |
|
63 private: |
|
64 THashMapIter<TDesC*, SHashVal<T> > iIter; |
|
65 }; |
|
66 |
|
67 inline TUint32 HashFn(TDesC* const& aKey); |
|
68 inline TBool IdFn(TDesC* const& aFirst, TDesC* const& aSecond); |
|
69 } |
|
70 |
|
71 |
|
72 // Nothing to see here, move along move along |
|
73 |
|
74 template <typename T> |
|
75 LtkUtils::RStringHash<T>::RStringHash() |
|
76 : iHash(THashFunction32<TDesC*>(&HashFn), TIdentityRelation<TDesC*>(&IdFn)), iSpare(NULL), iSpare2(NULL) |
|
77 { |
|
78 } |
|
79 |
|
80 inline TUint32 LtkUtils::HashFn(TDesC* const& aKey) |
|
81 { |
|
82 return DefaultHash::Des16(*aKey); |
|
83 } |
|
84 |
|
85 inline TBool LtkUtils::IdFn(TDesC* const& aFirst, TDesC* const& aSecond) |
|
86 { |
|
87 return DefaultIdentity::Des16(*aFirst, *aSecond); |
|
88 } |
|
89 |
|
90 template <typename T> |
|
91 inline T* LtkUtils::RStringHash<T>::Find(const TDesC& aKey) |
|
92 { |
|
93 SHashVal<T>* res = DoFind(aKey); |
|
94 if (res) return &res->iValue; |
|
95 else return NULL; |
|
96 } |
|
97 |
|
98 |
|
99 template <typename T> |
|
100 inline T LtkUtils::RStringHash<T>::FindPtr(const TDesC& aKey) |
|
101 { |
|
102 T* res = Find(aKey); |
|
103 if (res) return *res; |
|
104 else return NULL; |
|
105 } |
|
106 |
|
107 |
|
108 template <typename T> |
|
109 inline T const* LtkUtils::RStringHash<T>::Find(const TDesC& aKey) const |
|
110 { |
|
111 SHashVal<T> const* res = DoFind(aKey); |
|
112 if (res) return &res->iValue; |
|
113 else return NULL; |
|
114 } |
|
115 |
|
116 template <typename T> |
|
117 inline T const LtkUtils::RStringHash<T>::FindPtr(const TDesC& aKey) const |
|
118 { |
|
119 T const* res = Find(aKey); |
|
120 if (res) return *res; |
|
121 else return NULL; |
|
122 } |
|
123 |
|
124 template <typename T> |
|
125 inline T& LtkUtils::RStringHash<T>::FindL(const TDesC& aKey) |
|
126 { |
|
127 T* res = Find(aKey); |
|
128 if (!res) User::Leave(KErrNotFound); |
|
129 return *res; |
|
130 } |
|
131 |
|
132 template <typename T> |
|
133 inline T const& LtkUtils::RStringHash<T>::FindL(const TDesC& aKey) const |
|
134 { |
|
135 T const* res = Find(aKey); |
|
136 if (!res) User::Leave(KErrNotFound); |
|
137 return *res; |
|
138 } |
|
139 |
|
140 template <typename T> |
|
141 TInt LtkUtils::RStringHash<T>::Insert(const TDesC& aKey, const T& aValue) |
|
142 { |
|
143 SHashVal<T>* valPtr = DoFind(aKey); |
|
144 if (valPtr) |
|
145 { |
|
146 // Just update the value, no need to realloc anything |
|
147 memcpy(&valPtr->iValue, &aValue, sizeof(T)); |
|
148 return KErrNone; |
|
149 } |
|
150 |
|
151 HBufC* buf = aKey.Alloc(); |
|
152 if (!buf) return KErrNoMemory; |
|
153 // Avoid declaring an SHashVal<T> as that requires T to have a default constructor |
|
154 TUint8 valBuf[sizeof(SHashVal<T>)]; |
|
155 SHashVal<T>& val = *reinterpret_cast<SHashVal<T>*>(valBuf); |
|
156 val.iKey = buf; |
|
157 memcpy(&val.iValue, &aValue, sizeof(T)); |
|
158 TInt err = iHash.Insert(buf, val); |
|
159 if (err) |
|
160 { |
|
161 delete buf; |
|
162 } |
|
163 return err; |
|
164 } |
|
165 |
|
166 template <typename T> |
|
167 inline TInt LtkUtils::RStringHash<T>::Remove(const TDesC& aKey) |
|
168 { |
|
169 SHashVal<T>* valPtr = DoFind(aKey); |
|
170 if (valPtr) |
|
171 { |
|
172 HBufC* key = valPtr->iKey; |
|
173 iHash.Remove(key); |
|
174 delete key; |
|
175 return KErrNone; |
|
176 } |
|
177 else |
|
178 { |
|
179 return KErrNotFound; |
|
180 } |
|
181 } |
|
182 |
|
183 template <typename T> |
|
184 inline void LtkUtils::RStringHash<T>::Close() |
|
185 { |
|
186 THashMapIter<TDesC*, SHashVal<T> > iter(iHash); |
|
187 while (iter.NextValue() != NULL) |
|
188 { |
|
189 SHashVal<T>* current = const_cast<SHashVal<T>*>(iter.CurrentValue()); // const_cast not needed except on 9.1 |
|
190 HBufC* key = current->iKey; |
|
191 iter.RemoveCurrent(); |
|
192 delete key; |
|
193 } |
|
194 iHash.Close(); |
|
195 } |
|
196 |
|
197 template <typename T> |
|
198 inline void LtkUtils::RStringHash<T>::InsertL(const TDesC& aKey, const T& aValue) |
|
199 { |
|
200 User::LeaveIfError(Insert(aKey, aValue)); |
|
201 } |
|
202 |
|
203 template <typename T> |
|
204 inline TInt LtkUtils::RStringHash<T>::Count() const |
|
205 { |
|
206 return iHash.Count(); |
|
207 } |
|
208 |
|
209 template <typename T> |
|
210 inline TInt LtkUtils::RStringHash<T>::Reserve(TInt aCount) |
|
211 { |
|
212 return iHash.Reserve(aCount); |
|
213 } |
|
214 |
|
215 template <typename T> |
|
216 inline void LtkUtils::RStringHash<T>::ReserveL(TInt aCount) |
|
217 { |
|
218 User::LeaveIfError(Reserve(aCount)); |
|
219 } |
|
220 |
|
221 template <typename T> |
|
222 inline LtkUtils::SHashVal<T>* LtkUtils::RStringHash<T>::DoFind(const TDesC& aKey) |
|
223 { |
|
224 return iHash.Find(const_cast<TDesC*>(&aKey)); |
|
225 } |
|
226 |
|
227 template <typename T> |
|
228 inline LtkUtils::SHashVal<T> const* LtkUtils::RStringHash<T>::DoFind(const TDesC& aKey) const |
|
229 { |
|
230 return iHash.Find(const_cast<TDesC*>(&aKey)); |
|
231 } |
|
232 |
|
233 /// Iterator support |
|
234 |
|
235 template <typename T> |
|
236 inline const TDesC* LtkUtils::TStringHashIter<T>::CurrentKey() const |
|
237 { |
|
238 return *const_cast<TDesC**>(iIter.CurrentKey()); |
|
239 } |
|
240 |
|
241 template <typename T> |
|
242 inline const TDesC* LtkUtils::TStringHashIter<T>::NextKey() |
|
243 { |
|
244 return *const_cast<TDesC**>(iIter.NextKey()); |
|
245 } |
|
246 |
|
247 template <typename T> |
|
248 inline T* LtkUtils::TStringHashIter<T>::CurrentValue() |
|
249 { |
|
250 SHashVal<T>* val = const_cast<SHashVal<T>*>(iIter.CurrentValue()); // The const_cast isn't needed, except on 9.1 |
|
251 if (val) return &val->iValue; |
|
252 return NULL; |
|
253 } |
|
254 |
|
255 template <typename T> |
|
256 inline const T* LtkUtils::TStringHashIter<T>::NextValue() |
|
257 { |
|
258 const SHashVal<T>* val = iIter.NextValue(); |
|
259 if (val) return &val->iValue; |
|
260 return NULL; |
|
261 } |
|
262 |
|
263 template <typename T> |
|
264 inline void LtkUtils::TStringHashIter<T>::RemoveCurrent() |
|
265 { |
|
266 SHashVal<T>* val = iIter.CurrentValue(); |
|
267 if (val) |
|
268 { |
|
269 HBufC* key = val->iKey; |
|
270 iIter.RemoveCurrent(); |
|
271 delete key; |
|
272 } |
|
273 } |
|
274 |
|
275 template <typename T> |
|
276 inline LtkUtils::TStringHashIter<T>::TStringHashIter(const RStringHash<T>& aHash) |
|
277 : iIter(aHash.iHash) |
|
278 {} |
|
279 |
|
280 #endif |