]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/memstreams.h
2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // memstreams - primitive memory block streaming support
32 #include <security_utilities/memutils.h>
33 #include <security_utilities/endian.h>
34 #include <security_utilities/errors.h>
41 // Encapsulate these very sharp tools in a separate namespace
43 namespace LowLevelMemoryUtilities
48 // A simple utility for incremental creation of a contiguous memory block.
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.
54 // This layer allocates no memory; that's up to the caller (you).
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.
61 void *advance(size_t size
)
63 void *here
= alignUp(writePos
);
64 writePos
= increment(here
, size
);
70 Writer(void *base
) : writePos(base
) { }
71 void operator = (void *base
) { writePos
= base
; }
74 T
*operator () (const T
&obj
)
75 { T
*here
= (T
*)advance(sizeof(T
)); *here
= obj
; return here
; }
77 void *operator () (const void *addr
, size_t size
)
78 { void *here
= advance(size
); return memcpy(here
, addr
, size
); }
80 char *operator () (const char *s
)
81 { return (char *)(*this)(s
, strlen(s
) + 1); }
83 void countedData(const void *data
, size_t length
)
85 if (length
> uint32_t(~0))
86 UnixError::throwMe(ERANGE
);
87 Endian
<uint32_t> temp
= (uint32_t)length
; (*this)(temp
); (*this)(data
, length
);
91 void countedData(const Data
&data
)
92 { countedData(data
.data(), data
.length()); }
97 void *writePos
; // next byte address
100 class Writer::Counter
{
102 void align() { totalSoFar
= alignUp(totalSoFar
); }
105 Counter() : totalSoFar(0) { }
106 operator size_t () { return totalSoFar
; }
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; }
112 void countedData(const void *, size_t length
)
113 { insert(sizeof(uint32_t)); insert(length
); }
115 template <class Data
>
116 void countedData(const Data
&data
)
117 { countedData(data
.data(), data
.length()); }
120 size_t totalSoFar
; // total size counted so far
124 // A variant of Writer which returns offsets from the start of the buffer from the operator() functions.
125 class OffsetWriter
: Writer
{
128 OffsetWriter(void *base
) : Writer(base
), basePos(base
) { }
129 void operator = (void *base
) { basePos
= base
; Writer::operator = (base
); }
132 T
*operator () (const T
&obj
)
133 { return Writer::operator() (obj
) - basePos
; }
135 void *operator () (const void *addr
, size_t size
)
136 { return reinterpret_cast<void *>(uintptr_t(Writer::operator() (addr
, size
)) - uintptr_t(basePos
)); }
138 char *operator () (const char *s
)
139 { return (char *)(*this)(s
, strlen(s
) + 1); }
142 void *basePos
; // base address
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.
153 const void *advance(size_t size
= 0)
155 const void *here
= alignUp(readPos
);
156 readPos
= increment(here
, size
);
162 Reader(const void *base
) : readPos(base
) { }
163 void operator = (const void *base
) { readPos
= base
; }
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); }
171 const T
*get(size_t size
)
172 { return reinterpret_cast<const T
*>(advance(size
)); }
174 void countedData(const void * &data
, size_t &length
)
175 { Endian
<uint32_t> temp
; (*this)(temp
); length
= temp
; data
= advance(length
); }
178 // Explicitly forbid some invocations that are likely to be wrong.
179 void operator () (char * &s
); // can't get writable string in-place
182 const void *readPos
; // next byte address
186 } // end namespace LowLevelMemoryUtilities
188 } // end namespace Security