]>
git.saurik.com Git - apple/security.git/blob - libsecurity_utilities/lib/memstreams.h
2 * Copyright (c) 2000-2004 Apple Computer, 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
= 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(length
)); 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
125 // The Reader counter-part for a Writer.
126 // Again, Reader and Writer share alignment and representation rules, so what was
127 // Written shall be Read again, just fine.
131 const void *advance(size_t size
= 0)
133 const void *here
= alignUp(readPos
);
134 readPos
= increment(here
, size
);
140 Reader(const void *base
) : readPos(base
) { }
141 void operator = (const void *base
) { readPos
= base
; }
144 void operator () (T
&obj
) { obj
= *reinterpret_cast<const T
*>(advance(sizeof(T
))); }
145 void operator () (void *addr
, size_t size
) { memcpy(addr
, advance(size
), size
); }
146 void operator () (const char * &s
)
147 { s
= reinterpret_cast<const char *>(advance()); advance(strlen(s
) + 1); }
149 const T
*get(size_t size
)
150 { return reinterpret_cast<const T
*>(advance(size
)); }
152 void countedData(const void * &data
, size_t &length
)
153 { Endian
<uint32_t> temp
; (*this)(temp
); length
= temp
; data
= advance(length
); }
156 // Explicitly forbid some invocations that are likely to be wrong.
157 void operator () (char * &s
); // can't get writable string in-place
160 const void *readPos
; // next byte address
164 } // end namespace LowLevelMemoryUtilities
166 } // end namespace Security