2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // cssmlist - CSSM_LIST operational utilities
25 #include <Security/utilities.h>
26 #include <Security/cssmalloc.h>
27 #include <Security/walkers.h>
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).
48 class ListElement
: public PodWrapper
<ListElement
, CSSM_LIST_ELEMENT
> {
51 CSSM_LIST_ELEMENT_TYPE
type() const { return ElementType
; }
52 bool is(CSSM_LIST_ELEMENT_TYPE t
) const { return type() == t
; }
54 // list element chaining
55 ListElement
* &next() { return ListElement::overlayVar(NextElement
); }
56 ListElement
*next() const { return ListElement::overlay(NextElement
); }
59 // CssmData personality
60 ListElement(const CssmData
&data
);
61 ListElement(CssmAllocator
&alloc
, const CssmData
&data
);
62 ListElement(CssmAllocator
&alloc
, const std::string
&stringData
);
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
; }
73 void extract(T
&destination
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
)
74 { data().extract(destination
, error
); }
76 // CssmList (sublist) personality
77 ListElement(const 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;
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
; }
95 void *operator new (size_t size
, CssmAllocator
&alloc
)
96 { return alloc
.malloc(size
); }
98 void clear(CssmAllocator
&alloc
); // free my contents
101 } // end namespace Security
103 // specialize destroy() to call clear() for cleanup
104 inline void destroy(ListElement
*elem
, CssmAllocator
&alloc
)
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.
119 class CssmList
: public PodWrapper
<CssmList
, CSSM_LIST
> {
121 CssmList() { ListType
= CSSM_LIST_TYPE_UNKNOWN
; Head
= Tail
= NULL
; }
122 CssmList(const CssmList
&list
) { *(CssmList
*)this = list
; }
125 CSSM_LIST_TYPE
kind() const { return ListType
; } // type() reserved for TypedList
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
; }
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
); }
140 // logically remove the first element (skip it)
144 void clear(CssmAllocator
&alloc
); // free my contents
147 } // end namespace Security
149 inline void destroy(CssmList
*list
, CssmAllocator
&alloc
)
159 // Enhanced overlay for CssmLists whose first element is known to be a wordid.
161 class TypedList
: public CssmList
{
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
,
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
);
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
); }
179 CSSM_WORDID_TYPE
type() const
180 { assert(isProper()); return first()->word(); }
183 inline ListElement::operator TypedList
&()
184 { return TypedList::overlay(operator CssmList
&()); }
186 inline ListElement::operator const TypedList
&() const
187 { return TypedList::overlay(operator const CssmList
&()); }
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?
194 namespace DataWalkers
197 template <class Action
>
198 ListElement
*walk(Action
&operate
, ListElement
* &elem
)
201 switch (elem
->type()) {
202 case CSSM_LIST_ELEMENT_DATUM
:
203 walk(operate
, elem
->data());
205 case CSSM_LIST_ELEMENT_SUBLIST
:
206 walk(operate
, elem
->list());
208 case CSSM_LIST_ELEMENT_WORDID
:
214 walk(operate
, elem
->next());
218 template <class Action
>
219 ListElement
*walk(Action
&operate
, CSSM_LIST_ELEMENT
* &elem
)
220 { walk(operate
, ListElement::overlay(elem
)); }
222 template <class Action
>
223 void walk(Action
&operate
, CssmList
&list
)
226 walk(operate
, list
.first());
227 if (operate
.needsRelinking
)
228 list
.Tail
= list
.first()->last(); // re-establish "tail" link
232 template <class Action
>
233 void walk(Action
&operate
, CSSM_LIST
&list
)
234 { walk(operate
, CssmList::overlay(list
)); }
236 template <class Action
>
237 void walk(Action
&operate
, const CSSM_LIST
&list
)
238 { walk(operate
, const_cast<CSSM_LIST
&>(list
)); }
240 template <class Action
>
241 void walk(Action
&operate
, const CssmList
&list
)
242 { walk(operate
, const_cast<CssmList
&>(list
)); }
245 template <class Action
>
246 CSSM_LIST
*walk(Action
&operate
, CSSM_LIST
* &list
)
249 walk(operate
, *list
);
253 } // end namespace DataWalkers
255 }; // end namespace Security