]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/memstreams.h
Security-179.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / memstreams.h
1 /*
2 * Copyright (c) 2000-2003 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 // memstreams - primitive memory block streaming support
21 //
22 #ifndef _H_MEMSTREAMS
23 #define _H_MEMSTREAMS
24
25 #include <Security/memutils.h>
26 #include <Security/endian.h>
27
28
29 namespace Security
30 {
31
32 //
33 // Encapsulate these very sharp tools in a separate namespace
34 //
35 namespace LowLevelMemoryUtilities
36 {
37
38
39 //
40 // A simple utility for incremental creation of a contiguous memory block.
41 //
42 // Note that Writer and Writer::Counter go together. They use the same alignment
43 // and padding rules, so Writer::Counter will correctly calculate total buffer
44 // size for Writer, *presuming* that they are called in the same order.
45 //
46 // This layer allocates no memory; that's up to the caller (you).
47 //
48 // WARNING: There is no check for overflow. If you write too much, you will die.
49 // Writer::Counter can tell you how much you need.
50 //
51 class Writer {
52 private:
53 void *advance(size_t size)
54 {
55 void *here = alignUp(writePos);
56 writePos = increment(here, size);
57 return here;
58 }
59
60 public:
61 Writer() { }
62 Writer(void *base) : writePos(base) { }
63 void operator = (void *base) { writePos = base; }
64
65 template <class T>
66 T *operator () (const T &obj)
67 { T *here = (T *)advance(sizeof(T)); *here = obj; return here; }
68
69 void *operator () (const void *addr, size_t size)
70 { void *here = advance(size); return memcpy(here, addr, size); }
71
72 char *operator () (const char *s)
73 { return (char *)(*this)(s, strlen(s) + 1); }
74
75 void countedData(const void *data, uint32 length)
76 { Endian<uint32> temp = length; (*this)(temp); (*this)(data, length); }
77
78 template <class Data>
79 void countedData(const Data &data)
80 { countedData(data.data(), data.length()); }
81
82 class Counter;
83
84 private:
85 void *writePos; // next byte address
86 };
87
88 class Writer::Counter {
89 private:
90 void align() { totalSoFar = alignUp(totalSoFar); }
91
92 public:
93 Counter() : totalSoFar(0) { }
94 operator size_t () { return totalSoFar; }
95
96 template <class T> size_t operator () (const T &) { align(); return totalSoFar += sizeof(T); }
97 size_t insert(size_t size) { align(); return totalSoFar += size; }
98 size_t operator () (const char *s) { align(); return totalSoFar += strlen(s) + 1; }
99
100 void countedData(const void *, uint32 length)
101 { insert(sizeof(uint32)); insert(length); }
102
103 template <class Data>
104 void countedData(const Data &data)
105 { countedData(data.data(), data.length()); }
106
107 private:
108 size_t totalSoFar; // total size counted so far
109 };
110
111
112 //
113 // The Reader counter-part for a Writer.
114 // Again, Reader and Writer share alignment and representation rules, so what was
115 // Written shall be Read again, just fine.
116 //
117 class Reader {
118 private:
119 const void *advance(size_t size = 0)
120 {
121 const void *here = alignUp(readPos);
122 readPos = increment(here, size);
123 return here;
124 }
125
126 public:
127 Reader() { }
128 Reader(const void *base) : readPos(base) { }
129 void operator = (const void *base) { readPos = base; }
130
131 template <class T>
132 void operator () (T &obj) { obj = *reinterpret_cast<const T *>(advance(sizeof(T))); }
133 void operator () (void *addr, size_t size) { memcpy(addr, advance(size), size); }
134 void operator () (const char * &s)
135 { s = reinterpret_cast<const char *>(advance()); advance(strlen(s) + 1); }
136 template <class T>
137 const T *get(size_t size)
138 { return reinterpret_cast<const T *>(advance(size)); }
139
140 void countedData(const void * &data, uint32 &length)
141 { Endian<uint32> temp; (*this)(temp); length = temp; data = advance(length); }
142
143 private:
144 // Explicitly forbid some invocations that are likely to be wrong.
145 void operator () (char * &s); // can't get writable string in-place
146
147 private:
148 const void *readPos; // next byte address
149 };
150
151
152 } // end namespace LowLevelMemoryUtilities
153
154 } // end namespace Security
155
156 #endif //_H_MEMUTILS