]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/memstreams.h
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / memstreams.h
1 /*
2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // memstreams - primitive memory block streaming support
27 //
28 #ifndef _H_MEMSTREAMS
29 #define _H_MEMSTREAMS
30
31 #include <stdint.h>
32 #include <security_utilities/memutils.h>
33 #include <security_utilities/endian.h>
34 #include <security_utilities/errors.h>
35
36
37 namespace Security
38 {
39
40 //
41 // Encapsulate these very sharp tools in a separate namespace
42 //
43 namespace LowLevelMemoryUtilities
44 {
45
46
47 //
48 // A simple utility for incremental creation of a contiguous memory block.
49 //
50 // Note that Writer and Writer::Counter go together. They use the same alignment
51 // and padding rules, so Writer::Counter will correctly calculate total buffer
52 // size for Writer, *presuming* that they are called in the same order.
53 //
54 // This layer allocates no memory; that's up to the caller (you).
55 //
56 // WARNING: There is no check for overflow. If you write too much, you will die.
57 // Writer::Counter can tell you how much you need.
58 //
59 class Writer {
60 private:
61 void *advance(size_t size)
62 {
63 void *here = alignUp(writePos);
64 writePos = increment(here, size);
65 return here;
66 }
67
68 public:
69 Writer() { }
70 Writer(void *base) : writePos(base) { }
71 void operator = (void *base) { writePos = base; }
72
73 template <class T>
74 T *operator () (const T &obj)
75 { T *here = (T *)advance(sizeof(T)); *here = obj; return here; }
76
77 void *operator () (const void *addr, size_t size)
78 { void *here = advance(size); return memcpy(here, addr, size); }
79
80 char *operator () (const char *s)
81 { return (char *)(*this)(s, strlen(s) + 1); }
82
83 void countedData(const void *data, size_t length)
84 {
85 if (length > uint32_t(~0))
86 UnixError::throwMe(ERANGE);
87 Endian<uint32_t> temp = (uint32_t)length; (*this)(temp); (*this)(data, length);
88 }
89
90 template <class Data>
91 void countedData(const Data &data)
92 { countedData(data.data(), data.length()); }
93
94 class Counter;
95
96 private:
97 void *writePos; // next byte address
98 };
99
100 class Writer::Counter {
101 private:
102 void align() { totalSoFar = alignUp(totalSoFar); }
103
104 public:
105 Counter() : totalSoFar(0) { }
106 operator size_t () { return totalSoFar; }
107
108 template <class T> size_t operator () (const T &) { align(); return totalSoFar += sizeof(T); }
109 size_t insert(size_t size) { align(); return totalSoFar += size; }
110 size_t operator () (const char *s) { align(); return totalSoFar += strlen(s) + 1; }
111
112 void countedData(const void *, size_t length)
113 { insert(sizeof(uint32_t)); insert(length); }
114
115 template <class Data>
116 void countedData(const Data &data)
117 { countedData(data.data(), data.length()); }
118
119 private:
120 size_t totalSoFar; // total size counted so far
121 };
122
123
124 // A variant of Writer which returns offsets from the start of the buffer from the operator() functions.
125 class OffsetWriter : Writer {
126 public:
127 OffsetWriter() { }
128 OffsetWriter(void *base) : Writer(base), basePos(base) { }
129 void operator = (void *base) { basePos = base; Writer::operator = (base); }
130
131 template <class T>
132 T *operator () (const T &obj)
133 { return Writer::operator() (obj) - basePos; }
134
135 void *operator () (const void *addr, size_t size)
136 { return reinterpret_cast<void *>(uintptr_t(Writer::operator() (addr, size)) - uintptr_t(basePos)); }
137
138 char *operator () (const char *s)
139 { return (char *)(*this)(s, strlen(s) + 1); }
140
141 private:
142 void *basePos; // base address
143 };
144
145
146 //
147 // The Reader counter-part for a Writer.
148 // Again, Reader and Writer share alignment and representation rules, so what was
149 // Written shall be Read again, just fine.
150 //
151 class Reader {
152 private:
153 const void *advance(size_t size = 0)
154 {
155 const void *here = alignUp(readPos);
156 readPos = increment(here, size);
157 return here;
158 }
159
160 public:
161 Reader() { }
162 Reader(const void *base) : readPos(base) { }
163 void operator = (const void *base) { readPos = base; }
164
165 template <class T>
166 void operator () (T &obj) { obj = *reinterpret_cast<const T *>(advance(sizeof(T))); }
167 void operator () (void *addr, size_t size) { memcpy(addr, advance(size), size); }
168 void operator () (const char * &s)
169 { s = reinterpret_cast<const char *>(advance()); advance(strlen(s) + 1); }
170 template <class T>
171 const T *get(size_t size)
172 { return reinterpret_cast<const T *>(advance(size)); }
173
174 void countedData(const void * &data, size_t &length)
175 { Endian<uint32_t> temp; (*this)(temp); length = temp; data = advance(length); }
176
177 private:
178 // Explicitly forbid some invocations that are likely to be wrong.
179 void operator () (char * &s); // can't get writable string in-place
180
181 private:
182 const void *readPos; // next byte address
183 };
184
185
186 } // end namespace LowLevelMemoryUtilities
187
188 } // end namespace Security
189
190 #endif //_H_MEMUTILS