Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(890)

Side by Side Diff: nss/lib/libpkix/pkix/util/pkix_list.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/libpkix/pkix/util/pkix_list.h ('k') | nss/lib/libpkix/pkix/util/pkix_logger.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5 * pkix_list.c
6 *
7 * List Object Functions
8 *
9 */
10
11 #include "pkix_list.h"
12
13 /* --Private-Functions-------------------------------------------- */
14
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;
44
45 PKIX_ENTER(LIST, "pkix_List_Create_Internal");
46 PKIX_NULLCHECK_ONE(pList);
47
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);
53
54 list->item = NULL;
55 list->next = NULL;
56 list->immutable = PKIX_FALSE;
57 list->length = 0;
58 list->isHeader = isHeader;
59
60 *pList = list;
61
62 cleanup:
63
64 PKIX_RETURN(LIST);
65 }
66
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;
78
79 PKIX_ENTER(LIST, "pkix_List_Destroy");
80 PKIX_NULLCHECK_ONE(object);
81
82 /* Check that this object is a list */
83 PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
84 PKIX_OBJECTNOTLIST);
85
86 list = (PKIX_List *)object;
87
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;
98
99 cleanup:
100
101 PKIX_RETURN(LIST);
102 }
103
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;
137
138 PKIX_ENTER(LIST, "pkix_List_ToString_Helper");
139 PKIX_NULLCHECK_TWO(list, pString);
140
141 /* special case when list is the header */
142 if (list->isHeader){
143
144 PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext),
145 PKIX_LISTISEMPTYFAILED);
146
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 }
163
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);
168
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 }
195
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);
200
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);
209
210 PKIX_CHECK(PKIX_PL_Sprintf
211 (pString,
212 plContext,
213 format,
214 itemString,
215 nextString),
216 PKIX_SPRINTFFAILED);
217 }
218
219 cleanup:
220
221 PKIX_DECREF(itemString);
222 PKIX_DECREF(nextString);
223 PKIX_DECREF(format);
224
225 PKIX_RETURN(LIST);
226 }
227
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;
241
242 PKIX_ENTER(LIST, "pkix_List_ToString");
243 PKIX_NULLCHECK_TWO(object, pString);
244
245 PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
246 PKIX_OBJECTNOTLIST);
247
248 list = (PKIX_List *)object;
249
250 if (!list->isHeader){
251 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
252 }
253
254 PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext),
255 PKIX_LISTTOSTRINGHELPERFAILED);
256
257 PKIX_CHECK(PKIX_PL_String_Create
258 (PKIX_ESCASCII, "(%s)", 0, &format, plContext),
259 PKIX_STRINGCREATEFAILED);
260
261 PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString),
262 PKIX_SPRINTFFAILED);
263
264 cleanup:
265
266 PKIX_DECREF(listString);
267 PKIX_DECREF(format);
268
269 PKIX_RETURN(LIST);
270 }
271
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;
292
293 PKIX_ENTER(LIST, "pkix_List_Equals");
294 PKIX_NULLCHECK_THREE(first, second, pResult);
295
296 /* test that first is a List */
297 PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext),
298 PKIX_FIRSTOBJECTNOTLIST);
299
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 }
308
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;
317
318 firstList = (PKIX_List *)first;
319 secondList = (PKIX_List *)second;
320
321 if ((!firstList->isHeader) && (!secondList->isHeader)){
322 PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS);
323 }
324
325 firstLength = firstList->length;
326 secondLength = secondList->length;
327
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);
336
337 PKIX_CHECK(PKIX_List_GetItem
338 (secondList, i, &secondItem, plContext),
339 PKIX_LISTGETITEMFAILED);
340
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);
353
354 PKIX_DECREF(firstItem);
355 PKIX_DECREF(secondItem);
356 }
357 }
358 }
359
360 *pResult = cmpResult;
361
362 cleanup:
363
364 PKIX_DECREF(firstItem);
365 PKIX_DECREF(secondItem);
366
367 PKIX_RETURN(LIST);
368 }
369
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;
385
386 PKIX_ENTER(LIST, "pkix_List_Hashcode");
387 PKIX_NULLCHECK_TWO(object, pHashcode);
388
389 PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
390 PKIX_OBJECTNOTLIST);
391
392 list = (PKIX_List *)object;
393
394 if (!list->isHeader){
395 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
396 }
397
398 length = list->length;
399
400 for (i = 0; i < length; i++){
401 PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext),
402 PKIX_LISTGETITEMFAILED);
403
404 if (!element){
405 tempHash = 100;
406 } else {
407 PKIX_CHECK(PKIX_PL_Object_Hashcode
408 (element, &tempHash, plContext),
409 PKIX_LISTHASHCODEFAILED);
410 }
411
412 hash = 31 * hash + tempHash;
413
414 PKIX_DECREF(element);
415 }
416
417 *pHashcode = hash;
418
419 cleanup:
420
421 PKIX_DECREF(element);
422 PKIX_RETURN(LIST);
423 }
424
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;
437
438 PKIX_ENTER(LIST, "pkix_List_Duplicate");
439 PKIX_NULLCHECK_TWO(object, pNewObject);
440
441 PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
442 PKIX_OBJECTNOTLIST);
443
444 list = (PKIX_List *)object;
445
446 if (list->immutable){
447 PKIX_CHECK(pkix_duplicateImmutable
448 (object, pNewObject, plContext),
449 PKIX_DUPLICATEIMMUTABLEFAILED);
450 } else {
451
452 PKIX_CHECK(pkix_List_Create_Internal
453 (list->isHeader, &listDuplicate, plContext),
454 PKIX_LISTCREATEINTERNALFAILED);
455
456 listDuplicate->length = list->length;
457
458 PKIX_INCREF(list->item);
459 listDuplicate->item = list->item;
460
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 }
471
472 *pNewObject = (PKIX_PL_Object *)listDuplicate;
473 }
474
475 cleanup:
476
477 if (PKIX_ERROR_RECEIVED){
478 PKIX_DECREF(listDuplicate);
479 }
480
481 PKIX_RETURN(LIST);
482 }
483
484
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;
522
523 PKIX_ENTER(LIST, "pkix_List_GetElement");
524 PKIX_NULLCHECK_TWO(list, pElement);
525
526 if (!list->isHeader){
527 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
528 }
529
530 length = list->length;
531
532 if (index >= length) {
533 PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS);
534 }
535
536 for (iterator = list; position++ <= index; iterator = iterator->next)
537 ;
538
539 (*pElement) = iterator;
540
541 cleanup:
542
543 PKIX_RETURN(LIST);
544 }
545
546
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;
563
564 PKIX_ENTER(LIST, "pkix_List_RegisterSelf");
565
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;
575
576 systemClasses[PKIX_LIST_TYPE] = entry;
577
578 PKIX_RETURN(LIST);
579 }
580
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;
616
617 PKIX_ENTER(LIST, "pkix_List_Contains");
618 PKIX_NULLCHECK_THREE(list, object, pFound);
619
620 PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
621 PKIX_LISTGETLENGTHFAILED);
622
623 for (index = 0; index < numEntries; index++) {
624 PKIX_CHECK(PKIX_List_GetItem
625 (list, index, &current, plContext),
626 PKIX_LISTGETITEMFAILED);
627
628 if (current) {
629 PKIX_CHECK(PKIX_PL_Object_Equals
630 (object, current, &match, plContext),
631 PKIX_OBJECTEQUALSFAILED);
632
633 PKIX_DECREF(current);
634 }
635
636 if (match) {
637 break;
638 }
639 }
640
641 *pFound = match;
642
643 cleanup:
644
645 PKIX_DECREF(current);
646 PKIX_RETURN(LIST);
647 }
648
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;
681
682 PKIX_ENTER(LIST, "pkix_List_Remove");
683 PKIX_NULLCHECK_TWO(list, object);
684
685 PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
686 PKIX_LISTGETLENGTHFAILED);
687
688 for (index = 0; index < numEntries; index++) {
689 PKIX_CHECK(PKIX_List_GetItem
690 (list, index, &current, plContext),
691 PKIX_LISTGETITEMFAILED);
692
693 if (current) {
694 PKIX_CHECK(PKIX_PL_Object_Equals
695 (object, current, &match, plContext),
696 PKIX_OBJECTEQUALSFAILED);
697
698 PKIX_DECREF(current);
699 }
700
701 if (match) {
702 PKIX_CHECK(PKIX_List_DeleteItem
703 (list, index, plContext),
704 PKIX_LISTDELETEITEMFAILED);
705 break;
706 }
707 }
708
709 cleanup:
710
711 PKIX_DECREF(current);
712 PKIX_RETURN(LIST);
713 }
714
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;
747
748 PKIX_ENTER(LIST, "pkix_List_RemoveItems");
749 PKIX_NULLCHECK_TWO(list, deleteList);
750
751 PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext),
752 PKIX_LISTGETLENGTHFAILED);
753
754 for (index = 0; index < numEntries; index++) {
755 PKIX_CHECK(PKIX_List_GetItem
756 (deleteList, index, &current, plContext),
757 PKIX_LISTGETITEMFAILED);
758
759 if (current) {
760 PKIX_CHECK(pkix_List_Remove
761 (list, current, plContext),
762 PKIX_OBJECTEQUALSFAILED);
763
764 PKIX_DECREF(current);
765 }
766 }
767
768 cleanup:
769
770 PKIX_DECREF(current);
771 PKIX_RETURN(LIST);
772 }
773
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;
809
810 PKIX_ENTER(LIST, "pkix_List_MergeLists");
811 PKIX_NULLCHECK_ONE(pMergedList);
812
813 *pMergedList = NULL;
814
815 PKIX_CHECK(PKIX_List_Create(&list, plContext),
816 PKIX_LISTCREATEFAILED);
817
818 if (firstList != NULL) {
819
820 PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext),
821 PKIX_LISTGETLENGTHFAILED);
822 }
823
824 for (i = 0; i < numItems; i++) {
825
826 PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext),
827 PKIX_LISTGETITEMFAILED);
828
829 PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext),
830 PKIX_LISTAPPENDITEMFAILED);
831
832 PKIX_DECREF(item);
833 }
834
835 numItems = 0;
836 if (secondList != NULL) {
837
838 PKIX_CHECK(PKIX_List_GetLength
839 (secondList,
840 &numItems,
841 plContext),
842 PKIX_LISTGETLENGTHFAILED);
843
844 }
845
846 for (i = 0; i < numItems; i++) {
847
848 PKIX_CHECK(PKIX_List_GetItem
849 (secondList, i, &item, plContext),
850 PKIX_LISTGETITEMFAILED);
851
852 PKIX_CHECK(PKIX_List_AppendItem
853 (list, item, plContext), PKIX_LISTAPPENDITEMFAILED);
854
855 PKIX_DECREF(item);
856 }
857
858 *pMergedList = list;
859 list = NULL;
860
861 cleanup:
862 PKIX_DECREF(list);
863 PKIX_DECREF(item);
864
865 PKIX_RETURN(LIST);
866 }
867
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;
899
900 PKIX_ENTER(LIST, "pkix_List_AppendList");
901 PKIX_NULLCHECK_ONE(toList);
902
903 /* if fromList is NULL or is an empty list, no action */
904
905 if (fromList == NULL) {
906 goto cleanup;
907 }
908
909 PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext),
910 PKIX_LISTGETLENGTHFAILED);
911
912 if (numItems == 0) {
913 goto cleanup;
914 }
915
916 for (i = 0; i < numItems; i++) {
917
918 PKIX_CHECK(PKIX_List_GetItem
919 (fromList, i, &item, plContext),
920 PKIX_LISTGETITEMFAILED);
921
922 PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext),
923 PKIX_LISTAPPENDITEMFAILED);
924
925 PKIX_DECREF(item);
926 }
927
928 cleanup:
929
930 PKIX_DECREF(item);
931
932 PKIX_RETURN(LIST);
933 }
934
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;
969
970 PKIX_ENTER(BUILD, "pkix_List_AppendUnique");
971 PKIX_NULLCHECK_TWO(fromList, toList);
972
973 PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext),
974 PKIX_LISTGETLENGTHFAILED);
975
976 for (listIx = 0; listIx < listLen; listIx++) {
977
978 PKIX_CHECK(PKIX_List_GetItem
979 (fromList, listIx, &object, plContext),
980 PKIX_LISTGETITEMFAILED);
981
982 PKIX_CHECK(pkix_List_Contains
983 (toList, object, &isContained, plContext),
984 PKIX_LISTCONTAINSFAILED);
985
986 if (isContained == PKIX_FALSE) {
987 PKIX_CHECK(PKIX_List_AppendItem
988 (toList, object, plContext),
989 PKIX_LISTAPPENDITEMFAILED);
990 }
991
992 PKIX_DECREF(object);
993 }
994
995 cleanup:
996
997 PKIX_DECREF(object);
998
999 PKIX_RETURN(LIST);
1000 }
1001
1002 /*
1003 * FUNCTION: pkix_List_QuickSort
1004 * DESCRIPTION:
1005 *
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).
1009 *
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)
1037 {
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;
1048
1049 PKIX_ENTER(BUILD, "pkix_List_QuickSort");
1050 PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
1051
1052 PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext),
1053 PKIX_LISTGETLENGTHFAILED);
1054
1055 PKIX_CHECK(PKIX_List_Create(&lessList, plContext),
1056 PKIX_LISTCREATEFAILED);
1057
1058 PKIX_CHECK(PKIX_List_Create(&greaterList, plContext),
1059 PKIX_LISTCREATEFAILED);
1060
1061 PKIX_CHECK(PKIX_List_GetItem
1062 (fromList, 0, &object, plContext),
1063 PKIX_LISTGETITEMFAILED);
1064
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++) {
1073
1074 PKIX_CHECK(PKIX_List_GetItem
1075 (fromList, i, &cmpObj, plContext),
1076 PKIX_LISTGETITEMFAILED);
1077
1078 PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext),
1079 PKIX_COMPARATORCALLBACKFAILED);
1080
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);
1089 }
1090 PKIX_DECREF(cmpObj);
1091 }
1092
1093 PKIX_CHECK(PKIX_List_Create(&sortedList, plContext),
1094 PKIX_LISTCREATEFAILED);
1095
1096 PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext),
1097 PKIX_LISTGETLENGTHFAILED);
1098
1099 if (size > 1) {
1100
1101 PKIX_CHECK(pkix_List_QuickSort
1102 (lessList, comparator, &sortedLessList, plContext),
1103 PKIX_LISTQUICKSORTFAILED);
1104
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);
1112 }
1113
1114 PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext),
1115 PKIX_LISTAPPENDFAILED);
1116
1117 PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext),
1118 PKIX_LISTGETLENGTHFAILED);
1119
1120 if (size > 1) {
1121
1122 PKIX_CHECK(pkix_List_QuickSort
1123 (greaterList, comparator, &sortedGreaterList, plContext) ,
1124 PKIX_LISTQUICKSORTFAILED);
1125
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);
1133 }
1134
1135 *pSortedList = sortedList;
1136
1137 cleanup:
1138
1139 PKIX_DECREF(cmpObj);
1140 PKIX_DECREF(object);
1141 PKIX_DECREF(sortedGreaterList);
1142 PKIX_DECREF(sortedLessList);
1143 PKIX_DECREF(greaterList);
1144 PKIX_DECREF(lessList);
1145
1146 PKIX_RETURN(LIST);
1147 }
1148
1149 /*
1150 * FUNCTION: pkix_List_BubbleSort
1151 * DESCRIPTION:
1152 *
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).
1156 *
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)
1184 {
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;
1191
1192 PKIX_ENTER(BUILD, "pkix_List_BubbleSort");
1193 PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
1194
1195 if (fromList->immutable) {
1196 PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST);
1197 }
1198 PKIX_CHECK(pkix_List_Duplicate
1199 ((PKIX_PL_Object *) fromList,
1200 (PKIX_PL_Object **) &sortedList,
1201 plContext),
1202 PKIX_LISTDUPLICATEFAILED);
1203
1204 PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext),
1205 PKIX_LISTGETLENGTHFAILED);
1206
1207 if (size > 1) {
1208
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++) {
1215
1216 PKIX_CHECK(PKIX_List_GetItem
1217 (sortedList, i, &leastObj, plContext),
1218 PKIX_LISTGETITEMFAILED);
1219
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);
1231
1232 PKIX_DECREF(leastObj);
1233 leastObj = cmpObj;
1234 cmpObj = NULL;
1235 } else {
1236 PKIX_DECREF(cmpObj);
1237 }
1238 }
1239 PKIX_CHECK(PKIX_List_SetItem
1240 (sortedList, i, leastObj, plContext),
1241 PKIX_LISTSETITEMFAILED);
1242
1243 PKIX_DECREF(leastObj);
1244 }
1245
1246 }
1247
1248 *pSortedList = sortedList;
1249 sortedList = NULL;
1250 cleanup:
1251
1252 PKIX_DECREF(sortedList);
1253 PKIX_DECREF(leastObj);
1254 PKIX_DECREF(cmpObj);
1255
1256 PKIX_RETURN(LIST);
1257 }
1258
1259 /* --Public-List-Functions--------------------------------------------- */
1260
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)
1268 {
1269 PKIX_List *list = NULL;
1270
1271 PKIX_ENTER(LIST, "PKIX_List_Create");
1272 PKIX_NULLCHECK_ONE(pList);
1273
1274 PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext),
1275 PKIX_LISTCREATEINTERNALFAILED);
1276
1277 *pList = list;
1278
1279 cleanup:
1280
1281 PKIX_RETURN(LIST);
1282 }
1283
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)
1291 {
1292 PKIX_ENTER(LIST, "PKIX_List_SetImmutable");
1293 PKIX_NULLCHECK_ONE(list);
1294
1295 if (!list->isHeader){
1296 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1297 }
1298
1299 list->immutable = PKIX_TRUE;
1300
1301 cleanup:
1302
1303 PKIX_RETURN(LIST);
1304 }
1305
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)
1314 {
1315 PKIX_ENTER(LIST, "PKIX_List_IsImmutable");
1316 PKIX_NULLCHECK_TWO(list, pImmutable);
1317
1318 if (!list->isHeader){
1319 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1320 }
1321
1322 *pImmutable = list->immutable;
1323
1324 cleanup:
1325
1326 PKIX_RETURN(LIST);
1327 }
1328
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)
1337 {
1338 PKIX_ENTER(LIST, "PKIX_List_GetLength");
1339 PKIX_NULLCHECK_TWO(list, pLength);
1340
1341 if (!list->isHeader){
1342 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1343 }
1344
1345 *pLength = list->length;
1346
1347 cleanup:
1348
1349 PKIX_RETURN(LIST);
1350 }
1351
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)
1360 {
1361 PKIX_UInt32 length;
1362
1363 PKIX_ENTER(LIST, "PKIX_List_IsEmpty");
1364 PKIX_NULLCHECK_TWO(list, pEmpty);
1365
1366 if (!list->isHeader){
1367 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1368 }
1369
1370 length = list->length;
1371
1372 if (length == 0){
1373 *pEmpty = PKIX_TRUE;
1374 } else {
1375 *pEmpty = PKIX_FALSE;
1376 }
1377
1378 cleanup:
1379
1380 PKIX_RETURN(LIST);
1381 }
1382
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)
1391 {
1392 PKIX_List *lastElement = NULL;
1393 PKIX_List *newElement = NULL;
1394 PKIX_UInt32 length, i;
1395
1396 PKIX_ENTER(LIST, "PKIX_List_AppendItem");
1397 PKIX_NULLCHECK_ONE(list);
1398
1399 if (list->immutable){
1400 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
1401 }
1402
1403 if (!list->isHeader){
1404 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1405 }
1406
1407 length = list->length;
1408
1409 /* find last element of list and create new element there */
1410
1411 lastElement = list;
1412 for (i = 0; i < length; i++){
1413 lastElement = lastElement->next;
1414 }
1415
1416 PKIX_CHECK(pkix_List_Create_Internal
1417 (PKIX_FALSE, &newElement, plContext),
1418 PKIX_LISTCREATEINTERNALFAILED);
1419
1420 PKIX_INCREF(item);
1421 newElement->item = item;
1422
1423 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
1424 ((PKIX_PL_Object *)list, plContext),
1425 PKIX_OBJECTINVALIDATECACHEFAILED);
1426
1427 lastElement->next = newElement;
1428 newElement = NULL;
1429 list->length += 1;
1430
1431 cleanup:
1432
1433 PKIX_DECREF(newElement);
1434
1435 PKIX_RETURN(LIST);
1436 }
1437
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)
1447 {
1448 PKIX_List *element = NULL;
1449 PKIX_List *newElem = NULL;
1450
1451 PKIX_ENTER(LIST, "PKIX_List_InsertItem");
1452 PKIX_NULLCHECK_ONE(list);
1453
1454
1455 if (list->immutable){
1456 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
1457 }
1458
1459 if (!list->isHeader){
1460 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1461 }
1462
1463 /* Create a new list object */
1464 PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext),
1465 PKIX_LISTCREATEINTERNALFAILED);
1466
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;
1486 }
1487 list->length++;
1488
1489 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
1490 ((PKIX_PL_Object *)list, plContext),
1491 PKIX_OBJECTINVALIDATECACHEFAILED);
1492 cleanup:
1493 PKIX_DECREF(newElem);
1494
1495 PKIX_RETURN(LIST);
1496 }
1497
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)
1507 {
1508 PKIX_List *element = NULL;
1509
1510 PKIX_ENTER(LIST, "PKIX_List_GetItem");
1511 PKIX_NULLCHECK_TWO(list, pItem);
1512
1513 if (!list->isHeader){
1514 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1515 }
1516
1517 PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
1518 PKIX_LISTGETELEMENTFAILED);
1519
1520 PKIX_INCREF(element->item);
1521 *pItem = element->item;
1522
1523 cleanup:
1524
1525 PKIX_RETURN(LIST);
1526 }
1527
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)
1537 {
1538 PKIX_List *element;
1539
1540 PKIX_ENTER(LIST, "PKIX_List_SetItem");
1541 PKIX_NULLCHECK_ONE(list);
1542
1543 if (list->immutable){
1544 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
1545 }
1546
1547 if (!list->isHeader){
1548 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1549 }
1550
1551 PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
1552 PKIX_LISTGETELEMENTFAILED);
1553
1554 /* DecRef old contents */
1555 PKIX_DECREF(element->item);
1556
1557 /* Set New Contents */
1558 PKIX_INCREF(item);
1559 element->item = item;
1560
1561 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
1562 ((PKIX_PL_Object *)list, plContext),
1563 PKIX_OBJECTINVALIDATECACHEFAILED);
1564
1565 cleanup:
1566
1567 PKIX_RETURN(LIST);
1568 }
1569
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)
1578 {
1579 PKIX_List *element = NULL;
1580 PKIX_List *prevElement = NULL;
1581 PKIX_List *nextElement = NULL;
1582
1583 PKIX_ENTER(LIST, "PKIX_List_DeleteItem");
1584 PKIX_NULLCHECK_ONE(list);
1585
1586 if (list->immutable){
1587 PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
1588 }
1589
1590 if (!list->isHeader){
1591 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1592 }
1593
1594 PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
1595 PKIX_LISTGETELEMENTFAILED);
1596
1597 /* DecRef old contents */
1598 PKIX_DECREF(element->item);
1599
1600 nextElement = element->next;
1601
1602 if (nextElement != NULL) {
1603 /* If the next element exists, splice it out. */
1604
1605 /* Don't need to change ref counts for targets of next */
1606 element->item = nextElement->item;
1607 nextElement->item = NULL;
1608
1609 /* Don't need to change ref counts for targets of next */
1610 element->next = nextElement->next;
1611 nextElement->next = NULL;
1612
1613 PKIX_DECREF(nextElement);
1614
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;
1622 }
1623 prevElement->next = NULL;
1624
1625 /* Delete the element */
1626 PKIX_DECREF(element);
1627 }
1628
1629 PKIX_CHECK(PKIX_PL_Object_InvalidateCache
1630 ((PKIX_PL_Object *)list, plContext),
1631 PKIX_OBJECTINVALIDATECACHEFAILED);
1632
1633 list->length = list->length - 1;
1634
1635 cleanup:
1636
1637 PKIX_RETURN(LIST);
1638 }
1639
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)
1648 {
1649 PKIX_List *reversedList = NULL;
1650 PKIX_PL_Object *item = NULL;
1651 PKIX_PL_Object *duplicateItem = NULL;
1652 PKIX_UInt32 length, i;
1653
1654 PKIX_ENTER(LIST, "pkix_List_ReverseList");
1655 PKIX_NULLCHECK_TWO(list, pReversedList);
1656
1657 if (!list->isHeader){
1658 PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
1659 }
1660
1661 length = list->length;
1662
1663 /* Create a new list object */
1664 PKIX_CHECK(PKIX_List_Create(&reversedList, plContext),
1665 PKIX_LISTCREATEINTERNALFAILED);
1666
1667 /*
1668 * Starting with the last item and traversing backwards (from
1669 * the original list), append each item to the reversed list
1670 */
1671
1672 for (i = 1; i <= length; i++){
1673 PKIX_CHECK(PKIX_List_GetItem
1674 (list, (length - i), &item, plContext),
1675 PKIX_LISTGETITEMFAILED);
1676
1677 PKIX_CHECK(PKIX_PL_Object_Duplicate
1678 (item, &duplicateItem, plContext),
1679 PKIX_LISTDUPLICATEFAILED);
1680
1681 PKIX_CHECK(PKIX_List_AppendItem
1682 (reversedList, duplicateItem, plContext),
1683 PKIX_LISTAPPENDITEMFAILED);
1684
1685 PKIX_DECREF(item);
1686 PKIX_DECREF(duplicateItem);
1687 }
1688
1689 *pReversedList = reversedList;
1690
1691 cleanup:
1692
1693 PKIX_DECREF(item);
1694 PKIX_DECREF(duplicateItem);
1695
1696 if (PKIX_ERROR_RECEIVED){
1697 PKIX_DECREF(reversedList);
1698 }
1699
1700 PKIX_RETURN(LIST);
1701 }
OLDNEW
« no previous file with comments | « nss/lib/libpkix/pkix/util/pkix_list.h ('k') | nss/lib/libpkix/pkix/util/pkix_logger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698