#ifndef _H_CDSA_UTILITIES_CSSMDATA
#define _H_CDSA_UTILITIES_CSSMDATA
#include <Security/utilities.h>
#include <Security/cssmalloc.h>
#include <Security/refcount.h>
#ifdef _CPP_CDSA_UTILITIES_CSSMDATA
#pragma export on
#endif
namespace Security
{
class CssmManagedData {
public:
CssmManagedData(CssmAllocator &alloc) : allocator(alloc) { }
virtual ~CssmManagedData();
CssmAllocator &allocator;
virtual operator const CssmData & () const { return get(); }
template <class T> T *data() const { return reinterpret_cast<T *>(data()); }
void *data() const { return get().data(); }
size_t length() const { return get().length(); }
virtual CssmData &get() const throw() = 0; virtual CssmData release() = 0; virtual void reset() = 0; };
class CssmOwnedData : public CssmManagedData {
public:
CssmOwnedData(CssmAllocator &alloc, CssmData &mine) : CssmManagedData(alloc), referent(mine) { }
CssmOwnedData(CssmAllocator &alloc, CSSM_DATA &mine)
: CssmManagedData(alloc), referent(CssmData::overlay(mine)) { referent.clear(); }
operator void * () const { return referent; }
operator char * () const { return referent; }
operator signed char * () const { return referent; }
operator unsigned char * () const { return referent; }
operator bool () const { return referent; }
bool operator ! () const { return !referent; }
size_t length() const { return referent.length(); }
void *malloc(size_t len)
{
CssmAutoPtr<uint8> alloc(allocator, allocator.malloc<uint8>(len));
reset();
return referent = CssmData(alloc.release(), len);
}
void *realloc(size_t newLen)
{
return referent = CssmData(allocator.realloc<uint8>(referent.data(), newLen), newLen);
}
void length(size_t len) { realloc(len); }
void *append(const void *addData, size_t addLength)
{
size_t oldLength = length();
realloc(oldLength + addLength);
return memcpy(referent.at(oldLength), addData, addLength);
}
void *append(const CssmData &data)
{ return append(data.data(), data.length()); }
template <class T>
void set(T *data, size_t length)
{
reset();
referent = CssmData(data, length);
}
void set(CssmManagedData &source);
void set(const CSSM_DATA &source) { set(source.Data, source.Length); }
template <class T>
void copy(const T *data, size_t length)
{
CssmAutoPtr<void> newData(allocator, memcpy(allocator.malloc(length), data, length));
reset();
referent = CssmData(newData.release(), length);
}
void copy(const CssmData &source)
{ if (&source != &referent) copy(source.data(), source.length()); }
void copy(const CSSM_DATA &source)
{ if (&source != &referent) copy(source.Data, source.Length); }
void copy(CssmManagedData &source) { copy(source.get()); }
template <class Data>
void copy(const Data &source) { copy(source.data(), source.length()); }
void operator = (CssmManagedData &source) { set(source); }
void operator = (CssmOwnedData &source) { set(source); }
void operator = (const CSSM_DATA &source) { copy(source); }
CssmData &get() const throw() { return referent; }
protected:
CssmData &referent;
};
class CssmAutoData : public CssmOwnedData {
public:
CssmAutoData(CssmAllocator &alloc) : CssmOwnedData(alloc, mData) { }
template <class Data>
CssmAutoData(CssmAllocator &alloc, const Data &source) : CssmOwnedData(alloc, mData)
{ *this = source; }
explicit CssmAutoData(CssmManagedData &source) : CssmOwnedData(source.allocator, mData)
{ set(source); }
CssmAutoData(CssmAllocator &alloc, const void *data, size_t length)
: CssmOwnedData(alloc, mData) { copy(data, length); }
~CssmAutoData() { allocator.free(mData); }
CssmData release();
void reset();
void operator = (CssmManagedData &source) { set(source); }
void operator = (CssmOwnedData &source) { set(source); }
void operator = (CssmAutoData &source) { set(source); }
template <class Data>
void operator = (const Data &source) { copy(source); }
private:
CssmData mData;
};
class CssmRemoteData : public CssmOwnedData {
public:
CssmRemoteData(CssmAllocator &alloc, CssmData &mine)
: CssmOwnedData(alloc, mine), iOwnTheData(true) { }
CssmRemoteData(CssmAllocator &alloc, CSSM_DATA &mine)
: CssmOwnedData(alloc, mine), iOwnTheData(true) { }
~CssmRemoteData()
{ if (iOwnTheData) allocator.free(referent); }
CssmData release();
void reset();
void operator = (CssmManagedData &source) { set(source); }
void operator = (CssmOwnedData &source) { set(source); }
void operator = (CssmAutoData &source) { set(source); }
template <class Data>
void operator = (const Data &source) { copy(source); }
private:
bool iOwnTheData;
};
class CssmPolyData : public CssmData {
template <class T>
uint8 *set(const T &it)
{ return const_cast<uint8 *>(reinterpret_cast<const uint8 *>(&it)); }
public:
template <class char_T>
CssmPolyData(const char_T *s) : CssmData(const_cast<char_T *>(s), strlen(s)) {}
CssmPolyData(const string &s) : CssmData(const_cast<char *>(s.c_str()), s.size()) {}
CssmPolyData(const CSSM_DATA &data) : CssmData(data.Data, data.Length) {}
CssmPolyData(const bool &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const uint32 &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const sint32 &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const sint64 &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const double &t) : CssmData(set(t), sizeof(t)) { }
};
class CssmDateData : public CssmData
{
public:
CssmDateData(const CSSM_DATE &date);
private:
uint8 buffer[8];
};
class CssmGuidData : public CssmData
{
public:
CssmGuidData(const CSSM_GUID &guid);
private:
char buffer[Guid::stringRepLength + 1];
};
class CssmDLPolyData
{
public:
CssmDLPolyData(const CSSM_DATA &data, CSSM_DB_ATTRIBUTE_FORMAT format)
: mData(CssmData::overlay(data)), mFormat(format) {}
operator const char *() const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_STRING
|| mFormat == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE);
return reinterpret_cast<const char *>(mData.Data);
}
operator bool() const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32 || mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
return *reinterpret_cast<uint32 *>(mData.Data);
}
operator uint32() const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_UINT32);
return *reinterpret_cast<uint32 *>(mData.Data);
}
operator const uint32 *() const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32);
return reinterpret_cast<const uint32 *>(mData.Data);
}
operator sint32() const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_SINT32);
return *reinterpret_cast<sint32 *>(mData.Data);
}
operator double() const
{
assert(mFormat == CSSM_DB_ATTRIBUTE_FORMAT_REAL);
return *reinterpret_cast<double *>(mData.Data);
}
operator CSSM_DATE () const;
operator Guid () const;
operator const CssmData &() const
{
return mData;
}
private:
const CssmData &mData;
CSSM_DB_ATTRIBUTE_FORMAT mFormat;
};
class CssmDataContainer : public CssmData, public RefCount
{
public:
CssmDataContainer(CssmAllocator &inAllocator = CssmAllocator::standard()) :
CssmData(), mAllocator(inAllocator) {}
template <class T>
CssmDataContainer(const T *data, size_t length, CssmAllocator &inAllocator = CssmAllocator::standard()) :
CssmData(inAllocator.malloc(length), length), mAllocator(inAllocator)
{ if (length) ::memcpy(Data, data, length); }
void clear() { if (Data) { mAllocator.free(Data); Data = NULL; Length = 0; } }
~CssmDataContainer() { if (Data) mAllocator.free(Data); }
void append(const CssmPolyData &data)
{
uint32 newLength = Length + data.Length;
Data = reinterpret_cast<uint8 *>(mAllocator.realloc(Data, newLength));
memcpy(Data + Length, data.Data, data.Length);
Length = newLength;
}
CssmDataContainer(const CssmDataContainer &other)
: mAllocator(other.mAllocator)
{
Data = reinterpret_cast<uint8 *>(mAllocator.malloc(other.Length));
memcpy(Data, other.Data, other.Length);
Length = other.Length;
}
CssmDataContainer & operator = (const CSSM_DATA &other)
{
clear();
Data = reinterpret_cast<uint8 *>(mAllocator.malloc(other.Length));
memcpy(Data, other.Data, other.Length);
Length = other.Length;
return *this;
}
public:
CssmAllocator &mAllocator;
private:
operator CssmDataContainer * () const; };
typedef CssmDataContainer CssmOidContainer;
template <class Container>
class CssmBuffer : public RefPointer<Container>
{
public:
CssmBuffer() : RefPointer<Container>(new Container()) {} template <class T>
CssmBuffer(const T *data, size_t length, CssmAllocator &inAllocator = CssmAllocator::standard()) :
RefPointer<Container>(new Container(data, length, inAllocator)) {}
CssmBuffer(const CSSM_DATA &data, CssmAllocator &inAllocator = CssmAllocator::standard()) :
RefPointer<Container>(new Container(data.Data, data.Length, inAllocator)) {}
CssmBuffer(const CssmBuffer& other) : RefPointer<Container>(other) {}
CssmBuffer(Container *p) : RefPointer<Container>(p) {}
bool CssmBuffer::operator < (const CssmBuffer &other) const { return (**this) < (*other); }
};
}
#ifdef _CPP_CSSMDATA
#pragma export off
#endif
#endif // _H_CDSA_UTILITIES_CSSMDATA