2 * Copyright (c) 2000-2004,2006-2007,2011 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // cssmlist - CSSM_LIST operational utilities
28 #include <security_cdsa_utilities/cssmlist.h>
29 #include <security_cdsa_utilities/cssmdata.h>
33 // Managing list elements
35 ListElement
*ListElement::last()
37 for (ListElement
*p
= this; ; p
= p
->next())
38 if (p
->next() == NULL
)
44 ListElement::ListElement(CSSM_WORDID_TYPE word
)
46 ElementType
= CSSM_LIST_ELEMENT_WORDID
;
50 ListElement::ListElement(const CssmData
&data
)
52 ElementType
= CSSM_LIST_ELEMENT_DATUM
;
57 ListElement::ListElement(Allocator
&alloc
, const CssmData
&data
)
59 ElementType
= CSSM_LIST_ELEMENT_DATUM
;
61 Element
.Word
= CssmAutoData(alloc
, data
).release();
64 ListElement::ListElement(Allocator
&alloc
, const string
&s
)
66 ElementType
= CSSM_LIST_ELEMENT_DATUM
;
68 Element
.Word
= CssmAutoData(alloc
, s
.data(), s
.size()).release();
71 ListElement::ListElement(const CssmList
&list
)
73 ElementType
= CSSM_LIST_ELEMENT_SUBLIST
;
75 Element
.Sublist
= list
;
79 CssmData
&ListElement::data()
81 assert(type() == CSSM_LIST_ELEMENT_DATUM
);
82 return CssmData::overlay(Element
.Word
);
85 const CssmData
&ListElement::data() const
87 assert(type() == CSSM_LIST_ELEMENT_DATUM
);
88 return CssmData::overlay(Element
.Word
);
91 ListElement
&ListElement::operator = (const CssmData
&data
)
93 assert(type() == CSSM_LIST_ELEMENT_DATUM
);
99 CssmList
&ListElement::list()
101 assert(type() == CSSM_LIST_ELEMENT_SUBLIST
);
102 return CssmList::overlay(Element
.Sublist
);
105 const CssmList
&ListElement::list() const
107 assert(type() == CSSM_LIST_ELEMENT_SUBLIST
);
108 return CssmList::overlay(Element
.Sublist
);
111 TypedList
&ListElement::typedList()
113 return static_cast<TypedList
&>(list());
116 const TypedList
&ListElement::typedList() const
118 return static_cast<const TypedList
&>(list());
121 ListElement
&ListElement::operator = (const CssmList
&list
)
123 assert(type() == CSSM_LIST_ELEMENT_SUBLIST
);
124 Element
.Sublist
= list
;
129 CSSM_WORDID_TYPE
ListElement::word() const
131 assert(type() == CSSM_LIST_ELEMENT_WORDID
);
135 ListElement
&ListElement::operator = (CSSM_WORDID_TYPE word
)
137 assert(type() == CSSM_LIST_ELEMENT_WORDID
);
146 ListElement
&CssmList::operator [] (unsigned ix
) const
148 for (ListElement
*elem
= first(); elem
; elem
= elem
->next(), ix
--) {
155 unsigned int CssmList::length() const
157 unsigned int len
= 0;
158 for (ListElement
*elem
= first(); elem
; elem
= elem
->next())
163 CssmList
&CssmList::append(ListElement
*elem
)
165 if (Tail
== NULL
) { // first element
168 Tail
->NextElement
= elem
;
171 elem
->NextElement
= NULL
;
175 CssmList
&CssmList::insert(ListElement
*elem
, ListElement
*before
)
177 // null before -> append
181 // we have a real position
183 if (Head
== before
) { // before first element
184 elem
->NextElement
= before
;
186 } else { // before is not first
187 for (CSSM_LIST_ELEMENT
*p
= Head
; p
; p
= p
->NextElement
) {
188 if (p
->NextElement
== before
) {
189 elem
->NextElement
= before
;
190 p
->NextElement
= elem
;
194 // end of list, before not in list
200 CssmList
&CssmList::remove(ListElement
*elem
)
203 if (elem
== Head
) { // remove first element
204 Head
= Head
->NextElement
;
205 } else { // subsequent element
206 for (CSSM_LIST_ELEMENT
*p
= Head
; p
; p
= p
->NextElement
)
207 if (p
->NextElement
== elem
) {
208 p
->NextElement
= elem
->NextElement
;
209 if (elem
->NextElement
== NULL
) // removing last element
213 // end of list, elem not found
219 void CssmList::snip()
221 assert(Head
); // can't be empty
222 if (Head
== Tail
) { // single element, empty when snipped
224 } else { // more than one, bypass first
225 Head
= first()->next();
231 // Deep-destruction of CssmLists and ListElements.
232 // The underlying assumption is that all components were allocated from a single
233 // Allocator in canonical chunks.
235 void ListElement::clear(Allocator
&alloc
)
238 case CSSM_LIST_ELEMENT_WORDID
:
239 break; // no substructure
240 case CSSM_LIST_ELEMENT_DATUM
:
241 alloc
.free(data().data());
243 case CSSM_LIST_ELEMENT_SUBLIST
:
251 void CssmList::clear(Allocator
&alloc
)
253 ListElement
*elem
= first();
255 ListElement
*next
= elem
->next();
256 destroy(elem
, alloc
);
263 // Building TypedLists
265 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
)
267 append(new(alloc
) ListElement(type
));
270 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
)
272 append(new(alloc
) ListElement(type
));
276 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
)
278 append(new(alloc
) ListElement(type
));
283 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
, ListElement
*elem3
)
285 append(new(alloc
) ListElement(type
));
291 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
, ListElement
*elem3
, ListElement
*elem4
)
293 append(new(alloc
) ListElement(type
));
302 // Verify that a TypedList is "proper", i.e. has a first element of WORDID form
304 bool TypedList::isProper() const
306 return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID
;
309 void TypedList::checkProper(CSSM_RETURN error
) const
312 CssmError::throwMe(error
);