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 CssmList
&CssmList::operator =(const CssmList
& other
)
157 ListType
= other
.ListType
;
163 unsigned int CssmList::length() const
165 unsigned int len
= 0;
166 for (ListElement
*elem
= first(); elem
; elem
= elem
->next())
171 CssmList
&CssmList::append(ListElement
*elem
)
173 if (Tail
== NULL
) { // first element
176 Tail
->NextElement
= elem
;
179 elem
->NextElement
= NULL
;
183 CssmList
&CssmList::insert(ListElement
*elem
, ListElement
*before
)
185 // null before -> append
189 // we have a real position
191 if (Head
== before
) { // before first element
192 elem
->NextElement
= before
;
194 } else { // before is not first
195 for (CSSM_LIST_ELEMENT
*p
= Head
; p
; p
= p
->NextElement
) {
196 if (p
->NextElement
== before
) {
197 elem
->NextElement
= before
;
198 p
->NextElement
= elem
;
202 // end of list, before not in list
208 CssmList
&CssmList::remove(ListElement
*elem
)
211 if (elem
== Head
) { // remove first element
212 Head
= Head
->NextElement
;
213 } else { // subsequent element
214 for (CSSM_LIST_ELEMENT
*p
= Head
; p
; p
= p
->NextElement
)
215 if (p
->NextElement
== elem
) {
216 p
->NextElement
= elem
->NextElement
;
217 if (elem
->NextElement
== NULL
) // removing last element
221 // end of list, elem not found
227 void CssmList::snip()
229 assert(Head
); // can't be empty
230 if (Head
== Tail
) { // single element, empty when snipped
232 } else { // more than one, bypass first
233 Head
= first()->next();
239 // Deep-destruction of CssmLists and ListElements.
240 // The underlying assumption is that all components were allocated from a single
241 // Allocator in canonical chunks.
243 void ListElement::clear(Allocator
&alloc
)
246 case CSSM_LIST_ELEMENT_WORDID
:
247 break; // no substructure
248 case CSSM_LIST_ELEMENT_DATUM
:
249 alloc
.free(data().data());
251 case CSSM_LIST_ELEMENT_SUBLIST
:
259 void CssmList::clear(Allocator
&alloc
)
261 ListElement
*elem
= first();
263 ListElement
*next
= elem
->next();
264 destroy(elem
, alloc
);
271 // Building TypedLists
273 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
)
275 append(new(alloc
) ListElement(type
));
278 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
)
280 append(new(alloc
) ListElement(type
));
284 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
)
286 append(new(alloc
) ListElement(type
));
291 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
, ListElement
*elem3
)
293 append(new(alloc
) ListElement(type
));
299 TypedList::TypedList(Allocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
, ListElement
*elem3
, ListElement
*elem4
)
301 append(new(alloc
) ListElement(type
));
310 // Verify that a TypedList is "proper", i.e. has a first element of WORDID form
312 bool TypedList::isProper() const
314 return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID
;
317 void TypedList::checkProper(CSSM_RETURN error
) const
320 CssmError::throwMe(error
);