/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c

http://github.com/zpao/v8monkey · C · 617 lines · 278 code · 68 blank · 271 comment · 50 complexity · 26fa8445b8aecfbf21b0fde6fe0a3623 MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  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/
  8. *
  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.
  13. *
  14. * The Original Code is the PKIX-C library.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Sun Microsystems, Inc.
  18. * Portions created by the Initial Developer are
  19. * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Sun Microsystems, Inc.
  23. *
  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.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. * pkix_pl_primhash.c
  39. *
  40. * Primitive (non-object) Hashtable Functions
  41. *
  42. */
  43. #include "pkix_pl_primhash.h"
  44. /* --Private-Functions---------------------------------------- */
  45. /*
  46. * FUNCTION: pkix_pl_KeyComparator_Default
  47. * DESCRIPTION:
  48. *
  49. * Compares the integer pointed to by "firstKey" with the integer pointed to
  50. * by "secondKey" for equality and stores the Boolean result at "pResult".
  51. * This default key comparator assumes each key is a PKIX_UInt32, and it
  52. * simply tests them for equality.
  53. *
  54. * PARAMETERS:
  55. * "firstKey"
  56. * Address of the first integer key to compare. Must be non-NULL.
  57. * The EqualsCallback for this Object will be called.
  58. * "secondKey"
  59. * Address of the second integer key to compare. Must be non-NULL.
  60. * "pResult"
  61. * Address where Boolean will be stored. Must be non-NULL.
  62. * "plContext"
  63. * Platform-specific context pointer.
  64. * THREAD SAFETY:
  65. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  66. * RETURNS:
  67. * Returns NULL if the function succeeds.
  68. * Returns a Fatal Error if the function fails in an unrecoverable way.
  69. */
  70. static PKIX_Error *
  71. pkix_pl_KeyComparator_Default(
  72. PKIX_UInt32 *firstKey,
  73. PKIX_UInt32 *secondKey,
  74. PKIX_Boolean *pResult,
  75. void *plContext)
  76. {
  77. /* Assume both keys are pointers to PKIX_UInt32 */
  78. PKIX_UInt32 firstInt, secondInt;
  79. PKIX_ENTER(HASHTABLE, "pkix_pl_KeyComparator_Default");
  80. PKIX_NULLCHECK_THREE(firstKey, secondKey, pResult);
  81. firstInt = *firstKey;
  82. secondInt = *secondKey;
  83. *pResult = (firstInt == secondInt)?PKIX_TRUE:PKIX_FALSE;
  84. PKIX_RETURN(HASHTABLE);
  85. }
  86. /*
  87. * FUNCTION: pkix_pl_PrimHashTable_Create
  88. * DESCRIPTION:
  89. *
  90. * Creates a new PrimHashtable object with a number of buckets equal to
  91. * "numBuckets" and stores the result at "pResult".
  92. *
  93. * PARAMETERS:
  94. * "numBuckets"
  95. * The number of hash table buckets. Must be non-zero.
  96. * "pResult"
  97. * Address where PrimHashTable pointer will be stored. Must be non-NULL.
  98. * "plContext"
  99. * Platform-specific context pointer.
  100. * THREAD SAFETY:
  101. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  102. * RETURNS:
  103. * Returns NULL if the function succeeds.
  104. * Returns a Fatal Error if the function fails in an unrecoverable way.
  105. */
  106. PKIX_Error *
  107. pkix_pl_PrimHashTable_Create(
  108. PKIX_UInt32 numBuckets,
  109. pkix_pl_PrimHashTable **pResult,
  110. void *plContext)
  111. {
  112. pkix_pl_PrimHashTable *primHashTable = NULL;
  113. PKIX_UInt32 i;
  114. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Create");
  115. PKIX_NULLCHECK_ONE(pResult);
  116. if (numBuckets == 0) {
  117. PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO);
  118. }
  119. /* Allocate a new hashtable */
  120. PKIX_CHECK(PKIX_PL_Malloc
  121. (sizeof (pkix_pl_PrimHashTable),
  122. (void **)&primHashTable,
  123. plContext),
  124. PKIX_MALLOCFAILED);
  125. primHashTable->size = numBuckets;
  126. /* Allocate space for the buckets */
  127. PKIX_CHECK(PKIX_PL_Malloc
  128. (numBuckets * sizeof (pkix_pl_HT_Elem*),
  129. (void **)&primHashTable->buckets,
  130. plContext),
  131. PKIX_MALLOCFAILED);
  132. for (i = 0; i < numBuckets; i++) {
  133. primHashTable->buckets[i] = NULL;
  134. }
  135. *pResult = primHashTable;
  136. cleanup:
  137. if (PKIX_ERROR_RECEIVED){
  138. PKIX_FREE(primHashTable);
  139. }
  140. PKIX_RETURN(HASHTABLE);
  141. }
  142. /*
  143. * FUNCTION: pkix_pl_PrimHashTable_Add
  144. * DESCRIPTION:
  145. *
  146. * Adds the value pointed to by "value" to the PrimHashTable pointed to by
  147. * "ht" using the key pointed to by "key" and the hashCode value equal to
  148. * "hashCode", using the function pointed to by "keyComp" to compare keys.
  149. * Assumes the key is either a PKIX_UInt32 or a PKIX_PL_Object. If the value
  150. * already exists in the hashtable, this function returns a non-fatal error.
  151. *
  152. * PARAMETERS:
  153. * "ht"
  154. * Address of PrimHashtable to insert into. Must be non-NULL.
  155. * "key"
  156. * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object.
  157. * Must be non-NULL.
  158. * "value"
  159. * Address of Object to be added to PrimHashtable. Must be non-NULL.
  160. * "hashCode"
  161. * Hashcode value of the key.
  162. * "keyComp"
  163. * Address of function used to determine if two keys are equal.
  164. * If NULL, pkix_pl_KeyComparator_Default is used.
  165. * "plContext"
  166. * Platform-specific context pointer.
  167. * THREAD SAFETY:
  168. * Not Thread Safe - assumes exclusive access to "ht"
  169. * (see Thread Safety Definitions in Programmer's Guide)
  170. * RETURNS:
  171. * Returns NULL if the function succeeds.
  172. * Returns a HashTable Error if the function fails in a non-fatal way.
  173. * Returns a Fatal Error if the function fails in an unrecoverable way.
  174. */
  175. PKIX_Error *
  176. pkix_pl_PrimHashTable_Add(
  177. pkix_pl_PrimHashTable *ht,
  178. void *key,
  179. void *value,
  180. PKIX_UInt32 hashCode,
  181. PKIX_PL_EqualsCallback keyComp,
  182. void *plContext)
  183. {
  184. pkix_pl_HT_Elem **elemPtr = NULL;
  185. pkix_pl_HT_Elem *element = NULL;
  186. PKIX_Boolean compResult = PKIX_FALSE;
  187. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Add");
  188. PKIX_NULLCHECK_THREE(ht, key, value);
  189. for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr;
  190. element != NULL; elemPtr = &(element->next), element = *elemPtr) {
  191. if (element->hashCode != hashCode){
  192. /* no possibility of a match */
  193. continue;
  194. }
  195. if (keyComp == NULL){
  196. PKIX_CHECK(pkix_pl_KeyComparator_Default
  197. ((PKIX_UInt32 *)key,
  198. (PKIX_UInt32 *)(element->key),
  199. &compResult,
  200. plContext),
  201. PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
  202. } else {
  203. PKIX_CHECK(keyComp
  204. ((PKIX_PL_Object *)key,
  205. (PKIX_PL_Object *)(element->key),
  206. &compResult,
  207. plContext),
  208. PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
  209. }
  210. if ((element->hashCode == hashCode) &&
  211. (compResult == PKIX_TRUE)){
  212. /* Same key already exists in the table */
  213. PKIX_ERROR(PKIX_ATTEMPTTOADDDUPLICATEKEY);
  214. }
  215. }
  216. /* Next Element should be NULL at this point */
  217. if (element != NULL) {
  218. PKIX_ERROR(PKIX_ERRORTRAVERSINGBUCKET);
  219. }
  220. /* Create a new HT_Elem */
  221. PKIX_CHECK(PKIX_PL_Malloc
  222. (sizeof (pkix_pl_HT_Elem), (void **)elemPtr, plContext),
  223. PKIX_MALLOCFAILED);
  224. element = *elemPtr;
  225. element->key = key;
  226. element->value = value;
  227. element->hashCode = hashCode;
  228. element->next = NULL;
  229. cleanup:
  230. PKIX_RETURN(HASHTABLE);
  231. }
  232. /*
  233. * FUNCTION: pkix_pl_PrimHashTable_Remove
  234. * DESCRIPTION:
  235. *
  236. * Removes any objects with the key pointed to by "key" and hashCode value
  237. * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
  238. * function pointed to by "keyComp" to compare keys, and stores the object's
  239. * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
  240. * This function sets "pResult" to NULL if the key is not in the hashtable.
  241. *
  242. * PARAMETERS:
  243. * "ht"
  244. * Address of PrimHashtable to remove object. Must be non-NULL.
  245. * "key"
  246. * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
  247. * Must be non-NULL.
  248. * "value"
  249. * Address of Object to be added to PrimHashtable. Must be non-NULL.
  250. * "hashCode"
  251. * Hashcode value of the key.
  252. * "keyComp"
  253. * Address of function used to determine if two keys are equal.
  254. * If NULL, pkix_pl_KeyComparator_Default is used.
  255. * "pResult"
  256. * Address where value will be stored. Must be non-NULL.
  257. * "plContext"
  258. * Platform-specific context pointer.
  259. * THREAD SAFETY:
  260. * Not Thread Safe - assumes exclusive access to "ht"
  261. * (see Thread Safety Definitions in Programmer's Guide)
  262. * RETURNS:
  263. * Returns NULL if the function succeeds.
  264. * Returns a HashTable Error if the function fails in a non-fatal way.
  265. * Returns a Fatal Error if the function fails in an unrecoverable way.
  266. */
  267. PKIX_Error *
  268. pkix_pl_PrimHashTable_Remove(
  269. pkix_pl_PrimHashTable *ht,
  270. void *key,
  271. PKIX_UInt32 hashCode,
  272. PKIX_PL_EqualsCallback keyComp,
  273. void **pKey,
  274. void **pValue,
  275. void *plContext)
  276. {
  277. pkix_pl_HT_Elem *element = NULL;
  278. pkix_pl_HT_Elem *prior = NULL;
  279. PKIX_Boolean compResult;
  280. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
  281. PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue);
  282. *pKey = NULL;
  283. *pValue = NULL;
  284. for (element = ht->buckets[hashCode%ht->size], prior = element;
  285. (element != NULL);
  286. prior = element, element = element->next) {
  287. if (element->hashCode != hashCode){
  288. /* no possibility of a match */
  289. continue;
  290. }
  291. if (keyComp == NULL){
  292. PKIX_CHECK(pkix_pl_KeyComparator_Default
  293. ((PKIX_UInt32 *)key,
  294. (PKIX_UInt32 *)(element->key),
  295. &compResult,
  296. plContext),
  297. PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
  298. } else {
  299. PKIX_CHECK(keyComp
  300. ((PKIX_PL_Object *)key,
  301. (PKIX_PL_Object *)(element->key),
  302. &compResult,
  303. plContext),
  304. PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
  305. }
  306. if ((element->hashCode == hashCode) &&
  307. (compResult == PKIX_TRUE)){
  308. if (element != prior) {
  309. prior->next = element->next;
  310. } else {
  311. ht->buckets[hashCode%ht->size] = element->next;
  312. }
  313. *pKey = element->key;
  314. *pValue = element->value;
  315. element->key = NULL;
  316. element->value = NULL;
  317. element->next = NULL;
  318. PKIX_FREE(element);
  319. goto cleanup;
  320. }
  321. }
  322. cleanup:
  323. PKIX_RETURN(HASHTABLE);
  324. }
  325. /*
  326. * FUNCTION: pkix_pl_HashTableLookup
  327. * DESCRIPTION:
  328. *
  329. * Looks up object using the key pointed to by "key" and hashCode value
  330. * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
  331. * function pointed to by "keyComp" to compare keys, and stores the object's
  332. * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
  333. * This function sets "pResult" to NULL if the key is not in the hashtable.
  334. *
  335. * PARAMETERS:
  336. * "ht"
  337. * Address of PrimHashtable to lookup object from. Must be non-NULL.
  338. * "key"
  339. * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
  340. * Must be non-NULL.
  341. * "keyComp"
  342. * Address of function used to determine if two keys are equal.
  343. * If NULL, pkix_pl_KeyComparator_Default is used.
  344. * "hashCode"
  345. * Hashcode value of the key.
  346. * "pResult"
  347. * Address where value will be stored. Must be non-NULL.
  348. * "plContext"
  349. * Platform-specific context pointer.
  350. * THREAD SAFETY:
  351. * Conditionally Thread Safe
  352. * (see Thread Safety Definitions in Programmer's Guide)
  353. * RETURNS:
  354. * Returns NULL if the function succeeds.
  355. * Returns a Fatal Error if the function fails in an unrecoverable way.
  356. */
  357. PKIX_Error *
  358. pkix_pl_PrimHashTable_Lookup(
  359. pkix_pl_PrimHashTable *ht,
  360. void *key,
  361. PKIX_UInt32 hashCode,
  362. PKIX_PL_EqualsCallback keyComp,
  363. void **pResult,
  364. void *plContext)
  365. {
  366. pkix_pl_HT_Elem *element = NULL;
  367. PKIX_Boolean compResult = PKIX_FALSE;
  368. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Lookup");
  369. PKIX_NULLCHECK_THREE(ht, key, pResult);
  370. *pResult = NULL;
  371. for (element = (ht->buckets)[hashCode%ht->size];
  372. (element != NULL) && (*pResult == NULL);
  373. element = element->next) {
  374. if (element->hashCode != hashCode){
  375. /* no possibility of a match */
  376. continue;
  377. }
  378. if (keyComp == NULL){
  379. PKIX_CHECK(pkix_pl_KeyComparator_Default
  380. ((PKIX_UInt32 *)key,
  381. (PKIX_UInt32 *)(element->key),
  382. &compResult,
  383. plContext),
  384. PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
  385. } else {
  386. pkixErrorResult =
  387. keyComp((PKIX_PL_Object *)key,
  388. (PKIX_PL_Object *)(element->key),
  389. &compResult,
  390. plContext);
  391. if (pkixErrorResult) {
  392. pkixErrorClass = PKIX_FATAL_ERROR;
  393. pkixErrorCode = PKIX_COULDNOTTESTWHETHERKEYSEQUAL;
  394. goto cleanup;
  395. }
  396. }
  397. if ((element->hashCode == hashCode) &&
  398. (compResult == PKIX_TRUE)){
  399. *pResult = element->value;
  400. goto cleanup;
  401. }
  402. }
  403. /* if we've reached here, specified key doesn't exist in hashtable */
  404. *pResult = NULL;
  405. cleanup:
  406. PKIX_RETURN(HASHTABLE);
  407. }
  408. /*
  409. * FUNCTION: pkix_pl_PrimHashTable_Destroy
  410. *
  411. * Destroys PrimHashTable pointed to by "ht".
  412. *
  413. * PARAMETERS:
  414. * "ht"
  415. * Address of PrimHashtable to free. Must be non-NULL.
  416. * "plContext"
  417. * Platform-specific context pointer.
  418. * THREAD SAFETY:
  419. * Not Thread Safe - assumes exclusive access to "ht"
  420. * (see Thread Safety Definitions in Programmer's Guide)
  421. * RETURNS
  422. * Returns NULL if the function succeeds.
  423. * Returns a HashTable Error if the function fails in a non-fatal way.
  424. * Returns a Fatal Error if the function fails in an unrecoverable way.
  425. */
  426. PKIX_Error *
  427. pkix_pl_PrimHashTable_Destroy(
  428. pkix_pl_PrimHashTable *ht,
  429. void *plContext)
  430. {
  431. pkix_pl_HT_Elem *element = NULL;
  432. pkix_pl_HT_Elem *temp = NULL;
  433. PKIX_UInt32 i;
  434. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Destroy");
  435. PKIX_NULLCHECK_ONE(ht);
  436. /* Free each element (list) */
  437. for (i = 0; i < ht->size; i++) {
  438. for (element = ht->buckets[i];
  439. element != NULL;
  440. element = temp) {
  441. temp = element->next;
  442. element->value = NULL;
  443. element->key = NULL;
  444. element->hashCode = 0;
  445. element->next = NULL;
  446. PKIX_FREE(element);
  447. }
  448. }
  449. /* Free the pointer to the list array */
  450. PKIX_FREE(ht->buckets);
  451. ht->size = 0;
  452. /* Free the table itself */
  453. PKIX_FREE(ht);
  454. PKIX_RETURN(HASHTABLE);
  455. }
  456. /*
  457. * FUNCTION: pkix_pl_PrimHashTable_GetBucketSize
  458. * DESCRIPTION:
  459. *
  460. * Retruns number of entries in the bucket the "hashCode" is designated in
  461. * the hashtable "ht" in the address "pBucketSize".
  462. *
  463. * PARAMETERS:
  464. * "ht"
  465. * Address of PrimHashtable to get entries count. Must be non-NULL.
  466. * "hashCode"
  467. * Hashcode value of the key.
  468. * "pBucketSize"
  469. * Address that an PKIX_UInt32 is returned for number of entries in the
  470. * bucket associated with the hashCode. Must be non-NULL.
  471. * "plContext"
  472. * Platform-specific context pointer.
  473. * THREAD SAFETY:
  474. * Not Thread Safe - assumes exclusive access to "ht"
  475. * (see Thread Safety Definitions in Programmer's Guide)
  476. * RETURNS:
  477. * Returns NULL if the function succeeds.
  478. * Returns a HashTable Error if the function fails in a non-fatal way.
  479. * Returns a Fatal Error if the function fails in an unrecoverable way.
  480. */
  481. PKIX_Error *
  482. pkix_pl_PrimHashTable_GetBucketSize(
  483. pkix_pl_PrimHashTable *ht,
  484. PKIX_UInt32 hashCode,
  485. PKIX_UInt32 *pBucketSize,
  486. void *plContext)
  487. {
  488. pkix_pl_HT_Elem **elemPtr = NULL;
  489. pkix_pl_HT_Elem *element = NULL;
  490. PKIX_UInt32 bucketSize = 0;
  491. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_GetBucketSize");
  492. PKIX_NULLCHECK_TWO(ht, pBucketSize);
  493. for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr;
  494. element != NULL; elemPtr = &(element->next), element = *elemPtr) {
  495. bucketSize++;
  496. }
  497. *pBucketSize = bucketSize;
  498. PKIX_RETURN(HASHTABLE);
  499. }
  500. /*
  501. * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO
  502. * DESCRIPTION:
  503. *
  504. * Remove the first entry in the bucket the "hashCode" is designated in
  505. * the hashtable "ht". Since new entry is added at end of the link list
  506. * the first one is the oldest (FI) therefore removed first (FO).
  507. *
  508. * PARAMETERS:
  509. * "ht"
  510. * Address of PrimHashtable to get entries count. Must be non-NULL.
  511. * "hashCode"
  512. * Hashcode value of the key.
  513. * "pKey"
  514. * Address of key of the entry deleted. Must be non-NULL.
  515. * "pValue"
  516. * Address of Value of the entry deleted. Must be non-NULL.
  517. * "plContext"
  518. * Platform-specific context pointer.
  519. * THREAD SAFETY:
  520. * Not Thread Safe - assumes exclusive access to "ht"
  521. * (see Thread Safety Definitions in Programmer's Guide)
  522. * RETURNS:
  523. * Returns NULL if the function succeeds.
  524. * Returns a HashTable Error if the function fails in a non-fatal way.
  525. * Returns a Fatal Error if the function fails in an unrecoverable way.
  526. */
  527. PKIX_Error *
  528. pkix_pl_PrimHashTable_RemoveFIFO(
  529. pkix_pl_PrimHashTable *ht,
  530. PKIX_UInt32 hashCode,
  531. void **pKey,
  532. void **pValue,
  533. void *plContext)
  534. {
  535. pkix_pl_HT_Elem *element = NULL;
  536. PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
  537. PKIX_NULLCHECK_THREE(ht, pKey, pValue);
  538. element = (ht->buckets)[hashCode%ht->size];
  539. if (element != NULL) {
  540. *pKey = element->key;
  541. *pValue = element->value;
  542. ht->buckets[hashCode%ht->size] = element->next;
  543. element->key = NULL;
  544. element->value = NULL;
  545. element->next = NULL;
  546. PKIX_FREE(element);
  547. }
  548. PKIX_RETURN(HASHTABLE);
  549. }