ReadWriteSection.h [plain text]
#ifndef _H_APPLEDL_READWRITESECTION
#define _H_APPLEDL_READWRITESECTION
#include <Security/cssmalloc.h>
#include <Security/AtomicFile.h>
namespace Security
{
class Atom
{
public:
typedef constVector<Atom> Vector;
Atom() : mValue(0) {}
Atom(uint32 value) : mValue(htonl(value)) {}
operator uint32 () const { return ntohl(mValue); }
Atom &operator = (uint32 value) { mValue = htonl(value); return *this; }
private:
uint32 mValue;
};
enum {
AtomSize = sizeof(uint32) };
class Range
{
public:
Range(uint32 inOffset, uint32 inSize) : mOffset(inOffset), mSize(inSize) {}
uint32 mOffset;
uint32 mSize;
};
class ReadSection
{
protected:
ReadSection(uint8 *inAddress, size_t inLength) : mAddress(inAddress), mLength(inLength) {}
public:
ReadSection() : mAddress(NULL), mLength(0) {}
ReadSection(const uint8 *inAddress, size_t inLength) :
mAddress(const_cast<uint8 *>(inAddress)), mLength(inLength) {}
uint32 size() const { return mLength; }
uint32 at(uint32 inOffset) const
{
return ntohl(*reinterpret_cast<const uint32 *>(mAddress + inOffset));
}
uint32 operator[](uint32 inOffset) const
{
if (inOffset + sizeof(uint32) > mLength)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
return at(inOffset);
}
ReadSection subsection(uint32 inOffset) const
{
if (inOffset > mLength)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
return ReadSection(mAddress + inOffset, mLength - inOffset);
}
ReadSection subsection(uint32 inOffset, uint32 inLength) const
{
if (inOffset + inLength > mLength)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
return ReadSection(mAddress + inOffset, inLength);
}
ReadSection subsection(const Range &inRange) const
{
return subsection(inRange.mOffset, inRange.mSize);
}
const uint8 *range(const Range &inRange) const
{
if (inRange.mOffset + inRange.mSize > mLength)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
return mAddress + inRange.mOffset;
}
uint8 *allocCopyRange(const Range &inRange, CssmAllocator &inAllocator) const
{
uint8 *aData;
if (inRange.mSize == 0)
aData = NULL;
else
{
if (inRange.mOffset + inRange.mSize > mLength)
CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
aData = reinterpret_cast<uint8 *>(inAllocator.malloc(inRange.mSize));
memcpy(aData, mAddress + inRange.mOffset, inRange.mSize);
}
return aData;
}
static uint32 align(uint32 offset) { return (offset + AtomSize - 1) & ~(AtomSize - 1); }
protected:
uint8 *mAddress;
size_t mLength;
};
class WriteSection : public ReadSection
{
public:
static const size_t DefaultCapacity = 64;
WriteSection(CssmAllocator &inAllocator, size_t inCapacity) :
ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(inCapacity)), 0),
mAllocator(inAllocator),
mCapacity(inCapacity)
{
if (mCapacity > 0)
memset(mAddress, 0, mCapacity);
}
WriteSection(CssmAllocator &inAllocator = CssmAllocator::standard()) :
ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(DefaultCapacity)), 0),
mAllocator(inAllocator),
mCapacity(DefaultCapacity)
{
}
WriteSection(const WriteSection &ws, int length) :
ReadSection(reinterpret_cast<uint8 *>(ws.mAllocator.malloc(length)), length),
mAllocator(ws.mAllocator),
mCapacity(length)
{
memcpy(mAddress, ws.mAddress, length);
}
~WriteSection() { mAllocator.free(mAddress); }
private:
void grow(size_t inNewCapacity)
{
size_t aNewCapacity = max(mCapacity * 2, inNewCapacity);
mAddress = reinterpret_cast<uint8 *>(mAllocator.realloc(mAddress, aNewCapacity));
memset(mAddress + mCapacity, 0, aNewCapacity - mCapacity);
mCapacity = aNewCapacity;
}
public:
#if BUG_GCC
uint32 size() const { return ReadSection::size(); }
#else
using ReadSection::size;
#endif
void size(uint32 inLength) { mLength = inLength; }
uint32 put(uint32 inOffset, uint32 inValue)
{
uint32 aLength = inOffset + sizeof(inValue);
if (aLength > mCapacity)
grow(aLength);
*reinterpret_cast<uint32 *>(mAddress + inOffset) = htonl(inValue);
return aLength;
}
uint32 put(uint32 inOffset, uint32 inLength, const uint8 *inData)
{
uint32 aLength = inOffset + inLength;
uint32 aNewOffset = align(aLength);
if (aNewOffset > mCapacity)
grow(aNewOffset);
memcpy(mAddress + inOffset, inData, inLength);
for (uint32 anOffset = aLength; anOffset < aNewOffset; anOffset++)
mAddress[anOffset] = 0;
return aNewOffset;
}
const uint8 *address() const { return mAddress; }
uint8 *release()
{
uint8 *anAddress = mAddress;
mAddress = NULL;
mCapacity = 0;
return anAddress;
}
private:
CssmAllocator &mAllocator;
size_t mCapacity;
};
}
#endif // _H_APPLEDL_READWRITESECTION