]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/ReadWriteSection.h
Security-177.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / ReadWriteSection.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 //
20 // ReadWriteSection.h
21 //
22
23 #ifndef _H_APPLEDL_READWRITESECTION
24 #define _H_APPLEDL_READWRITESECTION
25
26 #include <Security/cssmalloc.h>
27 #include <Security/AtomicFile.h>
28 #include <Security/endian.h>
29
30 namespace Security
31 {
32
33 //
34 // Atom -- An Atom is a 32-bit unsigned integer value that is always internally
35 // represented using network byte order.
36 //
37 typedef Endian<uint32> Atom;
38
39 enum {
40 AtomSize = sizeof(uint32) // XXX Why not just use sizeof(Atom)?
41 };
42
43 //
44 // Class representing a range (or subrange of a buffer).
45 //
46 class Range
47 {
48 public:
49 Range(uint32 inOffset, uint32 inSize) : mOffset(inOffset), mSize(inSize) {}
50 uint32 mOffset;
51 uint32 mSize;
52 };
53
54 //
55 // Class representing a packed record. All the accessors on this class are const since the
56 // underlying data is read-only
57 //
58 // XXX Should be replaced by Atom::Vector
59 class ReadSection
60 {
61 protected:
62 ReadSection(uint8 *inAddress, size_t inLength) : mAddress(inAddress), mLength(inLength) {}
63 public:
64 ReadSection() : mAddress(NULL), mLength(0) {}
65 ReadSection(const uint8 *inAddress, size_t inLength) :
66 mAddress(const_cast<uint8 *>(inAddress)), mLength(inLength) {}
67
68 uint32 size() const { return mLength; }
69
70 uint32 at(uint32 inOffset) const
71 {
72 return ntohl(*reinterpret_cast<const uint32 *>(mAddress + inOffset));
73 }
74
75 uint32 operator[](uint32 inOffset) const
76 {
77 if (inOffset + sizeof(uint32) > mLength)
78 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
79 return at(inOffset);
80 }
81
82 // Return a subsection from inOffset to end of section.
83 ReadSection subsection(uint32 inOffset) const
84 {
85 if (inOffset > mLength)
86 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
87 return ReadSection(mAddress + inOffset, mLength - inOffset);
88 }
89
90 // Return a subsection from inOffset of inLength bytes.
91 ReadSection subsection(uint32 inOffset, uint32 inLength) const
92 {
93 if (inOffset + inLength > mLength)
94 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
95 return ReadSection(mAddress + inOffset, inLength);
96 }
97
98 ReadSection subsection(const Range &inRange) const
99 {
100 return subsection(inRange.mOffset, inRange.mSize);
101 }
102
103 const uint8 *range(const Range &inRange) const
104 {
105 if (inRange.mOffset + inRange.mSize > mLength)
106 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
107 return mAddress + inRange.mOffset;
108 }
109
110 uint8 *allocCopyRange(const Range &inRange, CssmAllocator &inAllocator) const
111 {
112 uint8 *aData;
113 if (inRange.mSize == 0)
114 aData = NULL;
115 else
116 {
117 if (inRange.mOffset + inRange.mSize > mLength)
118 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
119
120 aData = reinterpret_cast<uint8 *>(inAllocator.malloc(inRange.mSize));
121 memcpy(aData, mAddress + inRange.mOffset, inRange.mSize);
122 }
123
124 return aData;
125 }
126
127 static uint32 align(uint32 offset) { return (offset + AtomSize - 1) & ~(AtomSize - 1); }
128
129 protected:
130 uint8 *mAddress;
131 size_t mLength;
132 };
133
134 //
135 // Class representing a packed record (or buffer) used for writing.
136 //
137 class WriteSection : public ReadSection
138 {
139 public:
140 static const size_t DefaultCapacity = 64;
141
142 WriteSection(CssmAllocator &inAllocator, size_t inCapacity) :
143 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(inCapacity)), 0),
144 mAllocator(inAllocator),
145 mCapacity(inCapacity)
146 {
147 if (mCapacity > 0)
148 memset(mAddress, 0, mCapacity);
149 }
150
151 WriteSection(CssmAllocator &inAllocator = CssmAllocator::standard()) :
152 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(DefaultCapacity)), 0),
153 mAllocator(inAllocator),
154 mCapacity(DefaultCapacity)
155 {
156 }
157
158 WriteSection(const WriteSection &ws, int length) :
159 ReadSection(reinterpret_cast<uint8 *>(ws.mAllocator.malloc(length)), length),
160 mAllocator(ws.mAllocator),
161 mCapacity(length)
162 {
163 memcpy(mAddress, ws.mAddress, length);
164 }
165
166 ~WriteSection() { mAllocator.free(mAddress); }
167
168 private:
169 void grow(size_t inNewCapacity)
170 {
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;
175 }
176
177 public:
178 #if BUG_GCC
179 uint32 size() const { return ReadSection::size(); }
180 #else
181 // XXX This should work but egcs-2.95.2 doesn't like it.
182 using ReadSection::size;
183 #endif
184
185 void size(uint32 inLength) { mLength = inLength; }
186 uint32 put(uint32 inOffset, uint32 inValue)
187 {
188 uint32 aLength = inOffset + sizeof(inValue);
189 if (aLength > mCapacity)
190 grow(aLength);
191
192 *reinterpret_cast<uint32 *>(mAddress + inOffset) = htonl(inValue);
193 return aLength;
194 }
195
196 uint32 put(uint32 inOffset, uint32 inLength, const uint8 *inData)
197 {
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)
202 grow(aNewOffset);
203
204 memcpy(mAddress + inOffset, inData, inLength);
205
206 for (uint32 anOffset = aLength; anOffset < aNewOffset; anOffset++)
207 mAddress[anOffset] = 0;
208
209 return aNewOffset;
210 }
211
212 const uint8 *address() const { return mAddress; }
213 uint8 *release()
214 {
215 uint8 *anAddress = mAddress;
216 mAddress = NULL;
217 mCapacity = 0;
218 return anAddress;
219 }
220
221 private:
222 CssmAllocator &mAllocator;
223 size_t mCapacity;
224 };
225
226 } // end namespace Security
227
228 #endif // _H_APPLEDL_READWRITESECTION