1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 static const char CVS_ID
[] = "@(#) $RCSfile: hash.c,v $ $Revision: 1.9 $ $Date: 2005/01/20 02:25:45 $";
44 * This is merely a couple wrappers around NSPR's PLHashTable, using
45 * the identity hash and arena-aware allocators.
46 * This is a copy of ckfw/hash.c, with modifications to use NSS types
47 * (not Cryptoki types). Would like for this to be a single implementation,
48 * but doesn't seem like it will work.
70 PRBool i_alloced_arena
;
74 * The invariant that mutex protects is:
75 * The count accurately reflects the hashtable state.
78 PLHashTable
*plHashTable
;
88 PRUint32 i
= (PRUint32
)key
;
89 PR_ASSERT(sizeof(PLHashNumber
) == sizeof(PRUint32
));
90 return (PLHashNumber
)i
;
101 NSSItem
*it
= (NSSItem
*)key
;
103 for (i
=0; i
<it
->size
; i
++)
104 h
= (h
>> 28) ^ (h
<< 4) ^ ((unsigned char *)it
->data
)[i
];
109 nss_compare_items(const void *v1
, const void *v2
)
112 return (int)nssItem_Equal((NSSItem
*)v1
, (NSSItem
*)v2
, &ignore
);
119 NSS_IMPLEMENT nssHash
*
124 PLHashFunction keyHash
,
125 PLHashComparator keyCompare
,
126 PLHashComparator valueCompare
134 if( arenaOpt
&& PR_SUCCESS
!= nssArena_verifyPointer(arenaOpt
) ) {
135 nss_SetError(NSS_ERROR_INVALID_POINTER
);
136 return (nssHash
*)NULL
;
138 #endif /* NSSDEBUG */
142 i_alloced
= PR_FALSE
;
144 arena
= nssArena_Create();
148 rv
= nss_ZNEW(arena
, nssHash
);
149 if( (nssHash
*)NULL
== rv
) {
153 rv
->mutex
= PZ_NewLock(nssILockOther
);
154 if( (PZLock
*)NULL
== rv
->mutex
) {
158 rv
->plHashTable
= PL_NewHashTable(numBuckets
,
159 keyHash
, keyCompare
, valueCompare
,
160 &nssArenaHashAllocOps
, arena
);
161 if( (PLHashTable
*)NULL
== rv
->plHashTable
) {
162 (void)PZ_DestroyLock(rv
->mutex
);
168 rv
->i_alloced_arena
= i_alloced
;
172 (void)nss_ZFreeIf(rv
);
173 return (nssHash
*)NULL
;
177 * nssHash_CreatePointer
180 NSS_IMPLEMENT nssHash
*
181 nssHash_CreatePointer
187 return nssHash_Create(arenaOpt
, numBuckets
,
188 nss_identity_hash
, PL_CompareValues
, PL_CompareValues
);
192 * nssHash_CreateString
195 NSS_IMPLEMENT nssHash
*
202 return nssHash_Create(arenaOpt
, numBuckets
,
203 PL_HashString
, PL_CompareStrings
, PL_CompareStrings
);
210 NSS_IMPLEMENT nssHash
*
217 return nssHash_Create(arenaOpt
, numBuckets
,
218 nss_item_hash
, nss_compare_items
, PL_CompareValues
);
231 (void)PZ_DestroyLock(hash
->mutex
);
232 PL_HashTableDestroy(hash
->plHashTable
);
233 if (hash
->i_alloced_arena
) {
234 nssArena_Destroy(hash
->arena
);
244 NSS_IMPLEMENT PRStatus
252 PRStatus error
= PR_FAILURE
;
255 PZ_Lock(hash
->mutex
);
257 he
= PL_HashTableAdd(hash
->plHashTable
, key
, (void *)value
);
258 if( (PLHashEntry
*)NULL
== he
) {
259 nss_SetError(NSS_ERROR_NO_MEMORY
);
260 } else if (he
->value
!= value
) {
261 nss_SetError(NSS_ERROR_HASH_COLLISION
);
267 (void)PZ_Unlock(hash
->mutex
);
285 PZ_Lock(hash
->mutex
);
287 found
= PL_HashTableRemove(hash
->plHashTable
, it
);
292 (void)PZ_Unlock(hash
->mutex
);
300 NSS_IMPLEMENT PRUint32
308 PZ_Lock(hash
->mutex
);
312 (void)PZ_Unlock(hash
->mutex
);
330 PZ_Lock(hash
->mutex
);
332 value
= PL_HashTableLookup(hash
->plHashTable
, it
);
334 (void)PZ_Unlock(hash
->mutex
);
336 if( (void *)NULL
== value
) {
356 PZ_Lock(hash
->mutex
);
358 rv
= PL_HashTableLookup(hash
->plHashTable
, it
);
360 (void)PZ_Unlock(hash
->mutex
);
378 struct arg_str
*as
= (struct arg_str
*)arg
;
379 as
->fcn(he
->key
, he
->value
, as
->closure
);
380 return HT_ENUMERATE_NEXT
;
386 * NOTE that the iteration function will be called with the hashtable locked.
398 as
.closure
= closure
;
400 PZ_Lock(hash
->mutex
);
402 PL_HashTableEnumerateEntries(hash
->plHashTable
, nss_hash_enumerator
, &as
);
404 (void)PZ_Unlock(hash
->mutex
);