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
> {
50 // list element chaining
51 CSSM_LIST_ELEMENT_TYPE
type() const { return ElementType
; }
52 ListElement
* &next() { return ListElement::overlayVar(NextElement
); }
53 ListElement
*next() const { return ListElement::overlay(NextElement
); }
56 // CssmData personality
57 ListElement(const CssmData
&data
);
58 ListElement(CssmAllocator
&alloc
, string stringData
);
60 const CssmData
&data() const;
61 ListElement
&operator = (const CssmData
&data
);
62 operator CssmData
&() { return data(); }
63 operator string () const { return data(); }
64 bool operator == (const CssmData
&other
) const { return data() == other
; }
65 bool operator != (const CssmData
&other
) const { return data() != other
; }
68 void extract(T
&destination
, CSSM_RETURN error
= CSSM_ERRCODE_INVALID_DATA
)
69 { data().extract(destination
, error
); }
71 // CssmList (sublist) personality
72 ListElement(const CssmList
&list
);
74 const CssmList
&list() const;
75 ListElement
&operator = (const CssmList
&list
);
76 operator CssmList
&() { return list(); }
77 operator const CssmList
&() const { return list(); }
78 operator TypedList
&();
79 operator const TypedList
&() const;
81 // WORDID (number) personality
82 ListElement(CSSM_WORDID_TYPE word
);
83 CSSM_WORDID_TYPE
word() const;
84 ListElement
&operator = (CSSM_WORDID_TYPE word
);
85 operator CSSM_WORDID_TYPE () const { return word(); }
86 bool operator == (CSSM_WORDID_TYPE other
) const { return word() == other
; }
87 bool operator != (CSSM_WORDID_TYPE other
) const { return word() != other
; }
90 void *operator new (size_t size
, CssmAllocator
&alloc
)
91 { return alloc
.malloc(size
); }
93 void clear(CssmAllocator
&alloc
); // free my contents
96 } // end namespace Security
98 // specialize destroy() to call clear() for cleanup
99 inline void destroy(ListElement
*elem
, CssmAllocator
&alloc
)
109 // A POD Wrapper for CSSM_LIST.
110 // CssmList does no memory allocations. Retrieval functions return pointers or
111 // references into existing content, and modifiers modify in-place without any
112 // attempt to release previous dynamic content. May the Leaking God be with You.
114 class CssmList
: public PodWrapper
<CssmList
, CSSM_LIST
> {
116 CssmList() { ListType
= CSSM_LIST_TYPE_UNKNOWN
; Head
= Tail
= NULL
; }
117 CssmList(const CssmList
&list
) { *(CssmList
*)this = list
; }
120 CSSM_LIST_TYPE
kind() const { return ListType
; } // type() reserved for TypedList
122 ListElement
&operator [] (unsigned ix
) const;
123 unsigned int length() const;
124 ListElement
* &first() { return ListElement::overlayVar(Head
); }
125 ListElement
*first() const { return ListElement::overlay(Head
); }
126 ListElement
*last() const { return ListElement::overlay(Tail
); }
127 bool empty() const { return first() == NULL
; }
129 CssmList
&append(ListElement
*elem
);
130 CssmList
&insert(ListElement
*elem
, ListElement
*before
);
131 CssmList
&remove(ListElement
*elem
);
132 CssmList
&operator += (ListElement
*elem
) { return append(elem
); }
133 CssmList
&operator -= (ListElement
*elem
) { return remove(elem
); }
135 // logically remove the first element (skip it)
139 void clear(CssmAllocator
&alloc
); // free my contents
142 } // end namespace Security
144 inline void destroy(CssmList
*list
, CssmAllocator
&alloc
)
154 // Enhanced overlay for CssmLists whose first element is known to be a wordid.
156 class TypedList
: public CssmList
{
158 TypedList(const CSSM_LIST
&list
) { *(CSSM_LIST
*)this = list
; }
159 TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
);
160 TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
);
161 TypedList(CssmAllocator
&alloc
, CSSM_WORDID_TYPE type
, ListElement
*elem1
, ListElement
*elem2
);
163 bool isProper() const; // format check (does not throw)
164 static TypedList
&overlay(CSSM_LIST
&list
)
165 { return static_cast<TypedList
&>(list
); }
166 static const TypedList
&overlay(const CSSM_LIST
&list
)
167 { return static_cast<const TypedList
&>(list
); }
169 CSSM_WORDID_TYPE
type() const
170 { assert(isProper()); return first()->word(); }
173 inline ListElement::operator TypedList
&()
174 { return TypedList::overlay(operator CssmList
&()); }
176 inline ListElement::operator const TypedList
&() const
177 { return TypedList::overlay(operator const CssmList
&()); }
181 // Data walkers to parse list elements and lists.
182 // @@@ Walking lists by recursing over next() is stack intensive. Do this in CssmList walker by loop?
184 namespace DataWalkers
187 template <class Action
>
188 ListElement
*walk(Action
&operate
, ListElement
* &elem
)
191 switch (elem
->type()) {
192 case CSSM_LIST_ELEMENT_DATUM
:
193 walk(operate
, elem
->data());
195 case CSSM_LIST_ELEMENT_SUBLIST
:
196 walk(operate
, elem
->list());
198 case CSSM_LIST_ELEMENT_WORDID
:
204 walk(operate
, elem
->next());
208 template <class Action
>
209 ListElement
*walk(Action
&operate
, CSSM_LIST_ELEMENT
* &elem
)
210 { walk(operate
, ListElement::overlay(elem
)); }
212 template <class Action
>
213 void walk(Action
&operate
, CssmList
&list
)
216 walk(operate
, list
.first());
217 if (operate
.needsRelinking
)
218 list
.Tail
= list
.first()->last(); // re-establish "tail" link
222 template <class Action
>
223 void walk(Action
&operate
, CSSM_LIST
&list
)
224 { walk(operate
, CssmList::overlay(list
)); }
226 template <class Action
>
227 void walk(Action
&operate
, const CSSM_LIST
&list
)
228 { walk(operate
, const_cast<CSSM_LIST
&>(list
)); }
230 template <class Action
>
231 void walk(Action
&operate
, const CssmList
&list
)
232 { walk(operate
, const_cast<CssmList
&>(list
)); }
235 template <class Action
>
236 CSSM_LIST
*walk(Action
&operate
, CSSM_LIST
* &list
)
239 walk(operate
, *list
);
243 } // end namespace DataWalkers
245 }; // end namespace Security