2  * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 
   4  * The contents of this file constitute Original Code as defined in and are 
   5  * subject to the Apple Public Source License Version 1.2 (the 'License'). 
   6  * You may not use this file except in compliance with the License. Please obtain 
   7  * a copy of the License at http://www.apple.com/publicsource and read it before 
  10  * This Original Code and all software distributed under the License are 
  11  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 
  12  * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 
  13  * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
  14  * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 
  15  * specific language governing rights and limitations under the License. 
  20 // cssmlist - CSSM_LIST operational utilities 
  26 #include <Security/cssmlist.h> 
  30 // Managing list elements 
  32 ListElement 
*ListElement::last() 
  34         for (ListElement 
*p 
= this; ; p 
= p
->next()) 
  35                 if (p
->next() == NULL
) 
  41 ListElement::ListElement(CSSM_WORDID_TYPE word
) 
  43         ElementType 
= CSSM_LIST_ELEMENT_WORDID
; 
  47 ListElement::ListElement(const CssmData 
&data
) 
  49         ElementType 
= CSSM_LIST_ELEMENT_DATUM
; 
  54 ListElement::ListElement(CssmAllocator 
&alloc
, string s
) 
  56     ElementType 
= CSSM_LIST_ELEMENT_DATUM
; 
  58     size_t length 
= s
.size(); 
  59     Element
.Word 
= CssmData(memcpy(alloc
.alloc
<char>(length
), s
.data(), length
), length
); 
  62 ListElement::ListElement(const CssmList 
&list
) 
  64         ElementType 
= CSSM_LIST_ELEMENT_SUBLIST
; 
  66         Element
.Sublist 
= list
; 
  70 CssmData 
&ListElement::data() 
  72         assert(type() == CSSM_LIST_ELEMENT_DATUM
); 
  73         return CssmData::overlay(Element
.Word
); 
  76 const CssmData 
&ListElement::data() const 
  78         assert(type() == CSSM_LIST_ELEMENT_DATUM
); 
  79         return CssmData::overlay(Element
.Word
); 
  82 CssmList 
&ListElement::list() 
  84         assert(type() == CSSM_LIST_ELEMENT_SUBLIST
); 
  85         return CssmList::overlay(Element
.Sublist
); 
  88 const CssmList 
&ListElement::list() const 
  90         assert(type() == CSSM_LIST_ELEMENT_SUBLIST
); 
  91         return CssmList::overlay(Element
.Sublist
); 
  94 CSSM_WORDID_TYPE 
ListElement::word() const 
  96         assert(type() == CSSM_LIST_ELEMENT_WORDID
); 
 104 ListElement 
&CssmList::operator [] (unsigned ix
) const 
 106         for (ListElement 
*elem 
= first(); elem
; elem 
= elem
->next(), ix
--) { 
 113 unsigned int CssmList::length() const 
 115         unsigned int len 
= 0; 
 116         for (ListElement 
*elem 
= first(); elem
; elem 
= elem
->next()) 
 121 CssmList 
&CssmList::append(ListElement 
*elem
) 
 123         if (Tail 
== NULL
) {     // first element 
 126                 Tail
->NextElement 
= elem
; 
 129         elem
->NextElement 
= NULL
; 
 133 CssmList 
&CssmList::insert(ListElement 
*elem
, ListElement 
*before
) 
 135         // null before -> append 
 139         // we have a real position 
 141         if (Head 
== before
) { // before first element 
 142                 elem
->NextElement 
= before
; 
 144         } else { // before is not first 
 145                 for (CSSM_LIST_ELEMENT 
*p 
= Head
; p
; p 
= p
->NextElement
) { 
 146                         if (p
->NextElement 
== before
) { 
 147                                 elem
->NextElement 
= before
; 
 148                                 p
->NextElement 
= elem
; 
 152                 // end of list, before not in list 
 158 CssmList 
&CssmList::remove(ListElement 
*elem
) 
 161         if (elem 
== Head
) {     // remove first element 
 162                 Head 
= Head
->NextElement
; 
 163         } else { // subsequent element 
 164                 for (CSSM_LIST_ELEMENT 
*p 
= Head
; p
; p 
= p
->NextElement
) 
 165                         if (p
->NextElement 
== elem
) { 
 166                                 p
->NextElement 
= elem
->NextElement
; 
 167                                 if (elem
->NextElement 
== NULL
) // removing last element 
 171                 // end of list, elem not found 
 177 void CssmList::snip() 
 179     assert(Head
);       // can't be empty 
 180     if (Head 
== Tail
) { // single element, empty when snipped 
 182     } else {            // more than one, bypass first 
 183         Head 
= first()->next(); 
 189 // Deep-destruction of CssmLists and ListElements. 
 190 // The underlying assumption is that all components were allocated from a single 
 191 // CssmAllocator in canonical chunks. 
 193 void ListElement::clear(CssmAllocator 
&alloc
) 
 196         case CSSM_LIST_ELEMENT_WORDID
: 
 197                 break;  // no substructure 
 198         case CSSM_LIST_ELEMENT_DATUM
: 
 199                 alloc
.free(data().data()); 
 201         case CSSM_LIST_ELEMENT_SUBLIST
: 
 209 void CssmList::clear(CssmAllocator 
&alloc
) 
 211         ListElement 
*elem 
= first(); 
 213                 ListElement 
*next 
= elem
->next(); 
 214                 destroy(elem
, alloc
); 
 221 // Building TypedLists 
 223 TypedList::TypedList(CssmAllocator 
&alloc
, CSSM_WORDID_TYPE type
) 
 225         append(new(alloc
) ListElement(type
)); 
 228 TypedList::TypedList(CssmAllocator 
&alloc
, CSSM_WORDID_TYPE type
, ListElement 
*elem1
) 
 230         append(new(alloc
) ListElement(type
)); 
 234 TypedList::TypedList(CssmAllocator 
&alloc
, CSSM_WORDID_TYPE type
, ListElement 
*elem1
, ListElement 
*elem2
) 
 236         append(new(alloc
) ListElement(type
)); 
 243 // Verify that a TypedList is "proper", i.e. has a first element of WORDID form 
 245 bool TypedList::isProper() const 
 247         return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID
;