]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmlist.cpp
Security-54.1.3.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 CSSM_WORDID_TYPE ListElement::word() const
102 {
103 assert(type() == CSSM_LIST_ELEMENT_WORDID);
104 return WordID;
105 }
106
107
108 //
109 // List operations
110 //
111 ListElement &CssmList::operator [] (unsigned ix) const
112 {
113 for (ListElement *elem = first(); elem; elem = elem->next(), ix--) {
114 if (ix == 0)
115 return *elem;
116 }
117 throw 999; //@@@
118 }
119
120 unsigned int CssmList::length() const
121 {
122 unsigned int len = 0;
123 for (ListElement *elem = first(); elem; elem = elem->next())
124 len++;
125 return len;
126 }
127
128 CssmList &CssmList::append(ListElement *elem)
129 {
130 if (Tail == NULL) { // first element
131 Head = Tail = elem;
132 } else {
133 Tail->NextElement = elem;
134 Tail = elem;
135 }
136 elem->NextElement = NULL;
137 return *this;
138 }
139
140 CssmList &CssmList::insert(ListElement *elem, ListElement *before)
141 {
142 // null before -> append
143 if (before == NULL)
144 return append(elem);
145
146 // we have a real position
147 assert(!empty());
148 if (Head == before) { // before first element
149 elem->NextElement = before;
150 Head = elem;
151 } else { // before is not first
152 for (CSSM_LIST_ELEMENT *p = Head; p; p = p->NextElement) {
153 if (p->NextElement == before) {
154 elem->NextElement = before;
155 p->NextElement = elem;
156 return *this;
157 }
158 }
159 // end of list, before not in list
160 throw 999; //@@@
161 }
162 return *this;
163 }
164
165 CssmList &CssmList::remove(ListElement *elem)
166 {
167 assert(elem);
168 if (elem == Head) { // remove first element
169 Head = Head->NextElement;
170 } else { // subsequent element
171 for (CSSM_LIST_ELEMENT *p = Head; p; p = p->NextElement)
172 if (p->NextElement == elem) {
173 p->NextElement = elem->NextElement;
174 if (elem->NextElement == NULL) // removing last element
175 Tail = p;
176 return *this;
177 }
178 // end of list, elem not found
179 throw 999; //@@@
180 }
181 return *this;
182 }
183
184 void CssmList::snip()
185 {
186 assert(Head); // can't be empty
187 if (Head == Tail) { // single element, empty when snipped
188 Head = Tail = NULL;
189 } else { // more than one, bypass first
190 Head = first()->next();
191 }
192 }
193
194
195 //
196 // Deep-destruction of CssmLists and ListElements.
197 // The underlying assumption is that all components were allocated from a single
198 // CssmAllocator in canonical chunks.
199 //
200 void ListElement::clear(CssmAllocator &alloc)
201 {
202 switch (type()) {
203 case CSSM_LIST_ELEMENT_WORDID:
204 break; // no substructure
205 case CSSM_LIST_ELEMENT_DATUM:
206 alloc.free(data().data());
207 break;
208 case CSSM_LIST_ELEMENT_SUBLIST:
209 list().clear(alloc);
210 break;
211 default:
212 assert(false);
213 }
214 }
215
216 void CssmList::clear(CssmAllocator &alloc)
217 {
218 ListElement *elem = first();
219 while (elem) {
220 ListElement *next = elem->next();
221 destroy(elem, alloc);
222 elem = next;
223 }
224 }
225
226
227 //
228 // Building TypedLists
229 //
230 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type)
231 {
232 append(new(alloc) ListElement(type));
233 }
234
235 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1)
236 {
237 append(new(alloc) ListElement(type));
238 append(elem1);
239 }
240
241 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2)
242 {
243 append(new(alloc) ListElement(type));
244 append(elem1);
245 append(elem2);
246 }
247
248 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3)
249 {
250 append(new(alloc) ListElement(type));
251 append(elem1);
252 append(elem2);
253 append(elem3);
254 }
255
256 TypedList::TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1, ListElement *elem2, ListElement *elem3, ListElement *elem4)
257 {
258 append(new(alloc) ListElement(type));
259 append(elem1);
260 append(elem2);
261 append(elem3);
262 append(elem4);
263 }
264
265
266 //
267 // Verify that a TypedList is "proper", i.e. has a first element of WORDID form
268 //
269 bool TypedList::isProper() const
270 {
271 return first() && first()->type() == CSSM_LIST_ELEMENT_WORDID;
272 }