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.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 * Primitive (non-object) Hashtable Functions
44 #include "pkix_pl_primhash.h"
46 /* --Private-Functions---------------------------------------- */
49 * FUNCTION: pkix_pl_KeyComparator_Default
52 * Compares the integer pointed to by "firstKey" with the integer pointed to
53 * by "secondKey" for equality and stores the Boolean result at "pResult".
54 * This default key comparator assumes each key is a PKIX_UInt32, and it
55 * simply tests them for equality.
59 * Address of the first integer key to compare. Must be non-NULL.
60 * The EqualsCallback for this Object will be called.
62 * Address of the second integer key to compare. Must be non-NULL.
64 * Address where Boolean will be stored. Must be non-NULL.
66 * Platform-specific context pointer.
68 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
70 * Returns NULL if the function succeeds.
71 * Returns a Fatal Error if the function fails in an unrecoverable way.
74 pkix_pl_KeyComparator_Default(
75 PKIX_UInt32
*firstKey
,
76 PKIX_UInt32
*secondKey
,
77 PKIX_Boolean
*pResult
,
80 /* Assume both keys are pointers to PKIX_UInt32 */
81 PKIX_UInt32 firstInt
, secondInt
;
83 PKIX_ENTER(HASHTABLE
, "pkix_pl_KeyComparator_Default");
84 PKIX_NULLCHECK_THREE(firstKey
, secondKey
, pResult
);
87 secondInt
= *secondKey
;
89 *pResult
= (firstInt
== secondInt
)?PKIX_TRUE
:PKIX_FALSE
;
91 PKIX_RETURN(HASHTABLE
);
96 * FUNCTION: pkix_pl_PrimHashTable_Create
99 * Creates a new PrimHashtable object with a number of buckets equal to
100 * "numBuckets" and stores the result at "pResult".
104 * The number of hash table buckets. Must be non-zero.
106 * Address where PrimHashTable pointer will be stored. Must be non-NULL.
108 * Platform-specific context pointer.
110 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
112 * Returns NULL if the function succeeds.
113 * Returns a Fatal Error if the function fails in an unrecoverable way.
116 pkix_pl_PrimHashTable_Create(
117 PKIX_UInt32 numBuckets
,
118 pkix_pl_PrimHashTable
**pResult
,
121 pkix_pl_PrimHashTable
*primHashTable
= NULL
;
124 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_Create");
125 PKIX_NULLCHECK_ONE(pResult
);
127 if (numBuckets
== 0) {
128 PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO
);
131 /* Allocate a new hashtable */
132 PKIX_CHECK(PKIX_PL_Malloc
133 (sizeof (pkix_pl_PrimHashTable
),
134 (void **)&primHashTable
,
138 primHashTable
->size
= numBuckets
;
140 /* Allocate space for the buckets */
141 PKIX_CHECK(PKIX_PL_Malloc
142 (numBuckets
* sizeof (pkix_pl_HT_Elem
*),
143 (void **)&primHashTable
->buckets
,
147 for (i
= 0; i
< numBuckets
; i
++) {
148 primHashTable
->buckets
[i
] = NULL
;
151 *pResult
= primHashTable
;
155 if (PKIX_ERROR_RECEIVED
){
156 PKIX_FREE(primHashTable
);
159 PKIX_RETURN(HASHTABLE
);
163 * FUNCTION: pkix_pl_PrimHashTable_Add
166 * Adds the value pointed to by "value" to the PrimHashTable pointed to by
167 * "ht" using the key pointed to by "key" and the hashCode value equal to
168 * "hashCode", using the function pointed to by "keyComp" to compare keys.
169 * Assumes the key is either a PKIX_UInt32 or a PKIX_PL_Object. If the value
170 * already exists in the hashtable, this function returns a non-fatal error.
174 * Address of PrimHashtable to insert into. Must be non-NULL.
176 * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object.
179 * Address of Object to be added to PrimHashtable. Must be non-NULL.
181 * Hashcode value of the key.
183 * Address of function used to determine if two keys are equal.
184 * If NULL, pkix_pl_KeyComparator_Default is used.
186 * Platform-specific context pointer.
188 * Not Thread Safe - assumes exclusive access to "ht"
189 * (see Thread Safety Definitions in Programmer's Guide)
191 * Returns NULL if the function succeeds.
192 * Returns a HashTable Error if the function fails in a non-fatal way.
193 * Returns a Fatal Error if the function fails in an unrecoverable way.
196 pkix_pl_PrimHashTable_Add(
197 pkix_pl_PrimHashTable
*ht
,
200 PKIX_UInt32 hashCode
,
201 PKIX_PL_EqualsCallback keyComp
,
204 pkix_pl_HT_Elem
**elemPtr
= NULL
;
205 pkix_pl_HT_Elem
*element
= NULL
;
206 PKIX_Boolean compResult
= PKIX_FALSE
;
208 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_Add");
209 PKIX_NULLCHECK_THREE(ht
, key
, value
);
211 for (elemPtr
= &((ht
->buckets
)[hashCode
%ht
->size
]), element
= *elemPtr
;
212 element
!= NULL
; elemPtr
= &(element
->next
), element
= *elemPtr
) {
214 if (element
->hashCode
!= hashCode
){
215 /* no possibility of a match */
219 if (keyComp
== NULL
){
220 PKIX_CHECK(pkix_pl_KeyComparator_Default
222 (PKIX_UInt32
*)(element
->key
),
225 PKIX_COULDNOTTESTWHETHERKEYSEQUAL
);
228 ((PKIX_PL_Object
*)key
,
229 (PKIX_PL_Object
*)(element
->key
),
232 PKIX_COULDNOTTESTWHETHERKEYSEQUAL
);
235 if ((element
->hashCode
== hashCode
) &&
236 (compResult
== PKIX_TRUE
)){
237 /* Same key already exists in the table */
238 PKIX_ERROR(PKIX_ATTEMPTTOADDDUPLICATEKEY
);
242 /* Next Element should be NULL at this point */
243 if (element
!= NULL
) {
244 PKIX_ERROR(PKIX_ERRORTRAVERSINGBUCKET
);
247 /* Create a new HT_Elem */
248 PKIX_CHECK(PKIX_PL_Malloc
249 (sizeof (pkix_pl_HT_Elem
), (void **)elemPtr
, plContext
),
255 element
->value
= value
;
256 element
->hashCode
= hashCode
;
257 element
->next
= NULL
;
261 PKIX_RETURN(HASHTABLE
);
265 * FUNCTION: pkix_pl_PrimHashTable_Remove
268 * Removes any objects with the key pointed to by "key" and hashCode value
269 * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
270 * function pointed to by "keyComp" to compare keys, and stores the object's
271 * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
272 * This function sets "pResult" to NULL if the key is not in the hashtable.
276 * Address of PrimHashtable to remove object. Must be non-NULL.
278 * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
281 * Address of Object to be added to PrimHashtable. Must be non-NULL.
283 * Hashcode value of the key.
285 * Address of function used to determine if two keys are equal.
286 * If NULL, pkix_pl_KeyComparator_Default is used.
288 * Address where value will be stored. Must be non-NULL.
290 * Platform-specific context pointer.
292 * Not Thread Safe - assumes exclusive access to "ht"
293 * (see Thread Safety Definitions in Programmer's Guide)
295 * Returns NULL if the function succeeds.
296 * Returns a HashTable Error if the function fails in a non-fatal way.
297 * Returns a Fatal Error if the function fails in an unrecoverable way.
300 pkix_pl_PrimHashTable_Remove(
301 pkix_pl_PrimHashTable
*ht
,
303 PKIX_UInt32 hashCode
,
304 PKIX_PL_EqualsCallback keyComp
,
308 pkix_pl_HT_Elem
*element
= NULL
;
309 pkix_pl_HT_Elem
*prior
= NULL
;
310 PKIX_Boolean compResult
;
312 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_Remove");
313 PKIX_NULLCHECK_THREE(ht
, key
, pResult
);
315 for (element
= ht
->buckets
[hashCode
%ht
->size
], prior
= element
;
317 prior
= element
, element
= element
->next
) {
319 if (element
->hashCode
!= hashCode
){
320 /* no possibility of a match */
324 if (keyComp
== NULL
){
325 PKIX_CHECK(pkix_pl_KeyComparator_Default
327 (PKIX_UInt32
*)(element
->key
),
330 PKIX_COULDNOTTESTWHETHERKEYSEQUAL
);
333 ((PKIX_PL_Object
*)key
,
334 (PKIX_PL_Object
*)(element
->key
),
337 PKIX_COULDNOTTESTWHETHERKEYSEQUAL
);
340 if ((element
->hashCode
== hashCode
) &&
341 (compResult
== PKIX_TRUE
)){
342 if (element
!= prior
) {
343 prior
->next
= element
->next
;
345 ht
->buckets
[hashCode
%ht
->size
] = element
->next
;
347 *pResult
= element
->value
;
349 element
->value
= NULL
;
350 element
->next
= NULL
;
356 /* if we've reached here, specified key doesn't exist in hashtable */
361 PKIX_RETURN(HASHTABLE
);
366 * FUNCTION: pkix_pl_HashTableLookup
369 * Looks up object using the key pointed to by "key" and hashCode value
370 * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
371 * function pointed to by "keyComp" to compare keys, and stores the object's
372 * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
373 * This function sets "pResult" to NULL if the key is not in the hashtable.
377 * Address of PrimHashtable to lookup object from. Must be non-NULL.
379 * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
382 * Address of function used to determine if two keys are equal.
383 * If NULL, pkix_pl_KeyComparator_Default is used.
385 * Hashcode value of the key.
387 * Address where value will be stored. Must be non-NULL.
389 * Platform-specific context pointer.
391 * Conditionally Thread Safe
392 * (see Thread Safety Definitions in Programmer's Guide)
394 * Returns NULL if the function succeeds.
395 * Returns a Fatal Error if the function fails in an unrecoverable way.
398 pkix_pl_PrimHashTable_Lookup(
399 pkix_pl_PrimHashTable
*ht
,
401 PKIX_UInt32 hashCode
,
402 PKIX_PL_EqualsCallback keyComp
,
406 pkix_pl_HT_Elem
*element
= NULL
;
407 PKIX_Boolean compResult
= PKIX_FALSE
;
409 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_Lookup");
410 PKIX_NULLCHECK_THREE(ht
, key
, pResult
);
414 for (element
= (ht
->buckets
)[hashCode
%ht
->size
];
415 (element
!= NULL
) && (*pResult
== NULL
);
416 element
= element
->next
) {
418 if (element
->hashCode
!= hashCode
){
419 /* no possibility of a match */
423 if (keyComp
== NULL
){
424 PKIX_CHECK(pkix_pl_KeyComparator_Default
426 (PKIX_UInt32
*)(element
->key
),
429 PKIX_COULDNOTTESTWHETHERKEYSEQUAL
);
431 PKIX_CHECK_FATAL(keyComp
432 ((PKIX_PL_Object
*)key
,
433 (PKIX_PL_Object
*)(element
->key
),
436 PKIX_COULDNOTTESTWHETHERKEYSEQUAL
);
439 if ((element
->hashCode
== hashCode
) &&
440 (compResult
== PKIX_TRUE
)){
441 *pResult
= element
->value
;
446 /* if we've reached here, specified key doesn't exist in hashtable */
451 PKIX_RETURN(HASHTABLE
);
455 * FUNCTION: pkix_pl_PrimHashTable_Destroy
457 * Destroys PrimHashTable pointed to by "ht".
461 * Address of PrimHashtable to free. Must be non-NULL.
463 * Platform-specific context pointer.
465 * Not Thread Safe - assumes exclusive access to "ht"
466 * (see Thread Safety Definitions in Programmer's Guide)
468 * Returns NULL if the function succeeds.
469 * Returns a HashTable Error if the function fails in a non-fatal way.
470 * Returns a Fatal Error if the function fails in an unrecoverable way.
473 pkix_pl_PrimHashTable_Destroy(
474 pkix_pl_PrimHashTable
*ht
,
477 pkix_pl_HT_Elem
*element
= NULL
;
478 pkix_pl_HT_Elem
*temp
= NULL
;
481 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_Destroy");
482 PKIX_NULLCHECK_ONE(ht
);
484 /* Free each element (list) */
485 for (i
= 0; i
< ht
->size
; i
++) {
486 for (element
= ht
->buckets
[i
];
489 temp
= element
->next
;
490 element
->value
= NULL
;
492 element
->hashCode
= 0;
493 element
->next
= NULL
;
498 /* Free the pointer to the list array */
499 PKIX_FREE(ht
->buckets
);
502 /* Free the table itself */
505 PKIX_RETURN(HASHTABLE
);
509 * FUNCTION: pkix_pl_PrimHashTable_GetBucketSize
512 * Retruns number of entries in the bucket the "hashCode" is designated in
513 * the hashtable "ht" in the address "pBucketSize".
517 * Address of PrimHashtable to get entries count. Must be non-NULL.
519 * Hashcode value of the key.
521 * Address that an PKIX_UInt32 is returned for number of entries in the
522 * bucket associated with the hashCode. Must be non-NULL.
524 * Platform-specific context pointer.
526 * Not Thread Safe - assumes exclusive access to "ht"
527 * (see Thread Safety Definitions in Programmer's Guide)
529 * Returns NULL if the function succeeds.
530 * Returns a HashTable Error if the function fails in a non-fatal way.
531 * Returns a Fatal Error if the function fails in an unrecoverable way.
534 pkix_pl_PrimHashTable_GetBucketSize(
535 pkix_pl_PrimHashTable
*ht
,
536 PKIX_UInt32 hashCode
,
537 PKIX_UInt32
*pBucketSize
,
540 pkix_pl_HT_Elem
**elemPtr
= NULL
;
541 pkix_pl_HT_Elem
*element
= NULL
;
542 PKIX_UInt32 bucketSize
= 0;
544 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_GetBucketSize");
545 PKIX_NULLCHECK_TWO(ht
, pBucketSize
);
547 for (elemPtr
= &((ht
->buckets
)[hashCode
%ht
->size
]), element
= *elemPtr
;
548 element
!= NULL
; elemPtr
= &(element
->next
), element
= *elemPtr
) {
552 *pBucketSize
= bucketSize
;
554 PKIX_RETURN(HASHTABLE
);
558 * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO
561 * Remove the first entry in the bucket the "hashCode" is designated in
562 * the hashtable "ht". Since new entry is added at end of the link list
563 * the first one is the oldest (FI) therefore removed first (FO).
567 * Address of PrimHashtable to get entries count. Must be non-NULL.
569 * Hashcode value of the key.
571 * Address of key of the entry deleted. Must be non-NULL.
573 * Address of Value of the entry deleted. Must be non-NULL.
575 * Platform-specific context pointer.
577 * Not Thread Safe - assumes exclusive access to "ht"
578 * (see Thread Safety Definitions in Programmer's Guide)
580 * Returns NULL if the function succeeds.
581 * Returns a HashTable Error if the function fails in a non-fatal way.
582 * Returns a Fatal Error if the function fails in an unrecoverable way.
585 pkix_pl_PrimHashTable_RemoveFIFO(
586 pkix_pl_PrimHashTable
*ht
,
587 PKIX_UInt32 hashCode
,
592 pkix_pl_HT_Elem
*element
= NULL
;
594 PKIX_ENTER(HASHTABLE
, "pkix_pl_PrimHashTable_Remove");
595 PKIX_NULLCHECK_THREE(ht
, pKey
, pValue
);
597 element
= (ht
->buckets
)[hashCode
%ht
->size
];
599 if (element
!= NULL
) {
601 *pKey
= element
->key
;
602 *pValue
= element
->value
;
603 ht
->buckets
[hashCode
%ht
->size
] = element
->next
;
605 element
->value
= NULL
;
606 element
->next
= NULL
;
610 PKIX_RETURN(HASHTABLE
);