ovr_sdk

annotate LibOVR/Src/Net/OVR_BitStream.h @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
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 &currentValue, 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 &currentValue, 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 &currentValue);
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 &currentValue, const templateType &lastValue);
nuclear@0 268
nuclear@0 269 /// \brief Save as WriteCompressedDelta(const templateType &currentValue, const templateType &lastValue) when we have an unknown second parameter
nuclear@0 270 template <class templateType>
nuclear@0 271 void WriteCompressedDelta(const templateType &currentValue);
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 &currentValue, 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 &currentValue, 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 &currentValue);
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 &currentValue, 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 &currentValue, 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 &currentValue)
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 &currentValue, 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 &currentValue, 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 &currentValue, 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 &currentValue)
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 &currentValue)
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