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