1/*
2 * Copyright (c) 2000-2006 Apple Computer, 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// cssmdb.h
26//
27// classes for the DL related data structures
28//
29
30#ifndef _H_CDSA_UTILITIES_CSSMDB
31#define _H_CDSA_UTILITIES_CSSMDB
32
33#include <security_cdsa_utilities/cssmdata.h>
34#include <security_cdsa_utilities/cssmpods.h>
35#include <security_cdsa_utilities/cssmalloc.h>
36#include <security_cdsa_utilities/walkers.h>
37#include <security_cdsa_utilities/cssmdbname.h>
38
39
40namespace Security {
41
42
43//
44// Template class to build and maintain external arrays.
45// Feel free to add and vector<> member functions and behaviours as needed.
46//
47// This class differs from vector mainly because it does not construct or
48// destruct any of the elements it contains.  Rather it zero fills the
49// storage and returns references to elements.
50// Also it does not implement insert(), erase() or assign().  It does implement
51// which is equivalent to calling *insert(end()) on a vector.
52//
53template <class _Tp>
54class ArrayBuilder {
55public:
56	typedef _Tp value_type;
57	typedef value_type* pointer;
58	typedef const value_type* const_pointer;
59	typedef value_type* iterator;
60	typedef const value_type* const_iterator;
61	typedef value_type& reference;
62	typedef const value_type& const_reference;
63	typedef uint32 size_type;
64	typedef ptrdiff_t difference_type;
65
66	typedef reverse_iterator<const_iterator> const_reverse_iterator;
67	typedef reverse_iterator<iterator> reverse_iterator;
68
69protected:
70  void insert_aux(iterator __position, const _Tp& __x);
71  void insert_aux(iterator __position);
72
73public:
74	iterator begin() { return mArray; }
75	const_iterator begin() const { return mArray; }
76	iterator end() { return &mArray[mSize]; }
77	const_iterator end() const { return &mArray[mSize]; }
78
79	reverse_iterator rbegin()
80	{ return reverse_iterator(end()); }
81	const_reverse_iterator rbegin() const
82	{ return const_reverse_iterator(end()); }
83	reverse_iterator rend()
84	{ return reverse_iterator(begin()); }
85	const_reverse_iterator rend() const
86	{ return const_reverse_iterator(begin()); }
87
88	// Must be defined in base class.
89	//size_type size() const
90	//{ return mSize; }
91	size_type max_size() const
92	{ return size_type(-1) / sizeof(_Tp); }
93	size_type capacity() const
94	{ return mCapacity; }
95	bool empty() const
96	{ return begin() == end(); }
97
98	ArrayBuilder(pointer &array, size_type &size, size_type capacity = 0, Allocator &allocator = Allocator::standard()) :
99	mArray(array), mSize(size), mCapacity(capacity), mAllocator(allocator)
100	{
101#if BUG_GCC
102		mArray = reinterpret_cast<pointer>(mAllocator.malloc(sizeof(value_type) * mCapacity));
103#else
104		mArray = reinterpret_cast<pointer>(mAllocator.malloc(sizeof(value_type) * mCapacity));
105		//mArray = mAllocator.alloc(mCapacity);
106#endif
107		memset(mArray, 0, sizeof(value_type) * mCapacity);
108		mSize = 0;
109	}
110	~ArrayBuilder() { mAllocator.free(mArray); }
111
112	reference front() { return *begin(); }
113	const_reference front() const { return *begin(); }
114	reference back() { return *(end() - 1); }
115	const_reference back() const { return *(end() - 1); }
116
117	void reserve(size_type newCapacity)
118	{
119		if (newCapacity > mCapacity)
120		{
121#if BUG_GCC
122			mArray = reinterpret_cast<pointer>(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity));
123#else
124			mArray = reinterpret_cast<pointer>(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity));
125			//mArray = mAllocator.realloc<value_type>(mArray, newCapacity));
126#endif
127			memset(&mArray[mCapacity], 0, sizeof(value_type) * (newCapacity - mCapacity));
128			mCapacity = newCapacity;
129		}
130	}
131
132	// XXX Replace by push_back and insert.
133	reference add()
134	{
135		if (mSize >= mCapacity)
136			reserve(max(mSize + 1, mCapacity ? 2 * mCapacity : 1));
137
138		return mArray[mSize++];
139	}
140
141	const_pointer get() const { return mArray; }
142	pointer release() { const_pointer array = mArray; mArray = NULL; return array; }
143	void clear() { if (mSize) { memset(mArray, 0, sizeof(value_type) * mSize); } mSize = 0; }
144
145	// Must be defined in base class.
146	//reference at(size_type ix) { return mArray[ix]; }
147	//const_reference at(size_type ix) const { return mArray[ix]; }
148	//reference operator[] (size_type ix) { assert(ix < size()); return at(ix); }
149	//const_reference operator[] (size_type ix) const { assert(ix < size()); return at(ix); }
150protected:
151	Allocator &allocator() const { return mAllocator; }
152
153private:
154
155	pointer &mArray;
156	size_type &mSize;
157	size_type mCapacity;
158	Allocator &mAllocator;
159};
160
161
162//
163// A CSSM_DL_DB_LIST wrapper.
164// Note that there is a DLDBList class elsewhere that is quite
165// unrelated to this structure.
166//
167class CssmDlDbHandle : public PodWrapper<CssmDlDbHandle, CSSM_DL_DB_HANDLE> {
168public:
169	CssmDlDbHandle() { clearPod(); }
170	CssmDlDbHandle(CSSM_DL_HANDLE dl, CSSM_DB_HANDLE db) { DLHandle = dl; DBHandle = db; }
171
172	CSSM_DL_HANDLE dl() const	{ return DLHandle; }
173	CSSM_DB_HANDLE db() const	{ return DBHandle; }
174
175	operator bool() const		{ return DLHandle && DBHandle; }
176};
177
178inline bool operator < (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2)
179{
180	return h1.DLHandle < h2.DLHandle
181		|| (h1.DLHandle == h2.DLHandle && h1.DBHandle < h2.DBHandle);
182}
183
184inline bool operator == (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2)
185{
186	return h1.DLHandle == h2.DLHandle && h1.DBHandle == h2.DBHandle;
187}
188
189inline bool operator != (const CSSM_DL_DB_HANDLE &h1, const CSSM_DL_DB_HANDLE &h2)
190{
191	return h1.DLHandle != h2.DLHandle || h1.DBHandle != h2.DBHandle;
192}
193
194
195class CssmDlDbList : public PodWrapper<CssmDlDbList, CSSM_DL_DB_LIST> {
196public:
197	uint32 count() const		{ return NumHandles; }
198	uint32 &count()				{ return NumHandles; }
199	CssmDlDbHandle *handles() const { return CssmDlDbHandle::overlay(DLDBHandle); }
200	CssmDlDbHandle * &handles()	{ return CssmDlDbHandle::overlayVar(DLDBHandle); }
201
202	CssmDlDbHandle &operator [] (uint32 ix) const
203	{ assert(ix < count()); return CssmDlDbHandle::overlay(DLDBHandle[ix]); }
204
205	void setDlDbList(uint32 n, CSSM_DL_DB_HANDLE *list)
206	{ count() = n; handles() = CssmDlDbHandle::overlay(list); }
207};
208
209
210//
211// CssmDLPolyData
212//
213class CssmDLPolyData
214{
215public:
216	CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format)
217	: mData(CssmData::overlay(data))
218#ifndef NDEBUG
219    , mFormat(format)
220#endif
221    {}
222
223	// @@@ Don't use assert, but throw an exception.
224	// @@@ Do a size check on mData as well.
225
226	// @@@ This method is dangerous since the returned string is not guaranteed to be zero terminated.
227	operator const char *() const
228	{
229		assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_STRING
230               || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE);
231		return reinterpret_cast<const char *>(mData.Data);
232	}
233	operator bool() const
234	{
235		assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
236		return *reinterpret_cast<uint32 *>(mData.Data);
237	}
238	operator uint32() const
239	{
240		assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32);
241		return *reinterpret_cast<uint32 *>(mData.Data);
242	}
243	operator const uint32 *() const
244	{
245		assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32);
246		return reinterpret_cast<const uint32 *>(mData.Data);
247	}
248	operator sint32() const
249	{
250		assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
251		return *reinterpret_cast<sint32 *>(mData.Data);
252	}
253	operator double() const
254	{
255		assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_REAL);
256		return *reinterpret_cast<double *>(mData.Data);
257	}
258	operator CSSM_DATE () const;
259	operator Guid () const;
260	operator const CssmData &() const
261	{
262		return mData;
263	}
264
265private:
266	const CssmData &mData;
267#ifndef NDEBUG
268	CSSM_DB_ATTRIBUTE_FORMAT mFormat;
269#endif
270};
271
272
273//
274// CssmDbAttributeInfo pod wrapper for CSSM_DB_ATTRIBUTE_INFO
275//
276class CssmDbAttributeInfo : public PodWrapper<CssmDbAttributeInfo, CSSM_DB_ATTRIBUTE_INFO>
277{
278public:
279	CssmDbAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &attr)
280	{ assignPod(attr); }
281
282	CssmDbAttributeInfo(const char *name,
283		CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX);
284	CssmDbAttributeInfo(const CSSM_OID &oid,
285		CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX);
286	CssmDbAttributeInfo(uint32 id,
287		CSSM_DB_ATTRIBUTE_FORMAT vFormat = CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX);
288
289	CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat() const { return AttributeNameFormat; }
290	void nameFormat(CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat) { AttributeNameFormat = nameFormat; }
291
292	CSSM_DB_ATTRIBUTE_FORMAT format() const { return AttributeFormat; }
293	void format(CSSM_DB_ATTRIBUTE_FORMAT format) { AttributeFormat = format; }
294
295	const char *stringName() const
296	{
297		assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_STRING);
298		return Label.AttributeName;
299	}
300	const CssmOid &oidName() const
301	{
302		assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_OID);
303		return CssmOid::overlay(Label.AttributeOID);
304	}
305	uint32 intName() const
306	{
307		assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER);
308		return Label.AttributeID;
309	}
310
311	operator const char *() const { return stringName(); }
312	operator const CssmOid &() const { return oidName(); }
313	operator uint32() const { return intName(); }
314
315	bool operator <(const CssmDbAttributeInfo& other) const;
316	bool operator ==(const CssmDbAttributeInfo& other) const;
317	bool operator !=(const CssmDbAttributeInfo& other) const
318	{ return !(*this == other); }
319};
320
321//
322// CssmDbRecordAttributeInfo pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_INFO
323//
324class CssmDbRecordAttributeInfo : public PodWrapper<CssmDbRecordAttributeInfo, CSSM_DB_RECORD_ATTRIBUTE_INFO>
325{
326public:
327	CssmDbRecordAttributeInfo()
328	{ DataRecordType = CSSM_DL_DB_RECORD_ANY; }
329
330	CssmDbRecordAttributeInfo(CSSM_DB_RECORDTYPE recordType, uint32 numberOfAttributes,
331							  CSSM_DB_ATTRIBUTE_INFO_PTR attributeInfo)
332	{
333		DataRecordType = recordType;
334		NumberOfAttributes = numberOfAttributes;
335		AttributeInfo = attributeInfo;
336	}
337
338	CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; }
339	void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; }
340
341	uint32 size() const { return NumberOfAttributes; }
342
343	// attribute access
344	CssmDbAttributeInfo *&attributes()
345	{ return CssmDbAttributeInfo::overlayVar(AttributeInfo); }
346	CssmDbAttributeInfo *attributes() const
347	{ return CssmDbAttributeInfo::overlay(AttributeInfo); }
348    CssmDbAttributeInfo &at(uint32 ix) const
349	{ assert(ix < size()); return attributes()[ix]; }
350
351    CssmDbAttributeInfo &operator [] (uint32 ix) const { return at(ix); }
352};
353
354//
355// CssmAutoDbRecordAttributeInfo pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_INFO
356//
357class CssmAutoDbRecordAttributeInfo: public CssmDbRecordAttributeInfo, public ArrayBuilder<CssmDbAttributeInfo>
358{
359public:
360	CssmAutoDbRecordAttributeInfo(uint32 capacity = 0, Allocator &allocator = Allocator::standard()) :
361	CssmDbRecordAttributeInfo(),
362	ArrayBuilder<CssmDbAttributeInfo>(CssmDbAttributeInfo::overlayVar(AttributeInfo),
363									  NumberOfAttributes, capacity, allocator) {}
364};
365
366
367//
368// CssmDbAttributeData pod wrapper for CSSM_DB_ATTRIBUTE_DATA
369//
370class CssmDbAttributeData : public PodWrapper<CssmDbAttributeData, CSSM_DB_ATTRIBUTE_DATA>
371{
372public:
373	CssmDbAttributeData() { NumberOfValues = 0; Value = NULL; }
374	CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_DATA &attr)
375	{ assignPod(attr); }
376	CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_INFO &info)
377	{ Info = info; NumberOfValues = 0; Value = NULL; }
378
379	CssmDbAttributeInfo &info() { return CssmDbAttributeInfo::overlay(Info); }
380	const CssmDbAttributeInfo &info() const { return CssmDbAttributeInfo::overlay(Info); }
381	void info (const CSSM_DB_ATTRIBUTE_INFO &inInfo) { Info = inInfo; }
382
383	CSSM_DB_ATTRIBUTE_FORMAT format() const { return info().format(); }
384	void format(CSSM_DB_ATTRIBUTE_FORMAT f) { info().format(f); }
385
386	uint32 size() const { return NumberOfValues; }
387	CssmData *&values() { return CssmData::overlayVar(Value); }
388	CssmData *values() const { return CssmData::overlay(Value); }
389
390	CssmData &at(unsigned int ix) const
391	{
392		if (ix >= size()) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
393		return values()[ix];
394	}
395
396	CssmData &operator [] (unsigned int ix) const { return at(ix); }
397
398	template <class T>
399    T at(unsigned int ix) const { return CssmDLPolyData(Value[ix], format()); }
400
401	// this is intentionally unspecified since it could lead to bugs; the
402	// data is not guaranteed to be NULL-terminated
403	// operator const char *() const;
404
405	operator string() const;
406	operator const Guid &() const;
407	operator bool() const;
408	operator uint32() const;
409	operator const uint32 *() const;
410	operator sint32() const;
411	operator double() const;
412	operator const CssmData &() const;
413
414	// set values without allocation (caller owns the data contents)
415	void set(CssmData &data)	{ set(1, &data); }
416	void set(uint32 count, CssmData *datas) { NumberOfValues = count; Value = datas; }
417
418	// Set the value of this Attr (assuming it was not set before).
419	void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue,
420			 Allocator &inAllocator);
421
422	// copy (just) the return-value part from another AttributeData to this one
423	void copyValues(const CssmDbAttributeData &source, Allocator &alloc);
424
425	// Set the value of this Attr (which must be unset so far)
426	void set(const CSSM_DB_ATTRIBUTE_DATA &source, Allocator &alloc)
427	{
428		info(source.Info);
429		copyValues(source, alloc);
430	}
431
432	// Add a value to this attribute.
433	void add(const CssmPolyData &inValue, Allocator &inAllocator);
434
435	void add(const char *value, Allocator &alloc)
436	{ format(CSSM_DB_ATTRIBUTE_FORMAT_STRING); add(CssmPolyData(value), alloc); }
437
438	void add(const std::string &value, Allocator &alloc)
439	{ format(CSSM_DB_ATTRIBUTE_FORMAT_STRING); add(CssmPolyData(value), alloc); }
440
441	void add(uint32 value, Allocator &alloc)
442	{ format(CSSM_DB_ATTRIBUTE_FORMAT_UINT32); add(CssmPolyData(value), alloc); }
443
444	void add(sint32 value, Allocator &alloc)
445	{ format(CSSM_DB_ATTRIBUTE_FORMAT_SINT32); add(CssmPolyData(value), alloc); }
446
447	void add(const CssmData &value, Allocator &alloc)
448	{ format(CSSM_DB_ATTRIBUTE_FORMAT_BLOB); add(CssmPolyData(value), alloc); }
449
450	void add(const CssmDbAttributeData &src, Allocator &inAllocator);
451
452	// delete specific values if they are present in this attribute data
453	bool deleteValue(const CssmData &src, Allocator &inAllocator);
454	void deleteValues(const CssmDbAttributeData &src, Allocator &inAllocator);
455
456	void deleteValues(Allocator &inAllocator);
457
458	bool operator <(const CssmDbAttributeData& other) const;
459};
460
461
462//
463// CssmDbRecordAttributeData pod wrapper for CSSM_DB_RECORD_ATTRIBUTE_DATA
464//
465class CssmDbRecordAttributeData : public PodWrapper<CssmDbRecordAttributeData, CSSM_DB_RECORD_ATTRIBUTE_DATA>
466{
467public:
468	CssmDbRecordAttributeData()
469	{ clearPod(); DataRecordType = CSSM_DL_DB_RECORD_ANY; }
470
471	CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; }
472	void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; }
473
474	uint32 semanticInformation() const { return SemanticInformation; }
475	void semanticInformation(uint32 semanticInformation) { SemanticInformation = semanticInformation; }
476
477	uint32 size() const { return NumberOfAttributes; }
478	CssmDbAttributeData *&attributes()
479	{ return CssmDbAttributeData::overlayVar(AttributeData); }
480	CssmDbAttributeData *attributes() const
481	{ return CssmDbAttributeData::overlay(AttributeData); }
482
483	// Attributes by position
484    CssmDbAttributeData &at(unsigned int ix) const
485	{ assert(ix < size()); return attributes()[ix]; }
486
487    CssmDbAttributeData &operator [] (unsigned int ix) const { return at(ix); }
488
489    void deleteValues(Allocator &allocator)
490	{ for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); }
491
492	CssmDbAttributeData *find(const CSSM_DB_ATTRIBUTE_INFO &inInfo);
493
494	bool operator <(const CssmDbRecordAttributeData& other) const;
495};
496
497
498//
499// CssmAutoDbRecordAttributeData
500//
501class CssmAutoDbRecordAttributeData : public CssmDbRecordAttributeData, public ArrayBuilder<CssmDbAttributeData>
502{
503public:
504	CssmAutoDbRecordAttributeData(uint32 capacity = 0,
505								  Allocator &valueAllocator = Allocator::standard(),
506								  Allocator &dataAllocator = Allocator::standard()) :
507	CssmDbRecordAttributeData(),
508	ArrayBuilder<CssmDbAttributeData>(CssmDbAttributeData::overlayVar(AttributeData),
509									  NumberOfAttributes, capacity, dataAllocator),
510	mValueAllocator(valueAllocator) {}
511	~CssmAutoDbRecordAttributeData();
512
513	void clear();
514    void deleteValues() { CssmDbRecordAttributeData::deleteValues(mValueAllocator); }
515	void invalidate();
516
517	CssmDbAttributeData &add() { return ArrayBuilder<CssmDbAttributeData>::add(); } // XXX using doesn't work here.
518	CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info);
519	CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value);
520
521	// So clients can pass this as the allocator argument to add()
522	operator Allocator &() const { return mValueAllocator; }
523private:
524	Allocator &mValueAllocator;
525
526	CssmDbAttributeData* findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info);
527	CssmDbAttributeData& getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info);
528};
529
530
531//
532// CssmSelectionPredicate a PodWrapper for CSSM_SELECTION_PREDICATE
533//
534class CssmSelectionPredicate : public PodWrapper<CssmSelectionPredicate, CSSM_SELECTION_PREDICATE> {
535public:
536	CssmSelectionPredicate() { clearPod(); }
537
538	CSSM_DB_OPERATOR dbOperator() const { return DbOperator; }
539	void dbOperator(CSSM_DB_OPERATOR dbOperator) { DbOperator = dbOperator; }
540
541	CssmSelectionPredicate(CSSM_DB_OPERATOR inDbOperator)
542	{ dbOperator(inDbOperator); Attribute.NumberOfValues = 0; Attribute.Value = NULL; }
543
544	CssmDbAttributeData &attribute() { return CssmDbAttributeData::overlay(Attribute); }
545	const CssmDbAttributeData &attribute() const { return CssmDbAttributeData::overlay(Attribute); }
546
547	// Set the value of this CssmSelectionPredicate (assuming it was not set before).
548	void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo,
549			 const CssmPolyData &inValue, Allocator &inAllocator)
550	{ attribute().set(inInfo, inValue, inAllocator); }
551
552	// Set the value of this CssmSelectionPredicate using another CssmSelectionPredicate's value.
553	void set(const CSSM_SELECTION_PREDICATE &other, Allocator &inAllocator)
554	{ DbOperator = other.DbOperator; attribute().set(other.Attribute, inAllocator); }
555
556	// Add a value to the list of values for this CssmSelectionPredicate.
557	void add(const CssmPolyData &inValue, Allocator &inAllocator)
558	{ attribute().add(inValue, inAllocator); }
559
560	void deleteValues(Allocator &inAllocator) { attribute().deleteValues(inAllocator); }
561};
562
563class CssmQuery : public PodWrapper<CssmQuery, CSSM_QUERY> {
564public:
565    CssmQuery(CSSM_DB_RECORDTYPE type = CSSM_DL_DB_RECORD_ANY)
566    { clearPod(); RecordType = type; }
567
568	// copy or assign flat from CSSM_QUERY
569	CssmQuery(const CSSM_QUERY &q) { assignPod(q); }
570	CssmQuery &operator = (const CSSM_QUERY &q) { assignPod(q); return *this; }
571
572	// flat copy and change record type
573	CssmQuery(const CssmQuery &q, CSSM_DB_RECORDTYPE type)
574	{ *this = q; RecordType = type; }
575
576	CSSM_DB_RECORDTYPE recordType() const { return RecordType; }
577	void recordType(CSSM_DB_RECORDTYPE recordType)  { RecordType = recordType; }
578
579	CSSM_DB_CONJUNCTIVE conjunctive() const { return Conjunctive; }
580	void conjunctive(CSSM_DB_CONJUNCTIVE conjunctive)  { Conjunctive = conjunctive; }
581
582	CSSM_QUERY_LIMITS queryLimits() const { return QueryLimits; }
583	void queryLimits(CSSM_QUERY_LIMITS queryLimits)  { QueryLimits = queryLimits; }
584
585	CSSM_QUERY_FLAGS queryFlags() const { return QueryFlags; }
586	void queryFlags(CSSM_QUERY_FLAGS queryFlags)  { QueryFlags = queryFlags; }
587
588	uint32 size() const { return NumSelectionPredicates; }
589
590	CssmSelectionPredicate *&predicates()
591	{ return CssmSelectionPredicate::overlayVar(SelectionPredicate); }
592	CssmSelectionPredicate *predicates() const
593	{ return CssmSelectionPredicate::overlay(SelectionPredicate); }
594
595	CssmSelectionPredicate &at(uint32 ix) const
596	{ assert(ix < size()); return predicates()[ix]; }
597
598	CssmSelectionPredicate &operator[] (uint32 ix) const { return at(ix); }
599
600	void set(uint32 count, CSSM_SELECTION_PREDICATE *preds)
601	{ NumSelectionPredicates = count; SelectionPredicate = preds; }
602
603    void deleteValues(Allocator &allocator)
604	{ for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); }
605};
606
607
608class CssmAutoQuery : public CssmQuery, public ArrayBuilder<CssmSelectionPredicate> {
609public:
610	CssmAutoQuery(const CSSM_QUERY &query, Allocator &allocator = Allocator::standard());
611	CssmAutoQuery(uint32 capacity = 0, Allocator &allocator = Allocator::standard()) :
612	ArrayBuilder<CssmSelectionPredicate>(CssmSelectionPredicate::overlayVar(SelectionPredicate),
613										 NumSelectionPredicates,
614										 capacity, allocator) {}
615	~CssmAutoQuery();
616	void clear();
617    void deleteValues() { CssmQuery::deleteValues(allocator()); }
618
619	CssmSelectionPredicate &add() { return ArrayBuilder<CssmSelectionPredicate>::add(); }
620	CssmSelectionPredicate &add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value);
621
622	// So clients can pass this as the allocator argument to add()
623	operator Allocator &() const { return allocator(); }
624};
625
626
627//
628// DLDbIdentifier
629//
630class DLDbIdentifier
631{
632protected:
633    class Impl : public RefCount
634    {
635        NOCOPY(Impl)
636    public:
637        Impl(const CSSM_SUBSERVICE_UID &ssuid,const char *DbName,const CSSM_NET_ADDRESS *DbLocation) :
638            mCssmSubserviceUid(ssuid),mDbName(DbName,DbLocation) {}
639
640        ~Impl() {} // Must be public since RefPointer uses it.
641
642        // Accessors
643        const CssmSubserviceUid &ssuid() const { return mCssmSubserviceUid; }
644        const char *dbName() const { return mDbName.dbName(); }
645        const CssmNetAddress *dbLocation() const { return mDbName.dbLocation(); }
646
647        // comparison (simple lexicographic)
648        bool operator < (const Impl &other) const;
649        bool operator == (const Impl &other) const;
650    private:
651        // Private member variables
652        CssmSubserviceUid mCssmSubserviceUid;
653        DbName mDbName;
654    };
655
656public:
657    // Constructors
658    DLDbIdentifier() {}
659    DLDbIdentifier(const CSSM_SUBSERVICE_UID &ssuid, const char *DbName, const CSSM_NET_ADDRESS *DbLocation)
660        : mImpl(new Impl(ssuid, DbName, DbLocation)) {}
661	DLDbIdentifier(const char *name, const Guid &guid, uint32 ssid, uint32 sstype,
662		const CSSM_NET_ADDRESS *location = NULL)
663		: mImpl(new Impl(CssmSubserviceUid(guid, NULL, ssid, sstype), name, location)) { }
664
665	// Conversion Operators
666	bool operator !() const { return !mImpl; }
667	operator bool() const { return mImpl; }
668
669    // Operators
670	bool operator <(const DLDbIdentifier &other) const
671	{ return mImpl && other.mImpl ? *mImpl < *other.mImpl : mImpl.get() < other.mImpl.get(); }
672	bool operator ==(const DLDbIdentifier &other) const
673	{ return mImpl && other.mImpl ? *mImpl == *other.mImpl : mImpl.get() == other.mImpl.get(); }
674	DLDbIdentifier &operator =(const DLDbIdentifier &other)
675	{ mImpl = other.mImpl; return *this; }
676
677    // Accessors
678    const CssmSubserviceUid &ssuid() const { return mImpl->ssuid(); }
679    const char *dbName() const { return mImpl->dbName(); }
680    const CssmNetAddress *dbLocation() const { return mImpl->dbLocation(); }
681    bool IsImplEmpty() const {return mImpl == NULL;}
682
683    RefPointer<Impl> mImpl;
684};
685
686// Wrappers for index-related CSSM objects.
687
688class CssmDbIndexInfo : public PodWrapper<CssmDbIndexInfo, CSSM_DB_INDEX_INFO>
689{
690public:
691	CssmDbIndexInfo(const CSSM_DB_INDEX_INFO &attr)
692	{ (CSSM_DB_INDEX_INFO &)*this = attr; }
693
694	CSSM_DB_INDEX_TYPE indexType() const { return IndexType; }
695	void indexType(CSSM_DB_INDEX_TYPE indexType) { IndexType = indexType; }
696
697	CSSM_DB_INDEXED_DATA_LOCATION dataLocation() const { return IndexedDataLocation; }
698	void dataLocation(CSSM_DB_INDEXED_DATA_LOCATION dataLocation)
699	{
700		IndexedDataLocation = dataLocation;
701	}
702
703	const CssmDbAttributeInfo &attributeInfo() const
704	{
705		return CssmDbAttributeInfo::overlay(Info);
706	}
707};
708
709
710namespace DataWalkers {
711
712
713//
714// DLDbIdentifiers don't walk directly because they have Impl structure and use strings.
715// Happily, they are easily transcribed into a walkable form.
716//
717struct DLDbFlatIdentifier {
718    CssmSubserviceUid *uid;		// module reference
719    char *name;					// string name
720    CssmNetAddress *address;	// optional network address
721
722    DLDbFlatIdentifier(const DLDbIdentifier &ident) :
723		uid(const_cast<CssmSubserviceUid *>(&ident.ssuid())),
724		name(const_cast<char *>(ident.dbName())),
725		address(const_cast<CssmNetAddress *>(ident.dbLocation()))
726		{ }
727
728    operator DLDbIdentifier ()	{ return DLDbIdentifier(*uid, name, address); }
729};
730
731template<class Action>
732DLDbFlatIdentifier *walk(Action &operate, DLDbFlatIdentifier * &ident)
733{
734    operate(ident);
735    if (ident->uid)
736        walk(operate, ident->uid);
737    walk(operate, ident->name);
738    if (ident->address)
739        walk(operate, ident->address);
740    return ident;
741}
742
743
744//
745// Walkers for the byzantine data structures of the DL universe.
746// Geez, what WERE they smoking when they invented this?
747//
748
749// DbAttributeInfos
750template<class Action>
751void enumerate(Action &operate, CssmDbAttributeInfo &info)
752{
753	switch (info.nameFormat()) {
754	case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
755		walk(operate, info.Label.AttributeName);
756		break;
757	case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
758		walk(operate, info.Label.AttributeOID);
759		break;
760	default:
761		break;
762	}
763}
764
765template <class Action>
766void walk(Action &operate, CssmDbAttributeInfo &info)
767{
768	operate(info);
769	enumerate(operate, info);
770}
771
772template <class Action>
773CssmDbAttributeInfo *walk(Action &operate, CssmDbAttributeInfo * &info)
774{
775	operate(info);
776	enumerate(operate, *info);
777	return info;
778}
779
780// DbRecordAttributeInfo
781template <class Action>
782void walk(Action &operate, CssmDbRecordAttributeInfo &info)
783{
784	operate(info);
785	enumerateArray(operate, info, &CssmDbRecordAttributeInfo::attributes);
786}
787
788template <class Action>
789CssmDbRecordAttributeInfo *walk(Action &operate, CssmDbRecordAttributeInfo * &info)
790{
791	operate(info);
792	enumerateArray(operate, *info, &CssmDbRecordAttributeInfo::attributes);
793	return info;
794}
795
796// DbAttributeData (Info + value vector)
797template <class Action>
798void walk(Action &operate, CssmDbAttributeData &data)
799{
800	operate(data);
801	walk(operate, data.info());
802	enumerateArray(operate, data, &CssmDbAttributeData::values);
803}
804
805template <class Action>
806CssmDbAttributeData *walk(Action &operate, CssmDbAttributeData * &data)
807{
808	operate(data);
809	walk(operate, data->info());
810	enumerateArray(operate, *data, &CssmDbAttributeData::values);
811	return data;
812}
813
814// DbRecordAttributeData (array of ...datas)
815template <class Action>
816void walk(Action &operate, CssmDbRecordAttributeData &data)
817{
818	operate(data);
819	enumerateArray(operate, data, &CssmDbRecordAttributeData::attributes);
820}
821
822template <class Action>
823CssmDbRecordAttributeData *walk(Action &operate, CssmDbRecordAttributeData * &data)
824{
825	operate(data);
826	enumerateArray(operate, *data, &CssmDbRecordAttributeData::attributes);
827	return data;
828}
829
830// SelectionPredicates
831template <class Action>
832CssmSelectionPredicate *walk(Action &operate, CssmSelectionPredicate * &predicate)
833{
834	operate(predicate);
835	walk(operate, predicate->attribute());
836	return predicate;
837}
838
839template<class Action>
840void walk(Action &operate, CssmSelectionPredicate &predicate)
841{
842	operate(predicate);
843	walk(operate, predicate.attribute());
844}
845
846// Queries
847template <class Action>
848void walk(Action &operate, CssmQuery &query)
849{
850	operate(query);
851	enumerateArray(operate, query, &CssmQuery::predicates);
852}
853
854template <class Action>
855CssmQuery *walk(Action &operate, CssmQuery * &query)
856{
857	operate(query);
858	enumerateArray(operate, *query, &CssmQuery::predicates);
859	return query;
860}
861
862template <class Action>
863CSSM_QUERY *walk(Action &operate, CSSM_QUERY * &query)
864{
865	return walk(operate, CssmQuery::overlayVar(query));
866}
867
868
869} // end namespace DataWalkers
870} // end namespace Security
871
872
873#endif // _H_CDSA_UTILITIES_CSSMDB
874