comparison nss/lib/base/hash.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 /*
6 * hash.c
7 *
8 * This is merely a couple wrappers around NSPR's PLHashTable, using
9 * the identity hash and arena-aware allocators.
10 * This is a copy of ckfw/hash.c, with modifications to use NSS types
11 * (not Cryptoki types). Would like for this to be a single implementation,
12 * but doesn't seem like it will work.
13 */
14
15 #ifndef BASE_H
16 #include "base.h"
17 #endif /* BASE_H */
18
19 #include "prbit.h"
20
21 /*
22 * nssHash
23 *
24 * nssHash_Create
25 * nssHash_Destroy
26 * nssHash_Add
27 * nssHash_Remove
28 * nssHash_Count
29 * nssHash_Exists
30 * nssHash_Lookup
31 * nssHash_Iterate
32 */
33
34 struct nssHashStr {
35 NSSArena *arena;
36 PRBool i_alloced_arena;
37 PRLock *mutex;
38
39 /*
40 * The invariant that mutex protects is:
41 * The count accurately reflects the hashtable state.
42 */
43
44 PLHashTable *plHashTable;
45 PRUint32 count;
46 };
47
48 static PLHashNumber
49 nss_identity_hash
50 (
51 const void *key
52 )
53 {
54 PRUint32 i = (PRUint32)key;
55 PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32));
56 return (PLHashNumber)i;
57 }
58
59 static PLHashNumber
60 nss_item_hash
61 (
62 const void *key
63 )
64 {
65 unsigned int i;
66 PLHashNumber h;
67 NSSItem *it = (NSSItem *)key;
68 h = 0;
69 for (i=0; i<it->size; i++)
70 h = PR_ROTATE_LEFT32(h, 4) ^ ((unsigned char *)it->data)[i];
71 return h;
72 }
73
74 static int
75 nss_compare_items(const void *v1, const void *v2)
76 {
77 PRStatus ignore;
78 return (int)nssItem_Equal((NSSItem *)v1, (NSSItem *)v2, &ignore);
79 }
80
81 /*
82 * nssHash_create
83 *
84 */
85 NSS_IMPLEMENT nssHash *
86 nssHash_Create
87 (
88 NSSArena *arenaOpt,
89 PRUint32 numBuckets,
90 PLHashFunction keyHash,
91 PLHashComparator keyCompare,
92 PLHashComparator valueCompare
93 )
94 {
95 nssHash *rv;
96 NSSArena *arena;
97 PRBool i_alloced;
98
99 #ifdef NSSDEBUG
100 if( arenaOpt && PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
101 nss_SetError(NSS_ERROR_INVALID_POINTER);
102 return (nssHash *)NULL;
103 }
104 #endif /* NSSDEBUG */
105
106 if (arenaOpt) {
107 arena = arenaOpt;
108 i_alloced = PR_FALSE;
109 } else {
110 arena = nssArena_Create();
111 i_alloced = PR_TRUE;
112 }
113
114 rv = nss_ZNEW(arena, nssHash);
115 if( (nssHash *)NULL == rv ) {
116 goto loser;
117 }
118
119 rv->mutex = PZ_NewLock(nssILockOther);
120 if( (PZLock *)NULL == rv->mutex ) {
121 goto loser;
122 }
123
124 rv->plHashTable = PL_NewHashTable(numBuckets,
125 keyHash, keyCompare, valueCompare,
126 &nssArenaHashAllocOps, arena);
127 if( (PLHashTable *)NULL == rv->plHashTable ) {
128 (void)PZ_DestroyLock(rv->mutex);
129 goto loser;
130 }
131
132 rv->count = 0;
133 rv->arena = arena;
134 rv->i_alloced_arena = i_alloced;
135
136 return rv;
137 loser:
138 (void)nss_ZFreeIf(rv);
139 return (nssHash *)NULL;
140 }
141
142 /*
143 * nssHash_CreatePointer
144 *
145 */
146 NSS_IMPLEMENT nssHash *
147 nssHash_CreatePointer
148 (
149 NSSArena *arenaOpt,
150 PRUint32 numBuckets
151 )
152 {
153 return nssHash_Create(arenaOpt, numBuckets,
154 nss_identity_hash, PL_CompareValues, PL_CompareValues);
155 }
156
157 /*
158 * nssHash_CreateString
159 *
160 */
161 NSS_IMPLEMENT nssHash *
162 nssHash_CreateString
163 (
164 NSSArena *arenaOpt,
165 PRUint32 numBuckets
166 )
167 {
168 return nssHash_Create(arenaOpt, numBuckets,
169 PL_HashString, PL_CompareStrings, PL_CompareStrings);
170 }
171
172 /*
173 * nssHash_CreateItem
174 *
175 */
176 NSS_IMPLEMENT nssHash *
177 nssHash_CreateItem
178 (
179 NSSArena *arenaOpt,
180 PRUint32 numBuckets
181 )
182 {
183 return nssHash_Create(arenaOpt, numBuckets,
184 nss_item_hash, nss_compare_items, PL_CompareValues);
185 }
186
187 /*
188 * nssHash_Destroy
189 *
190 */
191 NSS_IMPLEMENT void
192 nssHash_Destroy
193 (
194 nssHash *hash
195 )
196 {
197 (void)PZ_DestroyLock(hash->mutex);
198 PL_HashTableDestroy(hash->plHashTable);
199 if (hash->i_alloced_arena) {
200 nssArena_Destroy(hash->arena);
201 } else {
202 nss_ZFreeIf(hash);
203 }
204 }
205
206 /*
207 * nssHash_Add
208 *
209 */
210 NSS_IMPLEMENT PRStatus
211 nssHash_Add
212 (
213 nssHash *hash,
214 const void *key,
215 const void *value
216 )
217 {
218 PRStatus error = PR_FAILURE;
219 PLHashEntry *he;
220
221 PZ_Lock(hash->mutex);
222
223 he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
224 if( (PLHashEntry *)NULL == he ) {
225 nss_SetError(NSS_ERROR_NO_MEMORY);
226 } else if (he->value != value) {
227 nss_SetError(NSS_ERROR_HASH_COLLISION);
228 } else {
229 hash->count++;
230 error = PR_SUCCESS;
231 }
232
233 (void)PZ_Unlock(hash->mutex);
234
235 return error;
236 }
237
238 /*
239 * nssHash_Remove
240 *
241 */
242 NSS_IMPLEMENT void
243 nssHash_Remove
244 (
245 nssHash *hash,
246 const void *it
247 )
248 {
249 PRBool found;
250
251 PZ_Lock(hash->mutex);
252
253 found = PL_HashTableRemove(hash->plHashTable, it);
254 if( found ) {
255 hash->count--;
256 }
257
258 (void)PZ_Unlock(hash->mutex);
259 return;
260 }
261
262 /*
263 * nssHash_Count
264 *
265 */
266 NSS_IMPLEMENT PRUint32
267 nssHash_Count
268 (
269 nssHash *hash
270 )
271 {
272 PRUint32 count;
273
274 PZ_Lock(hash->mutex);
275
276 count = hash->count;
277
278 (void)PZ_Unlock(hash->mutex);
279
280 return count;
281 }
282
283 /*
284 * nssHash_Exists
285 *
286 */
287 NSS_IMPLEMENT PRBool
288 nssHash_Exists
289 (
290 nssHash *hash,
291 const void *it
292 )
293 {
294 void *value;
295
296 PZ_Lock(hash->mutex);
297
298 value = PL_HashTableLookup(hash->plHashTable, it);
299
300 (void)PZ_Unlock(hash->mutex);
301
302 if( (void *)NULL == value ) {
303 return PR_FALSE;
304 } else {
305 return PR_TRUE;
306 }
307 }
308
309 /*
310 * nssHash_Lookup
311 *
312 */
313 NSS_IMPLEMENT void *
314 nssHash_Lookup
315 (
316 nssHash *hash,
317 const void *it
318 )
319 {
320 void *rv;
321
322 PZ_Lock(hash->mutex);
323
324 rv = PL_HashTableLookup(hash->plHashTable, it);
325
326 (void)PZ_Unlock(hash->mutex);
327
328 return rv;
329 }
330
331 struct arg_str {
332 nssHashIterator fcn;
333 void *closure;
334 };
335
336 static PRIntn
337 nss_hash_enumerator
338 (
339 PLHashEntry *he,
340 PRIntn index,
341 void *arg
342 )
343 {
344 struct arg_str *as = (struct arg_str *)arg;
345 as->fcn(he->key, he->value, as->closure);
346 return HT_ENUMERATE_NEXT;
347 }
348
349 /*
350 * nssHash_Iterate
351 *
352 * NOTE that the iteration function will be called with the hashtable locked.
353 */
354 NSS_IMPLEMENT void
355 nssHash_Iterate
356 (
357 nssHash *hash,
358 nssHashIterator fcn,
359 void *closure
360 )
361 {
362 struct arg_str as;
363 as.fcn = fcn;
364 as.closure = closure;
365
366 PZ_Lock(hash->mutex);
367
368 PL_HashTableEnumerateEntries(hash->plHashTable, nss_hash_enumerator, &as);
369
370 (void)PZ_Unlock(hash->mutex);
371
372 return;
373 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)