Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / system / pkix_pl_primhash.c
blob346723978b3cc31e7efe51ffc2a18b64c6fe272d
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
12 * License.
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.
21 * Contributor(s):
22 * Sun Microsystems
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 ***** */
38 * pkix_pl_primhash.c
40 * Primitive (non-object) Hashtable Functions
44 #include "pkix_pl_primhash.h"
46 /* --Private-Functions---------------------------------------- */
49 * FUNCTION: pkix_pl_KeyComparator_Default
50 * DESCRIPTION:
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.
57 * PARAMETERS:
58 * "firstKey"
59 * Address of the first integer key to compare. Must be non-NULL.
60 * The EqualsCallback for this Object will be called.
61 * "secondKey"
62 * Address of the second integer key to compare. Must be non-NULL.
63 * "pResult"
64 * Address where Boolean will be stored. Must be non-NULL.
65 * "plContext"
66 * Platform-specific context pointer.
67 * THREAD SAFETY:
68 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
69 * RETURNS:
70 * Returns NULL if the function succeeds.
71 * Returns a Fatal Error if the function fails in an unrecoverable way.
73 static PKIX_Error *
74 pkix_pl_KeyComparator_Default(
75 PKIX_UInt32 *firstKey,
76 PKIX_UInt32 *secondKey,
77 PKIX_Boolean *pResult,
78 void *plContext)
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);
86 firstInt = *firstKey;
87 secondInt = *secondKey;
89 *pResult = (firstInt == secondInt)?PKIX_TRUE:PKIX_FALSE;
91 PKIX_RETURN(HASHTABLE);
96 * FUNCTION: pkix_pl_PrimHashTable_Create
97 * DESCRIPTION:
99 * Creates a new PrimHashtable object with a number of buckets equal to
100 * "numBuckets" and stores the result at "pResult".
102 * PARAMETERS:
103 * "numBuckets"
104 * The number of hash table buckets. Must be non-zero.
105 * "pResult"
106 * Address where PrimHashTable pointer will be stored. Must be non-NULL.
107 * "plContext"
108 * Platform-specific context pointer.
109 * THREAD SAFETY:
110 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
111 * RETURNS:
112 * Returns NULL if the function succeeds.
113 * Returns a Fatal Error if the function fails in an unrecoverable way.
115 PKIX_Error *
116 pkix_pl_PrimHashTable_Create(
117 PKIX_UInt32 numBuckets,
118 pkix_pl_PrimHashTable **pResult,
119 void *plContext)
121 pkix_pl_PrimHashTable *primHashTable = NULL;
122 PKIX_UInt32 i;
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,
135 plContext),
136 PKIX_MALLOCFAILED);
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,
144 plContext),
145 PKIX_MALLOCFAILED);
147 for (i = 0; i < numBuckets; i++) {
148 primHashTable->buckets[i] = NULL;
151 *pResult = primHashTable;
153 cleanup:
155 if (PKIX_ERROR_RECEIVED){
156 PKIX_FREE(primHashTable);
159 PKIX_RETURN(HASHTABLE);
163 * FUNCTION: pkix_pl_PrimHashTable_Add
164 * DESCRIPTION:
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.
172 * PARAMETERS:
173 * "ht"
174 * Address of PrimHashtable to insert into. Must be non-NULL.
175 * "key"
176 * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object.
177 * Must be non-NULL.
178 * "value"
179 * Address of Object to be added to PrimHashtable. Must be non-NULL.
180 * "hashCode"
181 * Hashcode value of the key.
182 * "keyComp"
183 * Address of function used to determine if two keys are equal.
184 * If NULL, pkix_pl_KeyComparator_Default is used.
185 * "plContext"
186 * Platform-specific context pointer.
187 * THREAD SAFETY:
188 * Not Thread Safe - assumes exclusive access to "ht"
189 * (see Thread Safety Definitions in Programmer's Guide)
190 * RETURNS:
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.
195 PKIX_Error *
196 pkix_pl_PrimHashTable_Add(
197 pkix_pl_PrimHashTable *ht,
198 void *key,
199 void *value,
200 PKIX_UInt32 hashCode,
201 PKIX_PL_EqualsCallback keyComp,
202 void *plContext)
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 */
216 continue;
219 if (keyComp == NULL){
220 PKIX_CHECK(pkix_pl_KeyComparator_Default
221 ((PKIX_UInt32 *)key,
222 (PKIX_UInt32 *)(element->key),
223 &compResult,
224 plContext),
225 PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
226 } else {
227 PKIX_CHECK(keyComp
228 ((PKIX_PL_Object *)key,
229 (PKIX_PL_Object *)(element->key),
230 &compResult,
231 plContext),
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),
250 PKIX_MALLOCFAILED);
252 element = *elemPtr;
254 element->key = key;
255 element->value = value;
256 element->hashCode = hashCode;
257 element->next = NULL;
259 cleanup:
261 PKIX_RETURN(HASHTABLE);
265 * FUNCTION: pkix_pl_PrimHashTable_Remove
266 * DESCRIPTION:
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.
274 * PARAMETERS:
275 * "ht"
276 * Address of PrimHashtable to remove object. Must be non-NULL.
277 * "key"
278 * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
279 * Must be non-NULL.
280 * "value"
281 * Address of Object to be added to PrimHashtable. Must be non-NULL.
282 * "hashCode"
283 * Hashcode value of the key.
284 * "keyComp"
285 * Address of function used to determine if two keys are equal.
286 * If NULL, pkix_pl_KeyComparator_Default is used.
287 * "pResult"
288 * Address where value will be stored. Must be non-NULL.
289 * "plContext"
290 * Platform-specific context pointer.
291 * THREAD SAFETY:
292 * Not Thread Safe - assumes exclusive access to "ht"
293 * (see Thread Safety Definitions in Programmer's Guide)
294 * RETURNS:
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.
299 PKIX_Error *
300 pkix_pl_PrimHashTable_Remove(
301 pkix_pl_PrimHashTable *ht,
302 void *key,
303 PKIX_UInt32 hashCode,
304 PKIX_PL_EqualsCallback keyComp,
305 void **pResult,
306 void *plContext)
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;
316 (element != NULL);
317 prior = element, element = element->next) {
319 if (element->hashCode != hashCode){
320 /* no possibility of a match */
321 continue;
324 if (keyComp == NULL){
325 PKIX_CHECK(pkix_pl_KeyComparator_Default
326 ((PKIX_UInt32 *)key,
327 (PKIX_UInt32 *)(element->key),
328 &compResult,
329 plContext),
330 PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
331 } else {
332 PKIX_CHECK(keyComp
333 ((PKIX_PL_Object *)key,
334 (PKIX_PL_Object *)(element->key),
335 &compResult,
336 plContext),
337 PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
340 if ((element->hashCode == hashCode) &&
341 (compResult == PKIX_TRUE)){
342 if (element != prior) {
343 prior->next = element->next;
344 } else {
345 ht->buckets[hashCode%ht->size] = element->next;
347 *pResult = element->value;
348 element->key = NULL;
349 element->value = NULL;
350 element->next = NULL;
351 PKIX_FREE(element);
352 goto cleanup;
356 /* if we've reached here, specified key doesn't exist in hashtable */
357 *pResult = NULL;
359 cleanup:
361 PKIX_RETURN(HASHTABLE);
366 * FUNCTION: pkix_pl_HashTableLookup
367 * DESCRIPTION:
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.
375 * PARAMETERS:
376 * "ht"
377 * Address of PrimHashtable to lookup object from. Must be non-NULL.
378 * "key"
379 * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
380 * Must be non-NULL.
381 * "keyComp"
382 * Address of function used to determine if two keys are equal.
383 * If NULL, pkix_pl_KeyComparator_Default is used.
384 * "hashCode"
385 * Hashcode value of the key.
386 * "pResult"
387 * Address where value will be stored. Must be non-NULL.
388 * "plContext"
389 * Platform-specific context pointer.
390 * THREAD SAFETY:
391 * Conditionally Thread Safe
392 * (see Thread Safety Definitions in Programmer's Guide)
393 * RETURNS:
394 * Returns NULL if the function succeeds.
395 * Returns a Fatal Error if the function fails in an unrecoverable way.
397 PKIX_Error *
398 pkix_pl_PrimHashTable_Lookup(
399 pkix_pl_PrimHashTable *ht,
400 void *key,
401 PKIX_UInt32 hashCode,
402 PKIX_PL_EqualsCallback keyComp,
403 void **pResult,
404 void *plContext)
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);
412 *pResult = NULL;
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 */
420 continue;
423 if (keyComp == NULL){
424 PKIX_CHECK(pkix_pl_KeyComparator_Default
425 ((PKIX_UInt32 *)key,
426 (PKIX_UInt32 *)(element->key),
427 &compResult,
428 plContext),
429 PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
430 } else {
431 PKIX_CHECK_FATAL(keyComp
432 ((PKIX_PL_Object *)key,
433 (PKIX_PL_Object *)(element->key),
434 &compResult,
435 plContext),
436 PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
439 if ((element->hashCode == hashCode) &&
440 (compResult == PKIX_TRUE)){
441 *pResult = element->value;
442 goto cleanup;
446 /* if we've reached here, specified key doesn't exist in hashtable */
447 *pResult = NULL;
449 cleanup:
451 PKIX_RETURN(HASHTABLE);
455 * FUNCTION: pkix_pl_PrimHashTable_Destroy
457 * Destroys PrimHashTable pointed to by "ht".
459 * PARAMETERS:
460 * "ht"
461 * Address of PrimHashtable to free. Must be non-NULL.
462 * "plContext"
463 * Platform-specific context pointer.
464 * THREAD SAFETY:
465 * Not Thread Safe - assumes exclusive access to "ht"
466 * (see Thread Safety Definitions in Programmer's Guide)
467 * RETURNS
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.
472 PKIX_Error *
473 pkix_pl_PrimHashTable_Destroy(
474 pkix_pl_PrimHashTable *ht,
475 void *plContext)
477 pkix_pl_HT_Elem *element = NULL;
478 pkix_pl_HT_Elem *temp = NULL;
479 PKIX_UInt32 i;
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];
487 element != NULL;
488 element = temp) {
489 temp = element->next;
490 element->value = NULL;
491 element->key = NULL;
492 element->hashCode = 0;
493 element->next = NULL;
494 PKIX_FREE(element);
498 /* Free the pointer to the list array */
499 PKIX_FREE(ht->buckets);
500 ht->size = 0;
502 /* Free the table itself */
503 PKIX_FREE(ht);
505 PKIX_RETURN(HASHTABLE);
509 * FUNCTION: pkix_pl_PrimHashTable_GetBucketSize
510 * DESCRIPTION:
512 * Retruns number of entries in the bucket the "hashCode" is designated in
513 * the hashtable "ht" in the address "pBucketSize".
515 * PARAMETERS:
516 * "ht"
517 * Address of PrimHashtable to get entries count. Must be non-NULL.
518 * "hashCode"
519 * Hashcode value of the key.
520 * "pBucketSize"
521 * Address that an PKIX_UInt32 is returned for number of entries in the
522 * bucket associated with the hashCode. Must be non-NULL.
523 * "plContext"
524 * Platform-specific context pointer.
525 * THREAD SAFETY:
526 * Not Thread Safe - assumes exclusive access to "ht"
527 * (see Thread Safety Definitions in Programmer's Guide)
528 * RETURNS:
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.
533 PKIX_Error *
534 pkix_pl_PrimHashTable_GetBucketSize(
535 pkix_pl_PrimHashTable *ht,
536 PKIX_UInt32 hashCode,
537 PKIX_UInt32 *pBucketSize,
538 void *plContext)
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) {
549 bucketSize++;
552 *pBucketSize = bucketSize;
554 PKIX_RETURN(HASHTABLE);
558 * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO
559 * DESCRIPTION:
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).
565 * PARAMETERS:
566 * "ht"
567 * Address of PrimHashtable to get entries count. Must be non-NULL.
568 * "hashCode"
569 * Hashcode value of the key.
570 * "pKey"
571 * Address of key of the entry deleted. Must be non-NULL.
572 * "pValue"
573 * Address of Value of the entry deleted. Must be non-NULL.
574 * "plContext"
575 * Platform-specific context pointer.
576 * THREAD SAFETY:
577 * Not Thread Safe - assumes exclusive access to "ht"
578 * (see Thread Safety Definitions in Programmer's Guide)
579 * RETURNS:
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.
584 PKIX_Error *
585 pkix_pl_PrimHashTable_RemoveFIFO(
586 pkix_pl_PrimHashTable *ht,
587 PKIX_UInt32 hashCode,
588 void **pKey,
589 void **pValue,
590 void *plContext)
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;
604 element->key = NULL;
605 element->value = NULL;
606 element->next = NULL;
607 PKIX_FREE(element);
610 PKIX_RETURN(HASHTABLE);