]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_cdsa_utilities/lib/cssmlist.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_utilities / lib / cssmlist.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2000-2004,2006-2007,2011 Apple Inc. All Rights Reserved.
b1ab9ed8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// cssmlist - CSSM_LIST operational utilities
27//
28#include <security_cdsa_utilities/cssmlist.h>
29#include <security_cdsa_utilities/cssmdata.h>
30
31
32//
33// Managing list elements
34//
35ListElement *ListElement::last()
36{
37 for (ListElement *p = this; ; p = p->next())
38 if (p->next() == NULL)
39 return p;
40 // not reached
41}
42
43
44ListElement::ListElement(CSSM_WORDID_TYPE word)
45{
46 ElementType = CSSM_LIST_ELEMENT_WORDID;
47 WordID = word;
48}
49
50ListElement::ListElement(const CssmData &data)
51{
52 ElementType = CSSM_LIST_ELEMENT_DATUM;
53 WordID = 0;
54 Element.Word = data;
55}
56
57ListElement::ListElement(Allocator &alloc, const CssmData &data)
58{
59 ElementType = CSSM_LIST_ELEMENT_DATUM;
60 WordID = 0;
61 Element.Word = CssmAutoData(alloc, data).release();
62}
63
64ListElement::ListElement(Allocator &alloc, const string &s)
65{
66 ElementType = CSSM_LIST_ELEMENT_DATUM;
67 WordID = 0;
68 Element.Word = CssmAutoData(alloc, s.data(), s.size()).release();
69}
70
71ListElement::ListElement(const CssmList &list)
72{
73 ElementType = CSSM_LIST_ELEMENT_SUBLIST;
74 WordID = 0;
75 Element.Sublist = list;
76}
77
78
79CssmData &ListElement::data()
80{
81 assert(type() == CSSM_LIST_ELEMENT_DATUM);
82 return CssmData::overlay(Element.Word);
83}
84
85const CssmData &ListElement::data() const
86{
87 assert(type() == CSSM_LIST_ELEMENT_DATUM);
88 return CssmData::overlay(Element.Word);
89}
90
91ListElement &ListElement::operator = (const CssmData &data)
92{
93 assert(type() == CSSM_LIST_ELEMENT_DATUM);
94 Element.Word = data;
95 return *this;
96}
97
98
99CssmList &ListElement::list()
100{
101 assert(type() == CSSM_LIST_ELEMENT_SUBLIST);
102 return CssmList::overlay(Element.Sublist);
103}
104
105const CssmList &ListElement::list() const
106{
107 assert(type() == CSSM_LIST_ELEMENT_SUBLIST);
108 return CssmList::overlay(Element.Sublist);
109}
110
111TypedList &ListElement::typedList()
112{
113 return static_cast<TypedList &>(list());
114}
115
116const TypedList &ListElement::typedList() const
117{
118 return static_cast<const TypedList &>(list());
119}
120
121ListElement &ListElement::operator = (const CssmList &list)
122{
123 assert(type() == CSSM_LIST_ELEMENT_SUBLIST);
124 Element.Sublist = list;
125 return *this;
126}
127
128
129CSSM_WORDID_TYPE ListElement::word() const
130{
131 assert(type() == CSSM_LIST_ELEMENT_WORDID);
132 return WordID;
133}
134
135ListElement &ListElement::operator = (CSSM_WORDID_TYPE word)
136{
137 assert(type() == CSSM_LIST_ELEMENT_WORDID);
138 WordID = word;
139 return *this;
140}
141
142
143//
144// List operations
145//
146ListElement &CssmList::operator [] (unsigned ix) const
147{
148 for (ListElement *elem = first(); elem; elem = elem->next(), ix--) {
149 if (ix == 0)
150 return *elem;
151 }
152 throw 999; //@@@
153}
154
d64be36e
A
155CssmList &CssmList::operator =(const CssmList& other)
156{
157 ListType = other.ListType;
158 Head = other.Head;
159 Tail = other.Tail;
160 return *this;
161}
162
b1ab9ed8
A
163unsigned int CssmList::length() const
164{
165 unsigned int len = 0;
166 for (ListElement *elem = first(); elem; elem = elem->next())
167 len++;
168 return len;
169}
170
171CssmList &CssmList::append(ListElement *elem)
172{
173 if (Tail == NULL) { // first element
174 Head = Tail = elem;
175 } else {
176 Tail->NextElement = elem;
177 Tail = elem;
178 }
179 elem->NextElement = NULL;
180 return *this;
181}
182
183CssmList &CssmList::insert(ListElement *elem, ListElement *before)
184{
185 // null before -> append
186 if (before == NULL)
187 return append(elem);
188
189 // we have a real position
190 assert(!empty());
191 if (Head == before) { // before first element
192 elem->NextElement = before;
193 Head = elem;
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;
199 return *this;
200 }
201 }
202 // end of list, before not in list
203 throw 999; //@@@
204 }
205 return *this;
206}
207
208CssmList &CssmList::remove(ListElement *elem)
209{
210 assert(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
218 Tail = p;
219 return *this;
220 }
221 // end of list, elem not found
222 throw 999; //@@@
223 }
224 return *this;
225}
226
227void CssmList::snip()
228{
229 assert(Head); // can't be empty
230 if (Head == Tail) { // single element, empty when snipped
231 Head = Tail = NULL;
232 } else { // more than one, bypass first
233 Head = first()->next();
234 }
235}
236
237
238//
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.
242//
243void ListElement::clear(Allocator &alloc)
244{
245 switch (type()) {
246 case CSSM_LIST_ELEMENT_WORDID:
247 break; // no substructure
248 case CSSM_LIST_ELEMENT_DATUM:
249 alloc.free(data().data());
250 break;
251 case CSSM_LIST_ELEMENT_SUBLIST:
252 list().clear(alloc);
253 break;
254 default:
255 assert(false);
256 }
257}
258
259void CssmList::clear(Allocator &alloc)
260{
261 ListElement *elem = first();
262 while (elem) {
263 ListElement *next = elem->next();
264 destroy(elem, alloc);
265 elem = next;
266 }
267}
268
269
270//
271// Building TypedLists
272//
273TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type)
274{
275 append(new(alloc) ListElement(type));
276}
277
278TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1)
279{
280 append(new(alloc) ListElement(type));
281 append(elem1);
282}
283
284TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2)
285{
286 append(new(alloc) ListElement(type));
287 append(elem1);
288 append(elem2);
289}
290
291TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3)
292{
293 append(new(alloc) ListElement(type));
294 append(elem1);
295 append(elem2);
296 append(elem3);
297}
298
299TypedList::TypedList(Allocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3, ListElement *elem4)
300{
301 append(new(alloc) ListElement(type));
302 append(elem1);
303 append(elem2);
304 append(elem3);
305 append(elem4);
306}
307
308
309//
310// Verify that a TypedList is "proper", i.e. has a first element of WORDID form
311//
312bool TypedList::isProper() const
313{
314 return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID;
315}
316
317void TypedList::checkProper(CSSM_RETURN error) const
318{
319 if (!isProper())
320 CssmError::throwMe(error);
321}