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>
27 #include <Security/cssmdata.h>
31 // Managing list elements
33 ListElement
*ListElement::last()
35 for (ListElement
*p
= this; ; p
= p
->next())
36 if (p
->next() == NULL
)
42 ListElement::ListElement(CSSM_WORDID_TYPE word
)
44 ElementType
= CSSM_LIST_ELEMENT_WORDID
;
48 ListElement::ListElement(const CssmData
&data
)
50 ElementType
= CSSM_LIST_ELEMENT_DATUM
;
55 ListElement::ListElement(CssmAllocator
&alloc
, const CssmData
&data
)
57 ElementType
= CSSM_LIST_ELEMENT_DATUM
;
59 Element
.Word
= CssmAutoData(alloc
, data
).release();
62 ListElement::ListElement(CssmAllocator
&alloc
, const string
&s
)
64 ElementType
= CSSM_LIST_ELEMENT_DATUM
;
66 Element
.Word
= CssmAutoData(alloc
, s
.data(), s
.size()).release();
69 ListElement::ListElement(const CssmList
&list
)
71 ElementType
= CSSM_LIST_ELEMENT_SUBLIST
;
73 Element
.Sublist
= list
;
77 CssmData
&ListElement::data()
79 assert(type() == CSSM_LIST_ELEMENT_DATUM
);
80 return CssmData::overlay(Element
.Word
);
83 const CssmData
&ListElement::data() const
85 assert(type() == CSSM_LIST_ELEMENT_DATUM
);
86 return CssmData::overlay(Element
.Word
);
89 CssmList
&ListElement::list()
91 assert(type() == CSSM_LIST_ELEMENT_SUBLIST
);
92 return CssmList::overlay(Element
.Sublist
);
95 const CssmList
&ListElement::list() const
97 assert(type() == CSSM_LIST_ELEMENT_SUBLIST
);
98 return CssmList::overlay(Element
.Sublist
);
101 TypedList
&ListElement::typedList()
103 return static_cast<TypedList
&>(list());
106 const TypedList
&ListElement::typedList() const
108 return static_cast<const TypedList
&>(list());
111 CSSM_WORDID_TYPE
ListElement::word() const
113 assert(type() == CSSM_LIST_ELEMENT_WORDID
);
121 ListElement
&CssmList::operator [] (unsigned ix
) const
123 for (ListElement
*elem
= first(); elem
; elem
= elem
->next(), ix
--) {
130 unsigned int CssmList::length() const
132 unsigned int len
= 0;
133 for (ListElement
*elem
= first(); elem
; elem
= elem
->next())
138 CssmList
&CssmList::append(ListElement
*elem
)
140 if (Tail
== NULL
) { // first element
143 Tail
->NextElement
= elem
;
146 elem
->NextElement
= NULL
;
150 CssmList
&CssmList::insert(ListElement
*elem
, ListElement
*before
)
152 // null before -> append
156 // we have a real position
158 if (Head
== before
) { // before first element
159 elem
->NextElement
= before
;
161 } else { // before is not first
162 for (CSSM_LIST_ELEMENT
*p
= Head
; p
; p
= p
->NextElement
) {
163 if (p
->NextElement
== before
) {
164 elem
->NextElement
= before
;
165 p
->NextElement
= elem
;
169 // end of list, before not in list
175 CssmList
&CssmList::remove(ListElement
*elem
)
178 if (elem
== Head
) { // remove first element
179 Head
= Head
->NextElement
;
180 } else { // subsequent element
181 for (CSSM_LIST_ELEMENT
*p
= Head
; p
; p
= p
->NextElement
)
182 if (p
->NextElement
== elem
) {
183 p
->NextElement
= elem
->NextElement
;
184 if (elem
->NextElement
== NULL
) // removing last element
188 // end of list, elem not found
194 void CssmList::snip()
196 assert(Head
); // can't be empty
197 if (Head
== Tail
) { // single element, empty when snipped
199 } else { // more than one, bypass first
200 Head
= first()->next();
206 // Deep-destruction of CssmLists and ListElements.
207 // The underlying assumption is that all components were allocated from a single
208 // CssmAllocator in canonical chunks.
210 void ListElement::clear(CssmAllocator
&alloc
)
213 case CSSM_LIST_ELEMENT_WORDID
:
214 break; // no substructure
215 case CSSM_LIST_ELEMENT_DATUM
:
216 alloc
.free(data().data());
218 case CSSM_LIST_ELEMENT_SUBLIST
:
226 void CssmList::clear(CssmAllocator
&alloc
)
228 ListElement
*elem
= first();
230 ListElement
*next
= elem
->next();
231 destroy(elem
, alloc
);
238 // Building TypedLists
240 TypedList::TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
)
242 append(new(alloc
) ListElement(type
));
245 TypedList::TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
)
247 append(new(alloc
) ListElement(type
));
251 TypedList::TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
)
253 append(new(alloc
) ListElement(type
));
258 TypedList::TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
, ListElement
*elem3
)
260 append(new(alloc
) ListElement(type
));
266 TypedList::TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
, ListElement
*elem3
, ListElement
*elem4
)
268 append(new(alloc
) ListElement(type
));
277 // Verify that a TypedList is "proper", i.e. has a first element of WORDID form
279 bool TypedList::isProper() const
281 return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID
;
284 void TypedList::checkProper(CSSM_RETURN error
) const
287 CssmError::throwMe(error
);