]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/ReadWriteSection.h
Security-54.1.3.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 protected:
74 ReadSection(uint8 *inAddress, size_t inLength) : mAddress(inAddress), mLength(inLength) {}
75 public:
76 ReadSection() : mAddress(NULL), mLength(0) {}
77 ReadSection(const uint8 *inAddress, size_t inLength) :
78 mAddress(const_cast<uint8 *>(inAddress)), mLength(inLength) {}
79
80 uint32 size() const { return mLength; }
81
82 uint32 at(uint32 inOffset) const
83 {
84 return ntohl(*reinterpret_cast<const uint32 *>(mAddress + inOffset));
85 }
86
87 uint32 operator[](uint32 inOffset) const
88 {
89 if (inOffset + sizeof(uint32) > mLength)
90 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
91 return at(inOffset);
92 }
93
94 // Return a subsection from inOffset to end of section.
95 ReadSection subsection(uint32 inOffset) const
96 {
97 if (inOffset > mLength)
98 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
99 return ReadSection(mAddress + inOffset, mLength - inOffset);
100 }
101
102 // Return a subsection from inOffset of inLength bytes.
103 ReadSection subsection(uint32 inOffset, uint32 inLength) const
104 {
105 if (inOffset + inLength > mLength)
106 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
107 return ReadSection(mAddress + inOffset, inLength);
108 }
109
110 ReadSection subsection(const Range &inRange) const
111 {
112 return subsection(inRange.mOffset, inRange.mSize);
113 }
114
115 const uint8 *range(const Range &inRange) const
116 {
117 if (inRange.mOffset + inRange.mSize > mLength)
118 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
119 return mAddress + inRange.mOffset;
120 }
121
122 uint8 *allocCopyRange(const Range &inRange, CssmAllocator &inAllocator) const
123 {
124 uint8 *aData;
125 if (inRange.mSize == 0)
126 aData = NULL;
127 else
128 {
129 if (inRange.mOffset + inRange.mSize > mLength)
130 CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
131
132 aData = reinterpret_cast<uint8 *>(inAllocator.malloc(inRange.mSize));
133 memcpy(aData, mAddress + inRange.mOffset, inRange.mSize);
134 }
135
136 return aData;
137 }
138
139 static uint32 align(uint32 offset) { return (offset + AtomSize - 1) & ~(AtomSize - 1); }
140
141 protected:
142 uint8 *mAddress;
143 size_t mLength;
144 };
145
146 //
147 // Class representing a packed record (or buffer) used for writing.
148 //
149 class WriteSection : public ReadSection
150 {
151 public:
152 static const size_t DefaultCapacity = 64;
153
154 WriteSection(CssmAllocator &inAllocator, size_t inCapacity) :
155 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(inCapacity)), 0),
156 mAllocator(inAllocator),
157 mCapacity(inCapacity)
158 {
159 if (mCapacity > 0)
160 memset(mAddress, 0, mCapacity);
161 }
162
163 WriteSection(CssmAllocator &inAllocator = CssmAllocator::standard()) :
164 ReadSection(reinterpret_cast<uint8 *>(inAllocator.malloc(DefaultCapacity)), 0),
165 mAllocator(inAllocator),
166 mCapacity(DefaultCapacity)
167 {
168 }
169
170 WriteSection(const WriteSection &ws, int length) :
171 ReadSection(reinterpret_cast<uint8 *>(ws.mAllocator.malloc(length)), length),
172 mAllocator(ws.mAllocator),
173 mCapacity(length)
174 {
175 memcpy(mAddress, ws.mAddress, length);
176 }
177
178 ~WriteSection() { mAllocator.free(mAddress); }
179
180 private:
181 void grow(size_t inNewCapacity)
182 {
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;
187 }
188
189 public:
190 #if BUG_GCC
191 uint32 size() const { return ReadSection::size(); }
192 #else
193 // XXX This should work but egcs-2.95.2 doesn't like it.
194 using ReadSection::size;
195 #endif
196
197 void size(uint32 inLength) { mLength = inLength; }
198 uint32 put(uint32 inOffset, uint32 inValue)
199 {
200 uint32 aLength = inOffset + sizeof(inValue);
201 if (aLength > mCapacity)
202 grow(aLength);
203
204 *reinterpret_cast<uint32 *>(mAddress + inOffset) = htonl(inValue);
205 return aLength;
206 }
207
208 uint32 put(uint32 inOffset, uint32 inLength, const uint8 *inData)
209 {
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)
214 grow(aNewOffset);
215
216 memcpy(mAddress + inOffset, inData, inLength);
217
218 for (uint32 anOffset = aLength; anOffset < aNewOffset; anOffset++)
219 mAddress[anOffset] = 0;
220
221 return aNewOffset;
222 }
223
224 const uint8 *address() const { return mAddress; }
225 uint8 *release()
226 {
227 uint8 *anAddress = mAddress;
228 mAddress = NULL;
229 mCapacity = 0;
230 return anAddress;
231 }
232
233 private:
234 CssmAllocator &mAllocator;
235 size_t mCapacity;
236 };
237
238 } // end namespace Security
239
240 #endif // _H_APPLEDL_READWRITESECTION