2 * Copyright (c) 2000-2001 Apple Computer, 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.
23 #ifndef _H_APPLEDL_READWRITESECTION
24 #define _H_APPLEDL_READWRITESECTION
26 #include <Security/cssmalloc.h>
27 #include <Security/AtomicFile.h>
33 // Atom -- An Atom is a 32-bit unsigned integer value that is always internally
34 // represented using network byte order.
39 typedef constVector
<Atom
> Vector
;
42 Atom(uint32 value
) : mValue(htonl(value
)) {}
44 operator uint32 () const { return ntohl(mValue
); }
45 Atom
&operator = (uint32 value
) { mValue
= htonl(value
); return *this; }
52 AtomSize
= sizeof(uint32
) // XXX Why not just use sizeof(Atom)?
56 // Class representing a range (or subrange of a buffer).
61 Range(uint32 inOffset
, uint32 inSize
) : mOffset(inOffset
), mSize(inSize
) {}
67 // Class representing a packed record. All the accessors on this class are const since the
68 // underlying data is read-only
70 // XXX Should be replaced by Atom::Vector
74 ReadSection(uint8
*inAddress
, size_t inLength
) : mAddress(inAddress
), mLength(inLength
) {}
76 ReadSection() : mAddress(NULL
), mLength(0) {}
77 ReadSection(const uint8
*inAddress
, size_t inLength
) :
78 mAddress(const_cast<uint8
*>(inAddress
)), mLength(inLength
) {}
80 uint32
size() const { return mLength
; }
82 uint32
at(uint32 inOffset
) const
84 return ntohl(*reinterpret_cast<const uint32
*>(mAddress
+ inOffset
));
87 uint32
operator[](uint32 inOffset
) const
89 if (inOffset
+ sizeof(uint32
) > mLength
)
90 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
94 // Return a subsection from inOffset to end of section.
95 ReadSection
subsection(uint32 inOffset
) const
97 if (inOffset
> mLength
)
98 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
99 return ReadSection(mAddress
+ inOffset
, mLength
- inOffset
);
102 // Return a subsection from inOffset of inLength bytes.
103 ReadSection
subsection(uint32 inOffset
, uint32 inLength
) const
105 if (inOffset
+ inLength
> mLength
)
106 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
107 return ReadSection(mAddress
+ inOffset
, inLength
);
110 ReadSection
subsection(const Range
&inRange
) const
112 return subsection(inRange
.mOffset
, inRange
.mSize
);
115 const uint8
*range(const Range
&inRange
) const
117 if (inRange
.mOffset
+ inRange
.mSize
> mLength
)
118 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
119 return mAddress
+ inRange
.mOffset
;
122 uint8
*allocCopyRange(const Range
&inRange
, CssmAllocator
&inAllocator
) const
125 if (inRange
.mSize
== 0)
129 if (inRange
.mOffset
+ inRange
.mSize
> mLength
)
130 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
132 aData
= reinterpret_cast<uint8
*>(inAllocator
.malloc(inRange
.mSize
));
133 memcpy(aData
, mAddress
+ inRange
.mOffset
, inRange
.mSize
);
139 static uint32
align(uint32 offset
) { return (offset
+ AtomSize
- 1) & ~(AtomSize
- 1); }
147 // Class representing a packed record (or buffer) used for writing.
149 class WriteSection
: public ReadSection
152 static const size_t DefaultCapacity
= 64;
154 WriteSection(CssmAllocator
&inAllocator
, size_t inCapacity
) :
155 ReadSection(reinterpret_cast<uint8
*>(inAllocator
.malloc(inCapacity
)), 0),
156 mAllocator(inAllocator
),
157 mCapacity(inCapacity
)
160 memset(mAddress
, 0, mCapacity
);
163 WriteSection(CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
164 ReadSection(reinterpret_cast<uint8
*>(inAllocator
.malloc(DefaultCapacity
)), 0),
165 mAllocator(inAllocator
),
166 mCapacity(DefaultCapacity
)
170 WriteSection(const WriteSection
&ws
, int length
) :
171 ReadSection(reinterpret_cast<uint8
*>(ws
.mAllocator
.malloc(length
)), length
),
172 mAllocator(ws
.mAllocator
),
175 memcpy(mAddress
, ws
.mAddress
, length
);
178 ~WriteSection() { mAllocator
.free(mAddress
); }
181 void grow(size_t inNewCapacity
)
183 size_t aNewCapacity
= max(mCapacity
* 2, inNewCapacity
);
184 mAddress
= reinterpret_cast<uint8
*>(mAllocator
.realloc(mAddress
, aNewCapacity
));
185 memset(mAddress
+ mCapacity
, 0, aNewCapacity
- mCapacity
);
186 mCapacity
= aNewCapacity
;
191 uint32
size() const { return ReadSection::size(); }
193 // XXX This should work but egcs-2.95.2 doesn't like it.
194 using ReadSection::size
;
197 void size(uint32 inLength
) { mLength
= inLength
; }
198 uint32
put(uint32 inOffset
, uint32 inValue
)
200 uint32 aLength
= inOffset
+ sizeof(inValue
);
201 if (aLength
> mCapacity
)
204 *reinterpret_cast<uint32
*>(mAddress
+ inOffset
) = htonl(inValue
);
208 uint32
put(uint32 inOffset
, uint32 inLength
, const uint8
*inData
)
210 uint32 aLength
= inOffset
+ inLength
;
211 // Round up to nearest multiple of 4 bytes, to pad with zeros
212 uint32 aNewOffset
= align(aLength
);
213 if (aNewOffset
> mCapacity
)
216 memcpy(mAddress
+ inOffset
, inData
, inLength
);
218 for (uint32 anOffset
= aLength
; anOffset
< aNewOffset
; anOffset
++)
219 mAddress
[anOffset
] = 0;
224 const uint8
*address() const { return mAddress
; }
227 uint8
*anAddress
= mAddress
;
234 CssmAllocator
&mAllocator
;
238 } // end namespace Security
240 #endif // _H_APPLEDL_READWRITESECTION