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 PKIX-C library.
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.
22 * Sun Microsystems, Inc.
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 * Object Construction, Destruction and Callback Functions
44 #include "pkix_pl_object.h"
46 #ifdef PKIX_USER_OBJECT_TYPE
47 /* --Class-Table-Initializers------------------------------------ */
50 * Create storage space for 20 Class Table buckets.
51 * These are only for user-defined types. System types are registered
52 * separately by PKIX_PL_Initialize.
55 static pkix_pl_HT_Elem
*
56 pkix_Raw_ClassTable_Buckets
[] = {
57 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
58 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
62 * Allocate static memory for a ClassTable.
63 * XXX This assumes the bucket pointer will fit into a PKIX_UInt32
65 static pkix_pl_PrimHashTable pkix_Raw_ClassTable
= {
66 (void *)pkix_Raw_ClassTable_Buckets
, /* Buckets */
67 20 /* Number of Buckets */
69 static pkix_pl_PrimHashTable
* classTable
= &pkix_Raw_ClassTable
;
70 #endif /* PKIX_USER_OBJECT_TYPE */
72 /* --Private-Functions-------------------------------------------- */
75 * FUNCTION: pkix_pl_Object_GetHeader
78 * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and
79 * stores the value at "pObjectHeader".
83 * Address of Object to shift. Must be non-NULL.
85 * Address where object pointer will be stored. Must be non-NULL.
87 * Platform-specific context pointer.
89 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
91 * Returns NULL if the function succeeds.
92 * Returns a Fatal Error if the function fails in an unrecoverable way.
95 pkix_pl_Object_GetHeader(
96 PKIX_PL_Object
*object
,
97 PKIX_PL_Object
**pObjectHeader
,
100 PKIX_PL_Object
*header
= NULL
;
103 PKIX_ENTER(OBJECT
, "pkix_pl_Object_GetHeader");
104 PKIX_NULLCHECK_TWO(object
, pObjectHeader
);
106 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
108 /* The header is sizeof(PKIX_PL_Object) before the object pointer */
109 header
= (PKIX_PL_Object
*)((char *)object
- sizeof(PKIX_PL_Object
));
111 objType
= header
->type
;
113 if (objType
>= PKIX_NUMTYPES
) { /* if this is a user-defined type */
114 #ifdef PKIX_USER_OBJECT_TYPE
115 pkix_ClassTable_Entry
*ctEntry
= NULL
;
117 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
118 PR_Lock(classTableLock
);
120 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
127 PKIX_ERRORGETTINGCLASSTABLEENTRY
);
129 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
130 PR_Unlock(classTableLock
);
132 if (ctEntry
== NULL
) {
133 PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE
);
136 PORT_Assert(objType
< PKIX_NUMTYPES
);
137 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
138 pkixErrorClass
= PKIX_FATAL_ERROR
;
140 #endif /* PKIX_USER_OBJECT_TYPE */
143 #ifdef PKIX_OBJECT_LEAK_TEST
144 PORT_Assert(header
&& header
->magicHeader
== PKIX_MAGIC_HEADER
);
145 #endif /* PKIX_OBJECT_LEAK_TEST */
147 if ((header
== NULL
)||
148 (header
->magicHeader
!= PKIX_MAGIC_HEADER
)) {
149 PKIX_ERROR_ALLOC_ERROR();
152 *pObjectHeader
= header
;
160 * FUNCTION: pkix_Destroy_Object
163 * Destroys and deallocates Object pointed to by "object". The caller is
164 * assumed to hold the Object's lock, which is acquired in
165 * PKIX_PL_Object_DecRef().
169 * Address of Object to destroy. Must be non-NULL.
171 * Platform-specific context pointer.
173 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
175 * Returns NULL if the function succeeds.
176 * Returns a Fatal Error if the function fails in an unrecoverable way.
179 pkix_pl_Object_Destroy(
180 PKIX_PL_Object
*object
,
183 PKIX_PL_Object
*objectHeader
= NULL
;
185 PKIX_ENTER(OBJECT
, "pkix_pl_Object_Destroy");
186 PKIX_NULLCHECK_ONE(object
);
188 #ifdef PKIX_OBJECT_LEAK_TEST
189 PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
190 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
192 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
193 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
194 #endif /* PKIX_OBJECT_LEAK_TEST */
196 /* Attempt to delete an object still being used */
197 if (objectHeader
->references
!= 0) {
198 PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED
);
201 PKIX_DECREF(objectHeader
->stringRep
);
203 /* Destroy this object's lock */
204 PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
205 PR_DestroyLock(objectHeader
->lock
);
206 objectHeader
->lock
= NULL
;
209 objectHeader
->magicHeader
= PKIX_MAGIC_HEADER_DESTROYED
;
211 #ifdef PKIX_OBJECT_LEAK_TEST
212 memset(objectHeader
, 0xbf, systemClasses
[PKIX_OBJECT_TYPE
].typeObjectSize
);
215 PKIX_FREE(objectHeader
);
218 #ifdef PKIX_OBJECT_LEAK_TEST
225 /* --Default-Callbacks-------------------------------------------- */
228 * FUNCTION: pkix_pl_Object_Equals_Default
231 * Default Object_Equals callback: Compares the address of the Object pointed
232 * to by "firstObject" with the address of the Object pointed to by
233 * "secondObject" and stores the Boolean result at "pResult".
237 * Address of first Object to compare. Must be non-NULL.
239 * Address of second Object to compare. Must be non-NULL.
241 * Address where Boolean result will be stored. Must be non-NULL.
243 * Platform-specific context pointer.
245 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
247 * Returns NULL if the function succeeds.
248 * Returns a Fatal Error if the function fails in an unrecoverable way.
251 pkix_pl_Object_Equals_Default(
252 PKIX_PL_Object
*firstObject
,
253 PKIX_PL_Object
*secondObject
,
254 PKIX_Boolean
*pResult
,
257 PKIX_ENTER(OBJECT
, "pkix_pl_Object_Equals_Default");
258 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
260 /* Just compare pointer values */
261 *pResult
= (firstObject
== secondObject
)?PKIX_TRUE
:PKIX_FALSE
;
267 * FUNCTION: pkix_pl_Object_ToString_Default
270 * Default Object_ToString callback: Creates a string consisting of the
271 * typename and address of the Object pointed to by "object" and stores
272 * the result at "pString". The format for the string is
273 * "TypeName@Address: <address>", where the default typename is "Object".
277 * Address of Object to convert to a string. Must be non-NULL.
279 * Address where object pointer will be stored. Must be non-NULL.
281 * Platform-specific context pointer.
283 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
285 * Returns NULL if the function succeeds.
286 * Returns an Object Error if the function fails in a non-fatal way.
287 * Returns a Fatal Error if the function fails in an unrecoverable way.
290 pkix_pl_Object_ToString_Default(
291 PKIX_PL_Object
*object
,
292 PKIX_PL_String
**pString
,
295 PKIX_PL_String
*formatString
= NULL
;
296 PKIX_PL_String
*descString
= NULL
;
297 char *format
= "%s@Address: %x";
298 char *description
= NULL
;
301 PKIX_ENTER(OBJECT
, "pkix_pl_Object_ToString_Default");
302 PKIX_NULLCHECK_TWO(object
, pString
);
304 PKIX_CHECK(PKIX_PL_Object_GetType(object
, &objType
, plContext
),
305 PKIX_OBJECTGETTYPEFAILED
);
307 if (objType
>= PKIX_NUMTYPES
){
308 #ifdef PKIX_USER_OBJECT_TYPE
309 pkix_ClassTable_Entry
*ctEntry
= NULL
;
311 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
312 PR_Lock(classTableLock
);
313 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
320 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
321 PR_Unlock(classTableLock
);
322 if (pkixErrorResult
){
323 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY
);
326 if (ctEntry
== NULL
){
327 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY
);
329 description
= ctEntry
->description
;
330 if (description
== NULL
) {
331 description
= "User Type Object";
336 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
337 pkixErrorClass
= PKIX_FATAL_ERROR
;
339 #endif /* PKIX_USER_OBJECT_TYPE */
341 description
= systemClasses
[objType
].description
;
343 PKIX_CHECK(PKIX_PL_String_Create
349 PKIX_STRINGCREATEFAILED
);
351 PKIX_CHECK(PKIX_PL_String_Create
357 PKIX_STRINGCREATEFAILED
);
359 PKIX_CHECK(PKIX_PL_Sprintf
369 PKIX_DECREF(formatString
);
370 PKIX_DECREF(descString
);
376 * FUNCTION: pkix_pl_Object_Hashcode_Default
379 * Default Object_Hashcode callback. Creates the a hashcode value using the
380 * address of the Object pointed to by "object" and stores the result at
383 * XXX This isn't great since addresses are not uniformly distributed.
387 * Address of Object to compute hashcode for. Must be non-NULL.
389 * Address where PKIX_UInt32 will be stored. Must be non-NULL.
391 * Platform-specific context pointer.
393 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
395 * Returns NULL if the function succeeds.
396 * Returns a Fatal Error if the function fails in an unrecoverable way.
399 pkix_pl_Object_Hashcode_Default(
400 PKIX_PL_Object
*object
,
411 PKIX_ENTER(OBJECT
, "pkix_pl_Object_Hashcode_Default");
412 PKIX_NULLCHECK_TWO(object
, pValue
);
415 extracter
.pointer
= object
;
416 *pValue
= extracter
.hilo
[1];
418 *pValue
= (PKIX_UInt32
)object
;
425 * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback
428 * Retrieves Equals callback function of Object pointed to by "object and
429 * stores it at "pEqualsCallback". If the object's type is one of the system
430 * types, its callback function is retrieved from the systemClasses array;
431 * otherwise, its callback function is retrieve from the classTable hash
432 * table where user-defined types are stored.
436 * Address of Object whose equals callback is desired. Must be non-NULL.
438 * Address where EqualsCallback function pointer will be stored.
441 * Platform-specific context pointer.
443 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
445 * Returns NULL if the function succeeds.
446 * Returns an Object Error if the function fails in a non-fatal way.
447 * Returns a Fatal Error if the function fails in an unrecoverable way.
450 pkix_pl_Object_RetrieveEqualsCallback(
451 PKIX_PL_Object
*object
,
452 PKIX_PL_EqualsCallback
*pEqualsCallback
,
455 PKIX_PL_Object
*objectHeader
= NULL
;
456 PKIX_PL_EqualsCallback func
= NULL
;
457 pkix_ClassTable_Entry entry
;
460 PKIX_ENTER(OBJECT
, "pkix_pl_Object_RetrieveEqualsCallback");
461 PKIX_NULLCHECK_TWO(object
, pEqualsCallback
);
463 PKIX_CHECK(pkix_pl_Object_GetHeader
464 (object
, &objectHeader
, plContext
),
465 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
467 objType
= objectHeader
->type
;
469 if (objType
>= PKIX_NUMTYPES
){
470 #ifdef PKIX_USER_OBJECT_TYPE
471 pkix_ClassTable_Entry
*ctEntry
= NULL
;
473 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
474 PR_Lock(classTableLock
);
475 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
482 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
483 PR_Unlock(classTableLock
);
484 if (pkixErrorResult
){
485 PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY
);
488 if ((ctEntry
== NULL
) || (ctEntry
->equalsFunction
== NULL
)) {
489 PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK
);
491 *pEqualsCallback
= ctEntry
->equalsFunction
;
495 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
496 pkixErrorClass
= PKIX_FATAL_ERROR
;
498 #endif /* PKIX_USER_OBJECT_TYPE */
500 entry
= systemClasses
[objType
];
501 func
= entry
.equalsFunction
;
503 func
= pkix_pl_Object_Equals_Default
;
505 *pEqualsCallback
= func
;
514 * FUNCTION: pkix_pl_Object_RegisterSelf
516 * Registers PKIX_OBJECT_TYPE and its related functions with systemClasses[]
518 * Not Thread Safe - for performance and complexity reasons
520 * Since this function is only called by PKIX_PL_Initialize, which should
521 * only be called once, it is acceptable that this function is not
524 * PKIX_PL_Object should have all function pointes to be to NULL: they
525 * work as proxy function to a real objects.
529 pkix_pl_Object_RegisterSelf(void *plContext
)
531 pkix_ClassTable_Entry entry
;
533 PKIX_ENTER(ERROR
, "pkix_pl_Object_RegisterSelf");
535 entry
.description
= "Object";
536 entry
.objCounter
= 0;
537 entry
.typeObjectSize
= sizeof(PKIX_PL_Object
);
538 entry
.destructor
= NULL
;
539 entry
.equalsFunction
= NULL
;
540 entry
.hashcodeFunction
= NULL
;
541 entry
.toStringFunction
= NULL
;
542 entry
.comparator
= NULL
;
543 entry
.duplicateFunction
= NULL
;
545 systemClasses
[PKIX_OBJECT_TYPE
] = entry
;
550 /* --Public-Functions------------------------------------------------------- */
553 * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h)
556 PKIX_PL_Object_Alloc(
557 PKIX_TYPENUM objType
,
559 PKIX_PL_Object
**pObject
,
562 PKIX_PL_Object
*object
= NULL
;
563 pkix_ClassTable_Entry
*ctEntry
= NULL
;
565 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Alloc");
566 PKIX_NULLCHECK_ONE(pObject
);
569 * We need to ensure that user-defined types have been registered.
570 * All system types have already been registered by PKIX_PL_Initialize.
573 if (objType
>= PKIX_NUMTYPES
) { /* i.e. if this is a user-defined type */
574 #ifdef PKIX_USER_OBJECT_TYPE
575 PKIX_Boolean typeRegistered
;
576 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
577 PR_Lock(classTableLock
);
578 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
585 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
586 PR_Unlock(classTableLock
);
587 if (pkixErrorResult
){
588 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE
);
591 typeRegistered
= (ctEntry
!= NULL
);
593 if (!typeRegistered
) {
594 PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT
);
598 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
599 pkixErrorClass
= PKIX_FATAL_ERROR
;
601 #endif /* PKIX_USER_OBJECT_TYPE */
603 ctEntry
= &systemClasses
[objType
];
606 PORT_Assert(size
== ctEntry
->typeObjectSize
);
608 /* Allocate space for the object header and the requested size */
609 #ifdef PKIX_OBJECT_LEAK_TEST
610 PKIX_CHECK(PKIX_PL_Calloc
612 ((PKIX_UInt32
)sizeof (PKIX_PL_Object
))+size
,
617 PKIX_CHECK(PKIX_PL_Malloc
618 (((PKIX_UInt32
)sizeof (PKIX_PL_Object
))+size
,
622 #endif /* PKIX_OBJECT_LEAK_TEST */
624 /* Initialize all object fields */
625 object
->magicHeader
= PKIX_MAGIC_HEADER
;
626 object
->type
= objType
;
627 object
->references
= 1; /* Default to a single reference */
628 object
->stringRep
= NULL
;
629 object
->hashcode
= 0;
630 object
->hashcodeCached
= 0;
632 /* Cannot use PKIX_PL_Mutex because it depends on Object */
633 /* Using NSPR Locks instead */
634 PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
635 object
->lock
= PR_NewLock();
636 if (object
->lock
== NULL
) {
637 PKIX_ERROR_ALLOC_ERROR();
640 PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
643 /* Return a pointer to the user data. Need to offset by object size */
644 *pObject
= object
+ 1;
647 /* Atomically increment object counter */
648 PR_AtomicIncrement(&ctEntry
->objCounter
);
658 * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h)
661 PKIX_PL_Object_IsTypeRegistered(
666 #ifdef PKIX_USER_OBJECT_TYPE
667 pkix_ClassTable_Entry
*ctEntry
= NULL
;
670 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_IsTypeRegistered");
671 PKIX_NULLCHECK_ONE(pBool
);
673 /* first, we handle the system types */
674 if (objType
< PKIX_NUMTYPES
) {
679 #ifndef PKIX_USER_OBJECT_TYPE
681 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
682 pkixErrorClass
= PKIX_FATAL_ERROR
;
684 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
685 PR_Lock(classTableLock
);
686 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
693 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
694 PR_Unlock(classTableLock
);
696 if (pkixErrorResult
){
697 PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE
);
700 *pBool
= (ctEntry
!= NULL
);
701 #endif /* PKIX_USER_OBJECT_TYPE */
708 #ifdef PKIX_USER_OBJECT_TYPE
710 * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h)
713 PKIX_PL_Object_RegisterType(
716 PKIX_PL_DestructorCallback destructor
,
717 PKIX_PL_EqualsCallback equalsFunction
,
718 PKIX_PL_HashcodeCallback hashcodeFunction
,
719 PKIX_PL_ToStringCallback toStringFunction
,
720 PKIX_PL_ComparatorCallback comparator
,
721 PKIX_PL_DuplicateCallback duplicateFunction
,
724 pkix_ClassTable_Entry
*ctEntry
= NULL
;
725 pkix_pl_Integer
*key
= NULL
;
727 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_RegisterType");
730 * System types are registered on startup by PKIX_PL_Initialize.
731 * These can not be overwritten.
734 if (objType
< PKIX_NUMTYPES
) { /* if this is a system type */
735 PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE
);
738 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
739 PR_Lock(classTableLock
);
740 PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
747 PKIX_PRIMHASHTABLELOOKUPFAILED
);
749 /* If the type is already registered, throw an error */
751 PKIX_ERROR(PKIX_TYPEALREADYREGISTERED
);
754 PKIX_CHECK(PKIX_PL_Malloc
755 (((PKIX_UInt32
)sizeof (pkix_ClassTable_Entry
)),
760 /* Set Default Values if none specified */
762 if (description
== NULL
){
763 description
= "Object";
766 if (equalsFunction
== NULL
) {
767 equalsFunction
= pkix_pl_Object_Equals_Default
;
770 if (toStringFunction
== NULL
) {
771 toStringFunction
= pkix_pl_Object_ToString_Default
;
774 if (hashcodeFunction
== NULL
) {
775 hashcodeFunction
= pkix_pl_Object_Hashcode_Default
;
778 ctEntry
->destructor
= destructor
;
779 ctEntry
->equalsFunction
= equalsFunction
;
780 ctEntry
->toStringFunction
= toStringFunction
;
781 ctEntry
->hashcodeFunction
= hashcodeFunction
;
782 ctEntry
->comparator
= comparator
;
783 ctEntry
->duplicateFunction
= duplicateFunction
;
784 ctEntry
->description
= description
;
786 PKIX_CHECK(PKIX_PL_Malloc
787 (((PKIX_UInt32
)sizeof (pkix_pl_Integer
)),
790 PKIX_COULDNOTMALLOCNEWKEY
);
792 key
->ht_int
= objType
;
794 PKIX_CHECK(pkix_pl_PrimHashTable_Add
801 PKIX_PRIMHASHTABLEADDFAILED
);
804 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
805 PR_Unlock(classTableLock
);
809 #endif /* PKIX_USER_OBJECT_TYPE */
812 * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h)
815 PKIX_PL_Object_IncRef(
816 PKIX_PL_Object
*object
,
819 PKIX_PL_Object
*objectHeader
= NULL
;
820 PKIX_PL_NssContext
*context
= NULL
;
821 PKIX_Int32 refCount
= 0;
823 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_IncRef");
824 PKIX_NULLCHECK_ONE(object
);
828 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
829 * have a header therefore we cannot verify its type before
832 context
= (PKIX_PL_NssContext
*) plContext
;
833 if (context
->arena
!= NULL
) {
838 if (object
== (PKIX_PL_Object
*)PKIX_ALLOC_ERROR()) {
842 /* Shift pointer from user data to object header */
843 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
844 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
846 /* This object should never have zero references */
847 refCount
= PR_AtomicIncrement(&objectHeader
->references
);
850 PKIX_THROW(FATAL
, PKIX_OBJECTWITHNONPOSITIVEREFERENCES
);
859 * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h)
862 PKIX_PL_Object_DecRef(
863 PKIX_PL_Object
*object
,
866 PKIX_Int32 refCount
= 0;
867 PKIX_PL_Object
*objectHeader
= NULL
;
868 PKIX_PL_NssContext
*context
= NULL
;
870 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_DecRef");
871 PKIX_NULLCHECK_ONE(object
);
875 * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
876 * have a header therefore we cannot verify its type before
879 context
= (PKIX_PL_NssContext
*) plContext
;
880 if (context
->arena
!= NULL
) {
885 if (object
== (PKIX_PL_Object
*)PKIX_ALLOC_ERROR()) {
889 /* Shift pointer from user data to object header */
890 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
891 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
893 refCount
= PR_AtomicDecrement(&objectHeader
->references
);
896 PKIX_PL_DestructorCallback destructor
= NULL
;
897 pkix_ClassTable_Entry
*ctEntry
= NULL
;
898 PKIX_UInt32 objType
= objectHeader
->type
;
900 /* first, special handling for system types */
901 if (objType
>= PKIX_NUMTYPES
){
902 #ifdef PKIX_USER_OBJECT_TYPE
903 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
904 PR_Lock(classTableLock
);
905 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
913 ("\tCalling PR_Unlock).\n");
914 PR_Unlock(classTableLock
);
915 if (pkixErrorResult
){
917 (PKIX_ERRORINGETTINGDESTRUCTOR
);
920 if (ctEntry
!= NULL
){
921 destructor
= ctEntry
->destructor
;
925 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
926 pkixErrorClass
= PKIX_FATAL_ERROR
;
928 #endif /* PKIX_USER_OBJECT_TYPE */
930 ctEntry
= &systemClasses
[objType
];
931 destructor
= ctEntry
->destructor
;
934 if (destructor
!= NULL
){
935 /* Call destructor on user data if necessary */
936 pkixErrorResult
= destructor(object
, plContext
);
937 if (pkixErrorResult
) {
938 pkixErrorClass
= PKIX_FATAL_ERROR
;
939 PKIX_DoAddError(stdVarsPtr
, pkixErrorResult
, plContext
);
940 pkixErrorResult
= NULL
;
944 /* Atomically decrement object counter */
945 PR_AtomicDecrement(&ctEntry
->objCounter
);
947 /* pkix_pl_Object_Destroy assumes the lock is held */
948 /* It will call unlock and destroy the object */
949 pkixErrorResult
= pkix_pl_Object_Destroy(object
, plContext
);
954 PKIX_ERROR_ALLOC_ERROR();
965 * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h)
968 PKIX_PL_Object_Equals(
969 PKIX_PL_Object
*firstObject
,
970 PKIX_PL_Object
*secondObject
,
971 PKIX_Boolean
*pResult
,
974 PKIX_PL_Object
*firstObjectHeader
= NULL
;
975 PKIX_PL_Object
*secondObjectHeader
= NULL
;
976 PKIX_PL_EqualsCallback func
= NULL
;
977 pkix_ClassTable_Entry entry
;
980 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Equals");
981 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
983 PKIX_CHECK(pkix_pl_Object_GetHeader
984 (firstObject
, &firstObjectHeader
, plContext
),
985 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
987 PKIX_CHECK(pkix_pl_Object_GetHeader
988 (secondObject
, &secondObjectHeader
, plContext
),
989 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
991 /* if hashcodes are cached but not equal, objects can't be equal */
992 if (firstObjectHeader
->hashcodeCached
&&
993 secondObjectHeader
->hashcodeCached
){
994 if (firstObjectHeader
->hashcode
!=
995 secondObjectHeader
->hashcode
){
996 *pResult
= PKIX_FALSE
;
1001 objType
= firstObjectHeader
->type
;
1003 if (objType
>= PKIX_NUMTYPES
) {
1004 #ifdef PKIX_USER_OBJECT_TYPE
1005 pkix_ClassTable_Entry
*ctEntry
= NULL
;
1006 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1007 PR_Lock(classTableLock
);
1008 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
1010 (void *)&firstObjectHeader
->type
,
1011 firstObjectHeader
->type
,
1015 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1016 PR_Unlock(classTableLock
);
1018 if (pkixErrorResult
){
1019 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY
);
1022 if ((ctEntry
== NULL
) || (ctEntry
->equalsFunction
== NULL
)) {
1023 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK
);
1025 func
= ctEntry
->equalsFunction
;
1029 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
1030 pkixErrorClass
= PKIX_FATAL_ERROR
;
1032 #endif /* PKIX_USER_OBJECT_TYPE */
1034 entry
= systemClasses
[objType
];
1035 func
= entry
.equalsFunction
;
1037 func
= pkix_pl_Object_Equals_Default
;
1041 PKIX_CHECK(func(firstObject
, secondObject
, pResult
, plContext
),
1042 PKIX_OBJECTSPECIFICFUNCTIONFAILED
);
1046 PKIX_RETURN(OBJECT
);
1050 * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h)
1053 PKIX_PL_Object_Duplicate(
1054 PKIX_PL_Object
*firstObject
,
1055 PKIX_PL_Object
**pNewObject
,
1058 PKIX_PL_Object
*firstObjectHeader
= NULL
;
1059 PKIX_PL_DuplicateCallback func
= NULL
;
1060 pkix_ClassTable_Entry entry
;
1061 PKIX_UInt32 objType
;
1063 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Duplicate");
1064 PKIX_NULLCHECK_TWO(firstObject
, pNewObject
);
1066 PKIX_CHECK(pkix_pl_Object_GetHeader
1067 (firstObject
, &firstObjectHeader
, plContext
),
1068 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1070 objType
= firstObjectHeader
->type
;
1072 if (objType
>= PKIX_NUMTYPES
) {
1073 #ifdef PKIX_USER_OBJECT_TYPE
1074 pkix_ClassTable_Entry
*ctEntry
= NULL
;
1076 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1077 PR_Lock(classTableLock
);
1078 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
1085 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1086 PR_Unlock(classTableLock
);
1088 if (pkixErrorResult
){
1089 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY
);
1092 if ((ctEntry
== NULL
) || (ctEntry
->duplicateFunction
== NULL
)) {
1093 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK
);
1095 func
= ctEntry
->duplicateFunction
;
1099 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
1100 pkixErrorClass
= PKIX_FATAL_ERROR
;
1102 #endif /* PKIX_USER_OBJECT_TYPE */
1104 entry
= systemClasses
[objType
];
1105 func
= entry
.duplicateFunction
;
1107 PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION
);
1111 PKIX_CHECK(func(firstObject
, pNewObject
, plContext
),
1112 PKIX_OBJECTSPECIFICFUNCTIONFAILED
);
1116 PKIX_RETURN(OBJECT
);
1120 * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h)
1123 PKIX_PL_Object_Hashcode(
1124 PKIX_PL_Object
*object
,
1125 PKIX_UInt32
*pValue
,
1128 PKIX_PL_Object
*objectHeader
= NULL
;
1129 PKIX_PL_HashcodeCallback func
= NULL
;
1130 pkix_ClassTable_Entry entry
;
1131 PKIX_UInt32 objectHash
;
1133 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Hashcode");
1134 PKIX_NULLCHECK_TWO(object
, pValue
);
1136 /* Shift pointer from user data to object header */
1137 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
1138 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1140 /* if we don't have a cached copy from before, we create one */
1141 if (!objectHeader
->hashcodeCached
){
1143 PKIX_UInt32 objType
= objectHeader
->type
;
1145 /* first, special handling for system types */
1146 if (objType
>= PKIX_NUMTYPES
){
1147 #ifdef PKIX_USER_OBJECT_TYPE
1148 pkix_ClassTable_Entry
*ctEntry
= NULL
;
1150 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1151 PR_Lock(classTableLock
);
1152 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
1159 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1160 PR_Unlock(classTableLock
);
1162 if (pkixErrorResult
){
1164 (PKIX_ERRORGETTINGCLASSTABLEENTRY
);
1167 if ((ctEntry
== NULL
) ||
1168 (ctEntry
->hashcodeFunction
== NULL
)) {
1169 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK
);
1172 func
= ctEntry
->hashcodeFunction
;
1175 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
1176 pkixErrorClass
= PKIX_FATAL_ERROR
;
1178 #endif /* PKIX_USER_OBJECT_TYPE */
1180 entry
= systemClasses
[objType
];
1181 func
= entry
.hashcodeFunction
;
1183 func
= pkix_pl_Object_Hashcode_Default
;
1187 PKIX_CHECK(func(object
, &objectHash
, plContext
),
1188 PKIX_OBJECTSPECIFICFUNCTIONFAILED
);
1190 if (!objectHeader
->hashcodeCached
){
1192 PKIX_CHECK(pkix_LockObject(object
, plContext
),
1193 PKIX_ERRORLOCKINGOBJECT
);
1195 if (!objectHeader
->hashcodeCached
){
1196 /* save cached copy in case we need it again */
1197 objectHeader
->hashcode
= objectHash
;
1198 objectHeader
->hashcodeCached
= PKIX_TRUE
;
1201 PKIX_CHECK(pkix_UnlockObject(object
, plContext
),
1202 PKIX_ERRORUNLOCKINGOBJECT
);
1206 *pValue
= objectHeader
->hashcode
;
1210 PKIX_RETURN(OBJECT
);
1214 * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h)
1217 PKIX_PL_Object_ToString(
1218 PKIX_PL_Object
*object
,
1219 PKIX_PL_String
**pString
,
1222 PKIX_PL_Object
*objectHeader
= NULL
;
1223 PKIX_PL_ToStringCallback func
= NULL
;
1224 pkix_ClassTable_Entry entry
;
1225 PKIX_PL_String
*objectString
= NULL
;
1227 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_ToString");
1228 PKIX_NULLCHECK_TWO(object
, pString
);
1230 /* Shift pointer from user data to object header */
1231 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
1232 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1234 /* if we don't have a cached copy from before, we create one */
1235 if (!objectHeader
->stringRep
){
1237 PKIX_UInt32 objType
= objectHeader
->type
;
1239 if (objType
>= PKIX_NUMTYPES
){
1240 #ifdef PKIX_USER_OBJECT_TYPE
1241 pkix_ClassTable_Entry
*ctEntry
= NULL
;
1243 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1244 PR_Lock(classTableLock
);
1245 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
1252 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1253 PR_Unlock(classTableLock
);
1254 if (pkixErrorResult
){
1256 (PKIX_ERRORGETTINGCLASSTABLEENTRY
);
1259 if ((ctEntry
== NULL
) ||
1260 (ctEntry
->toStringFunction
== NULL
)) {
1261 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK
);
1264 func
= ctEntry
->toStringFunction
;
1267 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
1268 pkixErrorClass
= PKIX_FATAL_ERROR
;
1270 #endif /* PKIX_USER_OBJECT_TYPE */
1272 entry
= systemClasses
[objType
];
1273 func
= entry
.toStringFunction
;
1275 func
= pkix_pl_Object_ToString_Default
;
1279 PKIX_CHECK(func(object
, &objectString
, plContext
),
1280 PKIX_OBJECTSPECIFICFUNCTIONFAILED
);
1282 if (!objectHeader
->stringRep
){
1284 PKIX_CHECK(pkix_LockObject(object
, plContext
),
1285 PKIX_ERRORLOCKINGOBJECT
);
1287 if (!objectHeader
->stringRep
){
1288 /* save a cached copy */
1289 objectHeader
->stringRep
= objectString
;
1290 objectString
= NULL
;
1293 PKIX_CHECK(pkix_UnlockObject(object
, plContext
),
1294 PKIX_ERRORUNLOCKINGOBJECT
);
1299 *pString
= objectHeader
->stringRep
;
1300 objectHeader
->stringRep
= NULL
;
1304 PKIX_DECREF(objectHeader
->stringRep
);
1306 PKIX_DECREF(objectString
);
1308 PKIX_RETURN(OBJECT
);
1312 * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h)
1315 PKIX_PL_Object_InvalidateCache(
1316 PKIX_PL_Object
*object
,
1319 PKIX_PL_Object
*objectHeader
= NULL
;
1321 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_InvalidateCache");
1322 PKIX_NULLCHECK_ONE(object
);
1324 /* Shift pointer from user data to object header */
1325 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
1326 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1328 PKIX_CHECK(pkix_LockObject(object
, plContext
),
1329 PKIX_ERRORLOCKINGOBJECT
);
1331 /* invalidate hashcode */
1332 objectHeader
->hashcode
= 0;
1333 objectHeader
->hashcodeCached
= PKIX_FALSE
;
1335 PKIX_DECREF(objectHeader
->stringRep
);
1337 PKIX_CHECK(pkix_UnlockObject(object
, plContext
),
1338 PKIX_ERRORUNLOCKINGOBJECT
);
1342 PKIX_RETURN(OBJECT
);
1346 * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h)
1349 PKIX_PL_Object_Compare(
1350 PKIX_PL_Object
*firstObject
,
1351 PKIX_PL_Object
*secondObject
,
1352 PKIX_Int32
*pResult
,
1355 PKIX_PL_Object
*firstObjectHeader
= NULL
;
1356 PKIX_PL_Object
*secondObjectHeader
= NULL
;
1357 PKIX_PL_ComparatorCallback func
= NULL
;
1358 pkix_ClassTable_Entry entry
;
1359 PKIX_UInt32 objType
;
1361 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Compare");
1362 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
1364 /* Shift pointer from user data to object header */
1365 PKIX_CHECK(pkix_pl_Object_GetHeader
1366 (firstObject
, &firstObjectHeader
, plContext
),
1367 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1369 /* Shift pointer from user data to object header */
1370 PKIX_CHECK(pkix_pl_Object_GetHeader
1371 (secondObject
, &secondObjectHeader
, plContext
),
1372 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1374 objType
= firstObjectHeader
->type
;
1376 if (objType
>= PKIX_NUMTYPES
){
1377 #ifdef PKIX_USER_OBJECT_TYPE
1378 pkix_ClassTable_Entry
*ctEntry
= NULL
;
1380 PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
1381 PR_Lock(classTableLock
);
1382 pkixErrorResult
= pkix_pl_PrimHashTable_Lookup
1389 PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
1390 PR_Unlock(classTableLock
);
1391 if (pkixErrorResult
){
1392 PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY
);
1395 if ((ctEntry
== NULL
) || (ctEntry
->comparator
== NULL
)) {
1396 PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR
);
1399 func
= ctEntry
->comparator
;
1402 pkixErrorCode
= PKIX_UNKNOWNOBJECTTYPE
;
1403 pkixErrorClass
= PKIX_FATAL_ERROR
;
1405 #endif /* PKIX_USER_OBJECT_TYPE */
1407 /* special handling for system types */
1408 entry
= systemClasses
[objType
];
1409 func
= entry
.comparator
;
1411 PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR
);
1415 PKIX_CHECK(func(firstObject
, secondObject
, pResult
, plContext
),
1416 PKIX_OBJECTSPECIFICFUNCTIONFAILED
);
1420 PKIX_RETURN(OBJECT
);
1424 * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h)
1427 PKIX_PL_Object_Lock(
1428 PKIX_PL_Object
*object
,
1431 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Lock");
1432 PKIX_NULLCHECK_ONE(object
);
1434 PKIX_CHECK(pkix_LockObject(object
, plContext
),
1435 PKIX_LOCKOBJECTFAILED
);
1439 PKIX_RETURN(OBJECT
);
1443 * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h)
1446 PKIX_PL_Object_Unlock(
1447 PKIX_PL_Object
*object
,
1450 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_Unlock");
1451 PKIX_NULLCHECK_ONE(object
);
1453 PKIX_CHECK(pkix_UnlockObject(object
, plContext
),
1454 PKIX_UNLOCKOBJECTFAILED
);
1458 PKIX_RETURN(OBJECT
);
1463 * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h)
1466 PKIX_PL_Object_GetType(
1467 PKIX_PL_Object
*object
,
1471 PKIX_PL_Object
*objectHeader
= NULL
;
1473 PKIX_ENTER(OBJECT
, "PKIX_PL_Object_GetType");
1474 PKIX_NULLCHECK_TWO(object
, pType
);
1476 /* Shift pointer from user data to object header */
1477 PKIX_CHECK(pkix_pl_Object_GetHeader(object
, &objectHeader
, plContext
),
1478 PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT
);
1480 *pType
= objectHeader
->type
;
1484 PKIX_RETURN(OBJECT
);