]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/cssmlist.h
Security-163.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / cssmlist.h
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 #ifndef _H_CSSMLIST
23 #define _H_CSSMLIST
24
25 #include <Security/utilities.h>
26 #include <Security/cssmalloc.h>
27 #include <Security/cssmwalkers.h>
28
29
30 namespace Security {
31
32 class CssmList;
33 class TypedList;
34
35
36 //
37 // A POD Wrapper for CSSM_LIST_ELEMENTs.
38 // List elements are pseudo-polymorphic, so we provide ways to get and
39 // set their three personalities. It's up to the caller to get this right;
40 // you mustn't (for example) call the data() method on a list element that
41 // is not of (element) type CSSM_LIST_ELEMENT_DATUM. To violate this rule
42 // will get you an assertion (not exception).
43 //
44 class ListElement : public PodWrapper<ListElement, CSSM_LIST_ELEMENT> {
45 public:
46 // type control
47 CSSM_LIST_ELEMENT_TYPE type() const { return ElementType; }
48 bool is(CSSM_LIST_ELEMENT_TYPE t) const { return type() == t; }
49
50 // list element chaining
51 ListElement * &next() { return ListElement::overlayVar(NextElement); }
52 ListElement *next() const { return ListElement::overlay(NextElement); }
53 ListElement *last();
54
55 // CssmData personality
56 explicit ListElement(const CssmData &data);
57 explicit ListElement(CssmAllocator &alloc, const CssmData &data);
58 explicit ListElement(CssmAllocator &alloc, const std::string &stringData);
59 CssmData &data();
60 string toString() const { return data().toString(); }
61 const CssmData &data() const;
62 ListElement &operator = (const CssmData &data);
63 operator CssmData &() { return data(); }
64 operator std::string () const { return toString(); }
65 bool operator == (const CssmData &other) const { return data() == other; }
66 bool operator != (const CssmData &other) const { return data() != other; }
67
68 template <class T>
69 void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA)
70 { data().extract(destination, error); }
71
72 // CssmList (sublist) personality
73 explicit ListElement(const CssmList &list);
74 CssmList &list();
75 const CssmList &list() const;
76 TypedList &typedList();
77 const TypedList &typedList() const;
78 ListElement &operator = (const CssmList &list);
79 operator CssmList &() { return list(); }
80 operator TypedList &();
81
82 // WORDID (number) personality
83 explicit ListElement(CSSM_WORDID_TYPE word);
84 CSSM_WORDID_TYPE word() const;
85 ListElement &operator = (CSSM_WORDID_TYPE word);
86 operator CSSM_WORDID_TYPE () const { return word(); }
87
88 public:
89 void *operator new (size_t size, CssmAllocator &alloc)
90 { return alloc.malloc(size); }
91
92 void clear(CssmAllocator &alloc); // free my contents
93 };
94
95 } // end namespace Security
96
97 // specialize destroy() to call clear() for cleanup
98 inline void destroy(ListElement *elem, CssmAllocator &alloc)
99 {
100 elem->clear(alloc);
101 alloc.free(elem);
102 }
103
104 namespace Security {
105
106
107 //
108 // A POD Wrapper for CSSM_LIST.
109 // CssmList does no memory allocations. Retrieval functions return pointers or
110 // references into existing content, and modifiers modify in-place without any
111 // attempt to release previous dynamic content. May the Leaking God be with You.
112 //
113 class CssmList : public PodWrapper<CssmList, CSSM_LIST> {
114 public:
115 CssmList() { ListType = CSSM_LIST_TYPE_UNKNOWN; Head = Tail = NULL; }
116 CssmList(const CssmList &list) { *(CssmList *)this = list; }
117
118 public:
119 CSSM_LIST_TYPE kind() const { return ListType; } // type() reserved for TypedList
120
121 ListElement &operator [] (unsigned ix) const;
122 unsigned int length() const;
123 ListElement * &first() { return ListElement::overlayVar(Head); }
124 ListElement *first() const { return ListElement::overlay(Head); }
125 ListElement *last() const { return ListElement::overlay(Tail); }
126 bool empty() const { return first() == NULL; }
127
128 CssmList &append(ListElement *elem);
129 CssmList &insert(ListElement *elem, ListElement *before);
130 CssmList &remove(ListElement *elem);
131 CssmList &operator += (ListElement *elem) { return append(elem); }
132 CssmList &operator -= (ListElement *elem) { return remove(elem); }
133
134 // logically remove the first element (skip it)
135 void snip();
136
137 public:
138 void clear(CssmAllocator &alloc); // free my contents
139 };
140
141 } // end namespace Security
142
143 inline void destroy(CssmList *list, CssmAllocator &alloc)
144 {
145 list->clear(alloc);
146 alloc.free(list);
147 }
148
149 namespace Security
150 {
151
152 //
153 // Enhanced overlay for CssmLists whose first element is known to be a wordid.
154 //
155 class TypedList : public CssmList {
156 public:
157 explicit TypedList(const CSSM_LIST &list) { *(CSSM_LIST *)this = list; }
158 TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type);
159 TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1);
160 TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1,
161 ListElement *elem2);
162 TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1,
163 ListElement *elem2, ListElement *elem3);
164 TypedList(CssmAllocator &alloc, CSSM_WORDID_TYPE type, ListElement *elem1,
165 ListElement *elem2, ListElement *elem3, ListElement *elem4);
166
167 bool isProper() const; // format check (does not throw)
168 void checkProper(CSSM_RETURN error = CSSM_ERRCODE_INVALID_SAMPLE_VALUE) const;
169 static TypedList &overlay(CSSM_LIST &list)
170 { return static_cast<TypedList &>(list); }
171 static const TypedList &overlay(const CSSM_LIST &list)
172 { return static_cast<const TypedList &>(list); }
173
174 CSSM_WORDID_TYPE type() const
175 { assert(isProper()); return first()->word(); }
176 };
177
178 inline ListElement::operator TypedList &()
179 { return TypedList::overlay(operator CssmList &()); }
180
181
182 //
183 // Data walkers to parse list elements and lists.
184 // @@@ Walking lists by recursing over next() is stack intensive. Do this in CssmList walker by loop?
185 //
186 namespace DataWalkers {
187
188 // ListElement
189 template <class Action>
190 ListElement *walk(Action &operate, ListElement * &elem)
191 {
192 operate(elem);
193 switch (elem->type()) {
194 case CSSM_LIST_ELEMENT_DATUM:
195 walk(operate, elem->data());
196 break;
197 case CSSM_LIST_ELEMENT_SUBLIST:
198 walk(operate, elem->list());
199 break;
200 case CSSM_LIST_ELEMENT_WORDID:
201 break;
202 default:
203 secdebug("walkers", "invalid list element type (%lx)", elem->type());
204 break;
205 }
206 if (elem->next())
207 walk(operate, elem->next());
208 return elem;
209 }
210
211 template <class Action>
212 ListElement *walk(Action &operate, CSSM_LIST_ELEMENT * &elem)
213 { walk(operate, ListElement::overlayVar(elem)); }
214
215 // CssmList
216 template <class Action>
217 void enumerate(Action &operate, CssmList &list)
218 {
219 if (!list.empty()) {
220 walk(operate, list.first());
221 if (operate.needsRelinking)
222 list.Tail = list.first()->last(); // re-establish "tail" link
223 }
224 }
225
226 template <class Action>
227 CssmList *walk(Action &operate, CssmList * &list)
228 {
229 operate(list);
230 enumerate(operate, *list);
231 return list;
232 }
233
234 template <class Action>
235 void walk(Action &operate, CssmList &list)
236 {
237 operate(list);
238 enumerate(operate, list);
239 }
240
241 template <class Action>
242 void walk(Action &operate, const CssmList &list)
243 { walk(operate, const_cast<CssmList &>(list)); }
244
245 template <class Action>
246 void walk(Action &operate, CSSM_LIST &list)
247 { walk(operate, CssmList::overlay(list)); }
248
249 template <class Action>
250 void walk(Action &operate, const CSSM_LIST &list)
251 { walk(operate, const_cast<CSSM_LIST &>(list)); }
252
253 template <class Action>
254 CSSM_LIST *walk(Action &operate, CSSM_LIST * &list)
255 { return walk(operate, CssmList::overlayVar(list)); }
256
257 template <class Action>
258 TypedList *walk(Action &operate, TypedList * &list)
259 { return static_cast<TypedList *>(walk(operate, reinterpret_cast<CssmList * &>(list))); }
260
261 template <class Action>
262 void walk(Action &operate, TypedList &list)
263 { walk(operate, static_cast<CssmList &>(list)); }
264
265
266 } // end namespace DataWalkers
267 } // end namespace Security
268
269
270 #endif //_H_CSSMLIST