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>
28 #include <Security/endian.h>
34 // Atom -- An Atom is a 32-bit unsigned integer value that is always internally
35 // represented using network byte order.
37 typedef Endian
<uint32
> Atom
;
40 AtomSize
= sizeof(uint32
) // XXX Why not just use sizeof(Atom)?
44 // Class representing a range (or subrange of a buffer).
49 Range(uint32 inOffset
, uint32 inSize
) : mOffset(inOffset
), mSize(inSize
) {}
55 // Class representing a packed record. All the accessors on this class are const since the
56 // underlying data is read-only
58 // XXX Should be replaced by Atom::Vector
62 ReadSection(uint8
*inAddress
, size_t inLength
) : mAddress(inAddress
), mLength(inLength
) {}
64 ReadSection() : mAddress(NULL
), mLength(0) {}
65 ReadSection(const uint8
*inAddress
, size_t inLength
) :
66 mAddress(const_cast<uint8
*>(inAddress
)), mLength(inLength
) {}
68 uint32
size() const { return mLength
; }
70 uint32
at(uint32 inOffset
) const
72 return ntohl(*reinterpret_cast<const uint32
*>(mAddress
+ inOffset
));
75 uint32
operator[](uint32 inOffset
) const
77 if (inOffset
+ sizeof(uint32
) > mLength
)
78 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
82 // Return a subsection from inOffset to end of section.
83 ReadSection
subsection(uint32 inOffset
) const
85 if (inOffset
> mLength
)
86 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
87 return ReadSection(mAddress
+ inOffset
, mLength
- inOffset
);
90 // Return a subsection from inOffset of inLength bytes.
91 ReadSection
subsection(uint32 inOffset
, uint32 inLength
) const
93 if (inOffset
+ inLength
> mLength
)
94 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
95 return ReadSection(mAddress
+ inOffset
, inLength
);
98 ReadSection
subsection(const Range
&inRange
) const
100 return subsection(inRange
.mOffset
, inRange
.mSize
);
103 const uint8
*range(const Range
&inRange
) const
105 if (inRange
.mOffset
+ inRange
.mSize
> mLength
)
106 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
107 return mAddress
+ inRange
.mOffset
;
110 uint8
*allocCopyRange(const Range
&inRange
, CssmAllocator
&inAllocator
) const
113 if (inRange
.mSize
== 0)
117 if (inRange
.mOffset
+ inRange
.mSize
> mLength
)
118 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
120 aData
= reinterpret_cast<uint8
*>(inAllocator
.malloc(inRange
.mSize
));
121 memcpy(aData
, mAddress
+ inRange
.mOffset
, inRange
.mSize
);
127 static uint32
align(uint32 offset
) { return (offset
+ AtomSize
- 1) & ~(AtomSize
- 1); }
135 // Class representing a packed record (or buffer) used for writing.
137 class WriteSection
: public ReadSection
140 static const size_t DefaultCapacity
= 64;
142 WriteSection(CssmAllocator
&inAllocator
, size_t inCapacity
) :
143 ReadSection(reinterpret_cast<uint8
*>(inAllocator
.malloc(inCapacity
)), 0),
144 mAllocator(inAllocator
),
145 mCapacity(inCapacity
)
148 memset(mAddress
, 0, mCapacity
);
151 WriteSection(CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
152 ReadSection(reinterpret_cast<uint8
*>(inAllocator
.malloc(DefaultCapacity
)), 0),
153 mAllocator(inAllocator
),
154 mCapacity(DefaultCapacity
)
158 WriteSection(const WriteSection
&ws
, int length
) :
159 ReadSection(reinterpret_cast<uint8
*>(ws
.mAllocator
.malloc(length
)), length
),
160 mAllocator(ws
.mAllocator
),
163 memcpy(mAddress
, ws
.mAddress
, length
);
166 ~WriteSection() { mAllocator
.free(mAddress
); }
169 void grow(size_t inNewCapacity
)
171 size_t aNewCapacity
= max(mCapacity
* 2, inNewCapacity
);
172 mAddress
= reinterpret_cast<uint8
*>(mAllocator
.realloc(mAddress
, aNewCapacity
));
173 memset(mAddress
+ mCapacity
, 0, aNewCapacity
- mCapacity
);
174 mCapacity
= aNewCapacity
;
179 uint32
size() const { return ReadSection::size(); }
181 // XXX This should work but egcs-2.95.2 doesn't like it.
182 using ReadSection::size
;
185 void size(uint32 inLength
) { mLength
= inLength
; }
186 uint32
put(uint32 inOffset
, uint32 inValue
)
188 uint32 aLength
= inOffset
+ sizeof(inValue
);
189 if (aLength
> mCapacity
)
192 *reinterpret_cast<uint32
*>(mAddress
+ inOffset
) = htonl(inValue
);
196 uint32
put(uint32 inOffset
, uint32 inLength
, const uint8
*inData
)
198 uint32 aLength
= inOffset
+ inLength
;
199 // Round up to nearest multiple of 4 bytes, to pad with zeros
200 uint32 aNewOffset
= align(aLength
);
201 if (aNewOffset
> mCapacity
)
204 memcpy(mAddress
+ inOffset
, inData
, inLength
);
206 for (uint32 anOffset
= aLength
; anOffset
< aNewOffset
; anOffset
++)
207 mAddress
[anOffset
] = 0;
212 const uint8
*address() const { return mAddress
; }
215 uint8
*anAddress
= mAddress
;
222 CssmAllocator
&mAllocator
;
226 } // end namespace Security
228 #endif // _H_APPLEDL_READWRITESECTION