security/nss/lib/libpkix/pkix/util/pkix_list.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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_list.c
     6  *
     7  * List Object Functions
     8  *
     9  */
    11 #include "pkix_list.h"
    13 /* --Private-Functions-------------------------------------------- */
    15 /*
    16  * FUNCTION: pkix_List_Create_Internal
    17  * DESCRIPTION:
    18  *
    19  *  Creates a new List, using the Boolean value of "isHeader" to determine
    20  *  whether the new List should be a header, and stores it at "pList". The
    21  *  List is initially empty and holds no items. To initially add items to
    22  *  the List, use PKIX_List_AppendItem.
    23  *
    24  * PARAMETERS:
    25  *  "isHeader"
    26  *      Boolean value indicating whether new List should be a header.
    27  *  "pList"
    28  *      Address where object pointer will be stored. Must be non-NULL.
    29  *  "plContext"
    30  *      Platform-specific context pointer.
    31  * THREAD SAFETY:
    32  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    33  * RETURNS:
    34  *  Returns NULL if the function succeeds.
    35  *  Returns a Fatal Error if the function fails in an unrecoverable way.
    36  */
    37 static PKIX_Error *
    38 pkix_List_Create_Internal(
    39         PKIX_Boolean isHeader,
    40         PKIX_List **pList,
    41         void *plContext)
    42 {
    43         PKIX_List *list = NULL;
    45         PKIX_ENTER(LIST, "pkix_List_Create_Internal");
    46         PKIX_NULLCHECK_ONE(pList);
    48         PKIX_CHECK(PKIX_PL_Object_Alloc
    49                     (PKIX_LIST_TYPE,
    50                     ((PKIX_UInt32)(sizeof (PKIX_List))),
    51                     (PKIX_PL_Object **)&list, plContext),
    52                     PKIX_ERRORCREATINGLISTITEM);
    54         list->item = NULL;
    55         list->next = NULL;
    56         list->immutable = PKIX_FALSE;
    57         list->length = 0;
    58         list->isHeader = isHeader;
    60         *pList = list;
    62 cleanup:
    64         PKIX_RETURN(LIST);
    65 }
    67 /*
    68  * FUNCTION: pkix_List_Destroy
    69  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    70  */
    71 static PKIX_Error *
    72 pkix_List_Destroy(
    73         PKIX_PL_Object *object,
    74         void *plContext)
    75 {
    76         PKIX_List *list = NULL;
    77         PKIX_List *nextItem = NULL;
    79         PKIX_ENTER(LIST, "pkix_List_Destroy");
    80         PKIX_NULLCHECK_ONE(object);
    82         /* Check that this object is a list */
    83         PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
    84                     PKIX_OBJECTNOTLIST);
    86         list = (PKIX_List *)object;
    88         /* We have a valid list. DecRef its item and recurse on next */
    89         PKIX_DECREF(list->item);
    90         while ((nextItem = list->next) != NULL) {
    91             list->next = nextItem->next;
    92             nextItem->next = NULL;
    93             PKIX_DECREF(nextItem);
    94         }      
    95         list->immutable = PKIX_FALSE;
    96         list->length = 0;
    97         list->isHeader = PKIX_FALSE;
    99 cleanup:
   101         PKIX_RETURN(LIST);
   102 }
   104 /*
   105  * FUNCTION: pkix_List_ToString_Helper
   106  * DESCRIPTION:
   107  *
   108  *  Helper function that creates a string representation of the List pointed
   109  *  to by "list" and stores its address in the object pointed to by "pString".
   110  *
   111  * PARAMETERS
   112  *  "list"
   113  *      Address of List whose string representation is desired.
   114  *      Must be non-NULL.
   115  *  "pString"
   116  *      Address of object pointer's destination. Must be non-NULL.
   117  *  "plContext"
   118  *      Platform-specific context pointer.
   119  * THREAD SAFETY:
   120  *  Conditionally Thread Safe
   121  *      (see Thread Safety Definitions in Programmer's Guide)
   122  * RETURNS:
   123  *  Returns NULL if the function succeeds.
   124  *  Returns a List Error if the function fails in a non-fatal way.
   125  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   126  */
   127 static PKIX_Error *
   128 pkix_List_ToString_Helper(
   129         PKIX_List *list,
   130         PKIX_PL_String **pString,
   131         void *plContext)
   132 {
   133         PKIX_PL_String *itemString = NULL;
   134         PKIX_PL_String *nextString = NULL;
   135         PKIX_PL_String *format = NULL;
   136         PKIX_Boolean empty;
   138         PKIX_ENTER(LIST, "pkix_List_ToString_Helper");
   139         PKIX_NULLCHECK_TWO(list, pString);
   141         /* special case when list is the header */
   142         if (list->isHeader){
   144                 PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext),
   145                             PKIX_LISTISEMPTYFAILED);
   147                 if (empty){
   148                         PKIX_CHECK(PKIX_PL_String_Create
   149                                     (PKIX_ESCASCII,
   150                                     "EMPTY",
   151                                     0,
   152                                     &itemString,
   153                                     plContext),
   154                                     PKIX_ERRORCREATINGITEMSTRING);
   155                         (*pString) = itemString;
   156                         PKIX_DEBUG_EXIT(LIST);
   157                         return (NULL);
   158                 } else {
   159                         PKIX_CHECK(pkix_List_ToString_Helper
   160                                     (list->next, &itemString, plContext),
   161                                     PKIX_LISTTOSTRINGHELPERFAILED);
   162                 }
   164                 /* Create a string object from the format */
   165                 PKIX_CHECK(PKIX_PL_String_Create
   166                             (PKIX_ESCASCII, "%s", 0, &format, plContext),
   167                             PKIX_STRINGCREATEFAILED);
   169                 PKIX_CHECK(PKIX_PL_Sprintf
   170                             (pString, plContext, format, itemString),
   171                             PKIX_SPRINTFFAILED);
   172         } else {
   173                 /* Get a string for this list's item */
   174                 if (list->item == NULL) {
   175                         PKIX_CHECK(PKIX_PL_String_Create
   176                                     (PKIX_ESCASCII,
   177                                     "(null)",
   178                                     0,
   179                                     &itemString,
   180                                     plContext),
   181                                     PKIX_STRINGCREATEFAILED);
   182                 } else {
   183                         PKIX_CHECK(PKIX_PL_Object_ToString
   184                                     ((PKIX_PL_Object*)list->item,
   185                                     &itemString,
   186                                     plContext),
   187                                     PKIX_OBJECTTOSTRINGFAILED);
   188                 }
   189                 if (list->next == NULL) {
   190                         /* Just return the itemstring */
   191                         (*pString) = itemString;
   192                         PKIX_DEBUG_EXIT(LIST);
   193                         return (NULL);
   194                 }
   196                 /* Recursive call to get string for this list's next pointer */
   197                 PKIX_CHECK(pkix_List_ToString_Helper
   198                             (list->next, &nextString, plContext),
   199                             PKIX_LISTTOSTRINGHELPERFAILED);
   201                 /* Create a string object from the format */
   202                 PKIX_CHECK(PKIX_PL_String_Create
   203                             (PKIX_ESCASCII,
   204                             "%s, %s",
   205                             0,
   206                             &format,
   207                             plContext),
   208                             PKIX_STRINGCREATEFAILED);
   210                 PKIX_CHECK(PKIX_PL_Sprintf
   211                             (pString,
   212                             plContext,
   213                             format,
   214                             itemString,
   215                             nextString),
   216                             PKIX_SPRINTFFAILED);
   217         }
   219 cleanup:
   221         PKIX_DECREF(itemString);
   222         PKIX_DECREF(nextString);
   223         PKIX_DECREF(format);
   225         PKIX_RETURN(LIST);
   226 }
   228 /*
   229  * FUNCTION: pkix_List_ToString
   230  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
   231  */
   232 static PKIX_Error *
   233 pkix_List_ToString(
   234         PKIX_PL_Object *object,
   235         PKIX_PL_String **pString,
   236         void *plContext)
   237 {
   238         PKIX_List *list = NULL;
   239         PKIX_PL_String *listString = NULL;
   240         PKIX_PL_String *format = NULL;
   242         PKIX_ENTER(LIST, "pkix_List_ToString");
   243         PKIX_NULLCHECK_TWO(object, pString);
   245         PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
   246                     PKIX_OBJECTNOTLIST);
   248         list = (PKIX_List *)object;
   250         if (!list->isHeader){
   251                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
   252         }
   254         PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext),
   255                     PKIX_LISTTOSTRINGHELPERFAILED);
   257         PKIX_CHECK(PKIX_PL_String_Create
   258                     (PKIX_ESCASCII, "(%s)", 0, &format, plContext),
   259                     PKIX_STRINGCREATEFAILED);
   261         PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString),
   262                     PKIX_SPRINTFFAILED);
   264 cleanup:
   266         PKIX_DECREF(listString);
   267         PKIX_DECREF(format);
   269         PKIX_RETURN(LIST);
   270 }
   272 /*
   273  * FUNCTION: pkix_List_Equals
   274  * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
   275  */
   276 static PKIX_Error *
   277 pkix_List_Equals(
   278         PKIX_PL_Object *first,
   279         PKIX_PL_Object *second,
   280         PKIX_Boolean *pResult,
   281         void *plContext)
   282 {
   283         PKIX_UInt32 secondType;
   284         PKIX_Boolean cmpResult;
   285         PKIX_List *firstList = NULL;
   286         PKIX_List *secondList = NULL;
   287         PKIX_UInt32 firstLength = 0;
   288         PKIX_UInt32 secondLength = 0;
   289         PKIX_PL_Object *firstItem = NULL;
   290         PKIX_PL_Object *secondItem = NULL;
   291         PKIX_UInt32 i = 0;
   293         PKIX_ENTER(LIST, "pkix_List_Equals");
   294         PKIX_NULLCHECK_THREE(first, second, pResult);
   296         /* test that first is a List */
   297         PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext),
   298                 PKIX_FIRSTOBJECTNOTLIST);
   300         /*
   301          * Since we know first is a List, if both references are
   302          * identical, they must be equal
   303          */
   304         if (first == second){
   305                 *pResult = PKIX_TRUE;
   306                 goto cleanup;
   307         }
   309         /*
   310          * If second isn't a List, we don't throw an error.
   311          * We simply return a Boolean result of FALSE
   312          */
   313         *pResult = PKIX_FALSE;
   314         PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
   315                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
   316         if (secondType != PKIX_LIST_TYPE) goto cleanup;
   318         firstList = (PKIX_List *)first;
   319         secondList = (PKIX_List *)second;
   321         if ((!firstList->isHeader) && (!secondList->isHeader)){
   322                 PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS);
   323         }
   325         firstLength = firstList->length;
   326         secondLength = secondList->length;
   328         cmpResult = PKIX_FALSE;
   329         if (firstLength == secondLength){
   330                 for (i = 0, cmpResult = PKIX_TRUE;
   331                     ((i < firstLength) && cmpResult);
   332                     i++){
   333                         PKIX_CHECK(PKIX_List_GetItem
   334                                     (firstList, i, &firstItem, plContext),
   335                                     PKIX_LISTGETITEMFAILED);
   337                         PKIX_CHECK(PKIX_List_GetItem
   338                                     (secondList, i, &secondItem, plContext),
   339                                     PKIX_LISTGETITEMFAILED);
   341                         if ((!firstItem && secondItem) ||
   342                             (firstItem && !secondItem)){
   343                                         cmpResult = PKIX_FALSE;
   344                         } else if (!firstItem && !secondItem){
   345                                 continue;
   346                         } else {
   347                                 PKIX_CHECK(PKIX_PL_Object_Equals
   348                                             (firstItem,
   349                                             secondItem,
   350                                             &cmpResult,
   351                                             plContext),
   352                                             PKIX_OBJECTEQUALSFAILED);
   354                                 PKIX_DECREF(firstItem);
   355                                 PKIX_DECREF(secondItem);
   356                         }
   357                 }
   358         }
   360         *pResult = cmpResult;
   362 cleanup:
   364         PKIX_DECREF(firstItem);
   365         PKIX_DECREF(secondItem);
   367         PKIX_RETURN(LIST);
   368 }
   370 /*
   371  * FUNCTION: pkix_List_Hashcode
   372  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
   373  */
   374 static PKIX_Error *
   375 pkix_List_Hashcode(
   376         PKIX_PL_Object *object,
   377         PKIX_UInt32 *pHashcode,
   378         void *plContext)
   379 {
   380         PKIX_List *list = NULL;
   381         PKIX_PL_Object *element = NULL;
   382         PKIX_UInt32 hash = 0;
   383         PKIX_UInt32 tempHash = 0;
   384         PKIX_UInt32 length, i;
   386         PKIX_ENTER(LIST, "pkix_List_Hashcode");
   387         PKIX_NULLCHECK_TWO(object, pHashcode);
   389         PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
   390                     PKIX_OBJECTNOTLIST);
   392         list = (PKIX_List *)object;
   394         if (!list->isHeader){
   395                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
   396         }
   398         length = list->length;
   400         for (i = 0; i < length; i++){
   401                 PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext),
   402                             PKIX_LISTGETITEMFAILED);
   404                 if (!element){
   405                         tempHash = 100;
   406                 } else {
   407                         PKIX_CHECK(PKIX_PL_Object_Hashcode
   408                                     (element, &tempHash, plContext),
   409                                     PKIX_LISTHASHCODEFAILED);
   410                 }
   412                 hash = 31 * hash + tempHash;
   414                 PKIX_DECREF(element);
   415         }
   417         *pHashcode = hash;
   419 cleanup:
   421         PKIX_DECREF(element);
   422         PKIX_RETURN(LIST);
   423 }
   425 /*
   426  * FUNCTION: pkix_List_Duplicate
   427  * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
   428  */
   429 static PKIX_Error *
   430 pkix_List_Duplicate(
   431         PKIX_PL_Object *object,
   432         PKIX_PL_Object **pNewObject,
   433         void *plContext)
   434 {
   435         PKIX_List *list = NULL;
   436         PKIX_List *listDuplicate = NULL;
   438         PKIX_ENTER(LIST, "pkix_List_Duplicate");
   439         PKIX_NULLCHECK_TWO(object, pNewObject);
   441         PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
   442                     PKIX_OBJECTNOTLIST);
   444         list = (PKIX_List *)object;
   446         if (list->immutable){
   447                 PKIX_CHECK(pkix_duplicateImmutable
   448                             (object, pNewObject, plContext),
   449                             PKIX_DUPLICATEIMMUTABLEFAILED);
   450         } else {
   452                 PKIX_CHECK(pkix_List_Create_Internal
   453                             (list->isHeader, &listDuplicate, plContext),
   454                             PKIX_LISTCREATEINTERNALFAILED);
   456                 listDuplicate->length = list->length;
   458                 PKIX_INCREF(list->item);
   459                 listDuplicate->item = list->item;
   461                 if (list->next == NULL){
   462                         listDuplicate->next = NULL;
   463                 } else {
   464                         /* Recursively Duplicate list */
   465                         PKIX_CHECK(pkix_List_Duplicate
   466                                     ((PKIX_PL_Object *)list->next,
   467                                     (PKIX_PL_Object **)&listDuplicate->next,
   468                                     plContext),
   469                                     PKIX_LISTDUPLICATEFAILED);
   470                 }
   472                 *pNewObject = (PKIX_PL_Object *)listDuplicate;
   473         }
   475 cleanup:
   477         if (PKIX_ERROR_RECEIVED){
   478                 PKIX_DECREF(listDuplicate);
   479         }
   481         PKIX_RETURN(LIST);
   482 }
   485 /*
   486  * FUNCTION: pkix_List_GetElement
   487  * DESCRIPTION:
   488  *
   489  *  Copies the "list"'s element at "index" into "element". The input List must
   490  *  be the header of the List (as opposed to being an element of the List). The
   491  *  index counts from zero and must be less than the List's length. This
   492  *  function does NOT increment the reference count of the List element since
   493  *  the returned element's reference will not be stored by the calling
   494  *  function.
   495  *
   496  * PARAMETERS:
   497  *  "list"
   498  *      Address of List (must be header) to get element from. Must be non-NULL.
   499  *  "index"
   500  *      Index of list to get element from. Must be less than List's length.
   501  *  "pElement"
   502  *      Address where object pointer will be stored. Must be non-NULL.
   503  *  "plContext"
   504  *      Platform-specific context pointer.
   505  * THREAD SAFETY:
   506  *  Conditionally Thread Safe
   507  *      (see Thread Safety Definitions in Programmer's Guide)
   508  * RETURNS:
   509  *  Returns NULL if the function succeeds.
   510  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   511  */
   512 static PKIX_Error *
   513 pkix_List_GetElement(
   514         PKIX_List *list,
   515         PKIX_UInt32 index,
   516         PKIX_List **pElement,
   517         void *plContext)
   518 {
   519         PKIX_List *iterator = NULL;
   520         PKIX_UInt32 length;
   521         PKIX_UInt32 position = 0;
   523         PKIX_ENTER(LIST, "pkix_List_GetElement");
   524         PKIX_NULLCHECK_TWO(list, pElement);
   526         if (!list->isHeader){
   527                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
   528         }
   530         length = list->length;
   532         if (index >= length) {
   533                 PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS);
   534         }
   536         for (iterator = list; position++ <= index; iterator = iterator->next)
   537                 ;
   539         (*pElement) = iterator;
   541 cleanup:
   543         PKIX_RETURN(LIST);
   544 }
   547 /*
   548  * FUNCTION: pkix_List_RegisterSelf
   549  * DESCRIPTION:
   550  *  Registers PKIX_LIST_TYPE and its related functions with systemClasses[]
   551  * THREAD SAFETY:
   552  *  Not Thread Safe - for performance and complexity reasons
   553  *
   554  *  Since this function is only called by PKIX_PL_Initialize, which should
   555  *  only be called once, it is acceptable that this function is not
   556  *  thread-safe.
   557  */
   558 PKIX_Error *
   559 pkix_List_RegisterSelf(void *plContext)
   560 {
   561         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   562         pkix_ClassTable_Entry entry;
   564         PKIX_ENTER(LIST, "pkix_List_RegisterSelf");
   566         entry.description = "List";
   567         entry.objCounter = 0;
   568         entry.typeObjectSize = sizeof(PKIX_List);
   569         entry.destructor = pkix_List_Destroy;
   570         entry.equalsFunction = pkix_List_Equals;
   571         entry.hashcodeFunction = pkix_List_Hashcode;
   572         entry.toStringFunction = pkix_List_ToString;
   573         entry.comparator = NULL;
   574         entry.duplicateFunction = pkix_List_Duplicate;
   576         systemClasses[PKIX_LIST_TYPE] = entry;
   578         PKIX_RETURN(LIST);
   579 }
   581 /*
   582  * FUNCTION: pkix_List_Contains
   583  * DESCRIPTION:
   584  *
   585  *  Checks a List pointed to by "list", to determine whether it includes
   586  *  an entry that is equal to the Object pointed to by "object", and stores
   587  *  the result in "pFound".
   588  *
   589  * PARAMETERS:
   590  *  "list"
   591  *      List to be searched; may be empty; must be non-NULL
   592  *  "object"
   593  *      Object to be checked for; must be non-NULL
   594  *  "pFound"
   595  *      Address where the result of the search will be stored. Must
   596  *      be non-NULL
   597  *  "plContext"
   598  *      platform-specific context pointer
   599  * THREAD SAFETY:
   600  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   601  * RETURNS:
   602  *  Returns NULL if the function succeeds
   603  *  Returns a Fatal Error if the function fails in an unrecoverable way
   604  */
   605 PKIX_Error *
   606 pkix_List_Contains(
   607         PKIX_List *list,
   608         PKIX_PL_Object *object,
   609         PKIX_Boolean *pFound,
   610         void *plContext)
   611 {
   612         PKIX_PL_Object *current = NULL;
   613         PKIX_UInt32 numEntries = 0;
   614         PKIX_UInt32 index = 0;
   615         PKIX_Boolean match = PKIX_FALSE;
   617         PKIX_ENTER(LIST, "pkix_List_Contains");
   618         PKIX_NULLCHECK_THREE(list, object, pFound);
   620         PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
   621                 PKIX_LISTGETLENGTHFAILED);
   623         for (index = 0; index < numEntries; index++) {
   624                 PKIX_CHECK(PKIX_List_GetItem
   625                         (list, index, &current, plContext),
   626                         PKIX_LISTGETITEMFAILED);
   628                 if (current) {
   629                         PKIX_CHECK(PKIX_PL_Object_Equals
   630                                 (object, current, &match, plContext),
   631                                 PKIX_OBJECTEQUALSFAILED);
   633                         PKIX_DECREF(current);
   634                 }
   636                 if (match) {
   637                         break;
   638                 }
   639         }
   641         *pFound = match;
   643 cleanup:
   645         PKIX_DECREF(current);
   646         PKIX_RETURN(LIST);
   647 }
   649 /*
   650  * FUNCTION: pkix_List_Remove
   651  * DESCRIPTION:
   652  *
   653  *  Traverses the List pointed to by "list", to find and delete an entry
   654  *  that is equal to the Object pointed to by "object". If no such entry
   655  *  is found the function does not return an error.
   656  *
   657  * PARAMETERS:
   658  *  "list"
   659  *      List to be searched; may be empty; must be non-NULL
   660  *  "object"
   661  *      Object to be checked for and deleted, if found; must be non-NULL
   662  *  "plContext"
   663  *      platform-specific context pointer
   664  * THREAD SAFETY:
   665  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   666  * RETURNS:
   667  *  Returns NULL if the function succeeds
   668  *  Returns a Validate Error if the functions fails in a non-fatal way
   669  *  Returns a Fatal Error if the function fails in an unrecoverable way
   670  */
   671 PKIX_Error *
   672 pkix_List_Remove(
   673         PKIX_List *list,
   674         PKIX_PL_Object *object,
   675         void *plContext)
   676 {
   677         PKIX_PL_Object *current = NULL;
   678         PKIX_UInt32 numEntries = 0;
   679         PKIX_UInt32 index = 0;
   680         PKIX_Boolean match = PKIX_FALSE;
   682         PKIX_ENTER(LIST, "pkix_List_Remove");
   683         PKIX_NULLCHECK_TWO(list, object);
   685         PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
   686                 PKIX_LISTGETLENGTHFAILED);
   688         for (index = 0; index < numEntries; index++) {
   689                 PKIX_CHECK(PKIX_List_GetItem
   690                         (list, index, &current, plContext),
   691                         PKIX_LISTGETITEMFAILED);
   693                 if (current) {
   694                         PKIX_CHECK(PKIX_PL_Object_Equals
   695                                 (object, current, &match, plContext),
   696                                 PKIX_OBJECTEQUALSFAILED);
   698                         PKIX_DECREF(current);
   699                 }
   701                 if (match) {
   702                         PKIX_CHECK(PKIX_List_DeleteItem
   703                                 (list, index, plContext),
   704                                 PKIX_LISTDELETEITEMFAILED);
   705                         break;
   706                 }
   707         }
   709 cleanup:
   711         PKIX_DECREF(current);
   712         PKIX_RETURN(LIST);
   713 }
   715 /*
   716  * FUNCTION: pkix_List_RemoveItems
   717  * DESCRIPTION:
   718  *
   719  *  Traverses the List pointed to by "list", to find and delete an entry
   720  *  that is equal to the Object in the "deleteList". If no such entry
   721  *  is found the function does not return an error.
   722  *
   723  * PARAMETERS:
   724  *  "list"
   725  *      Object in "list" is checked for object in "deleteList" and deleted if
   726  *      found; may be empty; must be non-NULL
   727  *  "deleteList"
   728  *      List of objects to be searched ; may be empty; must be non-NULL
   729  *  "plContext"
   730  *      platform-specific context pointer
   731  * THREAD SAFETY:
   732  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   733  * RETURNS:
   734  *  Returns NULL if the function succeeds
   735  *  Returns a Validate Error if the functions fails in a non-fatal way
   736  *  Returns a Fatal Error if the function fails in an unrecoverable way
   737  */
   738 PKIX_Error *
   739 pkix_List_RemoveItems(
   740         PKIX_List *list,
   741         PKIX_List *deleteList,
   742         void *plContext)
   743 {
   744         PKIX_PL_Object *current = NULL;
   745         PKIX_UInt32 numEntries = 0;
   746         PKIX_UInt32 index = 0;
   748         PKIX_ENTER(LIST, "pkix_List_RemoveItems");
   749         PKIX_NULLCHECK_TWO(list, deleteList);
   751         PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext),
   752                 PKIX_LISTGETLENGTHFAILED);
   754         for (index = 0; index < numEntries; index++) {
   755                 PKIX_CHECK(PKIX_List_GetItem
   756                         (deleteList, index, &current, plContext),
   757                         PKIX_LISTGETITEMFAILED);
   759                 if (current) {
   760                         PKIX_CHECK(pkix_List_Remove
   761                                 (list, current, plContext),
   762                                 PKIX_OBJECTEQUALSFAILED);
   764                         PKIX_DECREF(current);
   765                 }
   766         }
   768 cleanup:
   770         PKIX_DECREF(current);
   771         PKIX_RETURN(LIST);
   772 }
   774 /*
   775  * FUNCTION: pkix_List_MergeLists
   776  * DESCRIPTION:
   777  *
   778  *  Creates a new list consisting of the items from "firstList", followed by
   779  *  the items on "secondList", returns the new list at "pMergedList". If
   780  *  both input lists are NULL or empty, the result is an empty list. If an error
   781  *  occurs, the result is NULL.
   782  *
   783  * PARAMETERS:
   784  *  "firstList"
   785  *      Address of list to be merged from. May be NULL or empty.
   786  *  "secondList"
   787  *      Address of list to be merged from. May be NULL or empty.
   788  *  "pMergedList"
   789  *      Address where returned object is stored.
   790  *  "plContext"
   791  *      platform-specific context pointer * THREAD SAFETY:
   792  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   793  * RETURNS:
   794  *  Returns NULL if the function succeeds
   795  *  Returns a List Error if the functions fails in a non-fatal way
   796  *  Returns a Fatal Error if the function fails in an unrecoverable way
   797  */
   798 PKIX_Error *
   799 pkix_List_MergeLists(
   800         PKIX_List *firstList,
   801         PKIX_List *secondList,
   802         PKIX_List **pMergedList,
   803         void *plContext)
   804 {
   805         PKIX_List *list = NULL;
   806         PKIX_PL_Object *item = NULL;
   807         PKIX_UInt32 numItems = 0;
   808         PKIX_UInt32 i;
   810         PKIX_ENTER(LIST, "pkix_List_MergeLists");
   811         PKIX_NULLCHECK_ONE(pMergedList);
   813         *pMergedList = NULL;
   815         PKIX_CHECK(PKIX_List_Create(&list, plContext),
   816                     PKIX_LISTCREATEFAILED);
   818         if (firstList != NULL) {
   820                 PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext),
   821                     PKIX_LISTGETLENGTHFAILED);
   822         }
   824         for (i = 0; i < numItems; i++) {
   826                 PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext),
   827                         PKIX_LISTGETITEMFAILED);
   829                 PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext),
   830                         PKIX_LISTAPPENDITEMFAILED);
   832                 PKIX_DECREF(item);
   833         }
   835         numItems = 0;
   836         if (secondList != NULL) {
   838                 PKIX_CHECK(PKIX_List_GetLength
   839                         (secondList,
   840                         &numItems,
   841                         plContext),
   842                         PKIX_LISTGETLENGTHFAILED);
   844         }
   846         for (i = 0; i < numItems; i++) {
   848                 PKIX_CHECK(PKIX_List_GetItem
   849                         (secondList, i, &item, plContext),
   850                         PKIX_LISTGETITEMFAILED);
   852                 PKIX_CHECK(PKIX_List_AppendItem
   853                         (list, item, plContext), PKIX_LISTAPPENDITEMFAILED);
   855                 PKIX_DECREF(item);
   856         }
   858         *pMergedList = list;
   859         list = NULL;
   861 cleanup:
   862         PKIX_DECREF(list);
   863         PKIX_DECREF(item);
   865         PKIX_RETURN(LIST);
   866 }
   868 /*
   869  * FUNCTION: pkix_List_AppendList
   870  * DESCRIPTION:
   871  *
   872  *  Append items on "fromList" to the "toList". Item reference count on
   873  *  "toList" is not incremented, but items appended from "fromList" are
   874  *  incremented.
   875  *
   876  * PARAMETERS:
   877  *  "toList"
   878  *      Address of list to be appended to. Must be non-NULL.
   879  *  "fromList"
   880  *      Address of list to be appended from. May be NULL or empty.
   881  *  "plContext"
   882  *      platform-specific context pointer
   883  * THREAD SAFETY:
   884  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   885  * RETURNS:
   886  *  Returns NULL if the function succeeds
   887  *  Returns a List Error if the functions fails in a non-fatal way
   888  *  Returns a Fatal Error if the function fails in an unrecoverable way
   889  */
   890 PKIX_Error *
   891 pkix_List_AppendList(
   892         PKIX_List *toList,
   893         PKIX_List *fromList,
   894         void *plContext)
   895 {
   896         PKIX_PL_Object *item = NULL;
   897         PKIX_UInt32 numItems = 0;
   898         PKIX_UInt32 i;
   900         PKIX_ENTER(LIST, "pkix_List_AppendList");
   901         PKIX_NULLCHECK_ONE(toList);
   903         /* if fromList is NULL or is an empty list, no action */
   905         if (fromList == NULL) {
   906                 goto cleanup;
   907         }
   909         PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext),
   910                     PKIX_LISTGETLENGTHFAILED);
   912         if (numItems == 0) {
   913                 goto cleanup;
   914         }
   916         for (i = 0; i < numItems; i++) {
   918                 PKIX_CHECK(PKIX_List_GetItem
   919                         (fromList, i, &item, plContext),
   920                         PKIX_LISTGETITEMFAILED);
   922                 PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext),
   923                             PKIX_LISTAPPENDITEMFAILED);
   925                 PKIX_DECREF(item);
   926         }
   928 cleanup:
   930         PKIX_DECREF(item);
   932         PKIX_RETURN(LIST);
   933 }
   935 /*
   936  * FUNCTION: pkix_List_AppendUnique
   937  * DESCRIPTION:
   938  *
   939  *  Adds each Object in the List pointed to by "fromList" to the List pointed
   940  *  to by "toList", if it is not already a member of that List. In other words,
   941  *  "toList" becomes the union of the two sets.
   942  *
   943  * PARAMETERS:
   944  *  "toList"
   945  *      Address of a List of Objects to be augmented by "fromList". Must be
   946  *      non-NULL, but may be empty.
   947  *  "fromList"
   948  *      Address of a List of Objects to be added, if not already present, to
   949  *      "toList". Must be non-NULL, but may be empty.
   950  *  "plContext"
   951  *      Platform-specific context pointer.
   952  * THREAD SAFETY:
   953  *  Not Thread Safe - assumes exclusive access to "toList"
   954  *  (see Thread Safety Definitions in Programmer's Guide)
   955  * RETURNS:
   956  *  Returns NULL if the function succeeds
   957  *  Returns a Fatal Error if the function fails in an unrecoverable way
   958  */
   959 PKIX_Error *
   960 pkix_List_AppendUnique(
   961         PKIX_List *toList,
   962         PKIX_List *fromList,
   963         void *plContext)
   964 {
   965         PKIX_Boolean isContained = PKIX_FALSE;
   966         PKIX_UInt32 listLen = 0;
   967         PKIX_UInt32 listIx = 0;
   968         PKIX_PL_Object *object = NULL;
   970         PKIX_ENTER(BUILD, "pkix_List_AppendUnique");
   971         PKIX_NULLCHECK_TWO(fromList, toList);
   973         PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext),
   974                 PKIX_LISTGETLENGTHFAILED);
   976         for (listIx = 0; listIx < listLen; listIx++) {
   978                 PKIX_CHECK(PKIX_List_GetItem
   979                         (fromList, listIx, &object, plContext),
   980                         PKIX_LISTGETITEMFAILED);
   982                 PKIX_CHECK(pkix_List_Contains
   983                         (toList, object, &isContained, plContext),
   984                         PKIX_LISTCONTAINSFAILED);
   986                 if (isContained == PKIX_FALSE) {
   987                         PKIX_CHECK(PKIX_List_AppendItem
   988                                 (toList, object, plContext),
   989                                 PKIX_LISTAPPENDITEMFAILED);
   990                 }
   992                 PKIX_DECREF(object);
   993         }
   995 cleanup:
   997         PKIX_DECREF(object);
   999         PKIX_RETURN(LIST);
  1002 /*
  1003  * FUNCTION: pkix_List_QuickSort
  1004  * DESCRIPTION:
  1006  *  Sorts List of Objects "fromList" using "comparatorCallback"'s result as
  1007  *  comasrison key and returns the sorted List at "pSortedList". The sorting
  1008  *  algorithm used is quick sort (n*logn).
  1010  * PARAMETERS:
  1011  *  "fromList"
  1012  *      Address of a List of Objects to be sorted. Must be non-NULL, but may be
  1013  *      empty.
  1014  *  "comparatorCallback"
  1015  *      Address of callback function that will compare two Objects on the List.
  1016  *      It should return -1 for less, 0 for equal and 1 for greater. The
  1017  *      callback implementation chooses what in Objects to be compared. Must be
  1018  *      non-NULL.
  1019  *  "pSortedList"
  1020  *      Address of a List of Objects that shall be sorted and returned. Must be
  1021  *      non-NULL, but may be empty.
  1022  *  "plContext"
  1023  *      Platform-specific context pointer.
  1024  * THREAD SAFETY:
  1025  *  Not Thread Safe - assumes exclusive access to "toList"
  1026  *  (see Thread Safety Definitions in Programmer's Guide)
  1027  * RETURNS:
  1028  *  Returns NULL if the function succeeds
  1029  *  Returns a Fatal Error if the function fails in an unrecoverable way
  1030  */
  1031 PKIX_Error *
  1032 pkix_List_QuickSort(
  1033         PKIX_List *fromList,
  1034         PKIX_List_SortComparatorCallback comparator,
  1035         PKIX_List **pSortedList,
  1036         void *plContext)
  1038         PKIX_List *sortedList = NULL;
  1039         PKIX_List *lessList = NULL;
  1040         PKIX_List *greaterList = NULL;
  1041         PKIX_List *sortedLessList = NULL;
  1042         PKIX_List *sortedGreaterList = NULL;
  1043         PKIX_PL_Object *object = NULL;
  1044         PKIX_PL_Object *cmpObj = NULL;
  1045         PKIX_Int32 cmpResult = 0;
  1046         PKIX_UInt32 size = 0;
  1047         PKIX_UInt32 i;
  1049         PKIX_ENTER(BUILD, "pkix_List_QuickSort");
  1050         PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
  1052         PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext),
  1053                 PKIX_LISTGETLENGTHFAILED);
  1055         PKIX_CHECK(PKIX_List_Create(&lessList, plContext),
  1056                     PKIX_LISTCREATEFAILED);
  1058         PKIX_CHECK(PKIX_List_Create(&greaterList, plContext),
  1059                     PKIX_LISTCREATEFAILED);
  1061         PKIX_CHECK(PKIX_List_GetItem
  1062                 (fromList, 0, &object, plContext),
  1063                 PKIX_LISTGETITEMFAILED);
  1065         /*
  1066          * Pick the first item on the list as the one to be compared.
  1067          * Separate rest of the itmes into two lists: less-than or greater-
  1068          * than lists. Sort those two lists recursively. Insert sorted
  1069          * less-than list before the picked item and append the greater-
  1070          * than list after the picked item.
  1071          */
  1072         for (i = 1; i < size; i++) {
  1074                 PKIX_CHECK(PKIX_List_GetItem
  1075                         (fromList, i, &cmpObj, plContext),
  1076                         PKIX_LISTGETITEMFAILED);
  1078                 PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext),
  1079                         PKIX_COMPARATORCALLBACKFAILED);
  1081                 if (cmpResult >= 0) {
  1082                         PKIX_CHECK(PKIX_List_AppendItem
  1083                                 (lessList, cmpObj, plContext),
  1084                                 PKIX_LISTAPPENDITEMFAILED);
  1085                 } else {
  1086                         PKIX_CHECK(PKIX_List_AppendItem
  1087                                 (greaterList, cmpObj, plContext),
  1088                                 PKIX_LISTAPPENDITEMFAILED);
  1090                 PKIX_DECREF(cmpObj);
  1093         PKIX_CHECK(PKIX_List_Create(&sortedList, plContext),
  1094                     PKIX_LISTCREATEFAILED);
  1096         PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext),
  1097                 PKIX_LISTGETLENGTHFAILED);
  1099         if (size > 1) {
  1101                 PKIX_CHECK(pkix_List_QuickSort
  1102                         (lessList, comparator, &sortedLessList, plContext),
  1103                         PKIX_LISTQUICKSORTFAILED);
  1105                 PKIX_CHECK(pkix_List_AppendList
  1106                         (sortedList, sortedLessList, plContext),
  1107                         PKIX_LISTAPPENDLISTFAILED);
  1108         } else {
  1109                 PKIX_CHECK(pkix_List_AppendList
  1110                         (sortedList, lessList, plContext),
  1111                         PKIX_LISTAPPENDLISTFAILED);
  1114         PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext),
  1115                 PKIX_LISTAPPENDFAILED);
  1117         PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext),
  1118                 PKIX_LISTGETLENGTHFAILED);
  1120         if (size > 1) {
  1122                 PKIX_CHECK(pkix_List_QuickSort
  1123                         (greaterList, comparator, &sortedGreaterList, plContext),
  1124                         PKIX_LISTQUICKSORTFAILED);
  1126                 PKIX_CHECK(pkix_List_AppendList
  1127                         (sortedList, sortedGreaterList, plContext),
  1128                         PKIX_LISTAPPENDLISTFAILED);
  1129         } else {
  1130                 PKIX_CHECK(pkix_List_AppendList
  1131                         (sortedList, greaterList, plContext),
  1132                         PKIX_LISTAPPENDLISTFAILED);
  1135         *pSortedList = sortedList;
  1137 cleanup:
  1139         PKIX_DECREF(cmpObj);
  1140         PKIX_DECREF(object);
  1141         PKIX_DECREF(sortedGreaterList);
  1142         PKIX_DECREF(sortedLessList);
  1143         PKIX_DECREF(greaterList);
  1144         PKIX_DECREF(lessList);
  1146         PKIX_RETURN(LIST);
  1149 /*
  1150  * FUNCTION: pkix_List_BubbleSort
  1151  * DESCRIPTION:
  1153  *  Sorts List of Objects "fromList" using "comparatorCallback"'s result as
  1154  *  comasrison key and returns the sorted List at "pSortedList". The sorting
  1155  *  algorithm used is bubble sort (n*n).
  1157  * PARAMETERS:
  1158  *  "fromList"
  1159  *      Address of a List of Objects to be sorted. Must be non-NULL, but may be
  1160  *      empty.
  1161  *  "comparatorCallback"
  1162  *      Address of callback function that will compare two Objects on the List.
  1163  *      It should return -1 for less, 0 for equal and 1 for greater. The
  1164  *      callback implementation chooses what in Objects to be compared. Must be
  1165  *      non-NULL.
  1166  *  "pSortedList"
  1167  *      Address of a List of Objects that shall be sorted and returned. Must be
  1168  *      non-NULL, but may be empty.
  1169  *  "plContext"
  1170  *      Platform-specific context pointer.
  1171  * THREAD SAFETY:
  1172  *  Not Thread Safe - assumes exclusive access to "toList"
  1173  *  (see Thread Safety Definitions in Programmer's Guide)
  1174  * RETURNS:
  1175  *  Returns NULL if the function succeeds
  1176  *  Returns a Fatal Error if the function fails in an unrecoverable way
  1177  */
  1178 PKIX_Error *
  1179 pkix_List_BubbleSort(
  1180         PKIX_List *fromList,
  1181         PKIX_List_SortComparatorCallback comparator,
  1182         PKIX_List **pSortedList,
  1183         void *plContext)
  1185         PKIX_List *sortedList = NULL;
  1186         PKIX_PL_Object *cmpObj = NULL;
  1187         PKIX_PL_Object *leastObj = NULL;
  1188         PKIX_Int32 cmpResult = 0;
  1189         PKIX_UInt32 size = 0;
  1190         PKIX_UInt32 i, j;
  1192         PKIX_ENTER(BUILD, "pkix_List_BubbleSort");
  1193         PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
  1195         if (fromList->immutable) {
  1196             PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST);
  1198         PKIX_CHECK(pkix_List_Duplicate
  1199                 ((PKIX_PL_Object *) fromList,
  1200                 (PKIX_PL_Object **) &sortedList,
  1201                  plContext),
  1202                 PKIX_LISTDUPLICATEFAILED);
  1204         PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext),
  1205                 PKIX_LISTGETLENGTHFAILED);
  1207         if (size > 1) {
  1209         /*
  1210          * Move from the first of the item on the list, For each iteration,
  1211          * compare and swap the least value to the head of the comparisoning
  1212          * sub-list.
  1213          */
  1214             for (i = 0; i < size - 1; i++) {
  1216                 PKIX_CHECK(PKIX_List_GetItem
  1217                         (sortedList, i, &leastObj, plContext),
  1218                         PKIX_LISTGETITEMFAILED);
  1220                 for (j = i + 1; j < size; j++) {
  1221                         PKIX_CHECK(PKIX_List_GetItem
  1222                                 (sortedList, j, &cmpObj, plContext),
  1223                                 PKIX_LISTGETITEMFAILED);
  1224                         PKIX_CHECK(comparator
  1225                                 (leastObj, cmpObj, &cmpResult, plContext),
  1226                                 PKIX_COMPARATORCALLBACKFAILED);
  1227                         if (cmpResult > 0) {
  1228                                 PKIX_CHECK(PKIX_List_SetItem
  1229                                            (sortedList, j, leastObj, plContext),
  1230                                            PKIX_LISTSETITEMFAILED);
  1232                                 PKIX_DECREF(leastObj);
  1233                                 leastObj = cmpObj;
  1234                                 cmpObj = NULL;
  1235                         } else {
  1236                                 PKIX_DECREF(cmpObj);
  1239                 PKIX_CHECK(PKIX_List_SetItem
  1240                            (sortedList, i, leastObj, plContext),
  1241                            PKIX_LISTSETITEMFAILED);
  1243                 PKIX_DECREF(leastObj);
  1248         *pSortedList = sortedList;
  1249         sortedList = NULL;
  1250 cleanup:
  1252         PKIX_DECREF(sortedList);
  1253         PKIX_DECREF(leastObj);
  1254         PKIX_DECREF(cmpObj);
  1256         PKIX_RETURN(LIST);
  1259 /* --Public-List-Functions--------------------------------------------- */
  1261 /*
  1262  * FUNCTION: PKIX_List_Create (see comments in pkix_util.h)
  1263  */
  1264 PKIX_Error *
  1265 PKIX_List_Create(
  1266         PKIX_List **pList,
  1267         void *plContext)
  1269         PKIX_List *list = NULL;
  1271         PKIX_ENTER(LIST, "PKIX_List_Create");
  1272         PKIX_NULLCHECK_ONE(pList);
  1274         PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext),
  1275                     PKIX_LISTCREATEINTERNALFAILED);
  1277         *pList = list;
  1279 cleanup:
  1281         PKIX_RETURN(LIST);
  1284 /*
  1285  * FUNCTION: PKIX_List_SetImmutable (see comments in pkix_util.h)
  1286  */
  1287 PKIX_Error *
  1288 PKIX_List_SetImmutable(
  1289         PKIX_List *list,
  1290         void *plContext)
  1292         PKIX_ENTER(LIST, "PKIX_List_SetImmutable");
  1293         PKIX_NULLCHECK_ONE(list);
  1295         if (!list->isHeader){
  1296                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1299         list->immutable = PKIX_TRUE;
  1301 cleanup:
  1303         PKIX_RETURN(LIST);
  1306 /*
  1307  * FUNCTION: PKIX_List_IsImmutable (see comments in pkix_util.h)
  1308  */
  1309 PKIX_Error *
  1310 PKIX_List_IsImmutable(
  1311         PKIX_List *list,
  1312         PKIX_Boolean *pImmutable,
  1313         void *plContext)
  1315         PKIX_ENTER(LIST, "PKIX_List_IsImmutable");
  1316         PKIX_NULLCHECK_TWO(list, pImmutable);
  1318         if (!list->isHeader){
  1319                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1322         *pImmutable = list->immutable;
  1324 cleanup:
  1326         PKIX_RETURN(LIST);
  1329 /*
  1330  * FUNCTION: PKIX_List_GetLength (see comments in pkix_util.h)
  1331  */
  1332 PKIX_Error *
  1333 PKIX_List_GetLength(
  1334         PKIX_List *list,
  1335         PKIX_UInt32 *pLength,
  1336         void *plContext)
  1338         PKIX_ENTER(LIST, "PKIX_List_GetLength");
  1339         PKIX_NULLCHECK_TWO(list, pLength);
  1341         if (!list->isHeader){
  1342                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1345         *pLength = list->length;
  1347 cleanup:
  1349         PKIX_RETURN(LIST);
  1352 /*
  1353  * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h)
  1354  */
  1355 PKIX_Error *
  1356 PKIX_List_IsEmpty(
  1357         PKIX_List *list,
  1358         PKIX_Boolean *pEmpty,
  1359         void *plContext)
  1361         PKIX_UInt32 length;
  1363         PKIX_ENTER(LIST, "PKIX_List_IsEmpty");
  1364         PKIX_NULLCHECK_TWO(list, pEmpty);
  1366         if (!list->isHeader){
  1367                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1370         length = list->length;
  1372         if (length == 0){
  1373                 *pEmpty = PKIX_TRUE;
  1374         } else {
  1375                 *pEmpty = PKIX_FALSE;
  1378 cleanup:
  1380         PKIX_RETURN(LIST);
  1383 /*
  1384  * FUNCTION: PKIX_List_AppendItem (see comments in pkix_util.h)
  1385  */
  1386 PKIX_Error *
  1387 PKIX_List_AppendItem(
  1388         PKIX_List *list,
  1389         PKIX_PL_Object *item,
  1390         void *plContext)
  1392         PKIX_List *lastElement = NULL;
  1393         PKIX_List *newElement = NULL;
  1394         PKIX_UInt32 length, i;
  1396         PKIX_ENTER(LIST, "PKIX_List_AppendItem");
  1397         PKIX_NULLCHECK_ONE(list);
  1399         if (list->immutable){
  1400                 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
  1403         if (!list->isHeader){
  1404                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1407         length = list->length;
  1409         /* find last element of list and create new element there */
  1411         lastElement = list;
  1412         for (i = 0; i < length; i++){
  1413                 lastElement = lastElement->next;
  1416         PKIX_CHECK(pkix_List_Create_Internal
  1417                     (PKIX_FALSE, &newElement, plContext),
  1418                     PKIX_LISTCREATEINTERNALFAILED);
  1420         PKIX_INCREF(item);
  1421         newElement->item = item;
  1423         PKIX_CHECK(PKIX_PL_Object_InvalidateCache
  1424                     ((PKIX_PL_Object *)list, plContext),
  1425                     PKIX_OBJECTINVALIDATECACHEFAILED);
  1427         lastElement->next = newElement;
  1428         newElement = NULL;
  1429         list->length += 1;
  1431 cleanup:
  1433         PKIX_DECREF(newElement);
  1435         PKIX_RETURN(LIST);
  1438 /*
  1439  * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h)
  1440  */
  1441 PKIX_Error *
  1442 PKIX_List_InsertItem(
  1443         PKIX_List *list,
  1444         PKIX_UInt32 index,
  1445         PKIX_PL_Object *item,
  1446         void *plContext)
  1448         PKIX_List *element = NULL;
  1449         PKIX_List *newElem = NULL;
  1451         PKIX_ENTER(LIST, "PKIX_List_InsertItem");
  1452         PKIX_NULLCHECK_ONE(list);
  1455         if (list->immutable){
  1456                 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
  1459         if (!list->isHeader){
  1460                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1463         /* Create a new list object */
  1464         PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext),
  1465                     PKIX_LISTCREATEINTERNALFAILED);
  1467         if (list->length) {
  1468             PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
  1469                        PKIX_LISTGETELEMENTFAILED);
  1470             /* Copy the old element's contents into the new element */
  1471             newElem->item = element->item;
  1472             /* Add new item to the list */
  1473             PKIX_INCREF(item);
  1474             element->item = item;
  1475             /* Set the new element's next pointer to the old element's next */
  1476             newElem->next = element->next;
  1477             /* Set the old element's next pointer to the new element */
  1478             element->next = newElem;
  1479             newElem = NULL;
  1480         } else {
  1481             PKIX_INCREF(item);
  1482             newElem->item = item;
  1483             newElem->next = NULL;
  1484             list->next = newElem;
  1485             newElem = NULL;
  1487         list->length++;
  1489         PKIX_CHECK(PKIX_PL_Object_InvalidateCache
  1490                     ((PKIX_PL_Object *)list, plContext),
  1491                     PKIX_OBJECTINVALIDATECACHEFAILED);
  1492 cleanup:
  1493         PKIX_DECREF(newElem);
  1495         PKIX_RETURN(LIST);
  1498 /*
  1499  * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h)
  1500  */
  1501 PKIX_Error *
  1502 PKIX_List_GetItem(
  1503         PKIX_List *list,
  1504         PKIX_UInt32 index,
  1505         PKIX_PL_Object **pItem,
  1506         void *plContext)
  1508         PKIX_List *element = NULL;
  1510         PKIX_ENTER(LIST, "PKIX_List_GetItem");
  1511         PKIX_NULLCHECK_TWO(list, pItem);
  1513         if (!list->isHeader){
  1514                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1517         PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
  1518                     PKIX_LISTGETELEMENTFAILED);
  1520         PKIX_INCREF(element->item);
  1521         *pItem = element->item;
  1523 cleanup:
  1525         PKIX_RETURN(LIST);
  1528 /*
  1529  * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h)
  1530  */
  1531 PKIX_Error *
  1532 PKIX_List_SetItem(
  1533         PKIX_List *list,
  1534         PKIX_UInt32 index,
  1535         PKIX_PL_Object *item,
  1536         void *plContext)
  1538         PKIX_List *element;
  1540         PKIX_ENTER(LIST, "PKIX_List_SetItem");
  1541         PKIX_NULLCHECK_ONE(list);
  1543         if (list->immutable){
  1544                 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
  1547         if (!list->isHeader){
  1548                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1551         PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
  1552                     PKIX_LISTGETELEMENTFAILED);
  1554         /* DecRef old contents */
  1555         PKIX_DECREF(element->item);
  1557         /* Set New Contents */
  1558         PKIX_INCREF(item);
  1559         element->item = item;
  1561         PKIX_CHECK(PKIX_PL_Object_InvalidateCache
  1562                     ((PKIX_PL_Object *)list, plContext),
  1563                     PKIX_OBJECTINVALIDATECACHEFAILED);
  1565 cleanup:
  1567         PKIX_RETURN(LIST);
  1570 /*
  1571  * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h)
  1572  */
  1573 PKIX_Error *
  1574 PKIX_List_DeleteItem(
  1575         PKIX_List *list,
  1576         PKIX_UInt32 index,
  1577         void *plContext)
  1579         PKIX_List *element = NULL;
  1580         PKIX_List *prevElement = NULL;
  1581         PKIX_List *nextElement = NULL;
  1583         PKIX_ENTER(LIST, "PKIX_List_DeleteItem");
  1584         PKIX_NULLCHECK_ONE(list);
  1586         if (list->immutable){
  1587                 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
  1590         if (!list->isHeader){
  1591                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1594         PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
  1595                     PKIX_LISTGETELEMENTFAILED);
  1597         /* DecRef old contents */
  1598         PKIX_DECREF(element->item);
  1600         nextElement = element->next;
  1602         if (nextElement != NULL) {
  1603                 /* If the next element exists, splice it out. */
  1605                 /* Don't need to change ref counts for targets of next */
  1606                 element->item = nextElement->item;
  1607                 nextElement->item = NULL;
  1609                 /* Don't need to change ref counts for targets of next */
  1610                 element->next = nextElement->next;
  1611                 nextElement->next = NULL;
  1613                 PKIX_DECREF(nextElement);
  1615         } else { /* The element is at the tail of the list */
  1616                 if (index != 0) {
  1617                         PKIX_CHECK(pkix_List_GetElement
  1618                                     (list, index-1, &prevElement, plContext),
  1619                                     PKIX_LISTGETELEMENTFAILED);
  1620                 } else if (index == 0){ /* prevElement must be header */
  1621                         prevElement = list;
  1623                 prevElement->next = NULL;
  1625                 /* Delete the element */
  1626                 PKIX_DECREF(element);
  1629         PKIX_CHECK(PKIX_PL_Object_InvalidateCache
  1630                     ((PKIX_PL_Object *)list, plContext),
  1631                     PKIX_OBJECTINVALIDATECACHEFAILED);
  1633         list->length = list->length - 1;
  1635 cleanup:
  1637         PKIX_RETURN(LIST);
  1640 /*
  1641  * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h)
  1642  */
  1643 PKIX_Error *
  1644 PKIX_List_ReverseList(
  1645         PKIX_List *list,
  1646         PKIX_List **pReversedList,
  1647         void *plContext)
  1649         PKIX_List *reversedList = NULL;
  1650         PKIX_PL_Object *item = NULL;
  1651         PKIX_PL_Object *duplicateItem = NULL;
  1652         PKIX_UInt32 length, i;
  1654         PKIX_ENTER(LIST, "pkix_List_ReverseList");
  1655         PKIX_NULLCHECK_TWO(list, pReversedList);
  1657         if (!list->isHeader){
  1658                 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
  1661         length = list->length;
  1663         /* Create a new list object */
  1664         PKIX_CHECK(PKIX_List_Create(&reversedList, plContext),
  1665                     PKIX_LISTCREATEINTERNALFAILED);
  1667         /*
  1668          * Starting with the last item and traversing backwards (from
  1669          * the original list), append each item to the reversed list
  1670          */
  1672         for (i = 1; i <= length; i++){
  1673                 PKIX_CHECK(PKIX_List_GetItem
  1674                             (list, (length - i), &item, plContext),
  1675                             PKIX_LISTGETITEMFAILED);
  1677                 PKIX_CHECK(PKIX_PL_Object_Duplicate
  1678                             (item, &duplicateItem, plContext),
  1679                             PKIX_LISTDUPLICATEFAILED);
  1681                 PKIX_CHECK(PKIX_List_AppendItem
  1682                             (reversedList, duplicateItem, plContext),
  1683                             PKIX_LISTAPPENDITEMFAILED);
  1685                 PKIX_DECREF(item);
  1686                 PKIX_DECREF(duplicateItem);
  1689         *pReversedList = reversedList;
  1691 cleanup:
  1693         PKIX_DECREF(item);
  1694         PKIX_DECREF(duplicateItem);
  1696         if (PKIX_ERROR_RECEIVED){
  1697                 PKIX_DECREF(reversedList);
  1700         PKIX_RETURN(LIST);

mercurial