bitStream.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _BITSTREAM_H_
  23. #define _BITSTREAM_H_
  24. //Includes
  25. #ifndef _PLATFORM_H_
  26. #include "platform/platform.h"
  27. #endif
  28. #ifndef _STREAM_H_
  29. #include "io/stream.h"
  30. #endif
  31. #ifndef _MPOINT_H_
  32. #include "math/mPoint.h"
  33. #endif
  34. #include "algorithm/crc.h"
  35. //-------------------------------------- Some caveats when using this class:
  36. // - Get/setPosition semantics are changed
  37. // to indicate bit position rather than
  38. // byte position.
  39. //
  40. class Point3F;
  41. class MatrixF;
  42. class HuffmanProcessor;
  43. class BitStream : public Stream
  44. {
  45. protected:
  46. U8 *dataPtr;
  47. S32 bitNum;
  48. S32 bufSize;
  49. bool error;
  50. S32 maxReadBitNum;
  51. S32 maxWriteBitNum;
  52. char *stringBuffer;
  53. bool mCompressRelative;
  54. Point3F mCompressPoint;
  55. friend class HuffmanProcessor;
  56. public:
  57. static BitStream *getPacketStream(U32 writeSize = 0);
  58. static void sendPacketStream(const NetAddress *addr);
  59. void setBuffer(void *bufPtr, S32 bufSize, S32 maxSize = 0);
  60. U8* getBuffer() { return dataPtr; }
  61. U8* getBytePtr();
  62. U32 getReadByteSize();
  63. S32 getCurPos() const;
  64. void setCurPos(const U32);
  65. BitStream(void *bufPtr, S32 bufSize, S32 maxWriteSize = -1) { setBuffer(bufPtr, bufSize,maxWriteSize); stringBuffer = NULL; }
  66. void clear();
  67. void setStringBuffer(char buffer[256]);
  68. void writeInt(S32 value, S32 bitCount);
  69. S32 readInt(S32 bitCount);
  70. /// Use this method to write out values in a concise but ass backwards way...
  71. /// Good for values you expect to be frequently zero, often small. Worst case
  72. /// this will bloat values by nearly 20% (5 extra bits!) Best case you'll get
  73. /// one bit (if it's zero).
  74. ///
  75. /// This is not so much for efficiency's sake, as to make life painful for
  76. /// people that want to reverse engineer our network or file formats.
  77. void writeCussedU32(U32 val)
  78. {
  79. // Is it zero?
  80. if(writeFlag(val == 0))
  81. return;
  82. if(writeFlag(val <= 0xF)) // 4 bit
  83. writeRangedU32(val, 0, 0xF);
  84. else if(writeFlag(val <= 0xFF)) // 8 bit
  85. writeRangedU32(val, 0, 0xFF);
  86. else if(writeFlag(val <= 0xFFFF)) // 16 bit
  87. writeRangedU32(val, 0, 0xFFFF);
  88. else if(writeFlag(val <= 0xFFFFFF)) // 24 bit
  89. writeRangedU32(val, 0, 0xFFFFFF);
  90. else
  91. writeRangedU32(val, 0, 0xFFFFFFFF);
  92. }
  93. U32 readCussedU32()
  94. {
  95. if(readFlag())
  96. return 0;
  97. if(readFlag())
  98. return readRangedU32(0, 0xF);
  99. else if(readFlag())
  100. return readRangedU32(0, 0xFF);
  101. else if(readFlag())
  102. return readRangedU32(0, 0xFFFF);
  103. else if(readFlag())
  104. return readRangedU32(0, 0xFFFFFF);
  105. else
  106. return readRangedU32(0, 0xFFFFFFFF);
  107. }
  108. void writeSignedInt(S32 value, S32 bitCount);
  109. S32 readSignedInt(S32 bitCount);
  110. void writeRangedU32(U32 value, U32 rangeStart, U32 rangeEnd);
  111. U32 readRangedU32(U32 rangeStart, U32 rangeEnd);
  112. /// Writes a clamped signed integer to the stream using
  113. /// an optimal amount of bits for the range.
  114. void writeRangedS32( S32 value, S32 min, S32 max );
  115. /// Reads a ranged signed integer written with writeRangedS32.
  116. S32 readRangedS32( S32 min, S32 max );
  117. // read and write floats... floats are 0 to 1 inclusive, signed floats are -1 to 1 inclusive
  118. F32 readFloat(S32 bitCount);
  119. F32 readSignedFloat(S32 bitCount);
  120. void writeFloat(F32 f, S32 bitCount);
  121. void writeSignedFloat(F32 f, S32 bitCount);
  122. /// Writes a clamped floating point value to the
  123. /// stream with the desired bits of precision.
  124. void writeRangedF32( F32 value, F32 min, F32 max, U32 numBits );
  125. /// Reads a ranged floating point value written with writeRangedF32.
  126. F32 readRangedF32( F32 min, F32 max, U32 numBits );
  127. void writeClassId(U32 classId, U32 classType, U32 classGroup);
  128. S32 readClassId(U32 classType, U32 classGroup); // returns -1 if the class type is out of range
  129. // writes a normalized vector
  130. void writeNormalVector(const Point3F& vec, S32 bitCount);
  131. void readNormalVector(Point3F *vec, S32 bitCount);
  132. void clearCompressionPoint();
  133. void setCompressionPoint(const Point3F& p);
  134. // Matching calls to these compression methods must, of course,
  135. // have matching scale values.
  136. void writeCompressedPoint(const Point3F& p,F32 scale = 0.01f);
  137. void readCompressedPoint(Point3F* p,F32 scale = 0.01f);
  138. // Uses the above method to reduce the precision of a normal vector so the server can
  139. // determine exactly what is on the client. (Pre-dumbing the vector before sending
  140. // to the client can result in precision errors...)
  141. static Point3F dumbDownNormal(const Point3F& vec, S32 bitCount);
  142. // writes a normalized vector using alternate method
  143. void writeNormalVector(const Point3F& vec, S32 angleBitCount, S32 zBitCount);
  144. void readNormalVector(Point3F *vec, S32 angleBitCount, S32 zBitCount);
  145. void readVector(Point3F * vec, F32 minMag, F32 maxMag, S32 magBits, S32 angleBits, S32 zBits);
  146. void writeVector(Point3F vec, F32 minMag, F32 maxMag, S32 magBits, S32 angleBits, S32 zBits);
  147. // writes an affine transform (full precision version)
  148. void writeAffineTransform(const MatrixF&);
  149. void readAffineTransform(MatrixF*);
  150. virtual void writeBits(S32 bitCount, const void *bitPtr);
  151. virtual void readBits(S32 bitCount, void *bitPtr);
  152. virtual bool writeFlag(bool val);
  153. virtual bool readFlag();
  154. void setBit(S32 bitCount, bool set);
  155. bool testBit(S32 bitCount);
  156. bool isFull() { return bitNum > (bufSize << 3); }
  157. bool isValid() { return !error; }
  158. bool _read (const U32 size,void* d);
  159. bool _write(const U32 size,const void* d);
  160. void readString(char stringBuf[256]);
  161. void writeString(const char *stringBuf, S32 maxLen=255);
  162. bool hasCapability(const Capability) const { return true; }
  163. U32 getPosition() const;
  164. bool setPosition(const U32 in_newPosition);
  165. U32 getStreamSize();
  166. };
  167. class ResizeBitStream : public BitStream
  168. {
  169. protected:
  170. U32 mMinSpace;
  171. public:
  172. ResizeBitStream(U32 minSpace = 1500, U32 initialSize = 0);
  173. void validate();
  174. ~ResizeBitStream();
  175. };
  176. /// This class acts to provide an "infinitely extending" stream.
  177. ///
  178. /// Basically, it does what ResizeBitStream does, but it validates
  179. /// on every write op, so that you never have to worry about overwriting
  180. /// the buffer.
  181. class InfiniteBitStream : public ResizeBitStream
  182. {
  183. public:
  184. InfiniteBitStream();
  185. ~InfiniteBitStream();
  186. /// Ensure we have space for at least upcomingBytes more bytes in the stream.
  187. void validate(U32 upcomingBytes);
  188. /// Reset the stream to zero length (but don't clean memory).
  189. void reset();
  190. /// Shrink the buffer down to match the actual size of the data.
  191. void compact();
  192. /// Write us out to a stream... Results in last byte getting padded!
  193. void writeToStream(Stream &s);
  194. virtual void writeBits(S32 bitCount, const void *bitPtr)
  195. {
  196. validate((bitCount >> 3) + 1); // Add a little safety.
  197. BitStream::writeBits(bitCount, bitPtr);
  198. }
  199. virtual bool writeFlag(bool val)
  200. {
  201. validate(1); // One bit will at most grow our buffer by a byte.
  202. return BitStream::writeFlag(val);
  203. }
  204. const U32 getCRC()
  205. {
  206. // This could be kinda inefficient - BJG
  207. return calculateCRC(getBuffer(), getStreamSize());
  208. }
  209. };
  210. //------------------------------------------------------------------------------
  211. //-------------------------------------- INLINES
  212. //
  213. inline S32 BitStream::getCurPos() const
  214. {
  215. return bitNum;
  216. }
  217. inline void BitStream::setCurPos(const U32 in_position)
  218. {
  219. AssertFatal(in_position < (U32)(bufSize << 3), "Out of range bitposition");
  220. bitNum = S32(in_position);
  221. }
  222. inline bool BitStream::readFlag()
  223. {
  224. if(bitNum > maxReadBitNum)
  225. {
  226. error = true;
  227. AssertFatal(false, "Out of range read");
  228. return false;
  229. }
  230. S32 mask = 1 << (bitNum & 0x7);
  231. bool ret = (*(dataPtr + (bitNum >> 3)) & mask) != 0;
  232. bitNum++;
  233. return ret;
  234. }
  235. inline void BitStream::writeRangedU32(U32 value, U32 rangeStart, U32 rangeEnd)
  236. {
  237. AssertFatal(value >= rangeStart && value <= rangeEnd, "Out of bounds value!");
  238. AssertFatal(rangeEnd >= rangeStart, "error, end of range less than start");
  239. U32 rangeSize = rangeEnd - rangeStart + 1;
  240. U32 rangeBits = getBinLog2(getNextPow2(rangeSize));
  241. writeInt(S32(value - rangeStart), S32(rangeBits));
  242. }
  243. inline U32 BitStream::readRangedU32(U32 rangeStart, U32 rangeEnd)
  244. {
  245. AssertFatal(rangeEnd >= rangeStart, "error, end of range less than start");
  246. U32 rangeSize = rangeEnd - rangeStart + 1;
  247. U32 rangeBits = getBinLog2(getNextPow2(rangeSize));
  248. U32 val = U32(readInt(S32(rangeBits)));
  249. return val + rangeStart;
  250. }
  251. inline void BitStream::writeRangedS32( S32 value, S32 min, S32 max )
  252. {
  253. value = mClamp( value, min, max );
  254. writeRangedU32( ( value - min ), 0, ( max - min ) );
  255. }
  256. inline S32 BitStream::readRangedS32( S32 min, S32 max )
  257. {
  258. return readRangedU32( 0, ( max - min ) ) + min;
  259. }
  260. inline void BitStream::writeRangedF32( F32 value, F32 min, F32 max, U32 numBits )
  261. {
  262. value = ( mClampF( value, min, max ) - min ) / ( max - min );
  263. writeInt( (S32)(value * ( (1 << numBits) - 1 )), numBits );
  264. }
  265. inline F32 BitStream::readRangedF32( F32 min, F32 max, U32 numBits )
  266. {
  267. F32 value = (F32)readInt( numBits );
  268. value /= F32( ( 1 << numBits ) - 1 );
  269. return min + value * ( max - min );
  270. }
  271. #endif //_BITSTREAM_H_