]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmlist.cpp
Security-164.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmlist.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // cssmlist - CSSM_LIST operational utilities
21 //
22 #ifdef __MWERKS__
23 #define _CPP_CSSMLIST
24 #endif
25
26 #include <Security/cssmlist.h>
27 #include <Security/cssmdata.h>
28
29
30 //
31 // Managing list elements
32 //
33 ListElement *ListElement::last()
34 {
35 for (ListElement *p = this; ; p = p->next())
36 if (p->next() == NULL)
37 return p;
38 // not reached
39 }
40
41
42 ListElement::ListElement(CSSM_WORDID_TYPE word)
43 {
44 ElementType = CSSM_LIST_ELEMENT_WORDID;
45 WordID = word;
46 }
47
48 ListElement::ListElement(const CssmData &data)
49 {
50 ElementType = CSSM_LIST_ELEMENT_DATUM;
51 WordID = 0;
52 Element.Word = data;
53 }
54
55 ListElement::ListElement(CssmAllocator &alloc, const CssmData &data)
56 {
57 ElementType = CSSM_LIST_ELEMENT_DATUM;
58 WordID = 0;
59 Element.Word = CssmAutoData(alloc, data).release();
60 }
61
62 ListElement::ListElement(CssmAllocator &alloc, const string &s)
63 {
64 ElementType = CSSM_LIST_ELEMENT_DATUM;
65 WordID = 0;
66 Element.Word = CssmAutoData(alloc, s.data(), s.size()).release();
67 }
68
69 ListElement::ListElement(const CssmList &list)
70 {
71 ElementType = CSSM_LIST_ELEMENT_SUBLIST;
72 WordID = 0;
73 Element.Sublist = list;
74 }
75
76
77 CssmData &ListElement::data()
78 {
79 assert(type() == CSSM_LIST_ELEMENT_DATUM);
80 return CssmData::overlay(Element.Word);
81 }
82
83 const CssmData &ListElement::data() const
84 {
85 assert(type() == CSSM_LIST_ELEMENT_DATUM);
86 return CssmData::overlay(Element.Word);
87 }
88
89 CssmList &ListElement::list()
90 {
91 assert(type() == CSSM_LIST_ELEMENT_SUBLIST);
92 return CssmList::overlay(Element.Sublist);
93 }
94
95 const CssmList &ListElement::list() const
96 {
97 assert(type() == CSSM_LIST_ELEMENT_SUBLIST);
98 return CssmList::overlay(Element.Sublist);
99 }
100
101 TypedList &ListElement::typedList()
102 {
103 return static_cast<TypedList &>(list());
104 }
105
106 const TypedList &ListElement::typedList() const
107 {
108 return static_cast<const TypedList &>(list());
109 }
110
111 CSSM_WORDID_TYPE ListElement::word() const
112 {
113 assert(type() == CSSM_LIST_ELEMENT_WORDID);
114 return WordID;
115 }
116
117
118 //
119 // List operations
120 //
121 ListElement &CssmList::operator [] (unsigned ix) const
122 {
123 for (ListElement *elem = first(); elem; elem = elem->next(), ix--) {
124 if (ix == 0)
125 return *elem;
126 }
127 throw 999; //@@@
128 }
129
130 unsigned int CssmList::length() const
131 {
132 unsigned int len = 0;
133 for (ListElement *elem = first(); elem; elem = elem->next())
134 len++;
135 return len;
136 }
137
138 CssmList &CssmList::append(ListElement *elem)
139 {
140 if (Tail == NULL) { // first element
141 Head = Tail = elem;
142 } else {
143 Tail->NextElement = elem;
144 Tail = elem;
145 }
146 elem->NextElement = NULL;
147 return *this;
148 }
149
150 CssmList &CssmList::insert(ListElement *elem, ListElement *before)
151 {
152 // null before -> append
153 if (before == NULL)
154 return append(elem);
155
156 // we have a real position
157 assert(!empty());
158 if (Head == before) { // before first element
159 elem->NextElement = before;
160 Head = elem;
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;
166 return *this;
167 }
168 }
169 // end of list, before not in list
170 throw 999; //@@@
171 }
172 return *this;
173 }
174
175 CssmList &CssmList::remove(ListElement *elem)
176 {
177 assert(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
185 Tail = p;
186 return *this;
187 }
188 // end of list, elem not found
189 throw 999; //@@@
190 }
191 return *this;
192 }
193
194 void CssmList::snip()
195 {
196 assert(Head); // can't be empty
197 if (Head == Tail) { // single element, empty when snipped
198 Head = Tail = NULL;
199 } else { // more than one, bypass first
200 Head = first()->next();
201 }
202 }
203
204
205 //
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.
209 //
210 void ListElement::clear(CssmAllocator &alloc)
211 {
212 switch (type()) {
213 case CSSM_LIST_ELEMENT_WORDID:
214 break; // no substructure
215 case CSSM_LIST_ELEMENT_DATUM:
216 alloc.free(data().data());
217 break;
218 case CSSM_LIST_ELEMENT_SUBLIST:
219 list().clear(alloc);
220 break;
221 default:
222 assert(false);
223 }
224 }
225
226 void CssmList::clear(CssmAllocator &alloc)
227 {
228 ListElement *elem = first();
229 while (elem) {
230 ListElement *next = elem->next();
231 destroy(elem, alloc);
232 elem = next;
233 }
234 }
235
236
237 //
238 // Building TypedLists
239 //
240 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type)
241 {
242 append(new(alloc) ListElement(type));
243 }
244
245 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1)
246 {
247 append(new(alloc) ListElement(type));
248 append(elem1);
249 }
250
251 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2)
252 {
253 append(new(alloc) ListElement(type));
254 append(elem1);
255 append(elem2);
256 }
257
258 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3)
259 {
260 append(new(alloc) ListElement(type));
261 append(elem1);
262 append(elem2);
263 append(elem3);
264 }
265
266 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3, ListElement *elem4)
267 {
268 append(new(alloc) ListElement(type));
269 append(elem1);
270 append(elem2);
271 append(elem3);
272 append(elem4);
273 }
274
275
276 //
277 // Verify that a TypedList is "proper", i.e. has a first element of WORDID form
278 //
279 bool TypedList::isProper() const
280 {
281 return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID;
282 }
283
284 void TypedList::checkProper(CSSM_RETURN error) const
285 {
286 if (!isProper())
287 CssmError::throwMe(error);
288 }