]>
git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/memutils.h
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.
20 // memutils - memory-related low-level utilities for easier living
25 #include <Security/utilities.h>
39 // Encapsulate these very sharp tools in a separate namespace
41 namespace LowLevelMemoryUtilities
46 // The default system alignment.
47 // @@@ We should really get this from somewhere... probably from utility_config.h.
49 static const size_t systemAlignment
= 4;
50 typedef UInt32 PointerInt
;
54 // Get the local alignment for a type.
57 inline size_t alignof() { struct { char c
; T t
; } s
; return sizeof(s
) - sizeof(T
); }
61 // Round up a size or pointer to an alignment boundary.
62 // Alignment must be a power of two; default is default alignment.
64 inline size_t alignUp(size_t size
, size_t alignment
= systemAlignment
)
66 return ((size
- 1) & ~(alignment
- 1)) + alignment
;
69 inline void *alignUp(void *p
, size_t alignment
= systemAlignment
)
71 return reinterpret_cast<void *>(alignUp(PointerInt(p
), alignment
));
74 inline const void *alignUp(const void *p
, size_t alignment
= systemAlignment
)
76 return reinterpret_cast<const void *>(alignUp(PointerInt(p
), alignment
));
80 inline const T
*increment(const void *p
, ptrdiff_t offset
)
81 { return reinterpret_cast<const T
*>(PointerInt(p
) + offset
); }
84 inline T
*increment(void *p
, ptrdiff_t offset
)
85 { return reinterpret_cast<T
*>(PointerInt(p
) + offset
); }
87 inline const void *increment(const void *p
, ptrdiff_t offset
)
88 { return increment
<const void>(p
, offset
); }
90 inline void *increment(void *p
, ptrdiff_t offset
)
91 { return increment
<void>(p
, offset
); }
94 inline const T
*increment(const void *p
, ptrdiff_t offset
, size_t alignment
)
95 { return increment
<const T
>(alignUp(p
, alignment
), offset
); }
98 inline T
*increment(void *p
, ptrdiff_t offset
, size_t alignment
)
99 { return increment
<T
>(alignUp(p
, alignment
), offset
); }
101 inline const void *increment(const void *p
, ptrdiff_t offset
, size_t alignment
)
102 { return increment
<const void>(p
, offset
, alignment
); }
104 inline void *increment(void *p
, ptrdiff_t offset
, size_t alignment
)
105 { return increment
<void>(p
, offset
, alignment
); }
107 inline ptrdiff_t difference(const void *p1
, const void *p2
)
108 { return PointerInt(p1
) - PointerInt(p2
); }
112 // A simple utility for incremental creation of a contiguous memory block.
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.
118 // WARNING: There is no check for overflow. If you write too much, you will die.
122 void *advance(size_t size
)
124 void *here
= alignUp(writePos
);
125 writePos
= increment(here
, size
);
131 Writer(void *base
) : writePos(base
) { }
132 void operator = (void *base
) { writePos
= base
; }
135 T
*operator () (const T
&obj
)
136 { T
*here
= (T
*)advance(sizeof(T
)); *here
= obj
; return here
; }
138 void *operator () (const void *addr
, size_t size
)
139 { void *here
= advance(size
); return memcpy(here
, addr
, size
); }
141 char *operator () (const char *s
)
142 { return (char *)(*this)(s
, strlen(s
) + 1); }
144 void countedData(const void *data
, uint32 length
)
145 { (*this)(length
); (*this)(data
, length
); }
147 template <class Data
>
148 void countedData(const Data
&data
)
149 { countedData(data
.data(), data
.length()); }
154 void *writePos
; // next byte address
157 class Writer::Counter
{
159 void align() { totalSoFar
= alignUp(totalSoFar
); }
162 Counter() : totalSoFar(0) { }
163 operator size_t () { return totalSoFar
; }
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; }
169 void countedData(const void *, uint32 length
)
170 { insert(sizeof(uint32
)); insert(length
); }
172 template <class Data
>
173 void countedData(const Data
&data
)
174 { countedData(data
.data(), data
.length()); }
177 size_t totalSoFar
; // total size counted so far
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.
188 const void *advance(size_t size
= 0)
190 const void *here
= alignUp(readPos
);
191 readPos
= increment(here
, size
);
197 Reader(const void *base
) : readPos(base
) { }
198 void operator = (const void *base
) { readPos
= base
; }
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); }
206 const T
*get(size_t size
)
207 { return reinterpret_cast<const T
*>(advance(size
)); }
209 void countedData(const void * &data
, uint32
&length
)
210 { (*this)(length
); data
= advance(length
); }
213 // Explicitly forbid some invocations that are likely to be wrong.
214 void operator () (char * &s
); // can't get writable string in-place
217 const void *readPos
; // next byte address
221 } // end namespace LowLevelMemoryUtilities
223 } // end namespace Security