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() : mAddress(NULL
), mLength(0) {}
75 ReadSection(const uint8
*inAddress
, size_t inLength
) :
76 mAddress(const_cast<uint8
*>(inAddress
)), mLength(inLength
) {}
78 uint32
size() const { return mLength
; }
80 uint32
at(uint32 inOffset
) const
82 return ntohl(*reinterpret_cast<const uint32
*>(mAddress
+ inOffset
));
85 uint32
operator[](uint32 inOffset
) const
87 if (inOffset
+ sizeof(uint32
) > mLength
)
88 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
92 // Return a subsection from inOffset to end of section.
93 ReadSection
subsection(uint32 inOffset
) const
95 if (inOffset
> mLength
)
96 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
97 return ReadSection(mAddress
+ inOffset
, mLength
- inOffset
);
100 // Return a subsection from inOffset of inLength bytes.
101 ReadSection
subsection(uint32 inOffset
, uint32 inLength
) const
103 if (inOffset
+ inLength
> mLength
)
104 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
105 return ReadSection(mAddress
+ inOffset
, inLength
);
108 ReadSection
subsection(const Range
&inRange
) const
110 return subsection(inRange
.mOffset
, inRange
.mSize
);
113 const uint8
*range(const Range
&inRange
) const
115 if (inRange
.mOffset
+ inRange
.mSize
> mLength
)
116 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
117 return mAddress
+ inRange
.mOffset
;
120 uint8
*allocCopyRange(const Range
&inRange
, CssmAllocator
&inAllocator
) const
123 if (inRange
.mSize
== 0)
127 if (inRange
.mOffset
+ inRange
.mSize
> mLength
)
128 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT
);
130 aData
= reinterpret_cast<uint8
*>(inAllocator
.malloc(inRange
.mSize
));
131 memcpy(aData
, mAddress
+ inRange
.mOffset
, inRange
.mSize
);
137 static uint32
align(uint32 offset
) { return (offset
+ AtomSize
- 1) & ~(AtomSize
- 1); }
140 ReadSection(uint8
*inAddress
, size_t inLength
) : mAddress(inAddress
), mLength(inLength
) {}
146 // Class representing a packed record (or buffer) used for writing.
148 class WriteSection
: public ReadSection
151 static const size_t DefaultCapacity
= 64;
153 WriteSection(CssmAllocator
&inAllocator
, size_t inCapacity
) :
154 ReadSection(reinterpret_cast<uint8
*>(inAllocator
.malloc(inCapacity
)), 0),
155 mAllocator(inAllocator
),
156 mCapacity(inCapacity
)
159 memset(mAddress
, 0, mCapacity
);
162 WriteSection(CssmAllocator
&inAllocator
= CssmAllocator::standard()) :
163 ReadSection(reinterpret_cast<uint8
*>(inAllocator
.malloc(DefaultCapacity
)), 0),
164 mAllocator(inAllocator
),
165 mCapacity(DefaultCapacity
)
169 WriteSection(const WriteSection
&ws
, int length
) :
170 ReadSection(reinterpret_cast<uint8
*>(ws
.mAllocator
.malloc(length
)), length
),
171 mAllocator(ws
.mAllocator
),
174 memcpy(mAddress
, ws
.mAddress
, length
);
177 ~WriteSection() { mAllocator
.free(mAddress
); }
180 uint32
size() const { return ReadSection::size(); }
182 // XXX This should work but egcs-2.95.2 doesn't like it.
183 using ReadSection::size
;
186 void size(uint32 inLength
) { mLength
= inLength
; }
187 uint32
put(uint32 inOffset
, uint32 inValue
)
189 uint32 aLength
= inOffset
+ sizeof(inValue
);
190 if (aLength
> mCapacity
)
193 *reinterpret_cast<uint32
*>(mAddress
+ inOffset
) = htonl(inValue
);
197 uint32
put(uint32 inOffset
, uint32 inLength
, const uint8
*inData
)
199 uint32 aLength
= inOffset
+ inLength
;
200 // Round up to nearest multiple of 4 bytes, to pad with zeros
201 uint32 aNewOffset
= align(aLength
);
202 if (aNewOffset
> mCapacity
)
205 memcpy(mAddress
+ inOffset
, inData
, inLength
);
207 for (uint32 anOffset
= aLength
; anOffset
< aNewOffset
; anOffset
++)
208 mAddress
[anOffset
] = 0;
213 const uint8
*address() const { return mAddress
; }
216 uint8
*anAddress
= mAddress
;
223 void grow(size_t inNewCapacity
)
225 size_t aNewCapacity
= max(mCapacity
* 2, inNewCapacity
);
226 mAddress
= reinterpret_cast<uint8
*>(mAllocator
.realloc(mAddress
, aNewCapacity
));
227 memset(mAddress
+ mCapacity
, 0, aNewCapacity
- mCapacity
);
228 mCapacity
= aNewCapacity
;
231 CssmAllocator
&mAllocator
;
235 } // end namespace Security
237 #endif // _H_APPLEDL_READWRITESECTION