#ifndef _H_CDSA_UTILITIES_CSSMDB
#define _H_CDSA_UTILITIES_CSSMDB
#include <Security/cssmdata.h>
#include <Security/cssmalloc.h>
#include <Security/walkers.h>
#include <Security/DbName.h>
#ifdef _CPP_UTILITIES
#pragma export on
#endif
namespace Security
{
#if 0
CSSM_RETURN AddFooToIntelList( void** theIntelListToAddItTo, unsigned long* theNumberOfThingsAlreadyInTheList, const void* theThingToAdd, size_t theSizeOfTheThingToAdd);
#endif
template <class _Tp>
class ArrayBuilder {
public:
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef uint32 size_type;
typedef ptrdiff_t difference_type;
typedef reverse_iterator<const_iterator> const_reverse_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
protected:
void insert_aux(iterator __position, const _Tp& __x);
void insert_aux(iterator __position);
public:
iterator begin() { return mArray; }
const_iterator begin() const { return mArray; }
iterator end() { return &mArray[mSize]; }
const_iterator end() const { return &mArray[mSize]; }
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator(end()); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rend() const
{ return const_reverse_iterator(begin()); }
size_type max_size() const
{ return size_type(-1) / sizeof(_Tp); }
size_type capacity() const
{ return mCapacity; }
bool empty() const
{ return begin() == end(); }
ArrayBuilder(pointer &array, size_type &size, size_type capacity = 0, CssmAllocator &allocator = CssmAllocator::standard()) :
mArray(array), mSize(size), mCapacity(capacity), mAllocator(allocator)
{
#if BUG_GCC
mArray = reinterpret_cast<pointer>(mAllocator.malloc(sizeof(value_type) * mCapacity));
#else
mArray = reinterpret_cast<pointer>(mAllocator.malloc(sizeof(value_type) * mCapacity));
#endif
memset(mArray, 0, sizeof(value_type) * mCapacity);
mSize = 0;
}
~ArrayBuilder() { mAllocator.free(mArray); }
reference front() { return *begin(); }
const_reference front() const { return *begin(); }
reference back() { return *(end() - 1); }
const_reference back() const { return *(end() - 1); }
void reserve(size_type newCapacity)
{
if (newCapacity > mCapacity)
{
#if BUG_GCC
mArray = reinterpret_cast<pointer>(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity));
#else
mArray = reinterpret_cast<pointer>(mAllocator.realloc(mArray, sizeof(value_type) * newCapacity));
#endif
memset(&mArray[mCapacity], 0, sizeof(value_type) * (newCapacity - mCapacity));
mCapacity = newCapacity;
}
}
reference add()
{
if (mSize >= mCapacity)
reserve(max(mSize + 1, mCapacity ? 2 * mCapacity : 1));
return mArray[mSize++];
}
const_pointer get() const { return mArray; }
pointer release() { const_pointer array = mArray; mArray = NULL; return array; }
void clear() { if (mSize) { memset(mArray, 0, sizeof(value_type) * mSize); } mSize = 0; }
protected:
CssmAllocator &allocator() const { return mAllocator; }
private:
pointer &mArray;
size_type &mSize;
size_type mCapacity;
CssmAllocator &mAllocator;
};
class CssmDbAttributeInfo : public PodWrapper<CssmDbAttributeInfo, CSSM_DB_ATTRIBUTE_INFO>
{
public:
CssmDbAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &attr)
{ (CSSM_DB_ATTRIBUTE_INFO &)*this = attr; }
CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat() const { return AttributeNameFormat; }
void nameFormat(CSSM_DB_ATTRIBUTE_NAME_FORMAT nameFormat) { AttributeNameFormat = nameFormat; }
CSSM_DB_ATTRIBUTE_FORMAT format() const { return AttributeFormat; }
void format(CSSM_DB_ATTRIBUTE_FORMAT format) { AttributeFormat = format; }
operator const char *() const
{
assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_STRING);
return Label.AttributeName;
}
operator const CssmOid &() const
{
assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_OID);
return CssmOid::overlay(Label.AttributeOID);
}
operator uint32() const
{
assert(nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER);
return Label.AttributeID;
}
bool operator <(const CssmDbAttributeInfo& other) const;
bool operator ==(const CssmDbAttributeInfo& other) const;
bool operator !=(const CssmDbAttributeInfo& other) const
{ return !(*this == other); }
};
class CssmDbRecordAttributeInfo : public PodWrapper<CssmDbRecordAttributeInfo, CSSM_DB_RECORD_ATTRIBUTE_INFO>
{
public:
CssmDbRecordAttributeInfo()
{ DataRecordType = CSSM_DL_DB_RECORD_ANY; }
CssmDbRecordAttributeInfo(CSSM_DB_RECORDTYPE recordType, uint32 numberOfAttributes,
CSSM_DB_ATTRIBUTE_INFO_PTR attributeInfo)
{
DataRecordType = recordType;
NumberOfAttributes = numberOfAttributes;
AttributeInfo = attributeInfo;
}
CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; }
void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; }
uint32 size() const { return NumberOfAttributes; }
CssmDbAttributeInfo &at(uint32 ix)
{ return CssmDbAttributeInfo::overlay(AttributeInfo[ix]); }
const CssmDbAttributeInfo &at(uint32 ix) const
{ return CssmDbAttributeInfo::overlay(AttributeInfo[ix]); }
CssmDbAttributeInfo &operator [](uint32 ix)
{ assert(ix < size()); return at(ix); }
const CssmDbAttributeInfo &operator [](uint32 ix) const
{ assert(ix < size()); return at(ix); }
};
class CssmAutoDbRecordAttributeInfo: public CssmDbRecordAttributeInfo, public ArrayBuilder<CssmDbAttributeInfo>
{
public:
CssmAutoDbRecordAttributeInfo(uint32 capacity = 0, CssmAllocator &allocator = CssmAllocator::standard()) :
CssmDbRecordAttributeInfo(),
ArrayBuilder<CssmDbAttributeInfo>(static_cast<CssmDbAttributeInfo *>(AttributeInfo),
NumberOfAttributes, capacity, allocator) {}
};
class CssmDbAttributeData : public PodWrapper<CssmDbAttributeData, CSSM_DB_ATTRIBUTE_DATA>
{
public:
CssmDbAttributeData() { NumberOfValues = 0; Value = NULL; }
CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_DATA &attr)
{ (CSSM_DB_ATTRIBUTE_DATA &)*this = attr; }
CssmDbAttributeData(const CSSM_DB_ATTRIBUTE_INFO &info)
{ Info = info; NumberOfValues = 0; Value = NULL; }
CSSM_DB_ATTRIBUTE_FORMAT format() const { return info().format(); }
CssmDbAttributeInfo &info() { return CssmDbAttributeInfo::overlay(Info); }
const CssmDbAttributeInfo &info() const { return CssmDbAttributeInfo::overlay(Info); }
void info (const CSSM_DB_ATTRIBUTE_INFO &inInfo) { Info = inInfo; }
uint32 size() const { return NumberOfValues; }
template <class T>
T at(unsigned int ix) const { return CssmDLPolyData(Value[ix], format()); }
template <class T>
T operator [](unsigned int ix) const
{ if (ix >= size()) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE); return at(ix); }
operator string() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_STRING);
return string(reinterpret_cast<const char *>(Value[0].Data), Value[0].Length);
}
operator bool() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32 || format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
return *reinterpret_cast<uint32 *>(Value[0].Data);
}
operator uint32() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_UINT32);
return *reinterpret_cast<uint32 *>(Value[0].Data);
}
operator const uint32 *() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32);
return reinterpret_cast<const uint32 *>(Value[0].Data);
}
operator sint32() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
return *reinterpret_cast<sint32 *>(Value[0].Data);
}
operator double() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_REAL);
return *reinterpret_cast<double *>(Value[0].Data);
}
operator CssmData &() const
{
if (size() < 1) CssmError::throwMe(CSSMERR_DL_MISSING_VALUE);
assert(format() == CSSM_DB_ATTRIBUTE_FORMAT_STRING
|| format() == CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM
|| format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
|| format() == CSSM_DB_ATTRIBUTE_FORMAT_BLOB
|| format() == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32);
return CssmData::overlay(Value[0]);
}
void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo, const CssmPolyData &inValue,
CssmAllocator &inAllocator)
{
info(inInfo);
NumberOfValues = 0;
Value = inAllocator.alloc<CSSM_DATA>();
Value[0].Length = 0;
Value[0].Data = inAllocator.alloc<uint8>(inValue.Length);
Value[0].Length = inValue.Length;
memcpy(Value[0].Data, inValue.Data, inValue.Length);
NumberOfValues = 1;
}
void set(const CSSM_DB_ATTRIBUTE_DATA &other, CssmAllocator &inAllocator)
{
info(other.Info);
Value = inAllocator.alloc<CSSM_DATA>(other.NumberOfValues);
NumberOfValues = other.NumberOfValues;
for (NumberOfValues = 0; NumberOfValues < other.NumberOfValues; NumberOfValues++)
{
Value[NumberOfValues].Length = 0;
Value[NumberOfValues].Data = inAllocator.alloc<uint8>(other.Value[NumberOfValues].Length);
Value[NumberOfValues].Length = other.Value[NumberOfValues].Length;
memcpy(Value[NumberOfValues].Data, other.Value[NumberOfValues].Data,
other.Value[NumberOfValues].Length);
}
}
void add(const CssmPolyData &inValue, CssmAllocator &inAllocator)
{
Value = reinterpret_cast<CSSM_DATA *>(inAllocator.realloc(Value, sizeof(*Value) * (NumberOfValues + 1)));
Value[NumberOfValues].Length = 0;
Value[NumberOfValues].Data = inAllocator.alloc<uint8>(inValue.Length);
Value[NumberOfValues].Length = inValue.Length;
memcpy(Value[NumberOfValues++].Data, inValue.Data, inValue.Length);
}
void add(const CssmDbAttributeData &src, CssmAllocator &inAllocator);
bool deleteValue(const CssmData &src, CssmAllocator &inAllocator);
void deleteValues(const CssmDbAttributeData &src, CssmAllocator &inAllocator);
void deleteValues(CssmAllocator &inAllocator);
bool operator <(const CssmDbAttributeData& other) const;
};
class CssmDbRecordAttributeData : public PodWrapper<CssmDbRecordAttributeData, CSSM_DB_RECORD_ATTRIBUTE_DATA>
{
public:
CssmDbRecordAttributeData()
{ DataRecordType = CSSM_DL_DB_RECORD_ANY; SemanticInformation = 0; }
CSSM_DB_RECORDTYPE recordType() const { return DataRecordType; }
void recordType(CSSM_DB_RECORDTYPE recordType) { DataRecordType = recordType; }
uint32 semanticInformation() const { return SemanticInformation; }
void semanticInformation(uint32 semanticInformation) { SemanticInformation = semanticInformation; }
uint32 size() const { return NumberOfAttributes; }
CssmDbAttributeData &at(unsigned int ix)
{ return CssmDbAttributeData::overlay(AttributeData[ix]); }
const CssmDbAttributeData &at(unsigned int ix) const
{ return CssmDbAttributeData::overlay(AttributeData[ix]); }
CssmDbAttributeData &operator [](unsigned int ix)
{ assert(ix < size()); return at(ix); }
const CssmDbAttributeData &operator [](unsigned int ix) const
{ assert(ix < size()); return at(ix); }
void deleteValues(CssmAllocator &allocator)
{ for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); }
CssmDbAttributeData *find(const CSSM_DB_ATTRIBUTE_INFO &inInfo);
bool operator <(const CssmDbRecordAttributeData& other) const;
};
class CssmAutoDbRecordAttributeData : public CssmDbRecordAttributeData, public ArrayBuilder<CssmDbAttributeData>
{
public:
CssmAutoDbRecordAttributeData(uint32 capacity = 0,
CssmAllocator &valueAllocator = CssmAllocator::standard(),
CssmAllocator &dataAllocator = CssmAllocator::standard()) :
CssmDbRecordAttributeData(),
ArrayBuilder<CssmDbAttributeData>(static_cast<CssmDbAttributeData *>(AttributeData),
NumberOfAttributes, capacity, dataAllocator),
mValueAllocator(valueAllocator) {}
~CssmAutoDbRecordAttributeData();
void clear();
void deleteValues() { CssmDbRecordAttributeData::deleteValues(mValueAllocator); }
CssmDbAttributeData &add() { return ArrayBuilder<CssmDbAttributeData>::add(); } CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info);
CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value);
operator CssmAllocator &() const { return mValueAllocator; }
private:
CssmAllocator &mValueAllocator;
};
class CssmSelectionPredicate : public PodWrapper<CssmSelectionPredicate, CSSM_SELECTION_PREDICATE> {
public:
CssmSelectionPredicate() { memset(this, 0, sizeof(*this)) ; }
CssmSelectionPredicate(CSSM_DB_OPERATOR inDbOperator)
{ dbOperator(inDbOperator); Attribute.NumberOfValues = 0; Attribute.Value = NULL; }
CSSM_DB_OPERATOR dbOperator() const { return DbOperator; }
void dbOperator(CSSM_DB_OPERATOR dbOperator) { DbOperator = dbOperator; }
CssmDbAttributeData &attribute() { return CssmDbAttributeData::overlay(Attribute); }
const CssmDbAttributeData &attribute() const { return CssmDbAttributeData::overlay(Attribute); }
void set(const CSSM_DB_ATTRIBUTE_INFO &inInfo,
const CssmPolyData &inValue, CssmAllocator &inAllocator)
{ attribute().set(inInfo, inValue, inAllocator); }
void set(const CSSM_SELECTION_PREDICATE &other, CssmAllocator &inAllocator)
{ DbOperator = other.DbOperator; attribute().set(other.Attribute, inAllocator); }
void add(const CssmPolyData &inValue, CssmAllocator &inAllocator)
{ attribute().add(inValue, inAllocator); }
void deleteValues(CssmAllocator &inAllocator) { attribute().deleteValues(inAllocator); }
};
class CssmQuery : public PodWrapper<CssmQuery, CSSM_QUERY> {
public:
CssmQuery()
{ memset(this, 0, sizeof(*this)) ; RecordType = CSSM_DL_DB_RECORD_ANY; }
CSSM_DB_RECORDTYPE recordType() const { return RecordType; }
void recordType(CSSM_DB_RECORDTYPE recordType) { RecordType = recordType; }
CSSM_DB_CONJUNCTIVE conjunctive() const { return Conjunctive; }
void conjunctive(CSSM_DB_CONJUNCTIVE conjunctive) { Conjunctive = conjunctive; }
CSSM_QUERY_LIMITS queryLimits() const { return QueryLimits; }
void queryLimits(CSSM_QUERY_LIMITS queryLimits) { QueryLimits = queryLimits; }
CSSM_QUERY_FLAGS queryFlags() const { return QueryFlags; }
void queryFlags(CSSM_QUERY_FLAGS queryFlags) { QueryFlags = queryFlags; }
uint32 size() const { return NumSelectionPredicates; }
CssmSelectionPredicate &at(uint32 ix)
{ return CssmSelectionPredicate::overlay(SelectionPredicate[ix]); }
const CssmSelectionPredicate &at(uint32 ix) const
{ return CssmSelectionPredicate::overlay(SelectionPredicate[ix]); }
CssmSelectionPredicate &operator[] (uint32 ix) { assert(ix < size()); return at(ix); }
const CssmSelectionPredicate &operator[] (uint32 ix) const { assert(ix < size()); return at(ix); }
void deleteValues(CssmAllocator &allocator)
{ for (uint32 ix = 0; ix < size(); ++ix) at(ix).deleteValues(allocator); }
};
class CssmAutoQuery : public CssmQuery, public ArrayBuilder<CssmSelectionPredicate> {
public:
CssmAutoQuery(const CSSM_QUERY &query, CssmAllocator &allocator = CssmAllocator::standard());
CssmAutoQuery(uint32 capacity = 0, CssmAllocator &allocator = CssmAllocator::standard()) :
ArrayBuilder<CssmSelectionPredicate>(static_cast<CssmSelectionPredicate *>(SelectionPredicate),
NumSelectionPredicates,
capacity, allocator) {}
~CssmAutoQuery();
void clear();
void deleteValues() { CssmQuery::deleteValues(allocator()); }
CssmSelectionPredicate &add() { return ArrayBuilder<CssmSelectionPredicate>::add(); }
CssmSelectionPredicate &add(CSSM_DB_OPERATOR dbOperator, const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value);
operator CssmAllocator &() const { return allocator(); }
};
class DLDbIdentifier
{
protected:
class Impl : public RefCount
{
NOCOPY(Impl)
public:
Impl(const CSSM_SUBSERVICE_UID &ssuid,const char *DbName,const CSSM_NET_ADDRESS *DbLocation) :
mCssmSubserviceUid(ssuid),mDbName(DbName,DbLocation) {}
~Impl() {}
const CssmSubserviceUid &ssuid() const { return mCssmSubserviceUid; }
const char *dbName() const { return mDbName.dbName().c_str(); }
const CssmNetAddress *dbLocation() const { return mDbName.dbLocation(); }
bool operator < (const Impl &other) const
{ return (mCssmSubserviceUid < other.mCssmSubserviceUid ||
(!(other.mCssmSubserviceUid < mCssmSubserviceUid) && mDbName < other.mDbName)); }
bool operator == (const Impl &other) const
{ return mCssmSubserviceUid == other.mCssmSubserviceUid && mDbName == other.mDbName; }
private:
CssmSubserviceUid mCssmSubserviceUid;
DbName mDbName;
};
public:
DLDbIdentifier() {}
DLDbIdentifier(const CSSM_SUBSERVICE_UID &ssuid,const char *DbName,const CSSM_NET_ADDRESS *DbLocation)
: mImpl(new Impl(ssuid, DbName, DbLocation)) {}
bool operator !() const { return !mImpl; }
operator bool() const { return mImpl; }
bool operator <(const DLDbIdentifier &other) const
{ return mImpl && other.mImpl ? *mImpl < *other.mImpl : &*mImpl < &*other.mImpl; }
bool operator ==(const DLDbIdentifier &other) const
{ return mImpl && other.mImpl ? *mImpl == *other.mImpl : &*mImpl == &*other.mImpl; }
const CssmSubserviceUid &ssuid() const { return mImpl->ssuid(); }
const char *dbName() const { return mImpl->dbName(); }
const CssmNetAddress *dbLocation() const { return mImpl->dbLocation(); }
RefPointer<Impl> mImpl;
};
class CssmDbIndexInfo : public PodWrapper<CssmDbIndexInfo, CSSM_DB_INDEX_INFO>
{
public:
CssmDbIndexInfo(const CSSM_DB_INDEX_INFO &attr)
{ (CSSM_DB_INDEX_INFO &)*this = attr; }
CSSM_DB_INDEX_TYPE indexType() const { return IndexType; }
void indexType(CSSM_DB_INDEX_TYPE indexType) { IndexType = indexType; }
CSSM_DB_INDEXED_DATA_LOCATION dataLocation() const { return IndexedDataLocation; }
void dataLocation(CSSM_DB_INDEXED_DATA_LOCATION dataLocation)
{
IndexedDataLocation = dataLocation;
}
const CssmDbAttributeInfo &attributeInfo() const
{
return CssmDbAttributeInfo::overlay(Info);
}
};
namespace DataWalkers
{
struct DLDbFlatIdentifier {
const CssmSubserviceUid *uid; const char *name; const CssmNetAddress *address;
DLDbFlatIdentifier(const DLDbIdentifier &ident)
: uid(&ident.ssuid()), name(ident.dbName()), address(ident.dbLocation()) { }
operator DLDbIdentifier () { return DLDbIdentifier(*uid, name, address); }
};
template<class Action>
DLDbFlatIdentifier *walk(Action &operate, DLDbFlatIdentifier * &ident)
{
operate(ident);
if (ident->uid)
walk(operate, ident->uid);
walk(operate, ident->name);
if (ident->address)
walk(operate, ident->address);
return ident;
}
}
}
#ifdef _CPP_UTILITIES
#pragma export off
#endif
#endif // _H_CDSA_UTILITIES_CSSMDB