]>
git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/memstreams.h
2 * Copyright (c) 2000-2003 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 // memstreams - primitive memory block streaming support
25 #include <Security/memutils.h>
26 #include <Security/endian.h>
33 // Encapsulate these very sharp tools in a separate namespace
35 namespace LowLevelMemoryUtilities
40 // A simple utility for incremental creation of a contiguous memory block.
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.
46 // This layer allocates no memory; that's up to the caller (you).
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.
53 void *advance(size_t size
)
55 void *here
= alignUp(writePos
);
56 writePos
= increment(here
, size
);
62 Writer(void *base
) : writePos(base
) { }
63 void operator = (void *base
) { writePos
= base
; }
66 T
*operator () (const T
&obj
)
67 { T
*here
= (T
*)advance(sizeof(T
)); *here
= obj
; return here
; }
69 void *operator () (const void *addr
, size_t size
)
70 { void *here
= advance(size
); return memcpy(here
, addr
, size
); }
72 char *operator () (const char *s
)
73 { return (char *)(*this)(s
, strlen(s
) + 1); }
75 void countedData(const void *data
, uint32 length
)
76 { Endian
<uint32
> temp
= length
; (*this)(temp
); (*this)(data
, length
); }
79 void countedData(const Data
&data
)
80 { countedData(data
.data(), data
.length()); }
85 void *writePos
; // next byte address
88 class Writer::Counter
{
90 void align() { totalSoFar
= alignUp(totalSoFar
); }
93 Counter() : totalSoFar(0) { }
94 operator size_t () { return totalSoFar
; }
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; }
100 void countedData(const void *, uint32 length
)
101 { insert(sizeof(uint32
)); insert(length
); }
103 template <class Data
>
104 void countedData(const Data
&data
)
105 { countedData(data
.data(), data
.length()); }
108 size_t totalSoFar
; // total size counted so far
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.
119 const void *advance(size_t size
= 0)
121 const void *here
= alignUp(readPos
);
122 readPos
= increment(here
, size
);
128 Reader(const void *base
) : readPos(base
) { }
129 void operator = (const void *base
) { readPos
= base
; }
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); }
137 const T
*get(size_t size
)
138 { return reinterpret_cast<const T
*>(advance(size
)); }
140 void countedData(const void * &data
, uint32
&length
)
141 { Endian
<uint32
> temp
; (*this)(temp
); length
= temp
; data
= advance(length
); }
144 // Explicitly forbid some invocations that are likely to be wrong.
145 void operator () (char * &s
); // can't get writable string in-place
148 const void *readPos
; // next byte address
152 } // end namespace LowLevelMemoryUtilities
154 } // end namespace Security