rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 PublicHeader: n/a
|
nuclear@0
|
4 Filename : OVR_BitStream.h
|
nuclear@0
|
5 Content : A generic serialization toolkit for packing data to a binary stream.
|
nuclear@0
|
6 Created : June 10, 2014
|
nuclear@0
|
7 Authors : Kevin Jenkins
|
nuclear@0
|
8
|
nuclear@0
|
9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
10
|
nuclear@0
|
11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
13 which is provided at the time of installation or download, or which
|
nuclear@0
|
14 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
15
|
nuclear@0
|
16 You may obtain a copy of the License at
|
nuclear@0
|
17
|
nuclear@0
|
18 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
19
|
nuclear@0
|
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
21 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
23 See the License for the specific language governing permissions and
|
nuclear@0
|
24 limitations under the License.
|
nuclear@0
|
25
|
nuclear@0
|
26 ************************************************************************************/
|
nuclear@0
|
27
|
nuclear@0
|
28 #ifndef OVR_Bitstream_h
|
nuclear@0
|
29 #define OVR_Bitstream_h
|
nuclear@0
|
30
|
nuclear@0
|
31 #include <math.h>
|
nuclear@0
|
32 #include "../Kernel/OVR_Types.h"
|
nuclear@0
|
33 #include "../Kernel/OVR_Std.h"
|
nuclear@0
|
34 #include "../Kernel/OVR_String.h"
|
nuclear@0
|
35
|
nuclear@0
|
36 namespace OVR { namespace Net {
|
nuclear@0
|
37
|
nuclear@0
|
38 typedef uint32_t BitSize_t;
|
nuclear@0
|
39 #define BITSTREAM_STACK_ALLOCATION_SIZE 256
|
nuclear@0
|
40 #define BITS_TO_BYTES(x) (((x)+7)>>3)
|
nuclear@0
|
41 #define BYTES_TO_BITS(x) ((x)<<3)
|
nuclear@0
|
42
|
nuclear@0
|
43
|
nuclear@0
|
44 //-----------------------------------------------------------------------------
|
nuclear@0
|
45 // BitStream
|
nuclear@0
|
46
|
nuclear@0
|
47 // Generic serialization class to binary stream
|
nuclear@0
|
48 class BitStream : public NewOverrideBase
|
nuclear@0
|
49 {
|
nuclear@0
|
50 public:
|
nuclear@0
|
51 /// Default Constructor
|
nuclear@0
|
52 BitStream();
|
nuclear@0
|
53
|
nuclear@0
|
54 /// \brief Create the bitstream, with some number of bytes to immediately allocate.
|
nuclear@0
|
55 /// \details There is no benefit to calling this, unless you know exactly how many bytes you need and it is greater than BITSTREAM_STACK_ALLOCATION_SIZE.
|
nuclear@0
|
56 /// In that case all it does is save you one or more realloc calls.
|
nuclear@0
|
57 /// \param[in] initialBytesToAllocate the number of bytes to pre-allocate.
|
nuclear@0
|
58 BitStream( const unsigned int initialBytesToAllocate );
|
nuclear@0
|
59
|
nuclear@0
|
60 /// \brief Initialize the BitStream, immediately setting the data it contains to a predefined pointer.
|
nuclear@0
|
61 /// \details Set \a _copyData to true if you want to make an internal copy of the data you are passing. Set it to false to just save a pointer to the data.
|
nuclear@0
|
62 /// You shouldn't call Write functions with \a _copyData as false, as this will write to unallocated memory
|
nuclear@0
|
63 /// 99% of the time you will use this function to cast Packet::data to a bitstream for reading, in which case you should write something as follows:
|
nuclear@0
|
64 /// \code
|
nuclear@0
|
65 /// RakNet::BitStream bs(packet->data, packet->length, false);
|
nuclear@0
|
66 /// \endcode
|
nuclear@0
|
67 /// \param[in] _data An array of bytes.
|
nuclear@0
|
68 /// \param[in] lengthInBytes Size of the \a _data.
|
nuclear@0
|
69 /// \param[in] _copyData true or false to make a copy of \a _data or not.
|
nuclear@0
|
70 BitStream( char* _data, const unsigned int lengthInBytes, bool _copyData );
|
nuclear@0
|
71
|
nuclear@0
|
72 // Destructor
|
nuclear@0
|
73 ~BitStream();
|
nuclear@0
|
74
|
nuclear@0
|
75 public:
|
nuclear@0
|
76 /// Resets the bitstream for reuse.
|
nuclear@0
|
77 void Reset( void );
|
nuclear@0
|
78
|
nuclear@0
|
79 /// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.
|
nuclear@0
|
80 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
81 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
82 /// \param[in] inOutTemplateVar The value to write
|
nuclear@0
|
83 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
84 template <class templateType>
|
nuclear@0
|
85 bool Serialize(bool writeToBitstream, templateType &inOutTemplateVar);
|
nuclear@0
|
86
|
nuclear@0
|
87 /// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.
|
nuclear@0
|
88 /// \details If the current value is different from the last value
|
nuclear@0
|
89 /// the current value will be written. Otherwise, a single bit will be written
|
nuclear@0
|
90 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
91 /// \param[in] inOutCurrentValue The current value to write
|
nuclear@0
|
92 /// \param[in] lastValue The last value to compare against. Only used if \a writeToBitstream is true.
|
nuclear@0
|
93 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
94 template <class templateType>
|
nuclear@0
|
95 bool SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue);
|
nuclear@0
|
96
|
nuclear@0
|
97 /// \brief Bidirectional version of SerializeDelta when you don't know what the last value is, or there is no last value.
|
nuclear@0
|
98 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
99 /// \param[in] inOutCurrentValue The current value to write
|
nuclear@0
|
100 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
101 template <class templateType>
|
nuclear@0
|
102 bool SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue);
|
nuclear@0
|
103
|
nuclear@0
|
104 /// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.
|
nuclear@0
|
105 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
106 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
107 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
108 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
109 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
110 /// \param[in] inOutTemplateVar The value to write
|
nuclear@0
|
111 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
112 template <class templateType>
|
nuclear@0
|
113 bool SerializeCompressed(bool writeToBitstream, templateType &inOutTemplateVar);
|
nuclear@0
|
114
|
nuclear@0
|
115 /// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.
|
nuclear@0
|
116 /// \details If the current value is different from the last value
|
nuclear@0
|
117 /// the current value will be written. Otherwise, a single bit will be written
|
nuclear@0
|
118 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
119 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
120 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
121 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
122 /// \param[in] inOutCurrentValue The current value to write
|
nuclear@0
|
123 /// \param[in] lastValue The last value to compare against. Only used if \a writeToBitstream is true.
|
nuclear@0
|
124 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
125 template <class templateType>
|
nuclear@0
|
126 bool SerializeCompressedDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue);
|
nuclear@0
|
127
|
nuclear@0
|
128 /// \brief Save as SerializeCompressedDelta(templateType ¤tValue, const templateType &lastValue) when we have an unknown second parameter
|
nuclear@0
|
129 /// \return true on data read. False on insufficient data in bitstream
|
nuclear@0
|
130 template <class templateType>
|
nuclear@0
|
131 bool SerializeCompressedDelta(bool writeToBitstream, templateType &inOutTemplateVar);
|
nuclear@0
|
132
|
nuclear@0
|
133 /// \brief Bidirectional serialize/deserialize an array or casted stream or raw data. This does NOT do endian swapping.
|
nuclear@0
|
134 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
135 /// \param[in] inOutByteArray a byte buffer
|
nuclear@0
|
136 /// \param[in] numberOfBytes the size of \a input in bytes
|
nuclear@0
|
137 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
138 bool Serialize(bool writeToBitstream, char* inOutByteArray, const unsigned int numberOfBytes );
|
nuclear@0
|
139
|
nuclear@0
|
140 /// \brief Serialize a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
|
nuclear@0
|
141 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
142 /// \param[in] inOutFloat The float to write
|
nuclear@0
|
143 /// \param[in] floatMin Predetermined minimum value of f
|
nuclear@0
|
144 /// \param[in] floatMax Predetermined maximum value of f
|
nuclear@0
|
145 bool SerializeFloat16(bool writeToBitstream, float &inOutFloat, float floatMin, float floatMax);
|
nuclear@0
|
146
|
nuclear@0
|
147 /// Serialize one type casted to another (smaller) type, to save bandwidth
|
nuclear@0
|
148 /// serializationType should be uint8_t, uint16_t, uint24_t, or uint32_t
|
nuclear@0
|
149 /// Example: int num=53; SerializeCasted<uint8_t>(true, num); would use 1 byte to write what would otherwise be an integer (4 or 8 bytes)
|
nuclear@0
|
150 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
151 /// \param[in] value The value to serialize
|
nuclear@0
|
152 template <class serializationType, class sourceType >
|
nuclear@0
|
153 bool SerializeCasted( bool writeToBitstream, sourceType &value );
|
nuclear@0
|
154
|
nuclear@0
|
155 /// Given the minimum and maximum values for an integer type, figure out the minimum number of bits to represent the range
|
nuclear@0
|
156 /// Then serialize only those bits
|
nuclear@0
|
157 /// \note A static is used so that the required number of bits for (maximum-minimum) is only calculated once. This does require that \a minimum and \maximum are fixed values for a given line of code for the life of the program
|
nuclear@0
|
158 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
159 /// \param[in] value Integer value to write, which should be between \a minimum and \a maximum
|
nuclear@0
|
160 /// \param[in] minimum Minimum value of \a value
|
nuclear@0
|
161 /// \param[in] maximum Maximum value of \a value
|
nuclear@0
|
162 /// \param[in] allowOutsideRange If true, all sends will take an extra bit, however value can deviate from outside \a minimum and \a maximum. If false, will assert if the value deviates
|
nuclear@0
|
163 template <class templateType>
|
nuclear@0
|
164 bool SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange=false );
|
nuclear@0
|
165 /// \param[in] requiredBits Primarily for internal use, called from above function() after calculating number of bits needed to represent maximum-minimum
|
nuclear@0
|
166 template <class templateType>
|
nuclear@0
|
167 bool SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange=false );
|
nuclear@0
|
168
|
nuclear@0
|
169 /// \brief Bidirectional serialize/deserialize a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.
|
nuclear@0
|
170 /// \details Will further compress y or z axis aligned vectors.
|
nuclear@0
|
171 /// Accurate to 1/32767.5.
|
nuclear@0
|
172 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
173 /// \param[in] x x
|
nuclear@0
|
174 /// \param[in] y y
|
nuclear@0
|
175 /// \param[in] z z
|
nuclear@0
|
176 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
177 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
178 bool SerializeNormVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z );
|
nuclear@0
|
179
|
nuclear@0
|
180 /// \brief Bidirectional serialize/deserialize a vector, using 10 bytes instead of 12.
|
nuclear@0
|
181 /// \details Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important.
|
nuclear@0
|
182 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
183 /// \param[in] x x
|
nuclear@0
|
184 /// \param[in] y y
|
nuclear@0
|
185 /// \param[in] z z
|
nuclear@0
|
186 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
187 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
188 bool SerializeVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z );
|
nuclear@0
|
189
|
nuclear@0
|
190 /// \brief Bidirectional serialize/deserialize a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes. Slightly lossy.
|
nuclear@0
|
191 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
192 /// \param[in] w w
|
nuclear@0
|
193 /// \param[in] x x
|
nuclear@0
|
194 /// \param[in] y y
|
nuclear@0
|
195 /// \param[in] z z
|
nuclear@0
|
196 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
197 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
198 bool SerializeNormQuat(bool writeToBitstream, templateType &w, templateType &x, templateType &y, templateType &z);
|
nuclear@0
|
199
|
nuclear@0
|
200 /// \brief Bidirectional serialize/deserialize an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each.
|
nuclear@0
|
201 /// \details Use 6 bytes instead of 36
|
nuclear@0
|
202 /// Lossy, although the result is renormalized
|
nuclear@0
|
203 /// \return true on success, false on failure.
|
nuclear@0
|
204 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
205 bool SerializeOrthMatrix(
|
nuclear@0
|
206 bool writeToBitstream,
|
nuclear@0
|
207 templateType &m00, templateType &m01, templateType &m02,
|
nuclear@0
|
208 templateType &m10, templateType &m11, templateType &m12,
|
nuclear@0
|
209 templateType &m20, templateType &m21, templateType &m22 );
|
nuclear@0
|
210
|
nuclear@0
|
211 /// \brief Bidirectional serialize/deserialize numberToSerialize bits to/from the input.
|
nuclear@0
|
212 /// \details Right aligned data means in the case of a partial byte, the bits are aligned
|
nuclear@0
|
213 /// from the right (bit 0) rather than the left (as in the normal
|
nuclear@0
|
214 /// internal representation) You would set this to true when
|
nuclear@0
|
215 /// writing user data, and false when copying bitstream data, such
|
nuclear@0
|
216 /// as writing one bitstream to another
|
nuclear@0
|
217 /// \param[in] writeToBitstream true to write from your data to this bitstream. False to read from this bitstream and write to your data
|
nuclear@0
|
218 /// \param[in] inOutByteArray The data
|
nuclear@0
|
219 /// \param[in] numberOfBitsToSerialize The number of bits to write
|
nuclear@0
|
220 /// \param[in] rightAlignedBits if true data will be right aligned
|
nuclear@0
|
221 /// \return true if \a writeToBitstream is true. true if \a writeToBitstream is false and the read was successful. false if \a writeToBitstream is false and the read was not successful.
|
nuclear@0
|
222 bool SerializeBits(bool writeToBitstream, unsigned char* inOutByteArray, const BitSize_t numberOfBitsToSerialize, const bool rightAlignedBits = true );
|
nuclear@0
|
223
|
nuclear@0
|
224 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
225 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
226 /// \param[in] inTemplateVar The value to write
|
nuclear@0
|
227 template <class templateType>
|
nuclear@0
|
228 void Write(const templateType &inTemplateVar);
|
nuclear@0
|
229
|
nuclear@0
|
230 /// \brief Write the dereferenced pointer to any integral type to a bitstream.
|
nuclear@0
|
231 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
232 /// \param[in] inTemplateVar The value to write
|
nuclear@0
|
233 template <class templateType>
|
nuclear@0
|
234 void WritePtr(templateType *inTemplateVar);
|
nuclear@0
|
235
|
nuclear@0
|
236 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
237 /// \details If the current value is different from the last value
|
nuclear@0
|
238 /// the current value will be written. Otherwise, a single bit will be written
|
nuclear@0
|
239 /// \param[in] currentValue The current value to write
|
nuclear@0
|
240 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
241 template <class templateType>
|
nuclear@0
|
242 void WriteDelta(const templateType ¤tValue, const templateType &lastValue);
|
nuclear@0
|
243
|
nuclear@0
|
244 /// \brief WriteDelta when you don't know what the last value is, or there is no last value.
|
nuclear@0
|
245 /// \param[in] currentValue The current value to write
|
nuclear@0
|
246 template <class templateType>
|
nuclear@0
|
247 void WriteDelta(const templateType ¤tValue);
|
nuclear@0
|
248
|
nuclear@0
|
249 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
250 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
251 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
252 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
253 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
254 /// \param[in] inTemplateVar The value to write
|
nuclear@0
|
255 template <class templateType>
|
nuclear@0
|
256 void WriteCompressed(const templateType &inTemplateVar);
|
nuclear@0
|
257
|
nuclear@0
|
258 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
259 /// \details If the current value is different from the last value
|
nuclear@0
|
260 /// the current value will be written. Otherwise, a single bit will be written
|
nuclear@0
|
261 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
262 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
263 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
264 /// \param[in] currentValue The current value to write
|
nuclear@0
|
265 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
266 template <class templateType>
|
nuclear@0
|
267 void WriteCompressedDelta(const templateType ¤tValue, const templateType &lastValue);
|
nuclear@0
|
268
|
nuclear@0
|
269 /// \brief Save as WriteCompressedDelta(const templateType ¤tValue, const templateType &lastValue) when we have an unknown second parameter
|
nuclear@0
|
270 template <class templateType>
|
nuclear@0
|
271 void WriteCompressedDelta(const templateType ¤tValue);
|
nuclear@0
|
272
|
nuclear@0
|
273 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
274 /// \details Define __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
275 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
276 /// \return true on success, false on failure.
|
nuclear@0
|
277 template <class templateType>
|
nuclear@0
|
278 bool Read(templateType &outTemplateVar);
|
nuclear@0
|
279
|
nuclear@0
|
280 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
281 /// \details If the written value differed from the value compared against in the write function,
|
nuclear@0
|
282 /// var will be updated. Otherwise it will retain the current value.
|
nuclear@0
|
283 /// ReadDelta is only valid from a previous call to WriteDelta
|
nuclear@0
|
284 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
285 /// \return true on success, false on failure.
|
nuclear@0
|
286 template <class templateType>
|
nuclear@0
|
287 bool ReadDelta(templateType &outTemplateVar);
|
nuclear@0
|
288
|
nuclear@0
|
289 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
290 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
291 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
292 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
293 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
294 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
295 /// \return true on success, false on failure.
|
nuclear@0
|
296 template <class templateType>
|
nuclear@0
|
297 bool ReadCompressed(templateType &outTemplateVar);
|
nuclear@0
|
298
|
nuclear@0
|
299 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
300 /// \details If the written value differed from the value compared against in the write function,
|
nuclear@0
|
301 /// var will be updated. Otherwise it will retain the current value.
|
nuclear@0
|
302 /// the current value will be updated.
|
nuclear@0
|
303 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
304 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
305 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
306 /// ReadCompressedDelta is only valid from a previous call to WriteDelta
|
nuclear@0
|
307 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
308 /// \return true on success, false on failure.
|
nuclear@0
|
309 template <class templateType>
|
nuclear@0
|
310 bool ReadCompressedDelta(templateType &outTemplateVar);
|
nuclear@0
|
311
|
nuclear@0
|
312 /// \brief Read one bitstream to another.
|
nuclear@0
|
313 /// \param[in] numberOfBits bits to read
|
nuclear@0
|
314 /// \param bitStream the bitstream to read into from
|
nuclear@0
|
315 /// \return true on success, false on failure.
|
nuclear@0
|
316 bool Read( BitStream *bitStream, BitSize_t numberOfBits );
|
nuclear@0
|
317 bool Read( BitStream *bitStream );
|
nuclear@0
|
318 bool Read( BitStream &bitStream, BitSize_t numberOfBits );
|
nuclear@0
|
319 bool Read( BitStream &bitStream );
|
nuclear@0
|
320
|
nuclear@0
|
321 /// \brief Write an array or casted stream or raw data. This does NOT do endian swapping.
|
nuclear@0
|
322 /// \param[in] inputByteArray a byte buffer
|
nuclear@0
|
323 /// \param[in] numberOfBytes the size of \a input in bytes
|
nuclear@0
|
324 void Write( const char* inputByteArray, const unsigned int numberOfBytes );
|
nuclear@0
|
325
|
nuclear@0
|
326 /// \brief Write one bitstream to another.
|
nuclear@0
|
327 /// \param[in] numberOfBits bits to write
|
nuclear@0
|
328 /// \param bitStream the bitstream to copy from
|
nuclear@0
|
329 void Write( BitStream *bitStream, BitSize_t numberOfBits );
|
nuclear@0
|
330 void Write( BitStream *bitStream );
|
nuclear@0
|
331 void Write( BitStream &bitStream, BitSize_t numberOfBits );
|
nuclear@0
|
332 void Write( BitStream &bitStream );\
|
nuclear@0
|
333
|
nuclear@0
|
334 /// \brief Write a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
|
nuclear@0
|
335 /// \param[in] x The float to write
|
nuclear@0
|
336 /// \param[in] floatMin Predetermined minimum value of f
|
nuclear@0
|
337 /// \param[in] floatMax Predetermined maximum value of f
|
nuclear@0
|
338 void WriteFloat16( float x, float floatMin, float floatMax );
|
nuclear@0
|
339
|
nuclear@0
|
340 /// Write one type serialized as another (smaller) type, to save bandwidth
|
nuclear@0
|
341 /// serializationType should be uint8_t, uint16_t, uint24_t, or uint32_t
|
nuclear@0
|
342 /// Example: int num=53; WriteCasted<uint8_t>(num); would use 1 byte to write what would otherwise be an integer (4 or 8 bytes)
|
nuclear@0
|
343 /// \param[in] value The value to write
|
nuclear@0
|
344 template <class serializationType, class sourceType >
|
nuclear@0
|
345 void WriteCasted( const sourceType &value );
|
nuclear@0
|
346
|
nuclear@0
|
347 /// Given the minimum and maximum values for an integer type, figure out the minimum number of bits to represent the range
|
nuclear@0
|
348 /// Then write only those bits
|
nuclear@0
|
349 /// \note A static is used so that the required number of bits for (maximum-minimum) is only calculated once. This does require that \a minimum and \maximum are fixed values for a given line of code for the life of the program
|
nuclear@0
|
350 /// \param[in] value Integer value to write, which should be between \a minimum and \a maximum
|
nuclear@0
|
351 /// \param[in] minimum Minimum value of \a value
|
nuclear@0
|
352 /// \param[in] maximum Maximum value of \a value
|
nuclear@0
|
353 /// \param[in] allowOutsideRange If true, all sends will take an extra bit, however value can deviate from outside \a minimum and \a maximum. If false, will assert if the value deviates. This should match the corresponding value passed to Read().
|
nuclear@0
|
354 template <class templateType>
|
nuclear@0
|
355 void WriteBitsFromIntegerRange( const templateType value, const templateType minimum, const templateType maximum, bool allowOutsideRange=false );
|
nuclear@0
|
356 /// \param[in] requiredBits Primarily for internal use, called from above function() after calculating number of bits needed to represent maximum-minimum
|
nuclear@0
|
357 template <class templateType>
|
nuclear@0
|
358 void WriteBitsFromIntegerRange( const templateType value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange=false );
|
nuclear@0
|
359
|
nuclear@0
|
360 /// \brief Write a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.
|
nuclear@0
|
361 /// \details Will further compress y or z axis aligned vectors.
|
nuclear@0
|
362 /// Accurate to 1/32767.5.
|
nuclear@0
|
363 /// \param[in] x x
|
nuclear@0
|
364 /// \param[in] y y
|
nuclear@0
|
365 /// \param[in] z z
|
nuclear@0
|
366 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
367 void WriteNormVector( templateType x, templateType y, templateType z );
|
nuclear@0
|
368
|
nuclear@0
|
369 /// \brief Write a vector, using 10 bytes instead of 12.
|
nuclear@0
|
370 /// \details Loses accuracy to about 3/10ths and only saves 2 bytes,
|
nuclear@0
|
371 /// so only use if accuracy is not important.
|
nuclear@0
|
372 /// \param[in] x x
|
nuclear@0
|
373 /// \param[in] y y
|
nuclear@0
|
374 /// \param[in] z z
|
nuclear@0
|
375 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
376 void WriteVector( templateType x, templateType y, templateType z );
|
nuclear@0
|
377
|
nuclear@0
|
378 /// \brief Write a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes. Slightly lossy.
|
nuclear@0
|
379 /// \param[in] w w
|
nuclear@0
|
380 /// \param[in] x x
|
nuclear@0
|
381 /// \param[in] y y
|
nuclear@0
|
382 /// \param[in] z z
|
nuclear@0
|
383 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
384 void WriteNormQuat( templateType w, templateType x, templateType y, templateType z);
|
nuclear@0
|
385
|
nuclear@0
|
386 /// \brief Write an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each.
|
nuclear@0
|
387 /// \details Use 6 bytes instead of 36
|
nuclear@0
|
388 /// Lossy, although the result is renormalized
|
nuclear@0
|
389 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
390 void WriteOrthMatrix(
|
nuclear@0
|
391 templateType m00, templateType m01, templateType m02,
|
nuclear@0
|
392 templateType m10, templateType m11, templateType m12,
|
nuclear@0
|
393 templateType m20, templateType m21, templateType m22 );
|
nuclear@0
|
394
|
nuclear@0
|
395 /// \brief Read an array or casted stream of byte.
|
nuclear@0
|
396 /// \details The array is raw data. There is no automatic endian conversion with this function
|
nuclear@0
|
397 /// \param[in] output The result byte array. It should be larger than @em numberOfBytes.
|
nuclear@0
|
398 /// \param[in] numberOfBytes The number of byte to read
|
nuclear@0
|
399 /// \return true on success false if there is some missing bytes.
|
nuclear@0
|
400 bool Read( char* output, const unsigned int numberOfBytes );
|
nuclear@0
|
401
|
nuclear@0
|
402 /// \brief Read a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
|
nuclear@0
|
403 /// \param[in] outFloat The float to read
|
nuclear@0
|
404 /// \param[in] floatMin Predetermined minimum value of f
|
nuclear@0
|
405 /// \param[in] floatMax Predetermined maximum value of f
|
nuclear@0
|
406 bool ReadFloat16( float &outFloat, float floatMin, float floatMax );
|
nuclear@0
|
407
|
nuclear@0
|
408 /// Read one type serialized to another (smaller) type, to save bandwidth
|
nuclear@0
|
409 /// serializationType should be uint8_t, uint16_t, uint24_t, or uint32_t
|
nuclear@0
|
410 /// Example: int num; ReadCasted<uint8_t>(num); would read 1 bytefrom the stream, and put the value in an integer
|
nuclear@0
|
411 /// \param[in] value The value to write
|
nuclear@0
|
412 template <class serializationType, class sourceType >
|
nuclear@0
|
413 bool ReadCasted( sourceType &value );
|
nuclear@0
|
414
|
nuclear@0
|
415 /// Given the minimum and maximum values for an integer type, figure out the minimum number of bits to represent the range
|
nuclear@0
|
416 /// Then read only those bits
|
nuclear@0
|
417 /// \note A static is used so that the required number of bits for (maximum-minimum) is only calculated once. This does require that \a minimum and \maximum are fixed values for a given line of code for the life of the program
|
nuclear@0
|
418 /// \param[in] value Integer value to read, which should be between \a minimum and \a maximum
|
nuclear@0
|
419 /// \param[in] minimum Minimum value of \a value
|
nuclear@0
|
420 /// \param[in] maximum Maximum value of \a value
|
nuclear@0
|
421 /// \param[in] allowOutsideRange If true, all sends will take an extra bit, however value can deviate from outside \a minimum and \a maximum. If false, will assert if the value deviates. This should match the corresponding value passed to Write().
|
nuclear@0
|
422 template <class templateType>
|
nuclear@0
|
423 bool ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange=false );
|
nuclear@0
|
424 /// \param[in] requiredBits Primarily for internal use, called from above function() after calculating number of bits needed to represent maximum-minimum
|
nuclear@0
|
425 template <class templateType>
|
nuclear@0
|
426 bool ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange=false );
|
nuclear@0
|
427
|
nuclear@0
|
428 /// \brief Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.
|
nuclear@0
|
429 /// \details Will further compress y or z axis aligned vectors.
|
nuclear@0
|
430 /// Accurate to 1/32767.5.
|
nuclear@0
|
431 /// \param[in] x x
|
nuclear@0
|
432 /// \param[in] y y
|
nuclear@0
|
433 /// \param[in] z z
|
nuclear@0
|
434 /// \return true on success, false on failure.
|
nuclear@0
|
435 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
436 bool ReadNormVector( templateType &x, templateType &y, templateType &z );
|
nuclear@0
|
437
|
nuclear@0
|
438 /// \brief Read 3 floats or doubles, using 10 bytes, where those float or doubles comprise a vector.
|
nuclear@0
|
439 /// \details Loses accuracy to about 3/10ths and only saves 2 bytes,
|
nuclear@0
|
440 /// so only use if accuracy is not important.
|
nuclear@0
|
441 /// \param[in] x x
|
nuclear@0
|
442 /// \param[in] y y
|
nuclear@0
|
443 /// \param[in] z z
|
nuclear@0
|
444 /// \return true on success, false on failure.
|
nuclear@0
|
445 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
446 bool ReadVector( templateType &x, templateType &y, templateType &z );
|
nuclear@0
|
447
|
nuclear@0
|
448 /// \brief Read a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes.
|
nuclear@0
|
449 /// \param[in] w w
|
nuclear@0
|
450 /// \param[in] x x
|
nuclear@0
|
451 /// \param[in] y y
|
nuclear@0
|
452 /// \param[in] z z
|
nuclear@0
|
453 /// \return true on success, false on failure.
|
nuclear@0
|
454 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
455 bool ReadNormQuat( templateType &w, templateType &x, templateType &y, templateType &z);
|
nuclear@0
|
456
|
nuclear@0
|
457 /// \brief Read an orthogonal matrix from a quaternion, reading 3 components of the quaternion in 2 bytes each and extrapolatig the 4th.
|
nuclear@0
|
458 /// \details Use 6 bytes instead of 36
|
nuclear@0
|
459 /// Lossy, although the result is renormalized
|
nuclear@0
|
460 /// \return true on success, false on failure.
|
nuclear@0
|
461 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
462 bool ReadOrthMatrix(
|
nuclear@0
|
463 templateType &m00, templateType &m01, templateType &m02,
|
nuclear@0
|
464 templateType &m10, templateType &m11, templateType &m12,
|
nuclear@0
|
465 templateType &m20, templateType &m21, templateType &m22 );
|
nuclear@0
|
466
|
nuclear@0
|
467 /// \brief Sets the read pointer back to the beginning of your data.
|
nuclear@0
|
468 void ResetReadPointer( void );
|
nuclear@0
|
469
|
nuclear@0
|
470 /// \brief Sets the write pointer back to the beginning of your data.
|
nuclear@0
|
471 void ResetWritePointer( void );
|
nuclear@0
|
472
|
nuclear@0
|
473 /// \brief This is good to call when you are done with the stream to make
|
nuclear@0
|
474 /// sure you didn't leave any data left over void
|
nuclear@0
|
475 void AssertStreamEmpty( void );
|
nuclear@0
|
476
|
nuclear@0
|
477 /// \brief RAKNET_DEBUG_PRINTF the bits in the stream. Great for debugging.
|
nuclear@0
|
478 void PrintBits( char *out ) const;
|
nuclear@0
|
479 void PrintBits( void ) const;
|
nuclear@0
|
480 void PrintHex( char *out ) const;
|
nuclear@0
|
481 void PrintHex( void ) const;
|
nuclear@0
|
482
|
nuclear@0
|
483 /// \brief Ignore data we don't intend to read
|
nuclear@0
|
484 /// \param[in] numberOfBits The number of bits to ignore
|
nuclear@0
|
485 void IgnoreBits( const BitSize_t numberOfBits );
|
nuclear@0
|
486
|
nuclear@0
|
487 /// \brief Ignore data we don't intend to read
|
nuclear@0
|
488 /// \param[in] numberOfBits The number of bytes to ignore
|
nuclear@0
|
489 void IgnoreBytes( const unsigned int numberOfBytes );
|
nuclear@0
|
490
|
nuclear@0
|
491 /// \brief Move the write pointer to a position on the array.
|
nuclear@0
|
492 /// \param[in] offset the offset from the start of the array.
|
nuclear@0
|
493 /// \attention
|
nuclear@0
|
494 /// \details Dangerous if you don't know what you are doing!
|
nuclear@0
|
495 /// For efficiency reasons you can only write mid-stream if your data is byte aligned.
|
nuclear@0
|
496 void SetWriteOffset( const BitSize_t offset );
|
nuclear@0
|
497
|
nuclear@0
|
498 /// \brief Returns the length in bits of the stream
|
nuclear@0
|
499 inline BitSize_t GetNumberOfBitsUsed( void ) const {return GetWriteOffset();}
|
nuclear@0
|
500 inline BitSize_t GetWriteOffset( void ) const {return numberOfBitsUsed;}
|
nuclear@0
|
501
|
nuclear@0
|
502 /// \brief Returns the length in bytes of the stream
|
nuclear@0
|
503 inline BitSize_t GetNumberOfBytesUsed( void ) const {return BITS_TO_BYTES( numberOfBitsUsed );}
|
nuclear@0
|
504
|
nuclear@0
|
505 /// \brief Returns the number of bits into the stream that we have read
|
nuclear@0
|
506 inline BitSize_t GetReadOffset( void ) const {return readOffset;}
|
nuclear@0
|
507
|
nuclear@0
|
508 /// \brief Sets the read bit index
|
nuclear@0
|
509 void SetReadOffset( const BitSize_t newReadOffset ) {readOffset=newReadOffset;}
|
nuclear@0
|
510
|
nuclear@0
|
511 /// \brief Returns the number of bits left in the stream that haven't been read
|
nuclear@0
|
512 inline BitSize_t GetNumberOfUnreadBits( void ) const {return numberOfBitsUsed - readOffset;}
|
nuclear@0
|
513
|
nuclear@0
|
514 /// \brief Makes a copy of the internal data for you \a _data will point to
|
nuclear@0
|
515 /// the stream. Partial bytes are left aligned.
|
nuclear@0
|
516 /// \param[out] _data The allocated copy of GetData()
|
nuclear@0
|
517 /// \return The length in bits of the stream.
|
nuclear@0
|
518 BitSize_t CopyData( unsigned char** _data ) const;
|
nuclear@0
|
519
|
nuclear@0
|
520 /// \internal
|
nuclear@0
|
521 /// Set the stream to some initial data.
|
nuclear@0
|
522 void SetData( unsigned char *inByteArray );
|
nuclear@0
|
523
|
nuclear@0
|
524 /// Gets the data that BitStream is writing to / reading from.
|
nuclear@0
|
525 /// Partial bytes are left aligned.
|
nuclear@0
|
526 /// \return A pointer to the internal state
|
nuclear@0
|
527 inline char* GetData( void ) const {return (char*) data;}
|
nuclear@0
|
528
|
nuclear@0
|
529 /// \brief Write numberToWrite bits from the input source.
|
nuclear@0
|
530 /// \details Right aligned data means in the case of a partial byte, the bits are aligned
|
nuclear@0
|
531 /// from the right (bit 0) rather than the left (as in the normal
|
nuclear@0
|
532 /// internal representation) You would set this to true when
|
nuclear@0
|
533 /// writing user data, and false when copying bitstream data, such
|
nuclear@0
|
534 /// as writing one bitstream to another.
|
nuclear@0
|
535 /// \param[in] inByteArray The data
|
nuclear@0
|
536 /// \param[in] numberOfBitsToWrite The number of bits to write
|
nuclear@0
|
537 /// \param[in] rightAlignedBits if true data will be right aligned
|
nuclear@0
|
538 void WriteBits( const unsigned char* inByteArray, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits = true );
|
nuclear@0
|
539
|
nuclear@0
|
540 /// \brief Align the bitstream to the byte boundary and then write the
|
nuclear@0
|
541 /// specified number of bits.
|
nuclear@0
|
542 /// \details This is faster than WriteBits but
|
nuclear@0
|
543 /// wastes the bits to do the alignment and requires you to call
|
nuclear@0
|
544 /// ReadAlignedBits at the corresponding read position.
|
nuclear@0
|
545 /// \param[in] inByteArray The data
|
nuclear@0
|
546 /// \param[in] numberOfBytesToWrite The size of input.
|
nuclear@0
|
547 void WriteAlignedBytes( const unsigned char *inByteArray, const unsigned int numberOfBytesToWrite );
|
nuclear@0
|
548
|
nuclear@0
|
549 // Endian swap bytes already in the bitstream
|
nuclear@0
|
550 void EndianSwapBytes( int byteOffset, int length );
|
nuclear@0
|
551
|
nuclear@0
|
552 /// \brief Aligns the bitstream, writes inputLength, and writes input. Won't write beyond maxBytesToWrite
|
nuclear@0
|
553 /// \param[in] inByteArray The data
|
nuclear@0
|
554 /// \param[in] inputLength The size of input.
|
nuclear@0
|
555 /// \param[in] maxBytesToWrite Max bytes to write
|
nuclear@0
|
556 void WriteAlignedBytesSafe( const char *inByteArray, const unsigned int inputLength, const unsigned int maxBytesToWrite );
|
nuclear@0
|
557
|
nuclear@0
|
558 /// \brief Read bits, starting at the next aligned bits.
|
nuclear@0
|
559 /// \details Note that the modulus 8 starting offset of the sequence must be the same as
|
nuclear@0
|
560 /// was used with WriteBits. This will be a problem with packet
|
nuclear@0
|
561 /// coalescence unless you byte align the coalesced packets.
|
nuclear@0
|
562 /// \param[in] inOutByteArray The byte array larger than @em numberOfBytesToRead
|
nuclear@0
|
563 /// \param[in] numberOfBytesToRead The number of byte to read from the internal state
|
nuclear@0
|
564 /// \return true if there is enough byte.
|
nuclear@0
|
565 bool ReadAlignedBytes( unsigned char *inOutByteArray, const unsigned int numberOfBytesToRead );
|
nuclear@0
|
566
|
nuclear@0
|
567 /// \brief Reads what was written by WriteAlignedBytesSafe.
|
nuclear@0
|
568 /// \param[in] inOutByteArray The data
|
nuclear@0
|
569 /// \param[in] maxBytesToRead Maximum number of bytes to read
|
nuclear@0
|
570 /// \return true on success, false on failure.
|
nuclear@0
|
571 bool ReadAlignedBytesSafe( char *inOutByteArray, int &inputLength, const int maxBytesToRead );
|
nuclear@0
|
572 bool ReadAlignedBytesSafe( char *inOutByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead );
|
nuclear@0
|
573
|
nuclear@0
|
574 /// \brief Same as ReadAlignedBytesSafe() but allocates the memory for you using new, rather than assuming it is safe to write to
|
nuclear@0
|
575 /// \param[in] outByteArray outByteArray will be deleted if it is not a pointer to 0
|
nuclear@0
|
576 /// \return true on success, false on failure.
|
nuclear@0
|
577 bool ReadAlignedBytesSafeAlloc( char **outByteArray, int &inputLength, const unsigned int maxBytesToRead );
|
nuclear@0
|
578 bool ReadAlignedBytesSafeAlloc( char **outByteArray, unsigned int &inputLength, const unsigned int maxBytesToRead );
|
nuclear@0
|
579
|
nuclear@0
|
580 /// \brief Align the next write and/or read to a byte boundary.
|
nuclear@0
|
581 /// \details This can be used to 'waste' bits to byte align for efficiency reasons It
|
nuclear@0
|
582 /// can also be used to force coalesced bitstreams to start on byte
|
nuclear@0
|
583 /// boundaries so so WriteAlignedBits and ReadAlignedBits both
|
nuclear@0
|
584 /// calculate the same offset when aligning.
|
nuclear@0
|
585 inline void AlignWriteToByteBoundary( void ) {numberOfBitsUsed += 8 - ( (( numberOfBitsUsed - 1 ) & 7) + 1 );}
|
nuclear@0
|
586
|
nuclear@0
|
587 /// \brief Align the next write and/or read to a byte boundary.
|
nuclear@0
|
588 /// \details This can be used to 'waste' bits to byte align for efficiency reasons It
|
nuclear@0
|
589 /// can also be used to force coalesced bitstreams to start on byte
|
nuclear@0
|
590 /// boundaries so so WriteAlignedBits and ReadAlignedBits both
|
nuclear@0
|
591 /// calculate the same offset when aligning.
|
nuclear@0
|
592 inline void AlignReadToByteBoundary( void ) {readOffset += 8 - ( (( readOffset - 1 ) & 7 ) + 1 );}
|
nuclear@0
|
593
|
nuclear@0
|
594 /// \brief Read \a numberOfBitsToRead bits to the output source.
|
nuclear@0
|
595 /// \details alignBitsToRight should be set to true to convert internal
|
nuclear@0
|
596 /// bitstream data to userdata. It should be false if you used
|
nuclear@0
|
597 /// WriteBits with rightAlignedBits false
|
nuclear@0
|
598 /// \param[in] inOutByteArray The resulting bits array
|
nuclear@0
|
599 /// \param[in] numberOfBitsToRead The number of bits to read
|
nuclear@0
|
600 /// \param[in] alignBitsToRight if true bits will be right aligned.
|
nuclear@0
|
601 /// \return true if there is enough bits to read
|
nuclear@0
|
602 bool ReadBits( unsigned char *inOutByteArray, BitSize_t numberOfBitsToRead, const bool alignBitsToRight = true );
|
nuclear@0
|
603
|
nuclear@0
|
604 /// \brief Write a 0
|
nuclear@0
|
605 void Write0( void );
|
nuclear@0
|
606
|
nuclear@0
|
607 /// \brief Write a 1
|
nuclear@0
|
608 void Write1( void );
|
nuclear@0
|
609
|
nuclear@0
|
610 /// \brief Reads 1 bit and returns true if that bit is 1 and false if it is 0.
|
nuclear@0
|
611 bool ReadBit( void );
|
nuclear@0
|
612
|
nuclear@0
|
613 /// \brief If we used the constructor version with copy data off, this
|
nuclear@0
|
614 /// *makes sure it is set to on and the data pointed to is copied.
|
nuclear@0
|
615 void AssertCopyData( void );
|
nuclear@0
|
616
|
nuclear@0
|
617 /// \brief Use this if you pass a pointer copy to the constructor
|
nuclear@0
|
618 /// *(_copyData==false) and want to overallocate to prevent
|
nuclear@0
|
619 /// reallocation.
|
nuclear@0
|
620 void SetNumberOfBitsAllocated( const BitSize_t lengthInBits );
|
nuclear@0
|
621
|
nuclear@0
|
622 /// \brief Reallocates (if necessary) in preparation of writing numberOfBitsToWrite
|
nuclear@0
|
623 void AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite );
|
nuclear@0
|
624
|
nuclear@0
|
625 /// \internal
|
nuclear@0
|
626 /// \return How many bits have been allocated internally
|
nuclear@0
|
627 BitSize_t GetNumberOfBitsAllocated(void) const;
|
nuclear@0
|
628
|
nuclear@0
|
629 /// Write zeros until the bitstream is filled up to \a bytes
|
nuclear@0
|
630 void PadWithZeroToByteLength( unsigned int bytes );
|
nuclear@0
|
631
|
nuclear@0
|
632 /// Get the number of leading zeros for a number
|
nuclear@0
|
633 /// \param[in] x Number to test
|
nuclear@0
|
634 static int NumberOfLeadingZeroes( uint8_t x );
|
nuclear@0
|
635 static int NumberOfLeadingZeroes( uint16_t x );
|
nuclear@0
|
636 static int NumberOfLeadingZeroes( uint32_t x );
|
nuclear@0
|
637 static int NumberOfLeadingZeroes( uint64_t x );
|
nuclear@0
|
638 static int NumberOfLeadingZeroes( int8_t x );
|
nuclear@0
|
639 static int NumberOfLeadingZeroes( int16_t x );
|
nuclear@0
|
640 static int NumberOfLeadingZeroes( int32_t x );
|
nuclear@0
|
641 static int NumberOfLeadingZeroes( int64_t x );
|
nuclear@0
|
642
|
nuclear@0
|
643 /// \internal Unrolled inner loop, for when performance is critical
|
nuclear@0
|
644 void WriteAlignedVar8(const char *inByteArray);
|
nuclear@0
|
645 /// \internal Unrolled inner loop, for when performance is critical
|
nuclear@0
|
646 bool ReadAlignedVar8(char *inOutByteArray);
|
nuclear@0
|
647 /// \internal Unrolled inner loop, for when performance is critical
|
nuclear@0
|
648 void WriteAlignedVar16(const char *inByteArray);
|
nuclear@0
|
649 /// \internal Unrolled inner loop, for when performance is critical
|
nuclear@0
|
650 bool ReadAlignedVar16(char *inOutByteArray);
|
nuclear@0
|
651 /// \internal Unrolled inner loop, for when performance is critical
|
nuclear@0
|
652 void WriteAlignedVar32(const char *inByteArray);
|
nuclear@0
|
653 /// \internal Unrolled inner loop, for when performance is critical
|
nuclear@0
|
654 bool ReadAlignedVar32(char *inOutByteArray);
|
nuclear@0
|
655
|
nuclear@0
|
656 inline void Write(const char * const inStringVar)
|
nuclear@0
|
657 {
|
nuclear@0
|
658 uint16_t l = (uint16_t) OVR_strlen(inStringVar);
|
nuclear@0
|
659 Write(l);
|
nuclear@0
|
660 WriteAlignedBytes((const unsigned char*) inStringVar, (const unsigned int) l);
|
nuclear@0
|
661 }
|
nuclear@0
|
662 inline void Write(const unsigned char * const inTemplateVar)
|
nuclear@0
|
663 {
|
nuclear@0
|
664 Write((const char*)inTemplateVar);
|
nuclear@0
|
665 }
|
nuclear@0
|
666 inline void Write(char * const inTemplateVar)
|
nuclear@0
|
667 {
|
nuclear@0
|
668 Write((const char*)inTemplateVar);
|
nuclear@0
|
669 }
|
nuclear@0
|
670 inline void Write(unsigned char * const inTemplateVar)
|
nuclear@0
|
671 {
|
nuclear@0
|
672 Write((const char*)inTemplateVar);
|
nuclear@0
|
673 }
|
nuclear@0
|
674
|
nuclear@0
|
675 /// ---- Member function template specialization declarations ----
|
nuclear@0
|
676 // Used for VC7
|
nuclear@0
|
677 #if defined(OVR_CC_MSVC) && _MSC_VER == 1300
|
nuclear@0
|
678 /// Write a bool to a bitstream.
|
nuclear@0
|
679 /// \param[in] var The value to write
|
nuclear@0
|
680 template <>
|
nuclear@0
|
681 void Write(const bool &var);
|
nuclear@0
|
682
|
nuclear@0
|
683 /// Write a RakNetGUID to a bitsteam
|
nuclear@0
|
684 /// \param[in] var The value to write
|
nuclear@0
|
685 template <>
|
nuclear@0
|
686 void Write(const RakNetGuid &var);
|
nuclear@0
|
687
|
nuclear@0
|
688 /// Write a string to a bitstream
|
nuclear@0
|
689 /// \param[in] var The value to write
|
nuclear@0
|
690 template <>
|
nuclear@0
|
691 void Write(const char* const &var);
|
nuclear@0
|
692 template <>
|
nuclear@0
|
693 void Write(const unsigned char* const &var);
|
nuclear@0
|
694 template <>
|
nuclear@0
|
695 void Write(char* const &var);
|
nuclear@0
|
696 template <>
|
nuclear@0
|
697 void Write(unsigned char* const &var);
|
nuclear@0
|
698 template <>
|
nuclear@0
|
699 void Write(const OVR::String &var);
|
nuclear@0
|
700
|
nuclear@0
|
701 /// \brief Write a bool delta.
|
nuclear@0
|
702 /// \details Same thing as just calling Write
|
nuclear@0
|
703 /// \param[in] currentValue The current value to write
|
nuclear@0
|
704 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
705 template <>
|
nuclear@0
|
706 void WriteDelta(const bool ¤tValue, const bool &lastValue);
|
nuclear@0
|
707
|
nuclear@0
|
708 template <>
|
nuclear@0
|
709 void WriteCompressed(const bool &var);
|
nuclear@0
|
710
|
nuclear@0
|
711 /// For values between -1 and 1
|
nuclear@0
|
712 template <>
|
nuclear@0
|
713 void WriteCompressed(const float &var);
|
nuclear@0
|
714
|
nuclear@0
|
715 /// For values between -1 and 1
|
nuclear@0
|
716 template <>
|
nuclear@0
|
717 void WriteCompressed(const double &var);
|
nuclear@0
|
718
|
nuclear@0
|
719 /// \brief Write a bool delta.
|
nuclear@0
|
720 /// \details Same thing as just calling Write
|
nuclear@0
|
721 /// \param[in] currentValue The current value to write
|
nuclear@0
|
722 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
723 template <>
|
nuclear@0
|
724 void WriteCompressedDelta(const bool ¤tValue, const bool &lastValue);
|
nuclear@0
|
725
|
nuclear@0
|
726 /// \brief Save as WriteCompressedDelta(bool currentValue, const templateType &lastValue)
|
nuclear@0
|
727 /// when we have an unknown second bool
|
nuclear@0
|
728 template <>
|
nuclear@0
|
729 void WriteCompressedDelta(const bool ¤tValue);
|
nuclear@0
|
730
|
nuclear@0
|
731 /// \brief Read a bool from a bitstream.
|
nuclear@0
|
732 /// \param[in] var The value to read
|
nuclear@0
|
733 /// \return true on success, false on failure.
|
nuclear@0
|
734 template <>
|
nuclear@0
|
735 bool Read(bool &var);
|
nuclear@0
|
736
|
nuclear@0
|
737 /// \brief Read a String from a bitstream.
|
nuclear@0
|
738 /// \param[in] var The value to read
|
nuclear@0
|
739 /// \return true on success, false on failure.
|
nuclear@0
|
740 template <>
|
nuclear@0
|
741 bool Read(char *&var);
|
nuclear@0
|
742 template <>
|
nuclear@0
|
743 bool Read(wchar_t *&var);
|
nuclear@0
|
744 template <>
|
nuclear@0
|
745 bool Read(unsigned char *&var);
|
nuclear@0
|
746
|
nuclear@0
|
747 /// \brief Read a bool from a bitstream.
|
nuclear@0
|
748 /// \param[in] var The value to read
|
nuclear@0
|
749 /// \return true on success, false on failure.
|
nuclear@0
|
750 template <>
|
nuclear@0
|
751 bool ReadDelta(bool &var);
|
nuclear@0
|
752
|
nuclear@0
|
753 template <>
|
nuclear@0
|
754 bool ReadCompressed(bool &var);
|
nuclear@0
|
755
|
nuclear@0
|
756 template <>
|
nuclear@0
|
757 bool ReadCompressed(float &var);
|
nuclear@0
|
758
|
nuclear@0
|
759 /// For values between -1 and 1
|
nuclear@0
|
760 /// \return true on success, false on failure.
|
nuclear@0
|
761 template <>
|
nuclear@0
|
762 bool ReadCompressed(double &var);
|
nuclear@0
|
763
|
nuclear@0
|
764 template <>
|
nuclear@0
|
765 bool ReadCompressed(char* &var);
|
nuclear@0
|
766 template <>
|
nuclear@0
|
767 bool ReadCompressed(wchar_t* &var);
|
nuclear@0
|
768 template <>
|
nuclear@0
|
769 bool ReadCompressed(unsigned char *&var);
|
nuclear@0
|
770 template <>
|
nuclear@0
|
771 bool ReadCompressed(OVR::String &var);
|
nuclear@0
|
772
|
nuclear@0
|
773 /// \brief Read a bool from a bitstream.
|
nuclear@0
|
774 /// \param[in] var The value to read
|
nuclear@0
|
775 /// \return true on success, false on failure.
|
nuclear@0
|
776 template <>
|
nuclear@0
|
777 bool ReadCompressedDelta(bool &var);
|
nuclear@0
|
778 #endif
|
nuclear@0
|
779
|
nuclear@0
|
780 inline static bool DoEndianSwap(void) {
|
nuclear@0
|
781 #ifndef __BITSTREAM_NATIVE_END
|
nuclear@0
|
782 return IsNetworkOrder()==false;
|
nuclear@0
|
783 #else
|
nuclear@0
|
784 return false;
|
nuclear@0
|
785 #endif
|
nuclear@0
|
786 }
|
nuclear@0
|
787 inline static bool IsBigEndian(void)
|
nuclear@0
|
788 {
|
nuclear@0
|
789 return IsNetworkOrder();
|
nuclear@0
|
790 }
|
nuclear@0
|
791 inline static bool IsNetworkOrder(void) {bool r = IsNetworkOrderInternal(); return r;}
|
nuclear@0
|
792 // Not inline, won't compile on PC due to winsock include errors
|
nuclear@0
|
793 static bool IsNetworkOrderInternal(void);
|
nuclear@0
|
794 static void ReverseBytes(unsigned char *inByteArray, unsigned char *inOutByteArray, const unsigned int length);
|
nuclear@0
|
795 static void ReverseBytesInPlace(unsigned char *inOutData,const unsigned int length);
|
nuclear@0
|
796
|
nuclear@0
|
797 private:
|
nuclear@0
|
798
|
nuclear@0
|
799 BitStream( const BitStream & /*invalid*/) : numberOfBitsUsed(0), numberOfBitsAllocated(0), readOffset(0),data(NULL), copyData(false) {
|
nuclear@0
|
800 OVR_ASSERT(0);
|
nuclear@0
|
801 }
|
nuclear@0
|
802
|
nuclear@0
|
803 BitStream& operator = ( const BitStream& /*invalid*/ ) {
|
nuclear@0
|
804 OVR_ASSERT(0);
|
nuclear@0
|
805 static BitStream i;
|
nuclear@0
|
806 return i;
|
nuclear@0
|
807 }
|
nuclear@0
|
808
|
nuclear@0
|
809 /// \brief Assume the input source points to a native type, compress and write it.
|
nuclear@0
|
810 void WriteCompressed( const unsigned char* inByteArray, const unsigned int size, const bool unsignedData );
|
nuclear@0
|
811
|
nuclear@0
|
812 /// \brief Assume the input source points to a compressed native type. Decompress and read it.
|
nuclear@0
|
813 bool ReadCompressed( unsigned char* inOutByteArray, const unsigned int size, const bool unsignedData );
|
nuclear@0
|
814
|
nuclear@0
|
815
|
nuclear@0
|
816 BitSize_t numberOfBitsUsed;
|
nuclear@0
|
817
|
nuclear@0
|
818 BitSize_t numberOfBitsAllocated;
|
nuclear@0
|
819
|
nuclear@0
|
820 BitSize_t readOffset;
|
nuclear@0
|
821
|
nuclear@0
|
822 unsigned char *data;
|
nuclear@0
|
823
|
nuclear@0
|
824 /// true if the internal buffer is copy of the data passed to the constructor
|
nuclear@0
|
825 bool copyData;
|
nuclear@0
|
826
|
nuclear@0
|
827 /// BitStreams that use less than BITSTREAM_STACK_ALLOCATION_SIZE use the stack, rather than the heap to store data. It switches over if BITSTREAM_STACK_ALLOCATION_SIZE is exceeded
|
nuclear@0
|
828 unsigned char stackData[BITSTREAM_STACK_ALLOCATION_SIZE];
|
nuclear@0
|
829 };
|
nuclear@0
|
830
|
nuclear@0
|
831 template <class templateType>
|
nuclear@0
|
832 inline bool BitStream::Serialize(bool writeToBitstream, templateType &inOutTemplateVar)
|
nuclear@0
|
833 {
|
nuclear@0
|
834 if (writeToBitstream)
|
nuclear@0
|
835 Write(inOutTemplateVar);
|
nuclear@0
|
836 else
|
nuclear@0
|
837 return Read(inOutTemplateVar);
|
nuclear@0
|
838 return true;
|
nuclear@0
|
839 }
|
nuclear@0
|
840
|
nuclear@0
|
841 template <class templateType>
|
nuclear@0
|
842 inline bool BitStream::SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue)
|
nuclear@0
|
843 {
|
nuclear@0
|
844 if (writeToBitstream)
|
nuclear@0
|
845 WriteDelta(inOutCurrentValue, lastValue);
|
nuclear@0
|
846 else
|
nuclear@0
|
847 return ReadDelta(inOutCurrentValue);
|
nuclear@0
|
848 return true;
|
nuclear@0
|
849 }
|
nuclear@0
|
850
|
nuclear@0
|
851 template <class templateType>
|
nuclear@0
|
852 inline bool BitStream::SerializeDelta(bool writeToBitstream, templateType &inOutCurrentValue)
|
nuclear@0
|
853 {
|
nuclear@0
|
854 if (writeToBitstream)
|
nuclear@0
|
855 WriteDelta(inOutCurrentValue);
|
nuclear@0
|
856 else
|
nuclear@0
|
857 return ReadDelta(inOutCurrentValue);
|
nuclear@0
|
858 return true;
|
nuclear@0
|
859 }
|
nuclear@0
|
860
|
nuclear@0
|
861 template <class templateType>
|
nuclear@0
|
862 inline bool BitStream::SerializeCompressed(bool writeToBitstream, templateType &inOutTemplateVar)
|
nuclear@0
|
863 {
|
nuclear@0
|
864 if (writeToBitstream)
|
nuclear@0
|
865 WriteCompressed(inOutTemplateVar);
|
nuclear@0
|
866 else
|
nuclear@0
|
867 return ReadCompressed(inOutTemplateVar);
|
nuclear@0
|
868 return true;
|
nuclear@0
|
869 }
|
nuclear@0
|
870
|
nuclear@0
|
871 template <class templateType>
|
nuclear@0
|
872 inline bool BitStream::SerializeCompressedDelta(bool writeToBitstream, templateType &inOutCurrentValue, const templateType &lastValue)
|
nuclear@0
|
873 {
|
nuclear@0
|
874 if (writeToBitstream)
|
nuclear@0
|
875 WriteCompressedDelta(inOutCurrentValue,lastValue);
|
nuclear@0
|
876 else
|
nuclear@0
|
877 return ReadCompressedDelta(inOutCurrentValue);
|
nuclear@0
|
878 return true;
|
nuclear@0
|
879 }
|
nuclear@0
|
880 //Stoppedhere
|
nuclear@0
|
881 template <class templateType>
|
nuclear@0
|
882 inline bool BitStream::SerializeCompressedDelta(bool writeToBitstream, templateType &inOutCurrentValue)
|
nuclear@0
|
883 {
|
nuclear@0
|
884 if (writeToBitstream)
|
nuclear@0
|
885 WriteCompressedDelta(inOutCurrentValue);
|
nuclear@0
|
886 else
|
nuclear@0
|
887 return ReadCompressedDelta(inOutCurrentValue);
|
nuclear@0
|
888 return true;
|
nuclear@0
|
889 }
|
nuclear@0
|
890
|
nuclear@0
|
891 inline bool BitStream::Serialize(bool writeToBitstream, char* inOutByteArray, const unsigned int numberOfBytes )
|
nuclear@0
|
892 {
|
nuclear@0
|
893 if (writeToBitstream)
|
nuclear@0
|
894 Write(inOutByteArray, numberOfBytes);
|
nuclear@0
|
895 else
|
nuclear@0
|
896 return Read(inOutByteArray, numberOfBytes);
|
nuclear@0
|
897 return true;
|
nuclear@0
|
898 }
|
nuclear@0
|
899
|
nuclear@0
|
900 template <class serializationType, class sourceType >
|
nuclear@0
|
901 bool BitStream::SerializeCasted( bool writeToBitstream, sourceType &value )
|
nuclear@0
|
902 {
|
nuclear@0
|
903 if (writeToBitstream) WriteCasted<serializationType>(value);
|
nuclear@0
|
904 else return ReadCasted<serializationType>(value);
|
nuclear@0
|
905 return true;
|
nuclear@0
|
906 }
|
nuclear@0
|
907
|
nuclear@0
|
908 template <class templateType>
|
nuclear@0
|
909 bool BitStream::SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange )
|
nuclear@0
|
910 {
|
nuclear@0
|
911 int requiredBits=BYTES_TO_BITS(sizeof(templateType))-NumberOfLeadingZeroes(templateType(maximum-minimum));
|
nuclear@0
|
912 return SerializeBitsFromIntegerRange(writeToBitstream,value,minimum,maximum,requiredBits,allowOutsideRange);
|
nuclear@0
|
913 }
|
nuclear@0
|
914 template <class templateType>
|
nuclear@0
|
915 bool BitStream::SerializeBitsFromIntegerRange( bool writeToBitstream, templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange )
|
nuclear@0
|
916 {
|
nuclear@0
|
917 if (writeToBitstream) WriteBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
|
nuclear@0
|
918 else return ReadBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
|
nuclear@0
|
919 return true;
|
nuclear@0
|
920 }
|
nuclear@0
|
921
|
nuclear@0
|
922 template <class templateType>
|
nuclear@0
|
923 inline bool BitStream::SerializeNormVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z )
|
nuclear@0
|
924 {
|
nuclear@0
|
925 if (writeToBitstream)
|
nuclear@0
|
926 WriteNormVector(x,y,z);
|
nuclear@0
|
927 else
|
nuclear@0
|
928 return ReadNormVector(x,y,z);
|
nuclear@0
|
929 return true;
|
nuclear@0
|
930 }
|
nuclear@0
|
931
|
nuclear@0
|
932 template <class templateType>
|
nuclear@0
|
933 inline bool BitStream::SerializeVector(bool writeToBitstream, templateType &x, templateType &y, templateType &z )
|
nuclear@0
|
934 {
|
nuclear@0
|
935 if (writeToBitstream)
|
nuclear@0
|
936 WriteVector(x,y,z);
|
nuclear@0
|
937 else
|
nuclear@0
|
938 return ReadVector(x,y,z);
|
nuclear@0
|
939 return true;
|
nuclear@0
|
940 }
|
nuclear@0
|
941
|
nuclear@0
|
942 template <class templateType>
|
nuclear@0
|
943 inline bool BitStream::SerializeNormQuat(bool writeToBitstream, templateType &w, templateType &x, templateType &y, templateType &z)
|
nuclear@0
|
944 {
|
nuclear@0
|
945 if (writeToBitstream)
|
nuclear@0
|
946 WriteNormQuat(w,x,y,z);
|
nuclear@0
|
947 else
|
nuclear@0
|
948 return ReadNormQuat(w,x,y,z);
|
nuclear@0
|
949 return true;
|
nuclear@0
|
950 }
|
nuclear@0
|
951
|
nuclear@0
|
952 template <class templateType>
|
nuclear@0
|
953 inline bool BitStream::SerializeOrthMatrix(
|
nuclear@0
|
954 bool writeToBitstream,
|
nuclear@0
|
955 templateType &m00, templateType &m01, templateType &m02,
|
nuclear@0
|
956 templateType &m10, templateType &m11, templateType &m12,
|
nuclear@0
|
957 templateType &m20, templateType &m21, templateType &m22 )
|
nuclear@0
|
958 {
|
nuclear@0
|
959 if (writeToBitstream)
|
nuclear@0
|
960 WriteOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22);
|
nuclear@0
|
961 else
|
nuclear@0
|
962 return ReadOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22);
|
nuclear@0
|
963 return true;
|
nuclear@0
|
964 }
|
nuclear@0
|
965
|
nuclear@0
|
966 inline bool BitStream::SerializeBits(bool writeToBitstream, unsigned char* inOutByteArray, const BitSize_t numberOfBitsToSerialize, const bool rightAlignedBits )
|
nuclear@0
|
967 {
|
nuclear@0
|
968 if (writeToBitstream)
|
nuclear@0
|
969 WriteBits(inOutByteArray,numberOfBitsToSerialize,rightAlignedBits);
|
nuclear@0
|
970 else
|
nuclear@0
|
971 return ReadBits(inOutByteArray,numberOfBitsToSerialize,rightAlignedBits);
|
nuclear@0
|
972 return true;
|
nuclear@0
|
973 }
|
nuclear@0
|
974
|
nuclear@0
|
975 template <class templateType>
|
nuclear@0
|
976 inline void BitStream::Write(const templateType &inTemplateVar)
|
nuclear@0
|
977 {
|
nuclear@0
|
978 #ifdef OVR_CC_MSVC
|
nuclear@0
|
979 #pragma warning(disable:4127) // conditional expression is constant
|
nuclear@0
|
980 #endif
|
nuclear@0
|
981 if (sizeof(inTemplateVar)==1)
|
nuclear@0
|
982 WriteBits( ( unsigned char* ) & inTemplateVar, sizeof( templateType ) * 8, true );
|
nuclear@0
|
983 else
|
nuclear@0
|
984 {
|
nuclear@0
|
985 #ifndef __BITSTREAM_NATIVE_END
|
nuclear@0
|
986 if (DoEndianSwap())
|
nuclear@0
|
987 {
|
nuclear@0
|
988 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
989 ReverseBytes((unsigned char*)&inTemplateVar, output, sizeof(templateType));
|
nuclear@0
|
990 WriteBits( ( unsigned char* ) output, sizeof(templateType) * 8, true );
|
nuclear@0
|
991 }
|
nuclear@0
|
992 else
|
nuclear@0
|
993 #endif
|
nuclear@0
|
994 WriteBits( ( unsigned char* ) & inTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
995 }
|
nuclear@0
|
996 }
|
nuclear@0
|
997
|
nuclear@0
|
998 template <class templateType>
|
nuclear@0
|
999 inline void BitStream::WritePtr(templateType *inTemplateVar)
|
nuclear@0
|
1000 {
|
nuclear@0
|
1001 #ifdef OVR_CC_MSVC
|
nuclear@0
|
1002 #pragma warning(disable:4127) // conditional expression is constant
|
nuclear@0
|
1003 #endif
|
nuclear@0
|
1004 if (sizeof(templateType)==1)
|
nuclear@0
|
1005 WriteBits( ( unsigned char* ) inTemplateVar, sizeof( templateType ) * 8, true );
|
nuclear@0
|
1006 else
|
nuclear@0
|
1007 {
|
nuclear@0
|
1008 #ifndef __BITSTREAM_NATIVE_END
|
nuclear@0
|
1009 if (DoEndianSwap())
|
nuclear@0
|
1010 {
|
nuclear@0
|
1011 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
1012 ReverseBytes((unsigned char*) inTemplateVar, output, sizeof(templateType));
|
nuclear@0
|
1013 WriteBits( ( unsigned char* ) output, sizeof(templateType) * 8, true );
|
nuclear@0
|
1014 }
|
nuclear@0
|
1015 else
|
nuclear@0
|
1016 #endif
|
nuclear@0
|
1017 WriteBits( ( unsigned char* ) inTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
1018 }
|
nuclear@0
|
1019 }
|
nuclear@0
|
1020
|
nuclear@0
|
1021 /// \brief Write a bool to a bitstream.
|
nuclear@0
|
1022 /// \param[in] inTemplateVar The value to write
|
nuclear@0
|
1023 template <>
|
nuclear@0
|
1024 inline void BitStream::Write(const bool &inTemplateVar)
|
nuclear@0
|
1025 {
|
nuclear@0
|
1026 if ( inTemplateVar )
|
nuclear@0
|
1027 Write1();
|
nuclear@0
|
1028 else
|
nuclear@0
|
1029 Write0();
|
nuclear@0
|
1030 }
|
nuclear@0
|
1031
|
nuclear@0
|
1032
|
nuclear@0
|
1033 /// \brief Write a string to a bitstream.
|
nuclear@0
|
1034 /// \param[in] var The value to write
|
nuclear@0
|
1035 template <>
|
nuclear@0
|
1036 inline void BitStream::Write(const OVR::String &inTemplateVar)
|
nuclear@0
|
1037 {
|
nuclear@0
|
1038 uint16_t l = (uint16_t) inTemplateVar.GetLength();
|
nuclear@0
|
1039 Write(l);
|
nuclear@0
|
1040 WriteAlignedBytes((const unsigned char*) inTemplateVar.ToCStr(), (const unsigned int) l);
|
nuclear@0
|
1041 }
|
nuclear@0
|
1042 template <>
|
nuclear@0
|
1043 inline void BitStream::Write(const char * const &inStringVar)
|
nuclear@0
|
1044 {
|
nuclear@0
|
1045 uint16_t l = (uint16_t) strlen(inStringVar);
|
nuclear@0
|
1046 Write(l);
|
nuclear@0
|
1047 WriteAlignedBytes((const unsigned char*) inStringVar, (const unsigned int) l);
|
nuclear@0
|
1048 }
|
nuclear@0
|
1049 template <>
|
nuclear@0
|
1050 inline void BitStream::Write(const unsigned char * const &inTemplateVar)
|
nuclear@0
|
1051 {
|
nuclear@0
|
1052 Write((const char*)inTemplateVar);
|
nuclear@0
|
1053 }
|
nuclear@0
|
1054 template <>
|
nuclear@0
|
1055 inline void BitStream::Write(char * const &inTemplateVar)
|
nuclear@0
|
1056 {
|
nuclear@0
|
1057 Write((const char*)inTemplateVar);
|
nuclear@0
|
1058 }
|
nuclear@0
|
1059 template <>
|
nuclear@0
|
1060 inline void BitStream::Write(unsigned char * const &inTemplateVar)
|
nuclear@0
|
1061 {
|
nuclear@0
|
1062 Write((const char*)inTemplateVar);
|
nuclear@0
|
1063 }
|
nuclear@0
|
1064
|
nuclear@0
|
1065 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
1066 /// \details If the current value is different from the last value
|
nuclear@0
|
1067 /// the current value will be written. Otherwise, a single bit will be written
|
nuclear@0
|
1068 /// \param[in] currentValue The current value to write
|
nuclear@0
|
1069 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
1070 template <class templateType>
|
nuclear@0
|
1071 inline void BitStream::WriteDelta(const templateType ¤tValue, const templateType &lastValue)
|
nuclear@0
|
1072 {
|
nuclear@0
|
1073 if (currentValue==lastValue)
|
nuclear@0
|
1074 {
|
nuclear@0
|
1075 Write(false);
|
nuclear@0
|
1076 }
|
nuclear@0
|
1077 else
|
nuclear@0
|
1078 {
|
nuclear@0
|
1079 Write(true);
|
nuclear@0
|
1080 Write(currentValue);
|
nuclear@0
|
1081 }
|
nuclear@0
|
1082 }
|
nuclear@0
|
1083
|
nuclear@0
|
1084 /// \brief Write a bool delta. Same thing as just calling Write
|
nuclear@0
|
1085 /// \param[in] currentValue The current value to write
|
nuclear@0
|
1086 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
1087 template <>
|
nuclear@0
|
1088 inline void BitStream::WriteDelta(const bool ¤tValue, const bool &lastValue)
|
nuclear@0
|
1089 {
|
nuclear@0
|
1090 (void) lastValue;
|
nuclear@0
|
1091
|
nuclear@0
|
1092 Write(currentValue);
|
nuclear@0
|
1093 }
|
nuclear@0
|
1094
|
nuclear@0
|
1095 /// \brief WriteDelta when you don't know what the last value is, or there is no last value.
|
nuclear@0
|
1096 /// \param[in] currentValue The current value to write
|
nuclear@0
|
1097 template <class templateType>
|
nuclear@0
|
1098 inline void BitStream::WriteDelta(const templateType ¤tValue)
|
nuclear@0
|
1099 {
|
nuclear@0
|
1100 Write(true);
|
nuclear@0
|
1101 Write(currentValue);
|
nuclear@0
|
1102 }
|
nuclear@0
|
1103
|
nuclear@0
|
1104 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
1105 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
1106 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
1107 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
1108 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
1109 /// \param[in] inTemplateVar The value to write
|
nuclear@0
|
1110 template <class templateType>
|
nuclear@0
|
1111 inline void BitStream::WriteCompressed(const templateType &inTemplateVar)
|
nuclear@0
|
1112 {
|
nuclear@0
|
1113 #ifdef OVR_CC_MSVC
|
nuclear@0
|
1114 #pragma warning(disable:4127) // conditional expression is constant
|
nuclear@0
|
1115 #endif
|
nuclear@0
|
1116 if (sizeof(inTemplateVar)==1)
|
nuclear@0
|
1117 WriteCompressed( ( unsigned char* ) & inTemplateVar, sizeof( templateType ) * 8, true );
|
nuclear@0
|
1118 else
|
nuclear@0
|
1119 {
|
nuclear@0
|
1120 #ifndef __BITSTREAM_NATIVE_END
|
nuclear@0
|
1121 #ifdef OVR_CC_MSVC
|
nuclear@0
|
1122 #pragma warning(disable:4244) // '=' : conversion from 'unsigned long' to 'uint16_t', possible loss of data
|
nuclear@0
|
1123 #endif
|
nuclear@0
|
1124
|
nuclear@0
|
1125 if (DoEndianSwap())
|
nuclear@0
|
1126 {
|
nuclear@0
|
1127 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
1128 ReverseBytes((unsigned char*)&inTemplateVar, output, sizeof(templateType));
|
nuclear@0
|
1129 WriteCompressed( ( unsigned char* ) output, sizeof(templateType) * 8, true );
|
nuclear@0
|
1130 }
|
nuclear@0
|
1131 else
|
nuclear@0
|
1132 #endif
|
nuclear@0
|
1133 WriteCompressed( ( unsigned char* ) & inTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
1134 }
|
nuclear@0
|
1135 }
|
nuclear@0
|
1136
|
nuclear@0
|
1137 template <>
|
nuclear@0
|
1138 inline void BitStream::WriteCompressed(const bool &inTemplateVar)
|
nuclear@0
|
1139 {
|
nuclear@0
|
1140 Write(inTemplateVar);
|
nuclear@0
|
1141 }
|
nuclear@0
|
1142
|
nuclear@0
|
1143 /// For values between -1 and 1
|
nuclear@0
|
1144 template <>
|
nuclear@0
|
1145 inline void BitStream::WriteCompressed(const float &inTemplateVar)
|
nuclear@0
|
1146 {
|
nuclear@0
|
1147 OVR_ASSERT(inTemplateVar > -1.01f && inTemplateVar < 1.01f);
|
nuclear@0
|
1148 float varCopy=inTemplateVar;
|
nuclear@0
|
1149 if (varCopy < -1.0f)
|
nuclear@0
|
1150 varCopy=-1.0f;
|
nuclear@0
|
1151 if (varCopy > 1.0f)
|
nuclear@0
|
1152 varCopy=1.0f;
|
nuclear@0
|
1153 Write((uint16_t)((varCopy+1.0f)*32767.5f));
|
nuclear@0
|
1154 }
|
nuclear@0
|
1155
|
nuclear@0
|
1156 /// For values between -1 and 1
|
nuclear@0
|
1157 template <>
|
nuclear@0
|
1158 inline void BitStream::WriteCompressed(const double &inTemplateVar)
|
nuclear@0
|
1159 {
|
nuclear@0
|
1160 OVR_ASSERT(inTemplateVar > -1.01 && inTemplateVar < 1.01);
|
nuclear@0
|
1161 double varCopy=inTemplateVar;
|
nuclear@0
|
1162 if (varCopy < -1.0f)
|
nuclear@0
|
1163 varCopy=-1.0f;
|
nuclear@0
|
1164 if (varCopy > 1.0f)
|
nuclear@0
|
1165 varCopy=1.0f;
|
nuclear@0
|
1166 Write((uint32_t)((varCopy+1.0)*2147483648.0));
|
nuclear@0
|
1167 }
|
nuclear@0
|
1168
|
nuclear@0
|
1169 /// \brief Write any integral type to a bitstream.
|
nuclear@0
|
1170 /// \details If the current value is different from the last value
|
nuclear@0
|
1171 /// the current value will be written. Otherwise, a single bit will be written
|
nuclear@0
|
1172 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
1173 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
1174 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
1175 /// \param[in] currentValue The current value to write
|
nuclear@0
|
1176 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
1177 template <class templateType>
|
nuclear@0
|
1178 inline void BitStream::WriteCompressedDelta(const templateType ¤tValue, const templateType &lastValue)
|
nuclear@0
|
1179 {
|
nuclear@0
|
1180 if (currentValue==lastValue)
|
nuclear@0
|
1181 {
|
nuclear@0
|
1182 Write(false);
|
nuclear@0
|
1183 }
|
nuclear@0
|
1184 else
|
nuclear@0
|
1185 {
|
nuclear@0
|
1186 Write(true);
|
nuclear@0
|
1187 WriteCompressed(currentValue);
|
nuclear@0
|
1188 }
|
nuclear@0
|
1189 }
|
nuclear@0
|
1190
|
nuclear@0
|
1191 /// \brief Write a bool delta. Same thing as just calling Write
|
nuclear@0
|
1192 /// \param[in] currentValue The current value to write
|
nuclear@0
|
1193 /// \param[in] lastValue The last value to compare against
|
nuclear@0
|
1194 template <>
|
nuclear@0
|
1195 inline void BitStream::WriteCompressedDelta(const bool ¤tValue, const bool &lastValue)
|
nuclear@0
|
1196 {
|
nuclear@0
|
1197 (void) lastValue;
|
nuclear@0
|
1198
|
nuclear@0
|
1199 Write(currentValue);
|
nuclear@0
|
1200 }
|
nuclear@0
|
1201
|
nuclear@0
|
1202 /// \brief Save as WriteCompressedDelta(const templateType ¤tValue, const templateType &lastValue)
|
nuclear@0
|
1203 /// when we have an unknown second parameter
|
nuclear@0
|
1204 template <class templateType>
|
nuclear@0
|
1205 inline void BitStream::WriteCompressedDelta(const templateType ¤tValue)
|
nuclear@0
|
1206 {
|
nuclear@0
|
1207 Write(true);
|
nuclear@0
|
1208 WriteCompressed(currentValue);
|
nuclear@0
|
1209 }
|
nuclear@0
|
1210
|
nuclear@0
|
1211 /// \brief Save as WriteCompressedDelta(bool currentValue, const templateType &lastValue)
|
nuclear@0
|
1212 /// when we have an unknown second bool
|
nuclear@0
|
1213 template <>
|
nuclear@0
|
1214 inline void BitStream::WriteCompressedDelta(const bool ¤tValue)
|
nuclear@0
|
1215 {
|
nuclear@0
|
1216 Write(currentValue);
|
nuclear@0
|
1217 }
|
nuclear@0
|
1218
|
nuclear@0
|
1219 /// \brief Read any integral type from a bitstream. Define __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
1220 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1221 template <class templateType>
|
nuclear@0
|
1222 inline bool BitStream::Read(templateType &outTemplateVar)
|
nuclear@0
|
1223 {
|
nuclear@0
|
1224 #ifdef OVR_CC_MSVC
|
nuclear@0
|
1225 #pragma warning(disable:4127) // conditional expression is constant
|
nuclear@0
|
1226 #endif
|
nuclear@0
|
1227 if (sizeof(outTemplateVar)==1)
|
nuclear@0
|
1228 return ReadBits( ( unsigned char* ) &outTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
1229 else
|
nuclear@0
|
1230 {
|
nuclear@0
|
1231 #ifndef __BITSTREAM_NATIVE_END
|
nuclear@0
|
1232 #ifdef OVR_CC_MSVC
|
nuclear@0
|
1233 #pragma warning(disable:4244) // '=' : conversion from 'unsigned long' to 'uint16_t', possible loss of data
|
nuclear@0
|
1234 #endif
|
nuclear@0
|
1235 if (DoEndianSwap())
|
nuclear@0
|
1236 {
|
nuclear@0
|
1237 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
1238 if (ReadBits( ( unsigned char* ) output, sizeof(templateType) * 8, true ))
|
nuclear@0
|
1239 {
|
nuclear@0
|
1240 ReverseBytes(output, (unsigned char*)&outTemplateVar, sizeof(templateType));
|
nuclear@0
|
1241 return true;
|
nuclear@0
|
1242 }
|
nuclear@0
|
1243 return false;
|
nuclear@0
|
1244 }
|
nuclear@0
|
1245 else
|
nuclear@0
|
1246 #endif
|
nuclear@0
|
1247 return ReadBits( ( unsigned char* ) & outTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
1248 }
|
nuclear@0
|
1249 }
|
nuclear@0
|
1250
|
nuclear@0
|
1251 /// \brief Read a bool from a bitstream.
|
nuclear@0
|
1252 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1253 template <>
|
nuclear@0
|
1254 inline bool BitStream::Read(bool &outTemplateVar)
|
nuclear@0
|
1255 {
|
nuclear@0
|
1256 if ( readOffset + 1 > numberOfBitsUsed )
|
nuclear@0
|
1257 return false;
|
nuclear@0
|
1258
|
nuclear@0
|
1259 if ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) ) // Is it faster to just write it out here?
|
nuclear@0
|
1260 outTemplateVar = true;
|
nuclear@0
|
1261 else
|
nuclear@0
|
1262 outTemplateVar = false;
|
nuclear@0
|
1263
|
nuclear@0
|
1264 // Has to be on a different line for Mac
|
nuclear@0
|
1265 readOffset++;
|
nuclear@0
|
1266
|
nuclear@0
|
1267 return true;
|
nuclear@0
|
1268 }
|
nuclear@0
|
1269
|
nuclear@0
|
1270 template <>
|
nuclear@0
|
1271 inline bool BitStream::Read(OVR::String &outTemplateVar)
|
nuclear@0
|
1272 {
|
nuclear@0
|
1273 bool b;
|
nuclear@0
|
1274 uint16_t l;
|
nuclear@0
|
1275 b=Read(l);
|
nuclear@0
|
1276 if (b && l>0)
|
nuclear@0
|
1277 {
|
nuclear@0
|
1278 AlignReadToByteBoundary();
|
nuclear@0
|
1279 outTemplateVar.AssignString((const char*) (data + ( readOffset >> 3 )), (size_t) l);
|
nuclear@0
|
1280 IgnoreBytes(l);
|
nuclear@0
|
1281 }
|
nuclear@0
|
1282 else
|
nuclear@0
|
1283 {
|
nuclear@0
|
1284 AlignReadToByteBoundary();
|
nuclear@0
|
1285 }
|
nuclear@0
|
1286 return b;
|
nuclear@0
|
1287 }
|
nuclear@0
|
1288 template <>
|
nuclear@0
|
1289 inline bool BitStream::Read(char *&varString)
|
nuclear@0
|
1290 {
|
nuclear@0
|
1291 bool b;
|
nuclear@0
|
1292 uint16_t l;
|
nuclear@0
|
1293 b=Read(l);
|
nuclear@0
|
1294 if (b && l>0)
|
nuclear@0
|
1295 {
|
nuclear@0
|
1296 memcpy(varString, data + ( readOffset >> 3 ), l);
|
nuclear@0
|
1297 IgnoreBytes(l);
|
nuclear@0
|
1298 }
|
nuclear@0
|
1299 else
|
nuclear@0
|
1300 {
|
nuclear@0
|
1301 AlignReadToByteBoundary();
|
nuclear@0
|
1302 }
|
nuclear@0
|
1303 return b;
|
nuclear@0
|
1304 }
|
nuclear@0
|
1305 template <>
|
nuclear@0
|
1306 inline bool BitStream::Read(unsigned char *&varString)
|
nuclear@0
|
1307 {
|
nuclear@0
|
1308 bool b;
|
nuclear@0
|
1309 uint16_t l;
|
nuclear@0
|
1310 b=Read(l);
|
nuclear@0
|
1311 if (b && l>0)
|
nuclear@0
|
1312 {
|
nuclear@0
|
1313 memcpy(varString, data + ( readOffset >> 3 ), l);
|
nuclear@0
|
1314 IgnoreBytes(l);
|
nuclear@0
|
1315 }
|
nuclear@0
|
1316 else
|
nuclear@0
|
1317 {
|
nuclear@0
|
1318 AlignReadToByteBoundary();
|
nuclear@0
|
1319 }
|
nuclear@0
|
1320 return b;
|
nuclear@0
|
1321 }
|
nuclear@0
|
1322
|
nuclear@0
|
1323 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
1324 /// \details If the written value differed from the value compared against in the write function,
|
nuclear@0
|
1325 /// var will be updated. Otherwise it will retain the current value.
|
nuclear@0
|
1326 /// ReadDelta is only valid from a previous call to WriteDelta
|
nuclear@0
|
1327 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1328 template <class templateType>
|
nuclear@0
|
1329 inline bool BitStream::ReadDelta(templateType &outTemplateVar)
|
nuclear@0
|
1330 {
|
nuclear@0
|
1331 bool dataWritten;
|
nuclear@0
|
1332 bool success;
|
nuclear@0
|
1333 success=Read(dataWritten);
|
nuclear@0
|
1334 if (dataWritten)
|
nuclear@0
|
1335 success=Read(outTemplateVar);
|
nuclear@0
|
1336 return success;
|
nuclear@0
|
1337 }
|
nuclear@0
|
1338
|
nuclear@0
|
1339 /// \brief Read a bool from a bitstream.
|
nuclear@0
|
1340 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1341 template <>
|
nuclear@0
|
1342 inline bool BitStream::ReadDelta(bool &outTemplateVar)
|
nuclear@0
|
1343 {
|
nuclear@0
|
1344 return Read(outTemplateVar);
|
nuclear@0
|
1345 }
|
nuclear@0
|
1346
|
nuclear@0
|
1347 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
1348 /// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
|
nuclear@0
|
1349 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
1350 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
1351 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
1352 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1353 template <class templateType>
|
nuclear@0
|
1354 inline bool BitStream::ReadCompressed(templateType &outTemplateVar)
|
nuclear@0
|
1355 {
|
nuclear@0
|
1356 #ifdef OVR_CC_MSVC
|
nuclear@0
|
1357 #pragma warning(disable:4127) // conditional expression is constant
|
nuclear@0
|
1358 #endif
|
nuclear@0
|
1359 if (sizeof(outTemplateVar)==1)
|
nuclear@0
|
1360 return ReadCompressed( ( unsigned char* ) &outTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
1361 else
|
nuclear@0
|
1362 {
|
nuclear@0
|
1363 #ifndef __BITSTREAM_NATIVE_END
|
nuclear@0
|
1364 if (DoEndianSwap())
|
nuclear@0
|
1365 {
|
nuclear@0
|
1366 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
1367 if (ReadCompressed( ( unsigned char* ) output, sizeof(templateType) * 8, true ))
|
nuclear@0
|
1368 {
|
nuclear@0
|
1369 ReverseBytes(output, (unsigned char*)&outTemplateVar, sizeof(templateType));
|
nuclear@0
|
1370 return true;
|
nuclear@0
|
1371 }
|
nuclear@0
|
1372 return false;
|
nuclear@0
|
1373 }
|
nuclear@0
|
1374 else
|
nuclear@0
|
1375 #endif
|
nuclear@0
|
1376 return ReadCompressed( ( unsigned char* ) & outTemplateVar, sizeof(templateType) * 8, true );
|
nuclear@0
|
1377 }
|
nuclear@0
|
1378 }
|
nuclear@0
|
1379
|
nuclear@0
|
1380 template <>
|
nuclear@0
|
1381 inline bool BitStream::ReadCompressed(bool &outTemplateVar)
|
nuclear@0
|
1382 {
|
nuclear@0
|
1383 return Read(outTemplateVar);
|
nuclear@0
|
1384 }
|
nuclear@0
|
1385
|
nuclear@0
|
1386 /// For values between -1 and 1
|
nuclear@0
|
1387 template <>
|
nuclear@0
|
1388 inline bool BitStream::ReadCompressed(float &outTemplateVar)
|
nuclear@0
|
1389 {
|
nuclear@0
|
1390 uint16_t compressedFloat;
|
nuclear@0
|
1391 if (Read(compressedFloat))
|
nuclear@0
|
1392 {
|
nuclear@0
|
1393 outTemplateVar = ((float)compressedFloat / 32767.5f - 1.0f);
|
nuclear@0
|
1394 return true;
|
nuclear@0
|
1395 }
|
nuclear@0
|
1396 return false;
|
nuclear@0
|
1397 }
|
nuclear@0
|
1398
|
nuclear@0
|
1399 /// For values between -1 and 1
|
nuclear@0
|
1400 template <>
|
nuclear@0
|
1401 inline bool BitStream::ReadCompressed(double &outTemplateVar)
|
nuclear@0
|
1402 {
|
nuclear@0
|
1403 uint32_t compressedFloat;
|
nuclear@0
|
1404 if (Read(compressedFloat))
|
nuclear@0
|
1405 {
|
nuclear@0
|
1406 outTemplateVar = ((double)compressedFloat / 2147483648.0 - 1.0);
|
nuclear@0
|
1407 return true;
|
nuclear@0
|
1408 }
|
nuclear@0
|
1409 return false;
|
nuclear@0
|
1410 }
|
nuclear@0
|
1411
|
nuclear@0
|
1412 /// \brief Read any integral type from a bitstream.
|
nuclear@0
|
1413 /// \details If the written value differed from the value compared against in the write function,
|
nuclear@0
|
1414 /// var will be updated. Otherwise it will retain the current value.
|
nuclear@0
|
1415 /// the current value will be updated.
|
nuclear@0
|
1416 /// For floating point, this is lossy, using 2 bytes for a float and 4 for a double. The range must be between -1 and +1.
|
nuclear@0
|
1417 /// For non-floating point, this is lossless, but only has benefit if you use less than half the bits of the type
|
nuclear@0
|
1418 /// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
|
nuclear@0
|
1419 /// ReadCompressedDelta is only valid from a previous call to WriteDelta
|
nuclear@0
|
1420 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1421 template <class templateType>
|
nuclear@0
|
1422 inline bool BitStream::ReadCompressedDelta(templateType &outTemplateVar)
|
nuclear@0
|
1423 {
|
nuclear@0
|
1424 bool dataWritten;
|
nuclear@0
|
1425 bool success;
|
nuclear@0
|
1426 success=Read(dataWritten);
|
nuclear@0
|
1427 if (dataWritten)
|
nuclear@0
|
1428 success=ReadCompressed(outTemplateVar);
|
nuclear@0
|
1429 return success;
|
nuclear@0
|
1430 }
|
nuclear@0
|
1431
|
nuclear@0
|
1432 /// \brief Read a bool from a bitstream.
|
nuclear@0
|
1433 /// \param[in] outTemplateVar The value to read
|
nuclear@0
|
1434 template <>
|
nuclear@0
|
1435 inline bool BitStream::ReadCompressedDelta(bool &outTemplateVar)
|
nuclear@0
|
1436 {
|
nuclear@0
|
1437 return Read(outTemplateVar);
|
nuclear@0
|
1438 }
|
nuclear@0
|
1439
|
nuclear@0
|
1440 template <class destinationType, class sourceType >
|
nuclear@0
|
1441 void BitStream::WriteCasted( const sourceType &value )
|
nuclear@0
|
1442 {
|
nuclear@0
|
1443 destinationType val = (destinationType) value;
|
nuclear@0
|
1444 Write(val);
|
nuclear@0
|
1445 }
|
nuclear@0
|
1446
|
nuclear@0
|
1447 template <class templateType>
|
nuclear@0
|
1448 void BitStream::WriteBitsFromIntegerRange( const templateType value, const templateType minimum,const templateType maximum, bool allowOutsideRange )
|
nuclear@0
|
1449 {
|
nuclear@0
|
1450 int requiredBits=BYTES_TO_BITS(sizeof(templateType))-NumberOfLeadingZeroes(templateType(maximum-minimum));
|
nuclear@0
|
1451 WriteBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
|
nuclear@0
|
1452 }
|
nuclear@0
|
1453 template <class templateType>
|
nuclear@0
|
1454 void BitStream::WriteBitsFromIntegerRange( const templateType value, const templateType minimum,const templateType maximum, const int requiredBits, bool allowOutsideRange )
|
nuclear@0
|
1455 {
|
nuclear@0
|
1456 OVR_ASSERT(maximum>=minimum);
|
nuclear@0
|
1457 OVR_ASSERT(allowOutsideRange==true || (value>=minimum && value<=maximum));
|
nuclear@0
|
1458 if (allowOutsideRange)
|
nuclear@0
|
1459 {
|
nuclear@0
|
1460 if (value<minimum || value>maximum)
|
nuclear@0
|
1461 {
|
nuclear@0
|
1462 Write(true);
|
nuclear@0
|
1463 Write(value);
|
nuclear@0
|
1464 return;
|
nuclear@0
|
1465 }
|
nuclear@0
|
1466 Write(false);
|
nuclear@0
|
1467 }
|
nuclear@0
|
1468 templateType valueOffMin=value-minimum;
|
nuclear@0
|
1469 if (IsBigEndian()==true)
|
nuclear@0
|
1470 {
|
nuclear@0
|
1471 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
1472 ReverseBytes((unsigned char*)&valueOffMin, output, sizeof(templateType));
|
nuclear@0
|
1473 WriteBits(output,requiredBits);
|
nuclear@0
|
1474 }
|
nuclear@0
|
1475 else
|
nuclear@0
|
1476 {
|
nuclear@0
|
1477 WriteBits((unsigned char*) &valueOffMin,requiredBits);
|
nuclear@0
|
1478 }
|
nuclear@0
|
1479 }
|
nuclear@0
|
1480
|
nuclear@0
|
1481 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1482 void BitStream::WriteNormVector( templateType x, templateType y, templateType z )
|
nuclear@0
|
1483 {
|
nuclear@0
|
1484 #ifdef _DEBUG
|
nuclear@0
|
1485 OVR_ASSERT(x <= 1.01 && y <= 1.01 && z <= 1.01 && x >= -1.01 && y >= -1.01 && z >= -1.01);
|
nuclear@0
|
1486 #endif
|
nuclear@0
|
1487
|
nuclear@0
|
1488 WriteFloat16((float)x,-1.0f,1.0f);
|
nuclear@0
|
1489 WriteFloat16((float)y,-1.0f,1.0f);
|
nuclear@0
|
1490 WriteFloat16((float)z,-1.0f,1.0f);
|
nuclear@0
|
1491 }
|
nuclear@0
|
1492
|
nuclear@0
|
1493 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1494 void BitStream::WriteVector( templateType x, templateType y, templateType z )
|
nuclear@0
|
1495 {
|
nuclear@0
|
1496 templateType magnitude = sqrt(x * x + y * y + z * z);
|
nuclear@0
|
1497 Write((float)magnitude);
|
nuclear@0
|
1498 if (magnitude > 0.00001f)
|
nuclear@0
|
1499 {
|
nuclear@0
|
1500 WriteCompressed((float)(x/magnitude));
|
nuclear@0
|
1501 WriteCompressed((float)(y/magnitude));
|
nuclear@0
|
1502 WriteCompressed((float)(z/magnitude));
|
nuclear@0
|
1503 // Write((uint16_t)((x/magnitude+1.0f)*32767.5f));
|
nuclear@0
|
1504 // Write((uint16_t)((y/magnitude+1.0f)*32767.5f));
|
nuclear@0
|
1505 // Write((uint16_t)((z/magnitude+1.0f)*32767.5f));
|
nuclear@0
|
1506 }
|
nuclear@0
|
1507 }
|
nuclear@0
|
1508
|
nuclear@0
|
1509 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1510 void BitStream::WriteNormQuat( templateType w, templateType x, templateType y, templateType z)
|
nuclear@0
|
1511 {
|
nuclear@0
|
1512 Write((bool)(w<0.0));
|
nuclear@0
|
1513 Write((bool)(x<0.0));
|
nuclear@0
|
1514 Write((bool)(y<0.0));
|
nuclear@0
|
1515 Write((bool)(z<0.0));
|
nuclear@0
|
1516 Write((uint16_t)(fabs(x)*65535.0));
|
nuclear@0
|
1517 Write((uint16_t)(fabs(y)*65535.0));
|
nuclear@0
|
1518 Write((uint16_t)(fabs(z)*65535.0));
|
nuclear@0
|
1519 // Leave out w and calculate it on the target
|
nuclear@0
|
1520 }
|
nuclear@0
|
1521
|
nuclear@0
|
1522 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1523 void BitStream::WriteOrthMatrix(
|
nuclear@0
|
1524 templateType m00, templateType m01, templateType m02,
|
nuclear@0
|
1525 templateType m10, templateType m11, templateType m12,
|
nuclear@0
|
1526 templateType m20, templateType m21, templateType m22 )
|
nuclear@0
|
1527 {
|
nuclear@0
|
1528
|
nuclear@0
|
1529 double qw;
|
nuclear@0
|
1530 double qx;
|
nuclear@0
|
1531 double qy;
|
nuclear@0
|
1532 double qz;
|
nuclear@0
|
1533
|
nuclear@0
|
1534 // Convert matrix to quat
|
nuclear@0
|
1535 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
|
nuclear@0
|
1536 float sum;
|
nuclear@0
|
1537 sum = 1 + m00 + m11 + m22;
|
nuclear@0
|
1538 if (sum < 0.0f) sum=0.0f;
|
nuclear@0
|
1539 qw = sqrt( sum ) / 2;
|
nuclear@0
|
1540 sum = 1 + m00 - m11 - m22;
|
nuclear@0
|
1541 if (sum < 0.0f) sum=0.0f;
|
nuclear@0
|
1542 qx = sqrt( sum ) / 2;
|
nuclear@0
|
1543 sum = 1 - m00 + m11 - m22;
|
nuclear@0
|
1544 if (sum < 0.0f) sum=0.0f;
|
nuclear@0
|
1545 qy = sqrt( sum ) / 2;
|
nuclear@0
|
1546 sum = 1 - m00 - m11 + m22;
|
nuclear@0
|
1547 if (sum < 0.0f) sum=0.0f;
|
nuclear@0
|
1548 qz = sqrt( sum ) / 2;
|
nuclear@0
|
1549 if (qw < 0.0) qw=0.0;
|
nuclear@0
|
1550 if (qx < 0.0) qx=0.0;
|
nuclear@0
|
1551 if (qy < 0.0) qy=0.0;
|
nuclear@0
|
1552 if (qz < 0.0) qz=0.0;
|
nuclear@0
|
1553 #ifdef OVR_OS_WIN32
|
nuclear@0
|
1554 qx = _copysign( (double) qx, (double) (m21 - m12) );
|
nuclear@0
|
1555 qy = _copysign( (double) qy, (double) (m02 - m20) );
|
nuclear@0
|
1556 qz = _copysign( (double) qz, (double) (m10 - m01) );
|
nuclear@0
|
1557 #else
|
nuclear@0
|
1558 qx = copysign( (double) qx, (double) (m21 - m12) );
|
nuclear@0
|
1559 qy = copysign( (double) qy, (double) (m02 - m20) );
|
nuclear@0
|
1560 qz = copysign( (double) qz, (double) (m10 - m01) );
|
nuclear@0
|
1561 #endif
|
nuclear@0
|
1562
|
nuclear@0
|
1563 WriteNormQuat(qw,qx,qy,qz);
|
nuclear@0
|
1564 }
|
nuclear@0
|
1565
|
nuclear@0
|
1566 template <class serializationType, class sourceType >
|
nuclear@0
|
1567 bool BitStream::ReadCasted( sourceType &value )
|
nuclear@0
|
1568 {
|
nuclear@0
|
1569 serializationType val;
|
nuclear@0
|
1570 bool success = Read(val);
|
nuclear@0
|
1571 value=(sourceType) val;
|
nuclear@0
|
1572 return success;
|
nuclear@0
|
1573 }
|
nuclear@0
|
1574
|
nuclear@0
|
1575 template <class templateType>
|
nuclear@0
|
1576 bool BitStream::ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, bool allowOutsideRange )
|
nuclear@0
|
1577 {
|
nuclear@0
|
1578 int requiredBits=BYTES_TO_BITS(sizeof(templateType))-NumberOfLeadingZeroes(templateType(maximum-minimum));
|
nuclear@0
|
1579 return ReadBitsFromIntegerRange(value,minimum,maximum,requiredBits,allowOutsideRange);
|
nuclear@0
|
1580 }
|
nuclear@0
|
1581 template <class templateType>
|
nuclear@0
|
1582 bool BitStream::ReadBitsFromIntegerRange( templateType &value, const templateType minimum, const templateType maximum, const int requiredBits, bool allowOutsideRange )
|
nuclear@0
|
1583 {
|
nuclear@0
|
1584 OVR_ASSERT_AND_UNUSED(maximum>=minimum, maximum);
|
nuclear@0
|
1585 if (allowOutsideRange)
|
nuclear@0
|
1586 {
|
nuclear@0
|
1587 bool isOutsideRange;
|
nuclear@0
|
1588 Read(isOutsideRange);
|
nuclear@0
|
1589 if (isOutsideRange)
|
nuclear@0
|
1590 return Read(value);
|
nuclear@0
|
1591 }
|
nuclear@0
|
1592 unsigned char output[sizeof(templateType)];
|
nuclear@0
|
1593 memset(output,0,sizeof(output));
|
nuclear@0
|
1594 bool success = ReadBits(output,requiredBits);
|
nuclear@0
|
1595 if (success)
|
nuclear@0
|
1596 {
|
nuclear@0
|
1597 if (IsBigEndian()==true)
|
nuclear@0
|
1598 ReverseBytesInPlace(output,sizeof(output));
|
nuclear@0
|
1599 memcpy(&value,output,sizeof(output));
|
nuclear@0
|
1600
|
nuclear@0
|
1601 value+=minimum;
|
nuclear@0
|
1602 }
|
nuclear@0
|
1603
|
nuclear@0
|
1604 return success;
|
nuclear@0
|
1605 }
|
nuclear@0
|
1606
|
nuclear@0
|
1607 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1608 bool BitStream::ReadNormVector( templateType &x, templateType &y, templateType &z )
|
nuclear@0
|
1609 {
|
nuclear@0
|
1610 float xIn,yIn,zIn;
|
nuclear@0
|
1611 ReadFloat16(xIn,-1.0f,1.0f);
|
nuclear@0
|
1612 ReadFloat16(yIn,-1.0f,1.0f);
|
nuclear@0
|
1613 ReadFloat16(zIn,-1.0f,1.0f);
|
nuclear@0
|
1614 x=xIn;
|
nuclear@0
|
1615 y=yIn;
|
nuclear@0
|
1616 z=zIn;
|
nuclear@0
|
1617 return true;
|
nuclear@0
|
1618 }
|
nuclear@0
|
1619
|
nuclear@0
|
1620 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1621 bool BitStream::ReadVector( templateType &x, templateType &y, templateType &z )
|
nuclear@0
|
1622 {
|
nuclear@0
|
1623 float magnitude;
|
nuclear@0
|
1624 //uint16_t sx,sy,sz;
|
nuclear@0
|
1625 if (!Read(magnitude))
|
nuclear@0
|
1626 return false;
|
nuclear@0
|
1627 if (magnitude>0.00001f)
|
nuclear@0
|
1628 {
|
nuclear@0
|
1629 // Read(sx);
|
nuclear@0
|
1630 // Read(sy);
|
nuclear@0
|
1631 // if (!Read(sz))
|
nuclear@0
|
1632 // return false;
|
nuclear@0
|
1633 // x=((float)sx / 32767.5f - 1.0f) * magnitude;
|
nuclear@0
|
1634 // y=((float)sy / 32767.5f - 1.0f) * magnitude;
|
nuclear@0
|
1635 // z=((float)sz / 32767.5f - 1.0f) * magnitude;
|
nuclear@0
|
1636 float cx=0.0f,cy=0.0f,cz=0.0f;
|
nuclear@0
|
1637 ReadCompressed(cx);
|
nuclear@0
|
1638 ReadCompressed(cy);
|
nuclear@0
|
1639 if (!ReadCompressed(cz))
|
nuclear@0
|
1640 return false;
|
nuclear@0
|
1641 x=cx;
|
nuclear@0
|
1642 y=cy;
|
nuclear@0
|
1643 z=cz;
|
nuclear@0
|
1644 x*=magnitude;
|
nuclear@0
|
1645 y*=magnitude;
|
nuclear@0
|
1646 z*=magnitude;
|
nuclear@0
|
1647 }
|
nuclear@0
|
1648 else
|
nuclear@0
|
1649 {
|
nuclear@0
|
1650 x=0.0;
|
nuclear@0
|
1651 y=0.0;
|
nuclear@0
|
1652 z=0.0;
|
nuclear@0
|
1653 }
|
nuclear@0
|
1654 return true;
|
nuclear@0
|
1655 }
|
nuclear@0
|
1656
|
nuclear@0
|
1657 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1658 bool BitStream::ReadNormQuat( templateType &w, templateType &x, templateType &y, templateType &z)
|
nuclear@0
|
1659 {
|
nuclear@0
|
1660 bool cwNeg=false, cxNeg=false, cyNeg=false, czNeg=false;
|
nuclear@0
|
1661 uint16_t cx,cy,cz;
|
nuclear@0
|
1662 Read(cwNeg);
|
nuclear@0
|
1663 Read(cxNeg);
|
nuclear@0
|
1664 Read(cyNeg);
|
nuclear@0
|
1665 Read(czNeg);
|
nuclear@0
|
1666 Read(cx);
|
nuclear@0
|
1667 Read(cy);
|
nuclear@0
|
1668 if (!Read(cz))
|
nuclear@0
|
1669 return false;
|
nuclear@0
|
1670
|
nuclear@0
|
1671 // Calculate w from x,y,z
|
nuclear@0
|
1672 x=(templateType)(cx/65535.0);
|
nuclear@0
|
1673 y=(templateType)(cy/65535.0);
|
nuclear@0
|
1674 z=(templateType)(cz/65535.0);
|
nuclear@0
|
1675 if (cxNeg) x=-x;
|
nuclear@0
|
1676 if (cyNeg) y=-y;
|
nuclear@0
|
1677 if (czNeg) z=-z;
|
nuclear@0
|
1678 float difference = 1.0f - x*x - y*y - z*z;
|
nuclear@0
|
1679 if (difference < 0.0f)
|
nuclear@0
|
1680 difference=0.0f;
|
nuclear@0
|
1681 w = (templateType)(sqrt(difference));
|
nuclear@0
|
1682 if (cwNeg)
|
nuclear@0
|
1683 w=-w;
|
nuclear@0
|
1684
|
nuclear@0
|
1685 return true;
|
nuclear@0
|
1686 }
|
nuclear@0
|
1687
|
nuclear@0
|
1688 template <class templateType> // templateType for this function must be a float or double
|
nuclear@0
|
1689 bool BitStream::ReadOrthMatrix(
|
nuclear@0
|
1690 templateType &m00, templateType &m01, templateType &m02,
|
nuclear@0
|
1691 templateType &m10, templateType &m11, templateType &m12,
|
nuclear@0
|
1692 templateType &m20, templateType &m21, templateType &m22 )
|
nuclear@0
|
1693 {
|
nuclear@0
|
1694 float qw,qx,qy,qz;
|
nuclear@0
|
1695 if (!ReadNormQuat(qw,qx,qy,qz))
|
nuclear@0
|
1696 return false;
|
nuclear@0
|
1697
|
nuclear@0
|
1698 // Quat to orthogonal rotation matrix
|
nuclear@0
|
1699 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
|
nuclear@0
|
1700 double sqw = (double)qw*(double)qw;
|
nuclear@0
|
1701 double sqx = (double)qx*(double)qx;
|
nuclear@0
|
1702 double sqy = (double)qy*(double)qy;
|
nuclear@0
|
1703 double sqz = (double)qz*(double)qz;
|
nuclear@0
|
1704 m00 = (templateType)(sqx - sqy - sqz + sqw); // since sqw + sqx + sqy + sqz =1
|
nuclear@0
|
1705 m11 = (templateType)(-sqx + sqy - sqz + sqw);
|
nuclear@0
|
1706 m22 = (templateType)(-sqx - sqy + sqz + sqw);
|
nuclear@0
|
1707
|
nuclear@0
|
1708 double tmp1 = (double)qx*(double)qy;
|
nuclear@0
|
1709 double tmp2 = (double)qz*(double)qw;
|
nuclear@0
|
1710 m10 = (templateType)(2.0 * (tmp1 + tmp2));
|
nuclear@0
|
1711 m01 = (templateType)(2.0 * (tmp1 - tmp2));
|
nuclear@0
|
1712
|
nuclear@0
|
1713 tmp1 = (double)qx*(double)qz;
|
nuclear@0
|
1714 tmp2 = (double)qy*(double)qw;
|
nuclear@0
|
1715 m20 =(templateType)(2.0 * (tmp1 - tmp2));
|
nuclear@0
|
1716 m02 = (templateType)(2.0 * (tmp1 + tmp2));
|
nuclear@0
|
1717 tmp1 = (double)qy*(double)qz;
|
nuclear@0
|
1718 tmp2 = (double)qx*(double)qw;
|
nuclear@0
|
1719 m21 = (templateType)(2.0 * (tmp1 + tmp2));
|
nuclear@0
|
1720 m12 = (templateType)(2.0 * (tmp1 - tmp2));
|
nuclear@0
|
1721
|
nuclear@0
|
1722 return true;
|
nuclear@0
|
1723 }
|
nuclear@0
|
1724
|
nuclear@0
|
1725 template <class templateType>
|
nuclear@0
|
1726 BitStream& operator<<(BitStream& out, templateType& c)
|
nuclear@0
|
1727 {
|
nuclear@0
|
1728 out.Write(c);
|
nuclear@0
|
1729 return out;
|
nuclear@0
|
1730 }
|
nuclear@0
|
1731 template <class templateType>
|
nuclear@0
|
1732 BitStream& operator>>(BitStream& in, templateType& c)
|
nuclear@0
|
1733 {
|
nuclear@0
|
1734 bool success = in.Read(c);
|
nuclear@0
|
1735 (void)success;
|
nuclear@0
|
1736
|
nuclear@0
|
1737 OVR_ASSERT(success);
|
nuclear@0
|
1738 return in;
|
nuclear@0
|
1739 }
|
nuclear@0
|
1740
|
nuclear@0
|
1741
|
nuclear@0
|
1742 }} // OVR::Net
|
nuclear@0
|
1743
|
nuclear@0
|
1744 #endif
|