1 /// \file BitStream_NoTemplate.h
2 /// \brief This class allows you to write and read native types as a string of bits.  BitStream is used extensively throughout RakNet and is designed to be used by users as well.
3 ///
4 /// This file is part of RakNet Copyright 2003 Jenkins Software LLC
5 ///
6 /// Raknet is available under the terms of the GPLv3 license, see /usr/local/share/licenses/raknet-3.9.2_10,1/GPLv3.
7 
8 
9 #if defined(_MSC_VER) && _MSC_VER < 1299 // VC6 doesn't support template specialization
10 
11 #ifndef __BITSTREAM_H
12 #define __BITSTREAM_H
13 
14 #include "RakMemoryOverride.h"
15 #include "RakNetDefines.h"
16 #include "Export.h"
17 #include "RakNetTypes.h"
18 #include "RakAssert.h"
19 #include "RakString.h"
20 
21 
22 
23 #include <cmath>
24 
25 #include <float.h>
26 
27 #ifdef _MSC_VER
28 #pragma warning( push )
29 #endif
30 
31 /// Arbitrary size, just picking something likely to be larger than most packets
32 #define BITSTREAM_STACK_ALLOCATION_SIZE 256
33 
34 /// The namespace RakNet is not consistently used.  It's only purpose is to avoid compiler errors for classes whose names are very common.
35 /// For the most part I've tried to avoid this simply by using names very likely to be unique for my classes.
36 namespace RakNet
37 {
38 	/// This class allows you to write and read native types as a string of bits.  BitStream is used extensively throughout RakNet and is designed to be used by users as well.
39 	/// \sa BitStreamSample.txt
40 	class RAK_DLL_EXPORT BitStream
41 	{
42 
43 	public:
44 		/// Default Constructor
45 		BitStream();
46 
47 		/// \brief Create the bitstream, with some number of bytes to immediately allocate.
48 		/// \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.
49 		/// In that case all it does is save you one or more realloc calls.
50 		/// \param[in] initialBytesToAllocate the number of bytes to pre-allocate.
51 		BitStream( const unsigned int initialBytesToAllocate );
52 
53 		/// \brief Initialize the BitStream, immediately setting the data it contains to a predefined pointer.
54 		/// \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.
55 		/// You shouldn't call Write functions with \a _copyData as false, as this will write to unallocated memory
56 		/// 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:
57 		/// \code
58 		/// RakNet::BitStream bs(packet->data, packet->length, false);
59 		/// \endcode
60 		/// \param[in] _data An array of bytes.
61 		/// \param[in] lengthInBytes Size of the \a _data.
62 		/// \param[in] _copyData true or false to make a copy of \a _data or not.
63 		BitStream( unsigned char* _data, const unsigned int lengthInBytes, bool _copyData );
64 
65 		// Destructor
66 		~BitStream();
67 
68 		/// Resets the bitstream for reuse.
69 		void Reset( void );
70 
71 		/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.  Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
72 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
73 		/// \param[in] var The value to write
74 		/// \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.
Serialize(bool writeToBitstream,bool & var)75 		bool Serialize(bool writeToBitstream, bool &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,unsigned char & var)76 		bool Serialize(bool writeToBitstream, unsigned char &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,char & var)77 		bool Serialize(bool writeToBitstream, char &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,unsigned short & var)78 		bool Serialize(bool writeToBitstream, unsigned short &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,short & var)79 		bool Serialize(bool writeToBitstream, short &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,unsigned int & var)80 		bool Serialize(bool writeToBitstream, unsigned int &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,int & var)81 		bool Serialize(bool writeToBitstream, int &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,unsigned long & var)82 		bool Serialize(bool writeToBitstream, unsigned long &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,long & var)83 		bool Serialize(bool writeToBitstream, long &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,long long & var)84 		bool Serialize(bool writeToBitstream, long long &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,unsigned long long & var)85 		bool Serialize(bool writeToBitstream, unsigned long long &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,float & var)86 		bool Serialize(bool writeToBitstream, float &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,double & var)87 		bool Serialize(bool writeToBitstream, double &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,long double & var)88 		bool Serialize(bool writeToBitstream, long double &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,char * var)89 		bool Serialize(bool writeToBitstream, char* var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,unsigned char * var)90 		bool Serialize(bool writeToBitstream, unsigned char* var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,RakNet::RakString & var)91 		bool Serialize(bool writeToBitstream, RakNet::RakString &var){if (writeToBitstream) Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,uint24_t & var)92 		bool Serialize(bool writeToBitstream, uint24_t &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
Serialize(bool writeToBitstream,RakNetGUID & var)93 		bool Serialize(bool writeToBitstream, RakNetGUID &var){if (writeToBitstream)Write(var);else return Read(var); return true;}
94 
95 		/// \brief Serialize a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
96 		/// \param[in] f The float to write
97 		/// \param[in] floatMin Predetermined minimum value of f
98 		/// \param[in] floatMax Predetermined maximum value of f
99 		bool SerializeFloat16(bool writeToBitstream, float &f, float floatMin, float floatMax);
100 
101 		/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.  If the current value is different from the last value
102 		/// the current value will be written.  Otherwise, a single bit will be written
103 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
104 		/// \param[in] currentValue The current value to write
105 		/// \param[in] lastValue The last value to compare against.  Only used if \a writeToBitstream is true.
106 		/// \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.
SerializeDelta(bool writeToBitstream,bool & currentValue,bool lastValue)107 		bool SerializeDelta(bool writeToBitstream, bool &currentValue, bool lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned char & currentValue,unsigned char lastValue)108 		bool SerializeDelta(bool writeToBitstream, unsigned char &currentValue, unsigned char lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,char & currentValue,char lastValue)109 		bool SerializeDelta(bool writeToBitstream, char &currentValue, char lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned short & currentValue,unsigned short lastValue)110 		bool SerializeDelta(bool writeToBitstream, unsigned short &currentValue, unsigned short lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,short & currentValue,short lastValue)111 		bool SerializeDelta(bool writeToBitstream, short &currentValue, short lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned int & currentValue,unsigned int lastValue)112 		bool SerializeDelta(bool writeToBitstream, unsigned int &currentValue, unsigned int lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,int & currentValue,int lastValue)113 		bool SerializeDelta(bool writeToBitstream, int &currentValue, int lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned long & currentValue,unsigned long lastValue)114 		bool SerializeDelta(bool writeToBitstream, unsigned long &currentValue, unsigned long lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,long long & currentValue,long long lastValue)115 		bool SerializeDelta(bool writeToBitstream, long long &currentValue, long long lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned long long & currentValue,unsigned long long lastValue)116 		bool SerializeDelta(bool writeToBitstream, unsigned long long &currentValue, unsigned long long lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,float & currentValue,float lastValue)117 		bool SerializeDelta(bool writeToBitstream, float &currentValue, float lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,double & currentValue,double lastValue)118 		bool SerializeDelta(bool writeToBitstream, double &currentValue, double lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,long double & currentValue,long double lastValue)119 		bool SerializeDelta(bool writeToBitstream, long double &currentValue, long double lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,char * currentValue,const char * lastValue)120 		bool SerializeDelta(bool writeToBitstream, char* currentValue, const char* lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned char * currentValue,const unsigned char * lastValue)121 		bool SerializeDelta(bool writeToBitstream, unsigned char* currentValue, const unsigned char* lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,RakNet::RakString & currentValue,const RakNet::RakString & lastValue)122 		bool SerializeDelta(bool writeToBitstream, RakNet::RakString &currentValue, const RakNet::RakString &lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,uint24_t & currentValue,const uint24_t lastValue)123 		bool SerializeDelta(bool writeToBitstream, uint24_t &currentValue, const uint24_t lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,RakNetGUID & currentValue,const RakNetGUID lastValue)124 		bool SerializeDelta(bool writeToBitstream, RakNetGUID &currentValue, const RakNetGUID lastValue){if (writeToBitstream) WriteDelta(currentValue, lastValue); else return ReadDelta(currentValue);return true;}
125 
126 		/// \brief Bidirectional version of SerializeDelta when you don't know what the last value is, or there is no last value.
127 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
128 		/// \param[in] currentValue The current value to write
129 		/// \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.
SerializeDelta(bool writeToBitstream,bool & currentValue)130 		bool SerializeDelta(bool writeToBitstream, bool &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned char & currentValue)131 		bool SerializeDelta(bool writeToBitstream, unsigned char &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,char & currentValue)132 		bool SerializeDelta(bool writeToBitstream, char &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned short & currentValue)133 		bool SerializeDelta(bool writeToBitstream, unsigned short &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,short & currentValue)134 		bool SerializeDelta(bool writeToBitstream, short &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned int & currentValue)135 		bool SerializeDelta(bool writeToBitstream, unsigned int &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,int & currentValue)136 		bool SerializeDelta(bool writeToBitstream, int &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned long & currentValue)137 		bool SerializeDelta(bool writeToBitstream, unsigned long &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,long long & currentValue)138 		bool SerializeDelta(bool writeToBitstream, long long &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned long long & currentValue)139 		bool SerializeDelta(bool writeToBitstream, unsigned long long &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,float & currentValue)140 		bool SerializeDelta(bool writeToBitstream, float &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,double & currentValue)141 		bool SerializeDelta(bool writeToBitstream, double &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,long double & currentValue)142 		bool SerializeDelta(bool writeToBitstream, long double &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,char * currentValue)143 		bool SerializeDelta(bool writeToBitstream, char* currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,unsigned char * currentValue)144 		bool SerializeDelta(bool writeToBitstream, unsigned char* currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,RakNet::RakString & currentValue)145 		bool SerializeDelta(bool writeToBitstream, RakNet::RakString &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,uint24_t & currentValue)146 		bool SerializeDelta(bool writeToBitstream, uint24_t &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
SerializeDelta(bool writeToBitstream,RakNetGUID & currentValue)147 		bool SerializeDelta(bool writeToBitstream, RakNetGUID &currentValue){if (writeToBitstream) WriteDelta(currentValue); else return ReadDelta(currentValue);return true;}
148 
149 		/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.  Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
150 		/// \details If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
151 		/// 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.
152 		/// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type
153 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
154 		/// \param[in] var The value to write
155 		/// \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.
SerializeCompressed(bool writeToBitstream,bool & var)156 		bool SerializeCompressed(bool writeToBitstream, bool &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,unsigned char & var)157 		bool SerializeCompressed(bool writeToBitstream, unsigned char &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,char & var)158 		bool SerializeCompressed(bool writeToBitstream, char &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,unsigned short & var)159 		bool SerializeCompressed(bool writeToBitstream, unsigned short &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,short & var)160 		bool SerializeCompressed(bool writeToBitstream, short &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,unsigned int & var)161 		bool SerializeCompressed(bool writeToBitstream, unsigned int &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,int & var)162 		bool SerializeCompressed(bool writeToBitstream, int &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,unsigned long & var)163 		bool SerializeCompressed(bool writeToBitstream, unsigned long &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,long & var)164 		bool SerializeCompressed(bool writeToBitstream, long &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,long long & var)165 		bool SerializeCompressed(bool writeToBitstream, long long &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,unsigned long long & var)166 		bool SerializeCompressed(bool writeToBitstream, unsigned long long &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,float & var)167 		bool SerializeCompressed(bool writeToBitstream, float &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,double & var)168 		bool SerializeCompressed(bool writeToBitstream, double &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,long double & var)169 		bool SerializeCompressed(bool writeToBitstream, long double &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,char * var)170 		bool SerializeCompressed(bool writeToBitstream, char* var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,unsigned char * var)171 		bool SerializeCompressed(bool writeToBitstream, unsigned char* var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,RakNet::RakString & var)172 		bool SerializeCompressed(bool writeToBitstream, RakNet::RakString &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,uint24_t & var)173 		bool SerializeCompressed(bool writeToBitstream, uint24_t &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
SerializeCompressed(bool writeToBitstream,RakNetGUID & var)174 		bool SerializeCompressed(bool writeToBitstream, RakNetGUID &var){if (writeToBitstream)WriteCompressed(var);else return ReadCompressed(var); return true;}
175 
176 		/// \brief Bidirectional serialize/deserialize any integral type to/from a bitstream.
177 		/// \details If the current value is different from the last value the current value will be written.
178 		/// Otherwise, a single bit will be written
179 		/// 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.
180 		/// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type
181 		/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
182 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
183 		/// \param[in] currentValue The current value to write
184 		/// \param[in] lastValue The last value to compare against.  Only used if \a writeToBitstream is true.
185 		/// \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.
SerializeCompressedDelta(bool writeToBitstream,bool & currentValue,bool lastValue)186 		bool SerializeCompressedDelta(bool writeToBitstream, bool &currentValue, bool lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned char & currentValue,unsigned char lastValue)187 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned char &currentValue, unsigned char lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,char & currentValue,char lastValue)188 		bool SerializeCompressedDelta(bool writeToBitstream, char &currentValue, char lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned short & currentValue,unsigned short lastValue)189 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned short &currentValue, unsigned short lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,short & currentValue,short lastValue)190 		bool SerializeCompressedDelta(bool writeToBitstream, short &currentValue, short lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned int & currentValue,unsigned int lastValue)191 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned int &currentValue, unsigned int lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,int & currentValue,int lastValue)192 		bool SerializeCompressedDelta(bool writeToBitstream, int &currentValue, int lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned long & currentValue,unsigned long lastValue)193 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned long &currentValue, unsigned long lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,long long & currentValue,long long lastValue)194 		bool SerializeCompressedDelta(bool writeToBitstream, long long &currentValue, long long lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned long long & currentValue,unsigned long long lastValue)195 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned long long &currentValue, unsigned long long lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,float & currentValue,float lastValue)196 		bool SerializeCompressedDelta(bool writeToBitstream, float &currentValue, float lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,double & currentValue,double lastValue)197 		bool SerializeCompressedDelta(bool writeToBitstream, double &currentValue, double lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,long double & currentValue,long double lastValue)198 		bool SerializeCompressedDelta(bool writeToBitstream, long double &currentValue, long double lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,char * currentValue,const char * lastValue)199 		bool SerializeCompressedDelta(bool writeToBitstream, char*currentValue, const char* lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned char * currentValue,const unsigned char * lastValue)200 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned char* currentValue, const unsigned char* lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,RakNet::RakString & currentValue,const RakNet::RakString & lastValue)201 		bool SerializeCompressedDelta(bool writeToBitstream, RakNet::RakString &currentValue, const RakNet::RakString &lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,uint24_t & currentValue,uint24_t & lastValue)202 		bool SerializeCompressedDelta(bool writeToBitstream, uint24_t &currentValue, uint24_t &lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
SerializeCompressedDelta(bool writeToBitstream,RakNetGUID & currentValue,RakNetGUID & lastValue)203 		bool SerializeCompressedDelta(bool writeToBitstream, RakNetGUID &currentValue, RakNetGUID &lastValue){if (writeToBitstream) WriteCompressedDelta(currentValue, lastValue); else return ReadCompressedDelta(currentValue);return true;}
204 
205 		/// Save as SerializeCompressedDelta(templateType &currentValue, templateType lastValue) when we have an unknown second parameter
SerializeCompressedDelta(bool writeToBitstream,bool & var)206 		bool SerializeCompressedDelta(bool writeToBitstream, bool &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned char & var)207 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned char &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,char & var)208 		bool SerializeCompressedDelta(bool writeToBitstream, char &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned short & var)209 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned short &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,short & var)210 		bool SerializeCompressedDelta(bool writeToBitstream, short &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned int & var)211 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned int &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,int & var)212 		bool SerializeCompressedDelta(bool writeToBitstream, int &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned long & var)213 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned long &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,long & var)214 		bool SerializeCompressedDelta(bool writeToBitstream, long &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,long long & var)215 		bool SerializeCompressedDelta(bool writeToBitstream, long long &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned long long & var)216 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned long long &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,float & var)217 		bool SerializeCompressedDelta(bool writeToBitstream, float &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,double & var)218 		bool SerializeCompressedDelta(bool writeToBitstream, double &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,long double & var)219 		bool SerializeCompressedDelta(bool writeToBitstream, long double &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,char * var)220 		bool SerializeCompressedDelta(bool writeToBitstream, char* var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,unsigned char * var)221 		bool SerializeCompressedDelta(bool writeToBitstream, unsigned char* var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,RakNet::RakString & var)222 		bool SerializeCompressedDelta(bool writeToBitstream, RakNet::RakString &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,uint24_t & var)223 		bool SerializeCompressedDelta(bool writeToBitstream, uint24_t &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
SerializeCompressedDelta(bool writeToBitstream,RakNetGUID & var)224 		bool SerializeCompressedDelta(bool writeToBitstream, RakNetGUID &var){if (writeToBitstream)WriteCompressedDelta(var);else return ReadCompressedDelta(var); return true;}
225 
226 		/// \brief Bidirectional serialize/deserialize an array or casted stream or raw data.  This does NOT do endian swapping.
227 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
228 		/// \param[in] input a byte buffer
229 		/// \param[in] numberOfBytes the size of \a input in bytes
230 		/// \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.
231 		bool Serialize(bool writeToBitstream,  char* input, const int numberOfBytes );
232 
233 		/// \brief Bidirectional serialize/deserialize a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.
234 		/// \details Will further compress y or z axis aligned vectors.
235 		/// Accurate to 1/32767.5.
236 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
237 		/// \param[in] x x
238 		/// \param[in] y y
239 		/// \param[in] z z
240 		/// \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.
SerializeNormVector(bool writeToBitstream,float & x,float & y,float z)241 		bool SerializeNormVector(bool writeToBitstream,  float &x, float &y, float z ){if (writeToBitstream) WriteNormVector(x,y,z); else return ReadNormVector(x,y,z); return true;}
SerializeNormVector(bool writeToBitstream,double & x,double & y,double & z)242 		bool SerializeNormVector(bool writeToBitstream,  double &x, double &y, double &z ){if (writeToBitstream) WriteNormVector(x,y,z); else return ReadNormVector(x,y,z); return true;}
243 
244 		/// \brief Bidirectional serialize/deserialize a vector, using 10 bytes instead of 12.
245 		/// \details Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important.
246 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
247 		/// \param[in] x x
248 		/// \param[in] y y
249 		/// \param[in] z z
250 		/// \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.
SerializeVector(bool writeToBitstream,float & x,float & y,float & z)251 		bool SerializeVector(bool writeToBitstream,  float &x, float &y, float &z ){if (writeToBitstream) WriteVector(x,y,z); else	return ReadVector(x,y,z); return true;}
SerializeVector(bool writeToBitstream,double & x,double & y,double & z)252 		bool SerializeVector(bool writeToBitstream,  double &x, double &y, double &z ){if (writeToBitstream) WriteVector(x,y,z); else	return ReadVector(x,y,z); return true;}
253 
254 		/// \brief Bidirectional serialize/deserialize a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes.  Slightly lossy.
255 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
256 		/// \param[in] w w
257 		/// \param[in] x x
258 		/// \param[in] y y
259 		/// \param[in] z z
260 		/// \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.
SerializeNormQuat(bool writeToBitstream,float & w,float & x,float & y,float & z)261 		bool SerializeNormQuat(bool writeToBitstream,  float &w, float &x, float &y, float &z){if (writeToBitstream) WriteNormQuat(w,x,y,z); else return ReadNormQuat(w,x,y,z); return true;}
SerializeNormQuat(bool writeToBitstream,double & w,double & x,double & y,double & z)262 		bool SerializeNormQuat(bool writeToBitstream,  double &w, double &x, double &y, double &z){if (writeToBitstream) WriteNormQuat(w,x,y,z); else return ReadNormQuat(w,x,y,z); return true;}
263 
264 		/// \brief Bidirectional serialize/deserialize an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each
265 		/// for 6 bytes instead of 36
266 		/// Lossy, although the result is renormalized
SerializeOrthMatrix(bool writeToBitstream,float & m00,float & m01,float & m02,float & m10,float & m11,float & m12,float & m20,float & m21,float & m22)267 		bool SerializeOrthMatrix(
268 		bool writeToBitstream,
269 		float &m00, float &m01, float &m02,
270 		float &m10, float &m11, float &m12,
271 		float &m20, float &m21, float &m22 ){if (writeToBitstream) WriteOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22); else return ReadOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22); return true;}
SerializeOrthMatrix(bool writeToBitstream,double & m00,double & m01,double & m02,double & m10,double & m11,double & m12,double & m20,double & m21,double & m22)272 		bool SerializeOrthMatrix(
273 		bool writeToBitstream,
274 		double &m00, double &m01, double &m02,
275 		double &m10, double &m11, double &m12,
276 		double &m20, double &m21, double &m22 ){if (writeToBitstream) WriteOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22); else return ReadOrthMatrix(m00,m01,m02,m10,m11,m12,m20,m21,m22); return true;}
277 
278 		/// \brief Bidirectional serialize/deserialize numberToSerialize bits to/from the input.
279 		/// \details Right aligned data means in the case of a partial byte, the bits are aligned
280 		/// from the right (bit 0) rather than the left (as in the normal
281 		/// internal representation) You would set this to true when
282 		/// writing user data, and false when copying bitstream data, such
283 		/// as writing one bitstream to another
284 		/// \param[in] writeToBitstream true to write from your data to this bitstream.  False to read from this bitstream and write to your data
285 		/// \param[in] input The data
286 		/// \param[in] numberOfBitsToSerialize The number of bits to write
287 		/// \param[in] rightAlignedBits if true data will be right aligned
288 		/// \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.
289 		bool SerializeBits(bool writeToBitstream, unsigned char* input, int numberOfBitsToSerialize, const bool rightAlignedBits = true );
290 
291 		/// Write any integral type to a bitstream.  Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
292 		/// \param[in] var The value to write
Write(bool var)293 		void Write(bool var){if ( var ) Write1(); else Write0();}
Write(unsigned char var)294 		void Write(unsigned char var){WriteBits( ( unsigned char* ) & var, sizeof( unsigned char ) * 8, true );}
Write(char var)295 		void Write(char var){WriteBits( ( unsigned char* ) & var, sizeof( char ) * 8, true );}
Write(unsigned short var)296 		void Write(unsigned short var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned short)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned short)); WriteBits( ( unsigned char* ) output, sizeof(unsigned short) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(unsigned short) * 8, true );}
Write(short var)297 		void Write(short var) {if (DoEndianSwap()){unsigned char output[sizeof(short)]; ReverseBytes((unsigned char*)&var, output, sizeof(short)); WriteBits( ( unsigned char* ) output, sizeof(short) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(short) * 8, true );}
Write(unsigned int var)298 		void Write(unsigned int var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned int)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned int)); WriteBits( ( unsigned char* ) output, sizeof(unsigned int) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(unsigned int) * 8, true );}
Write(int var)299 		void Write(int var) {if (DoEndianSwap()){unsigned char output[sizeof(int)]; ReverseBytes((unsigned char*)&var, output, sizeof(int)); WriteBits( ( unsigned char* ) output, sizeof(int) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(int) * 8, true );}
Write(unsigned long var)300 		void Write(unsigned long var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned long)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned long)); WriteBits( ( unsigned char* ) output, sizeof(unsigned long) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(unsigned long) * 8, true );}
Write(long var)301 		void Write(long var) {if (DoEndianSwap()){unsigned char output[sizeof(long)]; ReverseBytes((unsigned char*)&var, output, sizeof(long)); WriteBits( ( unsigned char* ) output, sizeof(long) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(long) * 8, true );}
Write(long long var)302 		void Write(long long var) {if (DoEndianSwap()){unsigned char output[sizeof(long long)]; ReverseBytes((unsigned char*)&var, output, sizeof(long long)); WriteBits( ( unsigned char* ) output, sizeof(long long) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(long long) * 8, true );}
Write(unsigned long long var)303 		void Write(unsigned long long var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned long long)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned long long)); WriteBits( ( unsigned char* ) output, sizeof(unsigned long long) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(unsigned long long) * 8, true );}
Write(float var)304 		void Write(float var) {if (DoEndianSwap()){unsigned char output[sizeof(float)]; ReverseBytes((unsigned char*)&var, output, sizeof(float)); WriteBits( ( unsigned char* ) output, sizeof(float) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(float) * 8, true );}
Write(double var)305 		void Write(double var) {if (DoEndianSwap()){unsigned char output[sizeof(double)]; ReverseBytes((unsigned char*)&var, output, sizeof(double)); WriteBits( ( unsigned char* ) output, sizeof(double) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(double) * 8, true );}
Write(long double var)306 		void Write(long double var) {if (DoEndianSwap()){unsigned char output[sizeof(long double)]; ReverseBytes((unsigned char*)&var, output, sizeof(long double)); WriteBits( ( unsigned char* ) output, sizeof(long double) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(long double) * 8, true );}
Write(const char * var)307 		void Write(const char* var) {RakString::Serialize(var, this);}
Write(const unsigned char * var)308 		void Write(const unsigned char* var) {RakString::Serialize((const char*) var, this);}
Write(const RakNet::RakString & var)309 		void Write(const RakNet::RakString &var) {var.Serialize(this);}
310 		void Write(const uint24_t &var);
Write(const RakNetGUID & var)311 		void Write(const RakNetGUID &var) {if (DoEndianSwap()){unsigned char output[sizeof(uint64_t)]; ReverseBytes((unsigned char*)&var, output, sizeof(uint64_t)); WriteBits( ( unsigned char* ) output, sizeof(uint64_t) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(uint64_t) * 8, true );}
Write(void * var)312 		void Write(void* var) {if (DoEndianSwap()){unsigned char output[sizeof(void*)]; ReverseBytes((unsigned char*)&var, output, sizeof(void*)); WriteBits( ( unsigned char* ) output, sizeof(void*) * 8, true );return;} WriteBits( ( unsigned char* ) & var, sizeof(void*) * 8, true );}
Write(SystemAddress var)313 		void Write(SystemAddress var){WriteBits( ( unsigned char* ) & var.binaryAddress, sizeof(var.binaryAddress) * 8, true ); Write(var.port);}
Write(NetworkID var)314 		void Write(NetworkID var){if (NetworkID::IsPeerToPeerMode()) Write(var.systemAddress); Write(var.localSystemAddress);}
315 
316 		/// \brief Write any integral type to a bitstream.
317 		/// \details If the current value is different from the last value
318 		/// the current value will be written.  Otherwise, a single bit will be written
319 		/// \param[in] currentValue The current value to write
320 		/// \param[in] lastValue The last value to compare against
WriteDelta(bool currentValue,bool lastValue)321 		void WriteDelta(bool currentValue, bool lastValue){
322 			#pragma warning(disable:4100)   // warning C4100: 'peer' : unreferenced formal parameter
323 			Write(currentValue);
324 		}
WriteDelta(unsigned char currentValue,unsigned char lastValue)325 		void WriteDelta(unsigned char currentValue, unsigned char lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(char currentValue,char lastValue)326 		void WriteDelta(char currentValue, char lastValue){if (currentValue==lastValue)	{Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(unsigned short currentValue,unsigned short lastValue)327 		void WriteDelta(unsigned short currentValue, unsigned short lastValue){if (currentValue==lastValue)	{Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(short currentValue,short lastValue)328 		void WriteDelta(short currentValue, short lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(unsigned int currentValue,unsigned int lastValue)329 		void WriteDelta(unsigned int currentValue, unsigned int lastValue){if (currentValue==lastValue)	{Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(int currentValue,int lastValue)330 		void WriteDelta(int currentValue, int lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(unsigned long currentValue,unsigned long lastValue)331 		void WriteDelta(unsigned long currentValue, unsigned long lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(long currentValue,long lastValue)332 		void WriteDelta(long currentValue, long lastValue){if (currentValue==lastValue)	{Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(long long currentValue,long long lastValue)333 		void WriteDelta(long long currentValue, long long lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(unsigned long long currentValue,unsigned long long lastValue)334 		void WriteDelta(unsigned long long currentValue, unsigned long long lastValue){if (currentValue==lastValue)	{Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(float currentValue,float lastValue)335 		void WriteDelta(float currentValue, float lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(double currentValue,double lastValue)336 		void WriteDelta(double currentValue, double lastValue){if (currentValue==lastValue)	{Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(long double currentValue,long double lastValue)337 		void WriteDelta(long double currentValue, long double lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(const char * currentValue,const char * lastValue)338 		void WriteDelta(const char* currentValue, const char* lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(const unsigned char * currentValue,const unsigned char * lastValue)339 		void WriteDelta(const unsigned char* currentValue, const unsigned char* lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(char * currentValue,char * lastValue)340 		void WriteDelta(char* currentValue, char* lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(unsigned char * currentValue,unsigned char * lastValue)341 		void WriteDelta(unsigned char* currentValue, unsigned char* lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(const RakNet::RakString & currentValue,const RakNet::RakString & lastValue)342 		void WriteDelta(const RakNet::RakString &currentValue, const RakNet::RakString &lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(const uint24_t & currentValue,const uint24_t & lastValue)343 		void WriteDelta(const uint24_t &currentValue, const uint24_t &lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(const RakNetGUID & currentValue,const RakNetGUID & lastValue)344 		void WriteDelta(const RakNetGUID &currentValue, const RakNetGUID &lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(SystemAddress currentValue,SystemAddress lastValue)345 		void WriteDelta(SystemAddress currentValue, SystemAddress lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
WriteDelta(NetworkID currentValue,NetworkID lastValue)346 		void WriteDelta(NetworkID currentValue, NetworkID lastValue){if (currentValue==lastValue) {Write(false);} else {Write(true); Write(currentValue);}}
347 
348 		/// WriteDelta when you don't know what the last value is, or there is no last value.
349 		/// \param[in] currentValue The current value to write
WriteDelta(bool var)350 		void WriteDelta(bool var){Write(var);}
WriteDelta(unsigned char var)351 		void WriteDelta(unsigned char var){Write(true); Write(var);}
WriteDelta(char var)352 		void WriteDelta(char var){Write(true); Write(var);}
WriteDelta(unsigned short var)353 		void WriteDelta(unsigned short var){Write(true); Write(var);}
WriteDelta(short var)354 		void WriteDelta(short var){Write(true); Write(var);}
WriteDelta(unsigned int var)355 		void WriteDelta(unsigned int var){Write(true); Write(var);}
WriteDelta(int var)356 		void WriteDelta(int var){Write(true); Write(var);}
WriteDelta(unsigned long var)357 		void WriteDelta(unsigned long var){Write(true); Write(var);}
WriteDelta(long var)358 		void WriteDelta(long var){Write(true); Write(var);}
WriteDelta(long long var)359 		void WriteDelta(long long var){Write(true); Write(var);}
WriteDelta(unsigned long long var)360 		void WriteDelta(unsigned long long var){Write(true); Write(var);}
WriteDelta(float var)361 		void WriteDelta(float var){Write(true); Write(var);}
WriteDelta(double var)362 		void WriteDelta(double var){Write(true); Write(var);}
WriteDelta(long double var)363 		void WriteDelta(long double var){Write(true); Write(var);}
WriteDelta(const char * var)364 		void WriteDelta(const char* var){Write(true); Write(var);}
WriteDelta(const unsigned char * var)365 		void WriteDelta(const unsigned char* var){Write(true); Write(var);}
WriteDelta(char * var)366 		void WriteDelta(char* var){Write(true); Write(var);}
WriteDelta(unsigned char * var)367 		void WriteDelta(unsigned char* var){Write(true); Write(var);}
WriteDelta(const RakNet::RakString & var)368 		void WriteDelta(const RakNet::RakString &var){Write(true); Write(var);}
WriteDelta(const uint24_t & var)369 		void WriteDelta(const uint24_t &var){Write(true); Write(var);}
WriteDelta(const RakNetGUID & var)370 		void WriteDelta(const RakNetGUID &var){Write(true); Write(var);}
WriteDelta(SystemAddress var)371 		void WriteDelta(SystemAddress var){Write(true); Write(var);}
WriteDelta(NetworkID var)372 		void WriteDelta(NetworkID var){Write(true); Write(var);}
373 
374 		/// \brief Write any integral type to a bitstream.
375 		/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
376 		/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
377 		/// 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.
378 		/// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type
379 		/// \param[in] var The value to write
WriteCompressed(bool var)380 		void WriteCompressed(bool var) {Write(var);}
WriteCompressed(unsigned char var)381 		void WriteCompressed(unsigned char var) {WriteCompressed( ( unsigned char* ) & var, sizeof( unsigned char ) * 8, true );}
WriteCompressed(char var)382 		void WriteCompressed(char var) {WriteCompressed( (unsigned char* ) & var, sizeof( unsigned char ) * 8, true );}
WriteCompressed(unsigned short var)383 		void WriteCompressed(unsigned short var) {if (DoEndianSwap()) {unsigned char output[sizeof(unsigned short)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned short)); WriteCompressed( ( unsigned char* ) output, sizeof(unsigned short) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(unsigned short) * 8, true );}
WriteCompressed(short var)384 		void WriteCompressed(short var) {if (DoEndianSwap()) {unsigned char output[sizeof(short)]; ReverseBytes((unsigned char*)&var, output, sizeof(short)); WriteCompressed( ( unsigned char* ) output, sizeof(short) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(short) * 8, true );}
WriteCompressed(unsigned int var)385 		void WriteCompressed(unsigned int var) {if (DoEndianSwap()) {unsigned char output[sizeof(unsigned int)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned int)); WriteCompressed( ( unsigned char* ) output, sizeof(unsigned int) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(unsigned int) * 8, true );}
WriteCompressed(int var)386 		void WriteCompressed(int var) {if (DoEndianSwap()) { unsigned char output[sizeof(int)]; ReverseBytes((unsigned char*)&var, output, sizeof(int)); WriteCompressed( ( unsigned char* ) output, sizeof(int) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(int) * 8, true );}
WriteCompressed(unsigned long var)387 		void WriteCompressed(unsigned long var) {if (DoEndianSwap()) {unsigned char output[sizeof(unsigned long)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned long)); WriteCompressed( ( unsigned char* ) output, sizeof(unsigned long) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(unsigned long) * 8, true );}
WriteCompressed(long var)388 		void WriteCompressed(long var) {if (DoEndianSwap()) {unsigned char output[sizeof(long)]; ReverseBytes((unsigned char*)&var, output, sizeof(long)); WriteCompressed( ( unsigned char* ) output, sizeof(long) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(long) * 8, true );}
WriteCompressed(long long var)389 		void WriteCompressed(long long var) {if (DoEndianSwap()) {unsigned char output[sizeof(long long)]; ReverseBytes((unsigned char*)&var, output, sizeof(long long)); WriteCompressed( ( unsigned char* ) output, sizeof(long long) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(long long) * 8, true );}
WriteCompressed(unsigned long long var)390 		void WriteCompressed(unsigned long long var) {if (DoEndianSwap()) {	unsigned char output[sizeof(unsigned long long)]; ReverseBytes((unsigned char*)&var, output, sizeof(unsigned long long)); WriteCompressed( ( unsigned char* ) output, sizeof(unsigned long long) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(unsigned long long) * 8, true );}
WriteCompressed(float var)391 		void WriteCompressed(float var) {RakAssert(var > -1.01f && var < 1.01f); if (var < -1.0f) var=-1.0f; if (var > 1.0f) var=1.0f; Write((unsigned short)((var+1.0f)*32767.5f));}
WriteCompressed(double var)392 		void WriteCompressed(double var) {RakAssert(var > -1.01 && var < 1.01); if (var < -1.0) var=-1.0; if (var > 1.0) var=1.0; Write((unsigned long)((var+1.0)*2147483648.0));}
WriteCompressed(long double var)393 		void WriteCompressed(long double var) {RakAssert(var > -1.01 && var < 1.01); if (var < -1.0) var=-1.0; if (var > 1.0) var=1.0; Write((unsigned long)((var+1.0)*2147483648.0));}
WriteCompressed(const char * var)394 		void WriteCompressed(const char* var) {RakString::SerializeCompressed(var,this);}
WriteCompressed(const unsigned char * var)395 		void WriteCompressed(const unsigned char* var)  {RakString::SerializeCompressed((const char*) var,this);}
WriteCompressed(const RakNet::RakString & var)396 		void WriteCompressed(const RakNet::RakString &var) {var.SerializeCompressed(this);}
WriteCompressed(const uint24_t & var)397 		void WriteCompressed(const uint24_t &var) {Write(var);}
WriteCompressed(const RakNetGUID & var)398 		void WriteCompressed(const RakNetGUID &var) {if (DoEndianSwap()) {unsigned char output[sizeof(uint64_t)]; ReverseBytes((unsigned char*)&var, output, sizeof(uint64_t)); WriteCompressed( ( unsigned char* ) output, sizeof(uint64_t) * 8, true );} else WriteCompressed( ( unsigned char* ) & var, sizeof(uint64_t) * 8, true );}
399 
400 		/// \brief Write any integral type to a bitstream.
401 		/// \details If the current value is different from the last value
402 		/// the current value will be written.  Otherwise, a single bit will be written
403 		/// 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.
404 		/// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type
405 		/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
406 		/// \param[in] currentValue The current value to write
407 		/// \param[in] lastValue The last value to compare against
WriteCompressedDelta(bool currentValue,bool lastValue)408 		void WriteCompressedDelta(bool currentValue, bool lastValue)
409 		{
410 			#pragma warning(disable:4100)   // warning C4100: 'peer' : unreferenced formal parameter
411 			Write(currentValue);
412 		}
WriteCompressedDelta(unsigned char currentValue,unsigned char lastValue)413 		void WriteCompressedDelta(unsigned char currentValue, unsigned char lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(char currentValue,char lastValue)414 		void WriteCompressedDelta(char currentValue, char lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(unsigned short currentValue,unsigned short lastValue)415 		void WriteCompressedDelta(unsigned short currentValue, unsigned short lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(short currentValue,short lastValue)416 		void WriteCompressedDelta(short currentValue, short lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(unsigned int currentValue,unsigned int lastValue)417 		void WriteCompressedDelta(unsigned int currentValue, unsigned int lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(int currentValue,int lastValue)418 		void WriteCompressedDelta(int currentValue, int lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(unsigned long currentValue,unsigned long lastValue)419 		void WriteCompressedDelta(unsigned long currentValue, unsigned long lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(long currentValue,long lastValue)420 		void WriteCompressedDelta(long currentValue, long lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(long long currentValue,long long lastValue)421 		void WriteCompressedDelta(long long currentValue, long long lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(unsigned long long currentValue,unsigned long long lastValue)422 		void WriteCompressedDelta(unsigned long long currentValue, unsigned long long lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(float currentValue,float lastValue)423 		void WriteCompressedDelta(float currentValue, float lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(double currentValue,double lastValue)424 		void WriteCompressedDelta(double currentValue, double lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(long double currentValue,long double lastValue)425 		void WriteCompressedDelta(long double currentValue, long double lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(const char * currentValue,const char * lastValue)426 		void WriteCompressedDelta(const char* currentValue, const char* lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(const unsigned char * currentValue,const unsigned char * lastValue)427 		void WriteCompressedDelta(const unsigned char* currentValue, const unsigned char* lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(char * currentValue,char * lastValue)428 		void WriteCompressedDelta(char* currentValue, char* lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(unsigned char * currentValue,unsigned char * lastValue)429 		void WriteCompressedDelta(unsigned char* currentValue, unsigned char* lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(const RakNet::RakString & currentValue,const RakNet::RakString & lastValue)430 		void WriteCompressedDelta(const RakNet::RakString &currentValue, const RakNet::RakString &lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(const uint24_t & currentValue,const uint24_t & lastValue)431 		void WriteCompressedDelta(const uint24_t &currentValue, const uint24_t &lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
WriteCompressedDelta(const RakNetGUID & currentValue,const RakNetGUID & lastValue)432 		void WriteCompressedDelta(const RakNetGUID &currentValue, const RakNetGUID &lastValue){if (currentValue==lastValue) {Write(false);} else { Write(true); WriteCompressed(currentValue);}}
433 
434 		/// Save as WriteCompressedDelta(templateType currentValue, templateType lastValue) when we have an unknown second parameter
WriteCompressedDelta(bool var)435 		void WriteCompressedDelta(bool var) {Write(var);}
WriteCompressedDelta(unsigned char var)436 		void WriteCompressedDelta(unsigned char var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(char var)437 		void WriteCompressedDelta(char var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(unsigned short var)438 		void WriteCompressedDelta(unsigned short var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(short var)439 		void WriteCompressedDelta(short var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(unsigned int var)440 		void WriteCompressedDelta(unsigned int var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(int var)441 		void WriteCompressedDelta(int var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(unsigned long var)442 		void WriteCompressedDelta(unsigned long var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(long var)443 		void WriteCompressedDelta(long var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(long long var)444 		void WriteCompressedDelta(long long var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(unsigned long long var)445 		void WriteCompressedDelta(unsigned long long var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(float var)446 		void WriteCompressedDelta(float var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(double var)447 		void WriteCompressedDelta(double var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(long double var)448 		void WriteCompressedDelta(long double var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(const char * var)449 		void WriteCompressedDelta(const char* var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(const unsigned char * var)450 		void WriteCompressedDelta(const unsigned char* var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(char * var)451 		void WriteCompressedDelta(char* var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(unsigned char * var)452 		void WriteCompressedDelta(unsigned char* var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(const RakNet::RakString & var)453 		void WriteCompressedDelta(const RakNet::RakString &var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(const uint24_t & var)454 		void WriteCompressedDelta(const uint24_t &var) { Write(true);	WriteCompressed(var); }
WriteCompressedDelta(const RakNetGUID & var)455 		void WriteCompressedDelta(const RakNetGUID &var) { Write(true);	WriteCompressed(var); }
456 
457 		/// \brief Read any integral type from a bitstream.
458 		/// \details Define __BITSTREAM_NATIVE_END if you need endian swapping.
459 		/// \param[in] var The value to read
Read(bool & var)460 		bool Read(bool &var){if ( readOffset + 1 > numberOfBitsUsed ) return false;
461 		if ( data[ readOffset >> 3 ] & ( 0x80 >> ( readOffset & 7 ) ) )
462 				var = true;
463 			else
464 				var = false;
465 			// Has to be on a different line for Mac
466 			readOffset++;
467 			return true;
468 		}
Read(unsigned char & var)469 		bool Read(unsigned char &var) {return ReadBits( ( unsigned char* ) &var, sizeof(unsigned char) * 8, true );}
Read(char & var)470 		bool Read(char &var) {return ReadBits( ( unsigned char* ) &var, sizeof(char) * 8, true );}
Read(unsigned short & var)471 		bool Read(unsigned short &var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned short)]; if (ReadBits( ( unsigned char* ) output, sizeof(unsigned short) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned short)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(unsigned short) * 8, true );}
Read(short & var)472 		bool Read(short &var) {if (DoEndianSwap()){unsigned char output[sizeof(short)]; if (ReadBits( ( unsigned char* ) output, sizeof(short) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(short)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(short) * 8, true );}
Read(unsigned int & var)473 		bool Read(unsigned int &var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned int)]; if (ReadBits( ( unsigned char* ) output, sizeof(unsigned int) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned int)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(unsigned int) * 8, true );}
Read(int & var)474 		bool Read(int &var) {if (DoEndianSwap()){unsigned char output[sizeof(int)]; if (ReadBits( ( unsigned char* ) output, sizeof(int) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(int)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(int) * 8, true );}
Read(unsigned long & var)475 		bool Read(unsigned long &var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned long)]; if (ReadBits( ( unsigned char* ) output, sizeof(unsigned long) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned long)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(unsigned long) * 8, true );}
Read(long & var)476 		bool Read(long &var) {if (DoEndianSwap()){unsigned char output[sizeof(long)]; if (ReadBits( ( unsigned char* ) output, sizeof(long) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(long)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(long) * 8, true );}
Read(long long & var)477 		bool Read(long long &var) {if (DoEndianSwap()){unsigned char output[sizeof(long long)]; if (ReadBits( ( unsigned char* ) output, sizeof(long long) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(long long)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(long long) * 8, true );}
Read(unsigned long long & var)478 		bool Read(unsigned long long &var) {if (DoEndianSwap()){unsigned char output[sizeof(unsigned long long)]; if (ReadBits( ( unsigned char* ) output, sizeof(unsigned long long) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned long long)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(unsigned long long) * 8, true );}
Read(float & var)479 		bool Read(float &var) {if (DoEndianSwap()){unsigned char output[sizeof(float)]; if (ReadBits( ( unsigned char* ) output, sizeof(float) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(float)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(float) * 8, true );}
Read(double & var)480 		bool Read(double &var) {if (DoEndianSwap()){unsigned char output[sizeof(double)]; if (ReadBits( ( unsigned char* ) output, sizeof(double) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(double)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(double) * 8, true );}
Read(long double & var)481 		bool Read(long double &var) {if (DoEndianSwap()){unsigned char output[sizeof(long double)]; if (ReadBits( ( unsigned char* ) output, sizeof(long double) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(long double)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(long double) * 8, true );}
Read(char * var)482 		bool Read(char* var) {return RakNet::RakString::Deserialize(var,this);}
Read(unsigned char * var)483 		bool Read(unsigned char* var) {return RakNet::RakString::Deserialize((char*) var,this);}
Read(RakString & var)484 		bool Read(RakString &var) {return var.Deserialize(this);}
485 		bool Read(uint24_t &var);
Read(const RakNetGUID & var)486 		bool Read(const RakNetGUID &var) {if (DoEndianSwap()){unsigned char output[sizeof(uint64_t)]; if (ReadBits( ( unsigned char* ) output, sizeof(uint64_t) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(uint64_t)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(uint64_t) * 8, true );}
Read(void * & var)487 		bool Read(void* &var) {if (DoEndianSwap()){unsigned char output[sizeof(void*)]; if (ReadBits( ( unsigned char* ) output, sizeof(void*) * 8, true )) { ReverseBytes(output, (unsigned char*)&var, sizeof(void*)); return true;} return false;} else return ReadBits( ( unsigned char* ) & var, sizeof(void*) * 8, true );}
Read(SystemAddress & var)488 		bool Read(SystemAddress &var){ReadBits( ( unsigned char* ) & var.binaryAddress, sizeof(var.binaryAddress) * 8, true ); return Read(var.port);}
Read(NetworkID & var)489 		bool Read(NetworkID &var){if (NetworkID::IsPeerToPeerMode()) Read(var.systemAddress); return Read(var.localSystemAddress);}
490 
491 		/// \brief Read any integral type from a bitstream.
492 		/// \details If the written value differed from the value compared against in the write function,
493 		/// var will be updated.  Otherwise it will retain the current value.
494 		/// ReadDelta is only valid from a previous call to WriteDelta
495 		/// \param[in] var The value to read
ReadDelta(bool & var)496 		bool ReadDelta(bool &var) {return Read(var);}
ReadDelta(unsigned char & var)497 		bool ReadDelta(unsigned char &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(char & var)498 		bool ReadDelta(char &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(unsigned short & var)499 		bool ReadDelta(unsigned short &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(short & var)500 		bool ReadDelta(short &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(unsigned int & var)501 		bool ReadDelta(unsigned int &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(int & var)502 		bool ReadDelta(int &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(unsigned long & var)503 		bool ReadDelta(unsigned long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(long & var)504 		bool ReadDelta(long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(long long & var)505 		bool ReadDelta(long long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(unsigned long long & var)506 		bool ReadDelta(unsigned long long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(float & var)507 		bool ReadDelta(float &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(double & var)508 		bool ReadDelta(double &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(long double & var)509 		bool ReadDelta(long double &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(char * var)510 		bool ReadDelta(char* var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(unsigned char * var)511 		bool ReadDelta(unsigned char* var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(RakString & var)512 		bool ReadDelta(RakString &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(uint24_t & var)513 		bool ReadDelta(uint24_t &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(RakNetGUID & var)514 		bool ReadDelta(RakNetGUID &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(SystemAddress & var)515 		bool ReadDelta(SystemAddress &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
ReadDelta(NetworkID & var)516 		bool ReadDelta(NetworkID &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=Read(var); return success;}
517 
518 
519 		/// \brief Read any integral type from a bitstream.
520 		/// \details Undefine __BITSTREAM_NATIVE_END if you need endian swapping.
521 		/// 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.
522 		/// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type
523 		/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
524 		/// \param[in] var The value to read
ReadCompressed(bool & var)525 		bool ReadCompressed(bool &var) {return Read(var);}
ReadCompressed(unsigned char & var)526 		bool ReadCompressed(unsigned char &var) {return ReadCompressed( ( unsigned char* ) &var, sizeof(unsigned char) * 8, true );}
ReadCompressed(char & var)527 		bool ReadCompressed(char &var) {return ReadCompressed( ( unsigned char* ) &var, sizeof(unsigned char) * 8, true );}
ReadCompressed(unsigned short & var)528 		bool ReadCompressed(unsigned short &var){if (DoEndianSwap()){unsigned char output[sizeof(unsigned short)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(unsigned short) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned short)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(unsigned short) * 8, true );}
ReadCompressed(short & var)529 		bool ReadCompressed(short &var){if (DoEndianSwap()){unsigned char output[sizeof(short)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(short) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(short)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(short) * 8, true );}
ReadCompressed(unsigned int & var)530 		bool ReadCompressed(unsigned int &var){if (DoEndianSwap()){unsigned char output[sizeof(unsigned int)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(unsigned int) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned int)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(unsigned int) * 8, true );}
ReadCompressed(int & var)531 		bool ReadCompressed(int &var){if (DoEndianSwap()){unsigned char output[sizeof(int)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(int) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(int)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(int) * 8, true );}
ReadCompressed(unsigned long & var)532 		bool ReadCompressed(unsigned long &var){if (DoEndianSwap()){unsigned char output[sizeof(unsigned long)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(unsigned long) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned long)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(unsigned long) * 8, true );}
ReadCompressed(long & var)533 		bool ReadCompressed(long &var){if (DoEndianSwap()){unsigned char output[sizeof(long)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(long) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(long)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(long) * 8, true );}
ReadCompressed(long long & var)534 		bool ReadCompressed(long long &var){if (DoEndianSwap()){unsigned char output[sizeof(long long)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(long long) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(long long)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(long long) * 8, true );}
ReadCompressed(unsigned long long & var)535 		bool ReadCompressed(unsigned long long &var){if (DoEndianSwap()){unsigned char output[sizeof(unsigned long long)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(unsigned long long) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(unsigned long long)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(unsigned long long) * 8, true );}
ReadCompressed(float & var)536 		bool ReadCompressed(float &var){unsigned short compressedFloat; if (Read(compressedFloat)) { var = ((float)compressedFloat / 32767.5f - 1.0f); return true;} return false;}
ReadCompressed(double & var)537 		bool ReadCompressed(double &var) {unsigned long compressedFloat; if (Read(compressedFloat)) { var = ((double)compressedFloat / 2147483648.0 - 1.0); return true; } return false;}
ReadCompressed(long double & var)538 		bool ReadCompressed(long double &var) {unsigned long compressedFloat; if (Read(compressedFloat)) { var = ((long double)compressedFloat / 2147483648.0 - 1.0); return true; } return false;}
ReadCompressed(char * var)539 		bool ReadCompressed(char* var) {return RakNet::RakString::DeserializeCompressed(var,this);}
ReadCompressed(unsigned char * var)540 		bool ReadCompressed(unsigned char* var) {return RakNet::RakString::DeserializeCompressed((char*) var,this);}
ReadCompressed(RakString & var)541 		bool ReadCompressed(RakString &var) {return var.DeserializeCompressed(this);}
ReadCompressed(uint24_t & var)542 		bool ReadCompressed(uint24_t &var) {return Read(var);}
ReadCompressed(const RakNetGUID & var)543 		bool ReadCompressed(const RakNetGUID &var){if (DoEndianSwap()){unsigned char output[sizeof(uint64_t)]; if (ReadCompressed( ( unsigned char* ) output, sizeof(uint64_t) * 8, true )){ReverseBytes(output, (unsigned char*)&var, sizeof(uint64_t)); return true;} return false;}else return ReadCompressed( ( unsigned char* ) & var, sizeof(uint64_t) * 8, true );}
ReadCompressed(SystemAddress & var)544 		bool ReadCompressed(SystemAddress &var) {return Read(var);}
ReadCompressed(NetworkID & var)545 		bool ReadCompressed(NetworkID &var) {return Read(var);}
546 
547 		/// \brief Read any integral type from a bitstream.
548 		/// \details If the written value differed from the value compared against in the write function,
549 		/// var will be updated.  Otherwise it will retain the current value.
550 		/// the current value will be updated.
551 		/// 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.
552 		/// For non-floating point, this is lossless, but only has benefit if you use less than half the range of the type
553 		/// If you are not using __BITSTREAM_NATIVE_END the opposite is true for types larger than 1 byte
554 		/// ReadCompressedDelta is only valid from a previous call to WriteDelta
555 		/// \param[in] var The value to read
ReadCompressedDelta(bool & var)556 		bool ReadCompressedDelta(bool &var) {return Read(var);}
ReadCompressedDelta(unsigned char & var)557 		bool ReadCompressedDelta(unsigned char &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(char & var)558 		bool ReadCompressedDelta(char &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(unsigned short & var)559 		bool ReadCompressedDelta(unsigned short &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(short & var)560 		bool ReadCompressedDelta(short &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(unsigned int & var)561 		bool ReadCompressedDelta(unsigned int &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(int & var)562 		bool ReadCompressedDelta(int &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(unsigned long & var)563 		bool ReadCompressedDelta(unsigned long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(long & var)564 		bool ReadCompressedDelta(long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(long long & var)565 		bool ReadCompressedDelta(long long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(unsigned long long & var)566 		bool ReadCompressedDelta(unsigned long long &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(float & var)567 		bool ReadCompressedDelta(float &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(double & var)568 		bool ReadCompressedDelta(double &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(long double & var)569 		bool ReadCompressedDelta(long double &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(char * var)570 		bool ReadCompressedDelta(char*var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(unsigned char * var)571 		bool ReadCompressedDelta(unsigned char*var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(RakString & var)572 		bool ReadCompressedDelta(RakString &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(uint24_t & var)573 		bool ReadCompressedDelta(uint24_t &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
ReadCompressedDelta(const RakNetGUID & var)574 		bool ReadCompressedDelta(const RakNetGUID &var){bool dataWritten; bool success; success=Read(dataWritten); if (dataWritten) success=ReadCompressed(var); return success;}
575 
576 		/// \brief Read one bitstream to another.
577 		/// \param[in] numberOfBits bits to read
578 		/// \param bitStream the bitstream to read into from
579 		/// \return true on success, false on failure.
580 		bool Read( BitStream *bitStream, BitSize_t numberOfBits );
581 		bool Read( BitStream *bitStream );
582 		bool Read( BitStream &bitStream, BitSize_t numberOfBits );
583 		bool Read( BitStream &bitStream );
584 
585 		/// \brief Write an array or casted stream or raw data.  This does NOT do endian swapping.
586 		/// \param[in] input a byte buffer
587 		/// \param[in] numberOfBytes the size of \a input in bytes
588 		void Write( const char* input, const unsigned int numberOfBytes );
589 
590 		/// \brief Write one bitstream to another.
591 		/// \param[in] numberOfBits bits to write
592 		/// \param bitStream the bitstream to copy from
593 		void Write( BitStream *bitStream, BitSize_t numberOfBits );
594 		void Write( BitStream *bitStream );
595 		void Write( BitStream &bitStream, BitSize_t numberOfBits );
596 		void Write( BitStream &bitStream );\
597 
598 		/// \brief Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.
599 		/// \details Will further compress y or z axis aligned vectors.
600 		/// Accurate to 1/32767.5.
601 		/// \param[in] x x
602 		/// \param[in] y y
603 		/// \param[in] z z
604 		void WriteNormVector( float x, float y, float z );
WriteNormVector(double x,double y,double z)605 		void WriteNormVector( double x, double y, double z ) {WriteNormVector((float)x,(float)y,(float)z);}
606 
607 		/// \brief Write a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
608 		/// \param[in] f The float to write
609 		/// \param[in] floatMin Predetermined minimum value of f
610 		/// \param[in] floatMax Predetermined maximum value of f
611 		void WriteFloat16( float f, float floatMin, float floatMax );
612 
613 		/// \brief Write a vector, using 10 bytes instead of 12.
614 		/// \details Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important.
615 		/// \param[in] x x
616 		/// \param[in] y y
617 		/// \param[in] z z
618 		void WriteVector( float x, float y, float z );
WriteVector(double x,double y,double z)619 		void WriteVector( double x, double y, double z ) {WriteVector((float)x, (float)y, (float)z);}
620 
621 		/// \brief Write a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes.  Slightly lossy.
622 		/// \param[in] w w
623 		/// \param[in] x x
624 		/// \param[in] y y
625 		/// \param[in] z z
626 		void WriteNormQuat( float w, float x, float y, float z);
WriteNormQuat(double w,double x,double y,double z)627 		void WriteNormQuat( double w, double x, double y, double z) {WriteNormQuat((float)w, (float) x, (float) y, (float) z);}
628 
629 		/// \brief Write an orthogonal matrix by creating a quaternion, and writing 3 components of the quaternion in 2 bytes each
630 		/// for 6 bytes instead of 36
631 		/// Lossy, although the result is renormalized
WriteOrthMatrix(float m00,float m01,float m02,float m10,float m11,float m12,float m20,float m21,float m22)632 		void WriteOrthMatrix(
633 			float m00, float m01, float m02,
634 			float m10, float m11, float m12,
635 			float m20, float m21, float m22 )
636 		{
637 			WriteOrthMatrix((double)m00,(double)m01,(double)m02,
638 			(double)m10,(double)m11,(double)m12,
639 			(double)m20,(double)m21,(double)m22);
640 		}
641 
642 		void WriteOrthMatrix(
643 			double m00, double m01, double m02,
644 			double m10, double m11, double m12,
645 			double m20, double m21, double m22 );
646 
647 		/// \brief Read an array or casted stream of byte.
648 		/// \details The array is raw data. There is no automatic endian conversion with this function
649 		/// \param[in] output The result byte array. It should be larger than @em numberOfBytes.
650 		/// \param[in] numberOfBytes The number of byte to read
651 		/// \return true on success false if there is some missing bytes.
652 		bool Read( char* output, const unsigned int numberOfBytes );
653 
654 		/// \brief Read a normalized 3D vector, using (at most) 4 bytes + 3 bits instead of 12-24 bytes.
655 		/// \details Will further compress y or z axis aligned vectors.
656 		/// Accurate to 1/32767.5.
657 		/// \param[in] x x
658 		/// \param[in] y y
659 		/// \param[in] z z
660 		bool ReadNormVector( float &x, float &y, float &z );
ReadNormVector(double & x,double & y,double & z)661 		bool ReadNormVector( double &x, double &y, double &z ) {float fx, fy, fz; bool b = ReadNormVector(fx, fy, fz); x=fx; y=fy; z=fz; return b;}
662 
663 		/// \brief Read a float into 2 bytes, spanning the range between \a floatMin and \a floatMax
664 		/// \param[in] f The float to read
665 		/// \param[in] floatMin Predetermined minimum value of f
666 		/// \param[in] floatMax Predetermined maximum value of f
667 		bool ReadFloat16( float &f, float floatMin, float floatMax );
668 
669 		/// \brief Read 3 floats or doubles, using 10 bytes, where those float or doubles comprise a vector.
670 		/// \details Loses accuracy to about 3/10ths and only saves 2 bytes, so only use if accuracy is not important.
671 		/// \param[in] x x
672 		/// \param[in] y y
673 		/// \param[in] z z
674 		bool ReadVector( float x, float y, float z );
ReadVector(double & x,double & y,double & z)675 		bool ReadVector( double &x, double &y, double &z ) {return ReadVector((float)x, (float)y, (float)z);}
676 
677 		/// \brief Read a normalized quaternion in 6 bytes + 4 bits instead of 16 bytes.
678 		/// \param[in] w w
679 		/// \param[in] x x
680 		/// \param[in] y y
681 		/// \param[in] z z
ReadNormQuat(float & w,float & x,float & y,float & z)682 		bool ReadNormQuat( float &w, float &x, float &y, float &z){double dw, dx, dy, dz; bool b=ReadNormQuat(dw, dx, dy, dz); w=(float)dw; x=(float)dx; y=(float)dy; z=(float)dz; return b;}
683 		bool ReadNormQuat( double &w, double &x, double &y, double &z);
684 
685 		/// \brief Read an orthogonal matrix from a quaternion, reading 3 components of the quaternion in 2 bytes each and extrapolating the 4th, for 6 bytes instead of 36.
686 		/// \details Lossy, although the result is renormalized
687 		bool ReadOrthMatrix(
688 			float &m00, float &m01, float &m02,
689 			float &m10, float &m11, float &m12,
690 			float &m20, float &m21, float &m22 );
691 		bool ReadOrthMatrix(
692 			double &m00, double &m01, double &m02,
693 			double &m10, double &m11, double &m12,
694 			double &m20, double &m21, double &m22 );
695 
696 		/// Sets the read pointer back to the beginning of your data.
697 		void ResetReadPointer( void );
698 
699 		/// Sets the write pointer back to the beginning of your data.
700 		void ResetWritePointer( void );
701 
702 		/// This is good to call when you are done with the stream to make
703 		/// sure you didn't leave any data left over void
704 		void AssertStreamEmpty( void );
705 
706 		/// \brief RAKNET_DEBUG_PRINTF the bits in the stream.  Great for debugging.
707 		void PrintBits( char *out ) const;
708 		void PrintBits( void ) const;
709 		void PrintHex( char *out ) const;
710 		void PrintHex( void ) const;
711 
712 		/// \brief Ignore data we don't intend to read
713 		/// \param[in] numberOfBits The number of bits to ignore
714 		void IgnoreBits( const BitSize_t numberOfBits );
715 
716 		/// \brief Ignore data we don't intend to read
717 		/// \param[in] numberOfBits The number of bytes to ignore
718 		void IgnoreBytes( const unsigned int numberOfBytes );
719 
720 		/// \brief Move the write pointer to a position on the array.
721 		/// \param[in] offset the offset from the start of the array.
722 		/// \attention
723 		/// \details Dangerous if you don't know what you are doing!
724 		/// For efficiency reasons you can only write mid-stream if your data is byte aligned.
725 		void SetWriteOffset( const BitSize_t offset );
726 
727 		/// \brief Returns the length in bits of the stream
GetNumberOfBitsUsed(void)728 		inline BitSize_t GetNumberOfBitsUsed( void ) const {return GetWriteOffset();}
GetWriteOffset(void)729 		inline BitSize_t GetWriteOffset( void ) const {return numberOfBitsUsed;}
730 
731 		/// \brief Returns the length in bytes of the stream
GetNumberOfBytesUsed(void)732 		inline BitSize_t GetNumberOfBytesUsed( void ) const {return BITS_TO_BYTES( numberOfBitsUsed );}
733 
734 		/// \brief Returns the number of bits into the stream that we have read
GetReadOffset(void)735 		inline BitSize_t GetReadOffset( void ) const {return readOffset;}
736 
737 		/// \brief Sets the read bit index
SetReadOffset(const BitSize_t newReadOffset)738 		void SetReadOffset( const BitSize_t newReadOffset ) {readOffset=newReadOffset;}
739 
740 		/// \brief Returns the number of bits left in the stream that haven't been read
GetNumberOfUnreadBits(void)741 		inline BitSize_t GetNumberOfUnreadBits( void ) const {return numberOfBitsUsed - readOffset;}
742 
743 		/// \brief Makes a copy of the internal data for you \a _data will point to
744 		/// the stream.
745 		/// \details Returns the length in bits of the stream. Partial
746 		/// bytes are left aligned.
747 		/// \param[out] _data The allocated copy of GetData()
748 		BitSize_t CopyData( unsigned char** _data ) const;
749 
750 		/// Set the stream to some initial data.
751 		/// \internal
752 		void SetData( unsigned char *input );
753 
754 		/// \brief Gets the data that BitStream is writing to / reading from.
755 		/// \details Partial bytes are left aligned.
756 		/// \return A pointer to the internal state
GetData(void)757 		inline unsigned char* GetData( void ) const {return data;}
758 
759 		/// \brief Write numberToWrite bits from the input source.
760 		/// \details Right aligned data means in the case of a partial byte, the bits are aligned
761 		/// from the right (bit 0) rather than the left (as in the normal
762 		/// internal representation) You would set this to true when
763 		/// writing user data, and false when copying bitstream data, such
764 		/// as writing one bitstream to another.
765 		/// \param[in] input The data
766 		/// \param[in] numberOfBitsToWrite The number of bits to write
767 		/// \param[in] rightAlignedBits if true data will be right aligned
768 		void WriteBits( const unsigned char* input, BitSize_t numberOfBitsToWrite, const bool rightAlignedBits = true );
769 
770 		/// \brief Align the bitstream to the byte boundary and then write the
771 		/// specified number of bits.
772 		/// \details This is faster than WriteBits but
773 		/// wastes the bits to do the alignment and requires you to call
774 		/// ReadAlignedBits at the corresponding read position.
775 		/// \param[in] input The data
776 		/// \param[in] numberOfBytesToWrite The size of input.
777 		void WriteAlignedBytes( const unsigned char *input, const unsigned int numberOfBytesToWrite );
778 
779 		// Endian swap bytes already in the bitstream
780 		void EndianSwapBytes( int byteOffset, int length );
781 
782 		/// \brief Aligns the bitstream, writes inputLength, and writes input. Won't write beyond maxBytesToWrite
783 		/// \param[in] input The data
784 		/// \param[in] inputLength The size of input.
785 		/// \param[in] maxBytesToWrite Max bytes to write
786 		void WriteAlignedBytesSafe( const char *input, const unsigned int inputLength, const unsigned int maxBytesToWrite );
787 
788 		/// \brief Read bits, starting at the next aligned bits.
789 		/// \details Note that the modulus 8 starting offset of the sequence must be the same as
790 		/// was used with WriteBits. This will be a problem with packet
791 		/// coalescence unless you byte align the coalesced packets.
792 		/// \param[in] output The byte array larger than @em numberOfBytesToRead
793 		/// \param[in] numberOfBytesToRead The number of byte to read from the internal state
794 		/// \return true if there is enough byte.
795 		bool ReadAlignedBytes( unsigned char *output, const unsigned int numberOfBytesToRead );
796 
797 		/// \brief Reads what was written by WriteAlignedBytesSafe.
798 		/// \param[in] input The data
799 		/// \param[in] maxBytesToRead Maximum number of bytes to read
800 		/// \return true on success, false on failure.
801 		bool ReadAlignedBytesSafe( char *input, int &inputLength, const int maxBytesToRead );
802 		bool ReadAlignedBytesSafe( char *input, unsigned int &inputLength, const unsigned int maxBytesToRead );
803 
804 		/// \brief Same as ReadAlignedBytesSafe() but allocates the memory for you using new, rather than assuming it is safe to write to
805 		/// \param[in] input input will be deleted if it is not a pointer to 0
806 		/// \return true on success, false on failure.
807 		bool ReadAlignedBytesSafeAlloc( char **input, int &inputLength, const unsigned int maxBytesToRead );
808 		bool ReadAlignedBytesSafeAlloc( char **input, unsigned int &inputLength, const unsigned int maxBytesToRead );
809 
810 		/// \brief Align the next write and/or read to a byte boundary.
811 		/// \details This can be used to 'waste' bits to byte align for efficiency reasons It
812 		/// can also be used to force coalesced bitstreams to start on byte
813 		/// boundaries so so WriteAlignedBits and ReadAlignedBits both
814 		/// calculate the same offset when aligning.
AlignWriteToByteBoundary(void)815 		inline void AlignWriteToByteBoundary( void ) {numberOfBitsUsed += 8 - ( (( numberOfBitsUsed - 1 ) & 7) + 1 );}
816 
817 		/// \brief Align the next write and/or read to a byte boundary.
818 		/// \details This can be used to 'waste' bits to byte align for efficiency reasons It
819 		/// can also be used to force coalesced bitstreams to start on byte
820 		/// boundaries so so WriteAlignedBits and ReadAlignedBits both
821 		/// calculate the same offset when aligning.
AlignReadToByteBoundary(void)822 		inline void AlignReadToByteBoundary( void ) {readOffset += 8 - ( (( readOffset - 1 ) & 7 ) + 1 );}
823 
824 		/// \brief Read \a numberOfBitsToRead bits to the output source.
825 		/// \details alignBitsToRight should be set to true to convert internal
826 		/// bitstream data to userdata. It should be false if you used
827 		/// WriteBits with rightAlignedBits false
828 		/// \param[in] output The resulting bits array
829 		/// \param[in] numberOfBitsToRead The number of bits to read
830 		/// \param[in] alignBitsToRight if true bits will be right aligned.
831 		/// \return true if there is enough bits to read
832 		bool ReadBits( unsigned char *output, BitSize_t numberOfBitsToRead, const bool alignBitsToRight = true );
833 
834 		/// Write a 0
835 		void Write0( void );
836 
837 		/// Write a 1
838 		void Write1( void );
839 
840 		/// Reads 1 bit and returns true if that bit is 1 and false if it is 0
841 		bool ReadBit( void );
842 
843 		/// If we used the constructor version with copy data off, this
844 		/// *makes sure it is set to on and the data pointed to is copied.
845 		void AssertCopyData( void );
846 
847 		/// \brief Use this if you pass a pointer copy to the constructor
848 		/// *(_copyData==false) and want to overallocate to prevent
849 		/// reallocation.
850 		void SetNumberOfBitsAllocated( const BitSize_t lengthInBits );
851 
852 		/// \brief Reallocates (if necessary) in preparation of writing numberOfBitsToWrite
853 		void AddBitsAndReallocate( const BitSize_t numberOfBitsToWrite );
854 
855 		/// \internal
856 		/// \return How many bits have been allocated internally
857 		unsigned int GetNumberOfBitsAllocated(void) const;
858 
859 		/// Write zeros until the bitstream is filled up to \a bytes
860 		void PadWithZeroToByteLength( unsigned int bytes );
861 
862 		/// \internal Unrolled inner loop, for when performance is critical
863 		void WriteAlignedVar8(const char *input);
864 		/// \internal Unrolled inner loop, for when performance is critical
865 		bool ReadAlignedVar8(char *output);
866 		/// \internal Unrolled inner loop, for when performance is critical
867 		void WriteAlignedVar16(const char *input);
868 		/// \internal Unrolled inner loop, for when performance is critical
869 		bool ReadAlignedVar16(char *output);
870 		/// \internal Unrolled inner loop, for when performance is critical
871 		void WriteAlignedVar32(const char *input);
872 		/// \internal Unrolled inner loop, for when performance is critical
873 		bool ReadAlignedVar32(char *output);
874 
DoEndianSwap(void)875 		inline static bool DoEndianSwap(void) {
876 #ifndef __BITSTREAM_NATIVE_END
877 			return IsNetworkOrder()==false;
878 #else
879 			return false;
880 #endif
881 		}
IsBigEndian(void)882 		inline static bool IsBigEndian(void)
883 		{
884 			return IsNetworkOrder();
885 		}
IsNetworkOrder(void)886 		inline static bool IsNetworkOrder(void) {static const bool r = IsNetworkOrderInternal(); return r;}
887 		// Not inline, won't compile on PC due to winsock include errors
888 		static bool IsNetworkOrderInternal(void);
889 		static void ReverseBytes(unsigned char *input, unsigned char *output, const unsigned int length);
890 		static void ReverseBytesInPlace(unsigned char *data,const unsigned int length);
891 
892 	private:
893 
BitStream(const BitStream & invalid)894 		BitStream( const BitStream &invalid) {
895 			#ifdef _MSC_VER
896 			#pragma warning(disable:4100)
897 			// warning C4100: 'invalid' : unreferenced formal parameter
898 			#endif
899 
900 		}
901 
902 		/// \brief Assume the input source points to a native type, compress and write it.
903 		void WriteCompressed( const unsigned char* input, const unsigned int size, const bool unsignedData );
904 
905 		/// \brief Assume the input source points to a compressed native type. Decompress and read it.
906 		bool ReadCompressed( unsigned char* output,	const unsigned int size, const bool unsignedData );
907 
908 
909 		int numberOfBitsUsed;
910 
911 		int numberOfBitsAllocated;
912 
913 		int readOffset;
914 
915 		unsigned char *data;
916 
917 		/// true if the internal buffer is copy of the data passed to the constructor
918 		bool copyData;
919 
920 		/// 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
921 		unsigned char stackData[BITSTREAM_STACK_ALLOCATION_SIZE];
922 	};
923 
SerializeBits(bool writeToBitstream,unsigned char * input,int numberOfBitsToSerialize,const bool rightAlignedBits)924 		inline bool BitStream::SerializeBits(bool writeToBitstream, unsigned char* input, int numberOfBitsToSerialize, const bool rightAlignedBits )
925 		{
926 			if (writeToBitstream)
927 				WriteBits(input,numberOfBitsToSerialize,rightAlignedBits);
928 			else
929 				return ReadBits(input,numberOfBitsToSerialize,rightAlignedBits);
930 			return true;
931 		}
932 
933 
934 }
935 
936 #ifdef _MSC_VER
937 #pragma warning( pop )
938 #endif
939 
940 #endif // VC6
941 
942 #endif
943