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