2 * Copyright (c) 2000-2004,2011,2014 Apple 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 // dliterators - DL/MDS table access as C++ iterators
22 // This is currently an almost read-only implementation.
23 // (You can erase but you can't create or modify.)
25 #ifndef _H_CDSA_CLIENT_DLITERATORS
26 #define _H_CDSA_CLIENT_DLITERATORS
28 #include <security_utilities/threading.h>
29 #include <security_utilities/globalizer.h>
30 #include <security_utilities/refcount.h>
31 #include <security_cdsa_utilities/cssmalloc.h>
32 #include <security_cdsa_utilities/cssmpods.h>
33 #include <security_cdsa_utilities/cssmerrors.h>
34 #include <security_cdsa_utilities/cssmdb.h>
35 #include <security_cdsa_client/dlquery.h>
39 namespace CssmClient
{
43 // An abstract interface to a (partial) DLDb-style object.
44 // This is a particular (open) database that you can perform CSSM database
51 virtual CSSM_HANDLE
dlGetFirst(const CSSM_QUERY
&query
,
52 CSSM_DB_RECORD_ATTRIBUTE_DATA
&attributes
, CSSM_DATA
*data
,
53 CSSM_DB_UNIQUE_RECORD
*&id
) = 0;
54 virtual bool dlGetNext(CSSM_HANDLE handle
,
55 CSSM_DB_RECORD_ATTRIBUTE_DATA
&attributes
, CSSM_DATA
*data
,
56 CSSM_DB_UNIQUE_RECORD
*&id
) = 0;
57 virtual void dlAbortQuery(CSSM_HANDLE handle
) = 0;
58 virtual void dlFreeUniqueId(CSSM_DB_UNIQUE_RECORD
*id
) = 0;
59 virtual void dlDeleteRecord(CSSM_DB_UNIQUE_RECORD
*id
) = 0;
60 virtual Allocator
&allocator() = 0;
65 // Abstract Database Records.
66 // Each database record type has a subclass of this.
67 // These are RefCounted; you can hang on to them as long as you like,
68 // stick (RefPointers to) them into maps, and so on. Just go for it.
70 class Record
: public RefCount
, public CssmAutoData
{
72 Record() : CssmAutoData(Allocator::standard(Allocator::sensitive
)) { }
73 Record(const char * const * attributeNames
); // sets mAttributes
75 static const CSSM_DB_RECORDTYPE recordType
= CSSM_DL_DB_RECORD_ANY
;
77 void addAttributes(const char * const * attributeNames
); // add more
79 // raw attribute access
80 CssmDbRecordAttributeData
&attributes() { return mAttributes
; }
81 const CssmDbRecordAttributeData
&attributes() const { return mAttributes
; }
82 CSSM_DB_RECORDTYPE
actualRecordType() const { return mAttributes
.recordType(); }
84 CssmAutoData
&recordData() { return *this; } // my data nature
87 CssmAutoDbRecordAttributeData mAttributes
;
92 // TableBase is an implementation class for template Table below.
93 // Do not use it directly (you'll be sorry).
94 // Continue reading at template Table below.
100 CSSM_DB_RECORDTYPE
recordType() const { return mRecordType
; }
101 void recordType(CSSM_DB_RECORDTYPE t
) { mRecordType
= t
; } // override
103 // erase all elements matching a query
104 uint32
erase(const CSSM_QUERY
&query
);
105 uint32
erase(const Query
&query
);
108 TableBase(DLAccess
&source
, CSSM_DB_RECORDTYPE type
, bool getData
= true);
110 class AccessRef
: public RefCount
{
112 AccessRef() : mAccess(NULL
) { }
113 AccessRef(DLAccess
*ac
) : mAccess(ac
) { }
117 struct Handle
: public AccessRef
{
119 Handle(DLAccess
*ac
, CSSM_HANDLE q
) : AccessRef(ac
), query(q
) { }
123 struct Uid
: public AccessRef
{
124 CSSM_DB_UNIQUE_RECORD
*uid
;
125 Uid(DLAccess
*ac
, CSSM_DB_UNIQUE_RECORD
*id
) : AccessRef(ac
), uid(id
) { }
131 const CSSM_DB_UNIQUE_RECORD
*recordHandle() const
132 { assert(mUid
); return mUid
->uid
; }
136 Iterator(DLAccess
*ac
, CSSM_HANDLE query
, CSSM_DB_UNIQUE_RECORD
*id
,
137 Record
*record
, bool getData
);
138 void advance(Record
*newRecord
); // generic operator ++ helper
140 DLAccess
*mAccess
; // data source
141 RefPointer
<Handle
> mQuery
; // DL/MDS query handle
142 RefPointer
<Uid
> mUid
; // record unique identifier
143 RefPointer
<Record
> mRecord
; // current record value
144 bool mGetData
; // ask for data on iteration
148 CSSM_DB_RECORDTYPE mRecordType
; // CSSM/MDS record type
149 bool mGetData
; // ask for record data on primary iteration
154 // A Table represents a single relation in a database (of some kind)
156 template <class RecordType
>
157 class Table
: private TableBase
{
158 typedef RefPointer
<RecordType
> RecPtr
;
160 Table(DLAccess
&source
) : TableBase(source
, RecordType::recordType
) { }
161 Table(DLAccess
&source
, CSSM_DB_RECORDTYPE type
) : TableBase(source
, type
) { }
162 Table(DLAccess
&source
, bool getData
) : TableBase(source
, RecordType::recordType
, getData
) { }
165 class iterator
: public Iterator
,
166 public std::iterator
<forward_iterator_tag
, RefPointer
<RecordType
> > {
171 bool operator == (const iterator
&other
) const
172 { return mUid
.get() == other
.mUid
.get(); }
173 bool operator != (const iterator
&other
) const
174 { return mUid
.get() != other
.mUid
.get(); }
176 RecPtr
operator * () const { return static_cast<RecordType
*>(mRecord
.get()); }
177 RecordType
*operator -> () const { return static_cast<RecordType
*>(mRecord
.get()); }
178 iterator
operator ++ () { advance(new RecordType
); return *this; }
179 iterator
operator ++ (int) { iterator old
= *this; operator ++ (); return old
; }
184 iterator(DLAccess
*ac
, CSSM_HANDLE query
, CSSM_DB_UNIQUE_RECORD
*id
,
185 RecordType
*record
, bool getData
)
186 : Iterator(ac
, query
, id
, record
, getData
) { }
191 iterator
find(const CSSM_QUERY
&query
);
192 iterator
find(const Query
&query
);
193 iterator
end() { return iterator(); }
194 RecPtr
fetch(const Query
&query
, CSSM_RETURN err
= CSSM_OK
) // one-stop shopping
195 { return fetchFirst(find(query
), err
); }
196 RecPtr
fetch(CSSM_RETURN err
= CSSM_OK
) // fetch first of type
197 { return fetchFirst(begin(), err
); }
199 // erase all records matching a query
200 void erase(const CSSM_QUERY
&query
);
201 void erase(const Query
&query
);
203 void erase(iterator it
) { it
.erase(); }
206 iterator
startQuery(const CssmQuery
&query
, bool getData
);
207 RecPtr
fetchFirst(iterator it
, CSSM_RETURN err
);
212 // Template out-of-line functions
214 template <class RecordType
>
215 typename Table
<RecordType
>::iterator Table
<RecordType
>::begin()
217 return startQuery(CssmQuery(mRecordType
), mGetData
);
220 template <class RecordType
>
221 typename Table
<RecordType
>::iterator Table
<RecordType
>::find(const CSSM_QUERY
&query
)
223 return startQuery(CssmQuery(CssmQuery::overlay(query
), mRecordType
), mGetData
);
226 template <class RecordType
>
227 typename Table
<RecordType
>::iterator Table
<RecordType
>::find(const Query
&query
)
229 return startQuery(CssmQuery(query
.cssmQuery(), mRecordType
), mGetData
);
232 template <class RecordType
>
233 RefPointer
<RecordType
> Table
<RecordType
>::fetchFirst(iterator it
, CSSM_RETURN err
)
237 CssmError::throwMe(err
);
245 template <class RecordType
>
246 typename Table
<RecordType
>::iterator Table
<RecordType
>::startQuery(const CssmQuery
&query
, bool getData
)
248 RefPointer
<RecordType
> record
= new RecordType
;
249 CSSM_DB_UNIQUE_RECORD
*id
;
250 CssmAutoData
data(database
.allocator());
251 CSSM_HANDLE queryHandle
= database
.dlGetFirst(query
, record
->attributes(),
252 getData
? &data
.get() : NULL
, id
);
253 if (queryHandle
== CSSM_INVALID_HANDLE
)
254 return end(); // not found
256 record
->recordData() = data
;
257 return iterator(&database
, queryHandle
, id
, record
, getData
);
261 template <class RecordType
>
262 void Table
<RecordType
>::iterator::erase()
264 mAccess
->dlDeleteRecord(mUid
->uid
);
269 } // end namespace CssmClient
270 } // end namespace Security
272 #endif // _H_CDSA_CLIENT_DLITERATORS