OLD | NEW |
| (Empty) |
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 * pkix_pl_object.c | |
6 * | |
7 * Object Construction, Destruction and Callback Functions | |
8 * | |
9 */ | |
10 | |
11 #include "pkix_pl_object.h" | |
12 | |
13 #ifdef PKIX_USER_OBJECT_TYPE | |
14 /* --Class-Table-Initializers------------------------------------ */ | |
15 | |
16 /* | |
17 * Create storage space for 20 Class Table buckets. | |
18 * These are only for user-defined types. System types are registered | |
19 * separately by PKIX_PL_Initialize. | |
20 */ | |
21 | |
22 static pkix_pl_HT_Elem* | |
23 pkix_Raw_ClassTable_Buckets[] = { | |
24 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
25 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL | |
26 }; | |
27 | |
28 /* | |
29 * Allocate static memory for a ClassTable. | |
30 * XXX This assumes the bucket pointer will fit into a PKIX_UInt32 | |
31 */ | |
32 static pkix_pl_PrimHashTable pkix_Raw_ClassTable = { | |
33 (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */ | |
34 20 /* Number of Buckets */ | |
35 }; | |
36 static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable; | |
37 #endif /* PKIX_USER_OBJECT_TYPE */ | |
38 | |
39 /* --Private-Functions-------------------------------------------- */ | |
40 | |
41 /* | |
42 * FUNCTION: pkix_pl_Object_GetHeader | |
43 * DESCRIPTION: | |
44 * | |
45 * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and | |
46 * stores the value at "pObjectHeader". | |
47 * | |
48 * PARAMETERS: | |
49 * "object" | |
50 * Address of Object to shift. Must be non-NULL. | |
51 * "pObjectHeader" | |
52 * Address where object pointer will be stored. Must be non-NULL. | |
53 * "plContext" | |
54 * Platform-specific context pointer. | |
55 * THREAD SAFETY: | |
56 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
57 * RETURNS: | |
58 * Returns NULL if the function succeeds. | |
59 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
60 */ | |
61 static PKIX_Error * | |
62 pkix_pl_Object_GetHeader( | |
63 PKIX_PL_Object *object, | |
64 PKIX_PL_Object **pObjectHeader, | |
65 void *plContext) | |
66 { | |
67 PKIX_PL_Object *header = NULL; | |
68 PKIX_UInt32 objType; | |
69 | |
70 PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader"); | |
71 PKIX_NULLCHECK_TWO(object, pObjectHeader); | |
72 | |
73 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); | |
74 | |
75 /* The header is sizeof(PKIX_PL_Object) before the object pointer */ | |
76 header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object)); | |
77 | |
78 objType = header->type; | |
79 | |
80 if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */ | |
81 #ifdef PKIX_USER_OBJECT_TYPE | |
82 pkix_ClassTable_Entry *ctEntry = NULL; | |
83 | |
84 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
85 PR_Lock(classTableLock); | |
86 | |
87 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup | |
88 (classTable, | |
89 (void *)&objType, | |
90 objType, | |
91 NULL, | |
92 (void **)&ctEntry, | |
93 plContext), | |
94 PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
95 | |
96 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
97 PR_Unlock(classTableLock); | |
98 | |
99 if (ctEntry == NULL) { | |
100 PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE); | |
101 } | |
102 #else | |
103 PORT_Assert(objType < PKIX_NUMTYPES); | |
104 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
105 pkixErrorClass = PKIX_FATAL_ERROR; | |
106 goto cleanup; | |
107 #endif /* PKIX_USER_OBJECT_TYPE */ | |
108 } | |
109 | |
110 #ifdef PKIX_OBJECT_LEAK_TEST | |
111 PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER); | |
112 #endif /* PKIX_OBJECT_LEAK_TEST */ | |
113 | |
114 if ((header == NULL)|| | |
115 (header->magicHeader != PKIX_MAGIC_HEADER)) { | |
116 PKIX_ERROR_ALLOC_ERROR(); | |
117 } | |
118 | |
119 *pObjectHeader = header; | |
120 | |
121 cleanup: | |
122 | |
123 PKIX_RETURN(OBJECT); | |
124 } | |
125 | |
126 /* | |
127 * FUNCTION: pkix_Destroy_Object | |
128 * DESCRIPTION: | |
129 * | |
130 * Destroys and deallocates Object pointed to by "object". The caller is | |
131 * assumed to hold the Object's lock, which is acquired in | |
132 * PKIX_PL_Object_DecRef(). | |
133 * | |
134 * PARAMETERS: | |
135 * "object" | |
136 * Address of Object to destroy. Must be non-NULL. | |
137 * "plContext" | |
138 * Platform-specific context pointer. | |
139 * THREAD SAFETY: | |
140 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
141 * RETURNS: | |
142 * Returns NULL if the function succeeds. | |
143 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
144 */ | |
145 static PKIX_Error * | |
146 pkix_pl_Object_Destroy( | |
147 PKIX_PL_Object *object, | |
148 void *plContext) | |
149 { | |
150 PKIX_PL_Object *objectHeader = NULL; | |
151 | |
152 PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy"); | |
153 PKIX_NULLCHECK_ONE(object); | |
154 | |
155 #ifdef PKIX_OBJECT_LEAK_TEST | |
156 PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plConte
xt), | |
157 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
158 #else | |
159 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
160 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
161 #endif /* PKIX_OBJECT_LEAK_TEST */ | |
162 | |
163 /* Attempt to delete an object still being used */ | |
164 if (objectHeader->references != 0) { | |
165 PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED); | |
166 } | |
167 | |
168 PKIX_DECREF(objectHeader->stringRep); | |
169 | |
170 /* Destroy this object's lock */ | |
171 PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n"); | |
172 PR_DestroyLock(objectHeader->lock); | |
173 objectHeader->lock = NULL; | |
174 object = NULL; | |
175 | |
176 objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED; | |
177 | |
178 #ifdef PKIX_OBJECT_LEAK_TEST | |
179 memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSiz
e); | |
180 #endif | |
181 | |
182 PKIX_FREE(objectHeader); | |
183 | |
184 cleanup: | |
185 #ifdef PKIX_OBJECT_LEAK_TEST | |
186 fatal: | |
187 #endif | |
188 | |
189 PKIX_RETURN(OBJECT); | |
190 } | |
191 | |
192 /* --Default-Callbacks-------------------------------------------- */ | |
193 | |
194 /* | |
195 * FUNCTION: pkix_pl_Object_Equals_Default | |
196 * DESCRIPTION: | |
197 * | |
198 * Default Object_Equals callback: Compares the address of the Object pointed | |
199 * to by "firstObject" with the address of the Object pointed to by | |
200 * "secondObject" and stores the Boolean result at "pResult". | |
201 * | |
202 * PARAMETERS: | |
203 * "firstObject" | |
204 * Address of first Object to compare. Must be non-NULL. | |
205 * "secondObject" | |
206 * Address of second Object to compare. Must be non-NULL. | |
207 * "pResult" | |
208 * Address where Boolean result will be stored. Must be non-NULL. | |
209 * "plContext" | |
210 * Platform-specific context pointer. | |
211 * THREAD SAFETY: | |
212 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
213 * RETURNS: | |
214 * Returns NULL if the function succeeds. | |
215 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
216 */ | |
217 static PKIX_Error * | |
218 pkix_pl_Object_Equals_Default( | |
219 PKIX_PL_Object *firstObject, | |
220 PKIX_PL_Object *secondObject, | |
221 PKIX_Boolean *pResult, | |
222 void *plContext) | |
223 { | |
224 PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default"); | |
225 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
226 | |
227 /* Just compare pointer values */ | |
228 *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE; | |
229 | |
230 PKIX_RETURN(OBJECT); | |
231 } | |
232 | |
233 /* | |
234 * FUNCTION: pkix_pl_Object_ToString_Default | |
235 * DESCRIPTION: | |
236 * | |
237 * Default Object_ToString callback: Creates a string consisting of the | |
238 * typename and address of the Object pointed to by "object" and stores | |
239 * the result at "pString". The format for the string is | |
240 * "TypeName@Address: <address>", where the default typename is "Object". | |
241 * | |
242 * PARAMETERS: | |
243 * "object" | |
244 * Address of Object to convert to a string. Must be non-NULL. | |
245 * "pString" | |
246 * Address where object pointer will be stored. Must be non-NULL. | |
247 * "plContext" | |
248 * Platform-specific context pointer. | |
249 * THREAD SAFETY: | |
250 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
251 * RETURNS: | |
252 * Returns NULL if the function succeeds. | |
253 * Returns an Object Error if the function fails in a non-fatal way. | |
254 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
255 */ | |
256 static PKIX_Error * | |
257 pkix_pl_Object_ToString_Default( | |
258 PKIX_PL_Object *object, | |
259 PKIX_PL_String **pString, | |
260 void *plContext) | |
261 { | |
262 PKIX_PL_String *formatString = NULL; | |
263 PKIX_PL_String *descString = NULL; | |
264 char *format = "%s@Address: %x"; | |
265 char *description = NULL; | |
266 PKIX_UInt32 objType; | |
267 | |
268 PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default"); | |
269 PKIX_NULLCHECK_TWO(object, pString); | |
270 | |
271 PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext), | |
272 PKIX_OBJECTGETTYPEFAILED); | |
273 | |
274 if (objType >= PKIX_NUMTYPES){ | |
275 #ifdef PKIX_USER_OBJECT_TYPE | |
276 pkix_ClassTable_Entry *ctEntry = NULL; | |
277 | |
278 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
279 PR_Lock(classTableLock); | |
280 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
281 (classTable, | |
282 (void *)&objType, | |
283 objType, | |
284 NULL, | |
285 (void **)&ctEntry, | |
286 plContext); | |
287 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
288 PR_Unlock(classTableLock); | |
289 if (pkixErrorResult){ | |
290 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
291 } | |
292 | |
293 if (ctEntry == NULL){ | |
294 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY); | |
295 } else { | |
296 description = ctEntry->description; | |
297 if (description == NULL) { | |
298 description = "User Type Object"; | |
299 } | |
300 } | |
301 #else | |
302 PORT_Assert (0); | |
303 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
304 pkixErrorClass = PKIX_FATAL_ERROR; | |
305 goto cleanup; | |
306 #endif /* PKIX_USER_OBJECT_TYPE */ | |
307 } else { | |
308 description = systemClasses[objType].description; | |
309 } | |
310 PKIX_CHECK(PKIX_PL_String_Create | |
311 (PKIX_ESCASCII, | |
312 (void *)format, | |
313 0, | |
314 &formatString, | |
315 plContext), | |
316 PKIX_STRINGCREATEFAILED); | |
317 | |
318 PKIX_CHECK(PKIX_PL_String_Create | |
319 (PKIX_ESCASCII, | |
320 (void *)description, | |
321 0, | |
322 &descString, | |
323 plContext), | |
324 PKIX_STRINGCREATEFAILED); | |
325 | |
326 PKIX_CHECK(PKIX_PL_Sprintf | |
327 (pString, | |
328 plContext, | |
329 formatString, | |
330 descString, | |
331 object), | |
332 PKIX_SPRINTFFAILED); | |
333 | |
334 cleanup: | |
335 | |
336 PKIX_DECREF(formatString); | |
337 PKIX_DECREF(descString); | |
338 | |
339 PKIX_RETURN(OBJECT); | |
340 } | |
341 | |
342 /* | |
343 * FUNCTION: pkix_pl_Object_Hashcode_Default | |
344 * DESCRIPTION: | |
345 * | |
346 * Default Object_Hashcode callback. Creates the a hashcode value using the | |
347 * address of the Object pointed to by "object" and stores the result at | |
348 * "pValue". | |
349 * | |
350 * XXX This isn't great since addresses are not uniformly distributed. | |
351 * | |
352 * PARAMETERS: | |
353 * "object" | |
354 * Address of Object to compute hashcode for. Must be non-NULL. | |
355 * "pValue" | |
356 * Address where PKIX_UInt32 will be stored. Must be non-NULL. | |
357 * "plContext" | |
358 * Platform-specific context pointer. | |
359 * THREAD SAFETY: | |
360 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
361 * RETURNS: | |
362 * Returns NULL if the function succeeds. | |
363 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
364 */ | |
365 static PKIX_Error * | |
366 pkix_pl_Object_Hashcode_Default( | |
367 PKIX_PL_Object *object, | |
368 PKIX_UInt32 *pValue, | |
369 void *plContext) | |
370 { | |
371 PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default"); | |
372 PKIX_NULLCHECK_TWO(object, pValue); | |
373 | |
374 *pValue = (PKIX_UInt32)((char *)object - (char *)NULL); | |
375 | |
376 PKIX_RETURN(OBJECT); | |
377 } | |
378 | |
379 /* | |
380 * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback | |
381 * DESCRIPTION: | |
382 * | |
383 * Retrieves Equals callback function of Object pointed to by "object and | |
384 * stores it at "pEqualsCallback". If the object's type is one of the system | |
385 * types, its callback function is retrieved from the systemClasses array; | |
386 * otherwise, its callback function is retrieve from the classTable hash | |
387 * table where user-defined types are stored. | |
388 * | |
389 * PARAMETERS: | |
390 * "object" | |
391 * Address of Object whose equals callback is desired. Must be non-NULL. | |
392 * "pEqualsCallback" | |
393 * Address where EqualsCallback function pointer will be stored. | |
394 * Must be non-NULL. | |
395 * "plContext" | |
396 * Platform-specific context pointer. | |
397 * THREAD SAFETY: | |
398 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
399 * RETURNS: | |
400 * Returns NULL if the function succeeds. | |
401 * Returns an Object Error if the function fails in a non-fatal way. | |
402 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
403 */ | |
404 PKIX_Error * | |
405 pkix_pl_Object_RetrieveEqualsCallback( | |
406 PKIX_PL_Object *object, | |
407 PKIX_PL_EqualsCallback *pEqualsCallback, | |
408 void *plContext) | |
409 { | |
410 PKIX_PL_Object *objectHeader = NULL; | |
411 PKIX_PL_EqualsCallback func = NULL; | |
412 pkix_ClassTable_Entry entry; | |
413 PKIX_UInt32 objType; | |
414 | |
415 PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback"); | |
416 PKIX_NULLCHECK_TWO(object, pEqualsCallback); | |
417 | |
418 PKIX_CHECK(pkix_pl_Object_GetHeader | |
419 (object, &objectHeader, plContext), | |
420 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
421 | |
422 objType = objectHeader->type; | |
423 | |
424 if (objType >= PKIX_NUMTYPES){ | |
425 #ifdef PKIX_USER_OBJECT_TYPE | |
426 pkix_ClassTable_Entry *ctEntry = NULL; | |
427 | |
428 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
429 PR_Lock(classTableLock); | |
430 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
431 (classTable, | |
432 (void *)&objType, | |
433 objType, | |
434 NULL, | |
435 (void **)&ctEntry, | |
436 plContext); | |
437 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
438 PR_Unlock(classTableLock); | |
439 if (pkixErrorResult){ | |
440 PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
441 } | |
442 | |
443 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { | |
444 PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK); | |
445 } else { | |
446 *pEqualsCallback = ctEntry->equalsFunction; | |
447 } | |
448 #else | |
449 PORT_Assert (0); | |
450 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
451 pkixErrorClass = PKIX_FATAL_ERROR; | |
452 goto cleanup; | |
453 #endif /* PKIX_USER_OBJECT_TYPE */ | |
454 } else { | |
455 entry = systemClasses[objType]; | |
456 func = entry.equalsFunction; | |
457 if (func == NULL){ | |
458 func = pkix_pl_Object_Equals_Default; | |
459 } | |
460 *pEqualsCallback = func; | |
461 } | |
462 | |
463 cleanup: | |
464 | |
465 PKIX_RETURN(OBJECT); | |
466 } | |
467 | |
468 /* | |
469 * FUNCTION: pkix_pl_Object_RegisterSelf | |
470 * DESCRIPTION: | |
471 * Registers PKIX_OBJECT_TYPE and its related functions with systemClasses[] | |
472 * THREAD SAFETY: | |
473 * Not Thread Safe - for performance and complexity reasons | |
474 * | |
475 * Since this function is only called by PKIX_PL_Initialize, which should | |
476 * only be called once, it is acceptable that this function is not | |
477 * thread-safe. | |
478 * | |
479 * PKIX_PL_Object should have all function pointes to be to NULL: they | |
480 * work as proxy function to a real objects. | |
481 * | |
482 */ | |
483 PKIX_Error * | |
484 pkix_pl_Object_RegisterSelf(void *plContext) | |
485 { | |
486 pkix_ClassTable_Entry entry; | |
487 | |
488 PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf"); | |
489 | |
490 entry.description = "Object"; | |
491 entry.objCounter = 0; | |
492 entry.typeObjectSize = sizeof(PKIX_PL_Object); | |
493 entry.destructor = NULL; | |
494 entry.equalsFunction = NULL; | |
495 entry.hashcodeFunction = NULL; | |
496 entry.toStringFunction = NULL; | |
497 entry.comparator = NULL; | |
498 entry.duplicateFunction = NULL; | |
499 | |
500 systemClasses[PKIX_OBJECT_TYPE] = entry; | |
501 | |
502 PKIX_RETURN(ERROR); | |
503 } | |
504 | |
505 /* --Public-Functions------------------------------------------------------- */ | |
506 | |
507 /* | |
508 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h) | |
509 */ | |
510 PKIX_Error * | |
511 PKIX_PL_Object_Alloc( | |
512 PKIX_TYPENUM objType, | |
513 PKIX_UInt32 size, | |
514 PKIX_PL_Object **pObject, | |
515 void *plContext) | |
516 { | |
517 PKIX_PL_Object *object = NULL; | |
518 pkix_ClassTable_Entry *ctEntry = NULL; | |
519 | |
520 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc"); | |
521 PKIX_NULLCHECK_ONE(pObject); | |
522 | |
523 /* | |
524 * We need to ensure that user-defined types have been registered. | |
525 * All system types have already been registered by PKIX_PL_Initialize. | |
526 */ | |
527 | |
528 if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type *
/ | |
529 #ifdef PKIX_USER_OBJECT_TYPE | |
530 PKIX_Boolean typeRegistered; | |
531 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
532 PR_Lock(classTableLock); | |
533 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
534 (classTable, | |
535 (void *)&objType, | |
536 objType, | |
537 NULL, | |
538 (void **)&ctEntry, | |
539 plContext); | |
540 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
541 PR_Unlock(classTableLock); | |
542 if (pkixErrorResult){ | |
543 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); | |
544 } | |
545 | |
546 typeRegistered = (ctEntry != NULL); | |
547 | |
548 if (!typeRegistered) { | |
549 PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT); | |
550 } | |
551 #else | |
552 PORT_Assert (0); | |
553 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
554 pkixErrorClass = PKIX_FATAL_ERROR; | |
555 goto cleanup; | |
556 #endif /* PKIX_USER_OBJECT_TYPE */ | |
557 } else { | |
558 ctEntry = &systemClasses[objType]; | |
559 } | |
560 | |
561 PORT_Assert(size == ctEntry->typeObjectSize); | |
562 | |
563 /* Allocate space for the object header and the requested size */ | |
564 #ifdef PKIX_OBJECT_LEAK_TEST | |
565 PKIX_CHECK(PKIX_PL_Calloc | |
566 (1, | |
567 ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, | |
568 (void **)&object, | |
569 plContext), | |
570 PKIX_MALLOCFAILED); | |
571 #else | |
572 PKIX_CHECK(PKIX_PL_Malloc | |
573 (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, | |
574 (void **)&object, | |
575 plContext), | |
576 PKIX_MALLOCFAILED); | |
577 #endif /* PKIX_OBJECT_LEAK_TEST */ | |
578 | |
579 /* Initialize all object fields */ | |
580 object->magicHeader = PKIX_MAGIC_HEADER; | |
581 object->type = objType; | |
582 object->references = 1; /* Default to a single reference */ | |
583 object->stringRep = NULL; | |
584 object->hashcode = 0; | |
585 object->hashcodeCached = 0; | |
586 | |
587 /* Cannot use PKIX_PL_Mutex because it depends on Object */ | |
588 /* Using NSPR Locks instead */ | |
589 PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n"); | |
590 object->lock = PR_NewLock(); | |
591 if (object->lock == NULL) { | |
592 PKIX_ERROR_ALLOC_ERROR(); | |
593 } | |
594 | |
595 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); | |
596 | |
597 | |
598 /* Return a pointer to the user data. Need to offset by object size */ | |
599 *pObject = object + 1; | |
600 object = NULL; | |
601 | |
602 /* Atomically increment object counter */ | |
603 PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter); | |
604 | |
605 cleanup: | |
606 | |
607 PKIX_FREE(object); | |
608 | |
609 PKIX_RETURN(OBJECT); | |
610 } | |
611 | |
612 /* | |
613 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h) | |
614 */ | |
615 PKIX_Error * | |
616 PKIX_PL_Object_IsTypeRegistered( | |
617 PKIX_UInt32 objType, | |
618 PKIX_Boolean *pBool, | |
619 void *plContext) | |
620 { | |
621 #ifdef PKIX_USER_OBJECT_TYPE | |
622 pkix_ClassTable_Entry *ctEntry = NULL; | |
623 #endif | |
624 | |
625 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered"); | |
626 PKIX_NULLCHECK_ONE(pBool); | |
627 | |
628 /* first, we handle the system types */ | |
629 if (objType < PKIX_NUMTYPES) { | |
630 *pBool = PKIX_TRUE; | |
631 goto cleanup; | |
632 } | |
633 | |
634 #ifndef PKIX_USER_OBJECT_TYPE | |
635 PORT_Assert (0); | |
636 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
637 pkixErrorClass = PKIX_FATAL_ERROR; | |
638 #else | |
639 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
640 PR_Lock(classTableLock); | |
641 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
642 (classTable, | |
643 (void *)&objType, | |
644 objType, | |
645 NULL, | |
646 (void **)&ctEntry, | |
647 plContext); | |
648 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
649 PR_Unlock(classTableLock); | |
650 | |
651 if (pkixErrorResult){ | |
652 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); | |
653 } | |
654 | |
655 *pBool = (ctEntry != NULL); | |
656 #endif /* PKIX_USER_OBJECT_TYPE */ | |
657 | |
658 cleanup: | |
659 | |
660 PKIX_RETURN(OBJECT); | |
661 } | |
662 | |
663 #ifdef PKIX_USER_OBJECT_TYPE | |
664 /* | |
665 * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h) | |
666 */ | |
667 PKIX_Error * | |
668 PKIX_PL_Object_RegisterType( | |
669 PKIX_UInt32 objType, | |
670 char *description, | |
671 PKIX_PL_DestructorCallback destructor, | |
672 PKIX_PL_EqualsCallback equalsFunction, | |
673 PKIX_PL_HashcodeCallback hashcodeFunction, | |
674 PKIX_PL_ToStringCallback toStringFunction, | |
675 PKIX_PL_ComparatorCallback comparator, | |
676 PKIX_PL_DuplicateCallback duplicateFunction, | |
677 void *plContext) | |
678 { | |
679 pkix_ClassTable_Entry *ctEntry = NULL; | |
680 pkix_pl_Integer *key = NULL; | |
681 | |
682 PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType"); | |
683 | |
684 /* | |
685 * System types are registered on startup by PKIX_PL_Initialize. | |
686 * These can not be overwritten. | |
687 */ | |
688 | |
689 if (objType < PKIX_NUMTYPES) { /* if this is a system type */ | |
690 PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE); | |
691 } | |
692 | |
693 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
694 PR_Lock(classTableLock); | |
695 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup | |
696 (classTable, | |
697 (void *)&objType, | |
698 objType, | |
699 NULL, | |
700 (void **)&ctEntry, | |
701 plContext), | |
702 PKIX_PRIMHASHTABLELOOKUPFAILED); | |
703 | |
704 /* If the type is already registered, throw an error */ | |
705 if (ctEntry) { | |
706 PKIX_ERROR(PKIX_TYPEALREADYREGISTERED); | |
707 } | |
708 | |
709 PKIX_CHECK(PKIX_PL_Malloc | |
710 (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)), | |
711 (void **)&ctEntry, | |
712 plContext), | |
713 PKIX_MALLOCFAILED); | |
714 | |
715 /* Set Default Values if none specified */ | |
716 | |
717 if (description == NULL){ | |
718 description = "Object"; | |
719 } | |
720 | |
721 if (equalsFunction == NULL) { | |
722 equalsFunction = pkix_pl_Object_Equals_Default; | |
723 } | |
724 | |
725 if (toStringFunction == NULL) { | |
726 toStringFunction = pkix_pl_Object_ToString_Default; | |
727 } | |
728 | |
729 if (hashcodeFunction == NULL) { | |
730 hashcodeFunction = pkix_pl_Object_Hashcode_Default; | |
731 } | |
732 | |
733 ctEntry->destructor = destructor; | |
734 ctEntry->equalsFunction = equalsFunction; | |
735 ctEntry->toStringFunction = toStringFunction; | |
736 ctEntry->hashcodeFunction = hashcodeFunction; | |
737 ctEntry->comparator = comparator; | |
738 ctEntry->duplicateFunction = duplicateFunction; | |
739 ctEntry->description = description; | |
740 | |
741 PKIX_CHECK(PKIX_PL_Malloc | |
742 (((PKIX_UInt32)sizeof (pkix_pl_Integer)), | |
743 (void **)&key, | |
744 plContext), | |
745 PKIX_COULDNOTMALLOCNEWKEY); | |
746 | |
747 key->ht_int = objType; | |
748 | |
749 PKIX_CHECK(pkix_pl_PrimHashTable_Add | |
750 (classTable, | |
751 (void *)key, | |
752 (void *)ctEntry, | |
753 objType, | |
754 NULL, | |
755 plContext), | |
756 PKIX_PRIMHASHTABLEADDFAILED); | |
757 | |
758 cleanup: | |
759 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
760 PR_Unlock(classTableLock); | |
761 | |
762 PKIX_RETURN(OBJECT); | |
763 } | |
764 #endif /* PKIX_USER_OBJECT_TYPE */ | |
765 | |
766 /* | |
767 * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h) | |
768 */ | |
769 PKIX_Error * | |
770 PKIX_PL_Object_IncRef( | |
771 PKIX_PL_Object *object, | |
772 void *plContext) | |
773 { | |
774 PKIX_PL_Object *objectHeader = NULL; | |
775 PKIX_PL_NssContext *context = NULL; | |
776 PKIX_Int32 refCount = 0; | |
777 | |
778 PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef"); | |
779 PKIX_NULLCHECK_ONE(object); | |
780 | |
781 if (plContext){ | |
782 /* | |
783 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't | |
784 * have a header therefore we cannot verify its type before | |
785 * casting. | |
786 */ | |
787 context = (PKIX_PL_NssContext *) plContext; | |
788 if (context->arena != NULL) { | |
789 goto cleanup; | |
790 } | |
791 } | |
792 | |
793 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { | |
794 goto cleanup; | |
795 } | |
796 | |
797 /* Shift pointer from user data to object header */ | |
798 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
799 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
800 | |
801 /* This object should never have zero references */ | |
802 refCount = PR_ATOMIC_INCREMENT(&objectHeader->references); | |
803 | |
804 if (refCount <= 1) { | |
805 PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES); | |
806 } | |
807 | |
808 cleanup: | |
809 | |
810 PKIX_RETURN(OBJECT); | |
811 } | |
812 | |
813 /* | |
814 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h) | |
815 */ | |
816 PKIX_Error * | |
817 PKIX_PL_Object_DecRef( | |
818 PKIX_PL_Object *object, | |
819 void *plContext) | |
820 { | |
821 PKIX_Int32 refCount = 0; | |
822 PKIX_PL_Object *objectHeader = NULL; | |
823 PKIX_PL_NssContext *context = NULL; | |
824 | |
825 PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef"); | |
826 PKIX_NULLCHECK_ONE(object); | |
827 | |
828 if (plContext){ | |
829 /* | |
830 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't | |
831 * have a header therefore we cannot verify its type before | |
832 * casting. | |
833 */ | |
834 context = (PKIX_PL_NssContext *) plContext; | |
835 if (context->arena != NULL) { | |
836 goto cleanup; | |
837 } | |
838 } | |
839 | |
840 if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { | |
841 goto cleanup; | |
842 } | |
843 | |
844 /* Shift pointer from user data to object header */ | |
845 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
846 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
847 | |
848 refCount = PR_ATOMIC_DECREMENT(&objectHeader->references); | |
849 | |
850 if (refCount == 0) { | |
851 PKIX_PL_DestructorCallback destructor = NULL; | |
852 pkix_ClassTable_Entry *ctEntry = NULL; | |
853 PKIX_UInt32 objType = objectHeader->type; | |
854 | |
855 /* first, special handling for system types */ | |
856 if (objType >= PKIX_NUMTYPES){ | |
857 #ifdef PKIX_USER_OBJECT_TYPE | |
858 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
859 PR_Lock(classTableLock); | |
860 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
861 (classTable, | |
862 (void *)&objType, | |
863 objType, | |
864 NULL, | |
865 (void **)&ctEntry, | |
866 plContext); | |
867 PKIX_OBJECT_DEBUG | |
868 ("\tCalling PR_Unlock).\n"); | |
869 PR_Unlock(classTableLock); | |
870 if (pkixErrorResult){ | |
871 PKIX_ERROR_FATAL | |
872 (PKIX_ERRORINGETTINGDESTRUCTOR); | |
873 } | |
874 | |
875 if (ctEntry != NULL){ | |
876 destructor = ctEntry->destructor; | |
877 } | |
878 #else | |
879 PORT_Assert (0); | |
880 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
881 pkixErrorClass = PKIX_FATAL_ERROR; | |
882 goto cleanup; | |
883 #endif /* PKIX_USER_OBJECT_TYPE */ | |
884 } else { | |
885 ctEntry = &systemClasses[objType]; | |
886 destructor = ctEntry->destructor; | |
887 } | |
888 | |
889 if (destructor != NULL){ | |
890 /* Call destructor on user data if necessary */ | |
891 pkixErrorResult = destructor(object, plContext); | |
892 if (pkixErrorResult) { | |
893 pkixErrorClass = PKIX_FATAL_ERROR; | |
894 PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext); | |
895 pkixErrorResult = NULL; | |
896 } | |
897 } | |
898 | |
899 /* Atomically decrement object counter */ | |
900 PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter); | |
901 | |
902 /* pkix_pl_Object_Destroy assumes the lock is held */ | |
903 /* It will call unlock and destroy the object */ | |
904 pkixErrorResult = pkix_pl_Object_Destroy(object, plContext); | |
905 goto cleanup; | |
906 } | |
907 | |
908 if (refCount < 0) { | |
909 PKIX_ERROR_ALLOC_ERROR(); | |
910 } | |
911 | |
912 cleanup: | |
913 | |
914 PKIX_RETURN(OBJECT); | |
915 } | |
916 | |
917 | |
918 | |
919 /* | |
920 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h) | |
921 */ | |
922 PKIX_Error * | |
923 PKIX_PL_Object_Equals( | |
924 PKIX_PL_Object *firstObject, | |
925 PKIX_PL_Object *secondObject, | |
926 PKIX_Boolean *pResult, | |
927 void *plContext) | |
928 { | |
929 PKIX_PL_Object *firstObjectHeader = NULL; | |
930 PKIX_PL_Object *secondObjectHeader = NULL; | |
931 PKIX_PL_EqualsCallback func = NULL; | |
932 pkix_ClassTable_Entry entry; | |
933 PKIX_UInt32 objType; | |
934 | |
935 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals"); | |
936 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
937 | |
938 PKIX_CHECK(pkix_pl_Object_GetHeader | |
939 (firstObject, &firstObjectHeader, plContext), | |
940 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
941 | |
942 PKIX_CHECK(pkix_pl_Object_GetHeader | |
943 (secondObject, &secondObjectHeader, plContext), | |
944 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
945 | |
946 /* if hashcodes are cached but not equal, objects can't be equal */ | |
947 if (firstObjectHeader->hashcodeCached && | |
948 secondObjectHeader->hashcodeCached){ | |
949 if (firstObjectHeader->hashcode != | |
950 secondObjectHeader->hashcode){ | |
951 *pResult = PKIX_FALSE; | |
952 goto cleanup; | |
953 } | |
954 } | |
955 | |
956 objType = firstObjectHeader->type; | |
957 | |
958 if (objType >= PKIX_NUMTYPES) { | |
959 #ifdef PKIX_USER_OBJECT_TYPE | |
960 pkix_ClassTable_Entry *ctEntry = NULL; | |
961 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
962 PR_Lock(classTableLock); | |
963 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
964 (classTable, | |
965 (void *)&firstObjectHeader->type, | |
966 firstObjectHeader->type, | |
967 NULL, | |
968 (void **)&ctEntry, | |
969 plContext); | |
970 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
971 PR_Unlock(classTableLock); | |
972 | |
973 if (pkixErrorResult){ | |
974 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
975 } | |
976 | |
977 if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { | |
978 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
979 } else { | |
980 func = ctEntry->equalsFunction; | |
981 } | |
982 #else | |
983 PORT_Assert (0); | |
984 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
985 pkixErrorClass = PKIX_FATAL_ERROR; | |
986 goto cleanup; | |
987 #endif /* PKIX_USER_OBJECT_TYPE */ | |
988 } else { | |
989 entry = systemClasses[objType]; | |
990 func = entry.equalsFunction; | |
991 if (func == NULL){ | |
992 func = pkix_pl_Object_Equals_Default; | |
993 } | |
994 } | |
995 | |
996 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), | |
997 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
998 | |
999 cleanup: | |
1000 | |
1001 PKIX_RETURN(OBJECT); | |
1002 } | |
1003 | |
1004 /* | |
1005 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h) | |
1006 */ | |
1007 PKIX_Error * | |
1008 PKIX_PL_Object_Duplicate( | |
1009 PKIX_PL_Object *firstObject, | |
1010 PKIX_PL_Object **pNewObject, | |
1011 void *plContext) | |
1012 { | |
1013 PKIX_PL_Object *firstObjectHeader = NULL; | |
1014 PKIX_PL_DuplicateCallback func = NULL; | |
1015 pkix_ClassTable_Entry entry; | |
1016 PKIX_UInt32 objType; | |
1017 | |
1018 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate"); | |
1019 PKIX_NULLCHECK_TWO(firstObject, pNewObject); | |
1020 | |
1021 PKIX_CHECK(pkix_pl_Object_GetHeader | |
1022 (firstObject, &firstObjectHeader, plContext), | |
1023 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1024 | |
1025 objType = firstObjectHeader->type; | |
1026 | |
1027 if (objType >= PKIX_NUMTYPES) { | |
1028 #ifdef PKIX_USER_OBJECT_TYPE | |
1029 pkix_ClassTable_Entry *ctEntry = NULL; | |
1030 | |
1031 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
1032 PR_Lock(classTableLock); | |
1033 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
1034 (classTable, | |
1035 (void *)&objType, | |
1036 objType, | |
1037 NULL, | |
1038 (void **)&ctEntry, | |
1039 plContext); | |
1040 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
1041 PR_Unlock(classTableLock); | |
1042 | |
1043 if (pkixErrorResult){ | |
1044 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
1045 } | |
1046 | |
1047 if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) { | |
1048 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
1049 } else { | |
1050 func = ctEntry->duplicateFunction; | |
1051 } | |
1052 #else | |
1053 PORT_Assert (0); | |
1054 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
1055 pkixErrorClass = PKIX_FATAL_ERROR; | |
1056 goto cleanup; | |
1057 #endif /* PKIX_USER_OBJECT_TYPE */ | |
1058 } else { | |
1059 entry = systemClasses[objType]; | |
1060 func = entry.duplicateFunction; | |
1061 if (!func){ | |
1062 PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION); | |
1063 } | |
1064 } | |
1065 | |
1066 PKIX_CHECK(func(firstObject, pNewObject, plContext), | |
1067 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
1068 | |
1069 cleanup: | |
1070 | |
1071 PKIX_RETURN(OBJECT); | |
1072 } | |
1073 | |
1074 /* | |
1075 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h) | |
1076 */ | |
1077 PKIX_Error * | |
1078 PKIX_PL_Object_Hashcode( | |
1079 PKIX_PL_Object *object, | |
1080 PKIX_UInt32 *pValue, | |
1081 void *plContext) | |
1082 { | |
1083 PKIX_PL_Object *objectHeader = NULL; | |
1084 PKIX_PL_HashcodeCallback func = NULL; | |
1085 pkix_ClassTable_Entry entry; | |
1086 PKIX_UInt32 objectHash; | |
1087 | |
1088 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode"); | |
1089 PKIX_NULLCHECK_TWO(object, pValue); | |
1090 | |
1091 /* Shift pointer from user data to object header */ | |
1092 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
1093 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1094 | |
1095 /* if we don't have a cached copy from before, we create one */ | |
1096 if (!objectHeader->hashcodeCached){ | |
1097 | |
1098 PKIX_UInt32 objType = objectHeader->type; | |
1099 | |
1100 /* first, special handling for system types */ | |
1101 if (objType >= PKIX_NUMTYPES){ | |
1102 #ifdef PKIX_USER_OBJECT_TYPE | |
1103 pkix_ClassTable_Entry *ctEntry = NULL; | |
1104 | |
1105 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
1106 PR_Lock(classTableLock); | |
1107 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
1108 (classTable, | |
1109 (void *)&objType, | |
1110 objType, | |
1111 NULL, | |
1112 (void **)&ctEntry, | |
1113 plContext); | |
1114 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
1115 PR_Unlock(classTableLock); | |
1116 | |
1117 if (pkixErrorResult){ | |
1118 PKIX_ERROR_FATAL | |
1119 (PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
1120 } | |
1121 | |
1122 if ((ctEntry == NULL) || | |
1123 (ctEntry->hashcodeFunction == NULL)) { | |
1124 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
1125 } | |
1126 | |
1127 func = ctEntry->hashcodeFunction; | |
1128 #else | |
1129 PORT_Assert (0); | |
1130 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
1131 pkixErrorClass = PKIX_FATAL_ERROR; | |
1132 goto cleanup; | |
1133 #endif /* PKIX_USER_OBJECT_TYPE */ | |
1134 } else { | |
1135 entry = systemClasses[objType]; | |
1136 func = entry.hashcodeFunction; | |
1137 if (func == NULL){ | |
1138 func = pkix_pl_Object_Hashcode_Default; | |
1139 } | |
1140 } | |
1141 | |
1142 PKIX_CHECK(func(object, &objectHash, plContext), | |
1143 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
1144 | |
1145 if (!objectHeader->hashcodeCached){ | |
1146 | |
1147 PKIX_CHECK(pkix_LockObject(object, plContext), | |
1148 PKIX_ERRORLOCKINGOBJECT); | |
1149 | |
1150 if (!objectHeader->hashcodeCached){ | |
1151 /* save cached copy in case we need it again */ | |
1152 objectHeader->hashcode = objectHash; | |
1153 objectHeader->hashcodeCached = PKIX_TRUE; | |
1154 } | |
1155 | |
1156 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
1157 PKIX_ERRORUNLOCKINGOBJECT); | |
1158 } | |
1159 } | |
1160 | |
1161 *pValue = objectHeader->hashcode; | |
1162 | |
1163 cleanup: | |
1164 | |
1165 PKIX_RETURN(OBJECT); | |
1166 } | |
1167 | |
1168 /* | |
1169 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h) | |
1170 */ | |
1171 PKIX_Error * | |
1172 PKIX_PL_Object_ToString( | |
1173 PKIX_PL_Object *object, | |
1174 PKIX_PL_String **pString, | |
1175 void *plContext) | |
1176 { | |
1177 PKIX_PL_Object *objectHeader = NULL; | |
1178 PKIX_PL_ToStringCallback func = NULL; | |
1179 pkix_ClassTable_Entry entry; | |
1180 PKIX_PL_String *objectString = NULL; | |
1181 | |
1182 PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString"); | |
1183 PKIX_NULLCHECK_TWO(object, pString); | |
1184 | |
1185 /* Shift pointer from user data to object header */ | |
1186 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
1187 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1188 | |
1189 /* if we don't have a cached copy from before, we create one */ | |
1190 if (!objectHeader->stringRep){ | |
1191 | |
1192 PKIX_UInt32 objType = objectHeader->type; | |
1193 | |
1194 if (objType >= PKIX_NUMTYPES){ | |
1195 #ifdef PKIX_USER_OBJECT_TYPE | |
1196 pkix_ClassTable_Entry *ctEntry = NULL; | |
1197 | |
1198 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
1199 PR_Lock(classTableLock); | |
1200 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
1201 (classTable, | |
1202 (void *)&objType, | |
1203 objType, | |
1204 NULL, | |
1205 (void **)&ctEntry, | |
1206 plContext); | |
1207 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
1208 PR_Unlock(classTableLock); | |
1209 if (pkixErrorResult){ | |
1210 PKIX_ERROR_FATAL | |
1211 (PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
1212 } | |
1213 | |
1214 if ((ctEntry == NULL) || | |
1215 (ctEntry->toStringFunction == NULL)) { | |
1216 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); | |
1217 } | |
1218 | |
1219 func = ctEntry->toStringFunction; | |
1220 #else | |
1221 PORT_Assert (0); | |
1222 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
1223 pkixErrorClass = PKIX_FATAL_ERROR; | |
1224 goto cleanup; | |
1225 #endif /* PKIX_USER_OBJECT_TYPE */ | |
1226 } else { | |
1227 entry = systemClasses[objType]; | |
1228 func = entry.toStringFunction; | |
1229 if (func == NULL){ | |
1230 func = pkix_pl_Object_ToString_Default; | |
1231 } | |
1232 } | |
1233 | |
1234 PKIX_CHECK(func(object, &objectString, plContext), | |
1235 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
1236 | |
1237 if (!objectHeader->stringRep){ | |
1238 | |
1239 PKIX_CHECK(pkix_LockObject(object, plContext), | |
1240 PKIX_ERRORLOCKINGOBJECT); | |
1241 | |
1242 if (!objectHeader->stringRep){ | |
1243 /* save a cached copy */ | |
1244 objectHeader->stringRep = objectString; | |
1245 objectString = NULL; | |
1246 } | |
1247 | |
1248 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
1249 PKIX_ERRORUNLOCKINGOBJECT); | |
1250 } | |
1251 } | |
1252 | |
1253 | |
1254 *pString = objectHeader->stringRep; | |
1255 objectHeader->stringRep = NULL; | |
1256 | |
1257 cleanup: | |
1258 if (objectHeader) { | |
1259 PKIX_DECREF(objectHeader->stringRep); | |
1260 } | |
1261 PKIX_DECREF(objectString); | |
1262 | |
1263 PKIX_RETURN(OBJECT); | |
1264 } | |
1265 | |
1266 /* | |
1267 * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h) | |
1268 */ | |
1269 PKIX_Error * | |
1270 PKIX_PL_Object_InvalidateCache( | |
1271 PKIX_PL_Object *object, | |
1272 void *plContext) | |
1273 { | |
1274 PKIX_PL_Object *objectHeader = NULL; | |
1275 | |
1276 PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache"); | |
1277 PKIX_NULLCHECK_ONE(object); | |
1278 | |
1279 /* Shift pointer from user data to object header */ | |
1280 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
1281 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1282 | |
1283 PKIX_CHECK(pkix_LockObject(object, plContext), | |
1284 PKIX_ERRORLOCKINGOBJECT); | |
1285 | |
1286 /* invalidate hashcode */ | |
1287 objectHeader->hashcode = 0; | |
1288 objectHeader->hashcodeCached = PKIX_FALSE; | |
1289 | |
1290 PKIX_DECREF(objectHeader->stringRep); | |
1291 | |
1292 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
1293 PKIX_ERRORUNLOCKINGOBJECT); | |
1294 | |
1295 cleanup: | |
1296 | |
1297 PKIX_RETURN(OBJECT); | |
1298 } | |
1299 | |
1300 /* | |
1301 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h) | |
1302 */ | |
1303 PKIX_Error * | |
1304 PKIX_PL_Object_Compare( | |
1305 PKIX_PL_Object *firstObject, | |
1306 PKIX_PL_Object *secondObject, | |
1307 PKIX_Int32 *pResult, | |
1308 void *plContext) | |
1309 { | |
1310 PKIX_PL_Object *firstObjectHeader = NULL; | |
1311 PKIX_PL_Object *secondObjectHeader = NULL; | |
1312 PKIX_PL_ComparatorCallback func = NULL; | |
1313 pkix_ClassTable_Entry entry; | |
1314 PKIX_UInt32 objType; | |
1315 | |
1316 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare"); | |
1317 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
1318 | |
1319 /* Shift pointer from user data to object header */ | |
1320 PKIX_CHECK(pkix_pl_Object_GetHeader | |
1321 (firstObject, &firstObjectHeader, plContext), | |
1322 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1323 | |
1324 /* Shift pointer from user data to object header */ | |
1325 PKIX_CHECK(pkix_pl_Object_GetHeader | |
1326 (secondObject, &secondObjectHeader, plContext), | |
1327 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1328 | |
1329 objType = firstObjectHeader->type; | |
1330 | |
1331 if (objType >= PKIX_NUMTYPES){ | |
1332 #ifdef PKIX_USER_OBJECT_TYPE | |
1333 pkix_ClassTable_Entry *ctEntry = NULL; | |
1334 | |
1335 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); | |
1336 PR_Lock(classTableLock); | |
1337 pkixErrorResult = pkix_pl_PrimHashTable_Lookup | |
1338 (classTable, | |
1339 (void *)&objType, | |
1340 objType, | |
1341 NULL, | |
1342 (void **)&ctEntry, | |
1343 plContext); | |
1344 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); | |
1345 PR_Unlock(classTableLock); | |
1346 if (pkixErrorResult){ | |
1347 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); | |
1348 } | |
1349 | |
1350 if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) { | |
1351 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR); | |
1352 } | |
1353 | |
1354 func = ctEntry->comparator; | |
1355 #else | |
1356 PORT_Assert (0); | |
1357 pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; | |
1358 pkixErrorClass = PKIX_FATAL_ERROR; | |
1359 goto cleanup; | |
1360 #endif /* PKIX_USER_OBJECT_TYPE */ | |
1361 } else { | |
1362 /* special handling for system types */ | |
1363 entry = systemClasses[objType]; | |
1364 func = entry.comparator; | |
1365 if (!func){ | |
1366 PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR); | |
1367 } | |
1368 } | |
1369 | |
1370 PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), | |
1371 PKIX_OBJECTSPECIFICFUNCTIONFAILED); | |
1372 | |
1373 cleanup: | |
1374 | |
1375 PKIX_RETURN(OBJECT); | |
1376 } | |
1377 | |
1378 /* | |
1379 * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h) | |
1380 */ | |
1381 PKIX_Error * | |
1382 PKIX_PL_Object_Lock( | |
1383 PKIX_PL_Object *object, | |
1384 void *plContext) | |
1385 { | |
1386 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock"); | |
1387 PKIX_NULLCHECK_ONE(object); | |
1388 | |
1389 PKIX_CHECK(pkix_LockObject(object, plContext), | |
1390 PKIX_LOCKOBJECTFAILED); | |
1391 | |
1392 cleanup: | |
1393 | |
1394 PKIX_RETURN(OBJECT); | |
1395 } | |
1396 | |
1397 /* | |
1398 * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h) | |
1399 */ | |
1400 PKIX_Error * | |
1401 PKIX_PL_Object_Unlock( | |
1402 PKIX_PL_Object *object, | |
1403 void *plContext) | |
1404 { | |
1405 PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock"); | |
1406 PKIX_NULLCHECK_ONE(object); | |
1407 | |
1408 PKIX_CHECK(pkix_UnlockObject(object, plContext), | |
1409 PKIX_UNLOCKOBJECTFAILED); | |
1410 | |
1411 cleanup: | |
1412 | |
1413 PKIX_RETURN(OBJECT); | |
1414 } | |
1415 | |
1416 | |
1417 /* | |
1418 * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h) | |
1419 */ | |
1420 PKIX_Error * | |
1421 PKIX_PL_Object_GetType( | |
1422 PKIX_PL_Object *object, | |
1423 PKIX_UInt32 *pType, | |
1424 void *plContext) | |
1425 { | |
1426 PKIX_PL_Object *objectHeader = NULL; | |
1427 | |
1428 PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType"); | |
1429 PKIX_NULLCHECK_TWO(object, pType); | |
1430 | |
1431 /* Shift pointer from user data to object header */ | |
1432 PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), | |
1433 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); | |
1434 | |
1435 *pType = objectHeader->type; | |
1436 | |
1437 cleanup: | |
1438 | |
1439 PKIX_RETURN(OBJECT); | |
1440 } | |
OLD | NEW |