]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/memutils.h
Security-54.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / memutils.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 // memutils - memory-related low-level utilities for easier living
21 //
22 #ifndef _H_MEMUTILS
23 #define _H_MEMUTILS
24
25 #include <Security/utilities.h>
26 #include <stdlib.h>
27 #include <algorithm>
28
29
30 #ifdef _CPP_MEMUTILS
31 # pragma export on
32 #endif
33
34
35 namespace Security
36 {
37
38 //
39 // Encapsulate these very sharp tools in a separate namespace
40 //
41 namespace LowLevelMemoryUtilities
42 {
43
44
45 //
46 // The default system alignment.
47 // @@@ We should really get this from somewhere... probably from utility_config.h.
48 //
49 static const size_t systemAlignment = 4;
50 typedef UInt32 PointerInt;
51
52
53 //
54 // Get the local alignment for a type.
55 //
56 template <class T>
57 inline size_t alignof() { struct { char c; T t; } s; return sizeof(s) - sizeof(T); }
58
59
60 //
61 // Round up a size or pointer to an alignment boundary.
62 // Alignment must be a power of two; default is default alignment.
63 //
64 inline size_t alignUp(size_t size, size_t alignment = systemAlignment)
65 {
66 return ((size - 1) & ~(alignment - 1)) + alignment;
67 }
68
69 inline void *alignUp(void *p, size_t alignment = systemAlignment)
70 {
71 return reinterpret_cast<void *>(alignUp(PointerInt(p), alignment));
72 }
73
74 inline const void *alignUp(const void *p, size_t alignment = systemAlignment)
75 {
76 return reinterpret_cast<const void *>(alignUp(PointerInt(p), alignment));
77 }
78
79 template <class T>
80 inline const T *increment(const void *p, ptrdiff_t offset)
81 { return reinterpret_cast<const T *>(PointerInt(p) + offset); }
82
83 template <class T>
84 inline T *increment(void *p, ptrdiff_t offset)
85 { return reinterpret_cast<T *>(PointerInt(p) + offset); }
86
87 inline const void *increment(const void *p, ptrdiff_t offset)
88 { return increment<const void>(p, offset); }
89
90 inline void *increment(void *p, ptrdiff_t offset)
91 { return increment<void>(p, offset); }
92
93 template <class T>
94 inline const T *increment(const void *p, ptrdiff_t offset, size_t alignment)
95 { return increment<const T>(alignUp(p, alignment), offset); }
96
97 template <class T>
98 inline T *increment(void *p, ptrdiff_t offset, size_t alignment)
99 { return increment<T>(alignUp(p, alignment), offset); }
100
101 inline const void *increment(const void *p, ptrdiff_t offset, size_t alignment)
102 { return increment<const void>(p, offset, alignment); }
103
104 inline void *increment(void *p, ptrdiff_t offset, size_t alignment)
105 { return increment<void>(p, offset, alignment); }
106
107 inline ptrdiff_t difference(const void *p1, const void *p2)
108 { return PointerInt(p1) - PointerInt(p2); }
109
110
111 //
112 // A simple utility for incremental creation of a contiguous memory block.
113 //
114 // Note that Writer and Writer::Counter go together. They use the same alignment
115 // and padding rules, so Writer::Counter will correctly calculate total buffer
116 // size for Writer, *presuming* that they are called in the same order.
117 //
118 // WARNING: There is no check for overflow. If you write too much, you will die.
119 //
120 class Writer {
121 private:
122 void *advance(size_t size)
123 {
124 void *here = alignUp(writePos);
125 writePos = increment(here, size);
126 return here;
127 }
128
129 public:
130 Writer() { }
131 Writer(void *base) : writePos(base) { }
132 void operator = (void *base) { writePos = base; }
133
134 template <class T>
135 T *operator () (const T &obj)
136 { T *here = (T *)advance(sizeof(T)); *here = obj; return here; }
137
138 void *operator () (const void *addr, size_t size)
139 { void *here = advance(size); return memcpy(here, addr, size); }
140
141 char *operator () (const char *s)
142 { return (char *)(*this)(s, strlen(s) + 1); }
143
144 void countedData(const void *data, uint32 length)
145 { (*this)(length); (*this)(data, length); }
146
147 template <class Data>
148 void countedData(const Data &data)
149 { countedData(data.data(), data.length()); }
150
151 class Counter;
152
153 private:
154 void *writePos; // next byte address
155 };
156
157 class Writer::Counter {
158 private:
159 void align() { totalSoFar = alignUp(totalSoFar); }
160
161 public:
162 Counter() : totalSoFar(0) { }
163 operator size_t () { return totalSoFar; }
164
165 template <class T> size_t operator () (const T &) { align(); return totalSoFar += sizeof(T); }
166 size_t insert(size_t size) { align(); return totalSoFar += size; }
167 size_t operator () (const char *s) { align(); return totalSoFar += strlen(s) + 1; }
168
169 void countedData(const void *, uint32 length)
170 { insert(sizeof(uint32)); insert(length); }
171
172 template <class Data>
173 void countedData(const Data &data)
174 { countedData(data.data(), data.length()); }
175
176 private:
177 size_t totalSoFar; // total size counted so far
178 };
179
180
181 //
182 // The Reader counter-part for a Writer.
183 // Again, Reader and Writer share alignment and representation rules, so what was
184 // Written shall be Read again, just fine.
185 //
186 class Reader {
187 private:
188 const void *advance(size_t size = 0)
189 {
190 const void *here = alignUp(readPos);
191 readPos = increment(here, size);
192 return here;
193 }
194
195 public:
196 Reader() { }
197 Reader(const void *base) : readPos(base) { }
198 void operator = (const void *base) { readPos = base; }
199
200 template <class T>
201 void operator () (T &obj) { obj = *reinterpret_cast<const T *>(advance(sizeof(T))); }
202 void operator () (void *addr, size_t size) { memcpy(addr, advance(size), size); }
203 void operator () (const char * &s)
204 { s = reinterpret_cast<const char *>(advance()); advance(strlen(s) + 1); }
205 template <class T>
206 const T *get(size_t size)
207 { return reinterpret_cast<const T *>(advance(size)); }
208
209 void countedData(const void * &data, uint32 &length)
210 { (*this)(length); data = advance(length); }
211
212 private:
213 // Explicitly forbid some invocations that are likely to be wrong.
214 void operator () (char * &s); // can't get writable string in-place
215
216 private:
217 const void *readPos; // next byte address
218 };
219
220
221 } // end namespace LowLevelMemoryUtilities
222
223 } // end namespace Security
224
225 #ifdef _CPP_MEMUTILS
226 # pragma export off
227 #endif
228
229 #endif //_H_MEMUTILS