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