bitStream.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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. #ifndef _STREAM_H_
  25. #include "core/stream/stream.h"
  26. #endif
  27. #ifndef _MPOINT3_H_
  28. #include "math/mPoint3.h"
  29. #endif
  30. #ifndef _CRC_H_
  31. #include "core/crc.h"
  32. #endif
  33. //-------------------------------------- Some caveats when using this class:
  34. // - Get/setPosition semantics are changed
  35. // to indicate bit position rather than
  36. // byte position.
  37. //
  38. class Point3F;
  39. class MatrixF;
  40. class HuffmanProcessor;
  41. class BitVector;
  42. class QuatF;
  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. Point3F mCompressPoint;
  54. friend class HuffmanProcessor;
  55. public:
  56. static BitStream *getPacketStream(U32 writeSize = 0);
  57. static void sendPacketStream(const NetAddress *addr);
  58. void setBuffer(void *bufPtr, S32 bufSize, S32 maxSize = 0);
  59. U8* getBuffer() { return dataPtr; }
  60. U8* getBytePtr();
  61. U32 getReadByteSize();
  62. U32 getWriteByteSize();
  63. S32 getCurPos() const;
  64. void setCurPos(const U32);
  65. // HACK: We reverted BitStream to this previous version
  66. // because it was crashing the build.
  67. //
  68. // These are just here so that we don't have to revert
  69. // the changes from the rest of the code.
  70. //
  71. // 9/11/2008 - Tom Spilman
  72. //
  73. S32 getBitPosition() const { return getCurPos(); }
  74. void clearStringBuffer();
  75. BitStream(void *bufPtr, S32 bufSize, S32 maxWriteSize = -1) { setBuffer(bufPtr, bufSize,maxWriteSize); stringBuffer = NULL; }
  76. void clear();
  77. void setStringBuffer(char buffer[256]);
  78. void writeInt(S32 value, S32 bitCount);
  79. S32 readInt(S32 bitCount);
  80. /// Use this method to write out values in a concise but ass backwards way...
  81. /// Good for values you expect to be frequently zero, often small. Worst case
  82. /// this will bloat values by nearly 20% (5 extra bits!) Best case you'll get
  83. /// one bit (if it's zero).
  84. ///
  85. /// This is not so much for efficiency's sake, as to make life painful for
  86. /// people that want to reverse engineer our network or file formats.
  87. void writeCussedU32(U32 val)
  88. {
  89. // Is it zero?
  90. if(writeFlag(val == 0))
  91. return;
  92. if(writeFlag(val <= 0xF)) // 4 bit
  93. writeRangedU32(val, 0, 0xF);
  94. else if(writeFlag(val <= 0xFF)) // 8 bit
  95. writeRangedU32(val, 0, 0xFF);
  96. else if(writeFlag(val <= 0xFFFF)) // 16 bit
  97. writeRangedU32(val, 0, 0xFFFF);
  98. else if(writeFlag(val <= 0xFFFFFF)) // 24 bit
  99. writeRangedU32(val, 0, 0xFFFFFF);
  100. else
  101. writeRangedU32(val, 0, 0xFFFFFFFF);
  102. }
  103. U32 readCussedU32()
  104. {
  105. if(readFlag())
  106. return 0;
  107. if(readFlag())
  108. return readRangedU32(0, 0xF);
  109. else if(readFlag())
  110. return readRangedU32(0, 0xFF);
  111. else if(readFlag())
  112. return readRangedU32(0, 0xFFFF);
  113. else if(readFlag())
  114. return readRangedU32(0, 0xFFFFFF);
  115. else
  116. return readRangedU32(0, 0xFFFFFFFF);
  117. }
  118. void writeSignedInt(S32 value, S32 bitCount);
  119. S32 readSignedInt(S32 bitCount);
  120. void writeRangedU32(U32 value, U32 rangeStart, U32 rangeEnd);
  121. U32 readRangedU32(U32 rangeStart, U32 rangeEnd);
  122. /// Writes a clamped signed integer to the stream using
  123. /// an optimal amount of bits for the range.
  124. void writeRangedS32( S32 value, S32 min, S32 max );
  125. /// Reads a ranged signed integer written with writeRangedS32.
  126. S32 readRangedS32( S32 min, S32 max );
  127. // read and write floats... floats are 0 to 1 inclusive, signed floats are -1 to 1 inclusive
  128. F32 readFloat(S32 bitCount);
  129. F32 readSignedFloat(S32 bitCount);
  130. void writeFloat(F32 f, S32 bitCount);
  131. void writeSignedFloat(F32 f, S32 bitCount);
  132. /// Writes a clamped floating point value to the
  133. /// stream with the desired bits of precision.
  134. void writeRangedF32( F32 value, F32 min, F32 max, U32 numBits );
  135. /// Reads a ranged floating point value written with writeRangedF32.
  136. F32 readRangedF32( F32 min, F32 max, U32 numBits );
  137. void writeClassId(U32 classId, U32 classType, U32 classGroup);
  138. S32 readClassId(U32 classType, U32 classGroup); // returns -1 if the class type is out of range
  139. // writes a normalized vector
  140. void writeNormalVector(const Point3F& vec, S32 bitCount);
  141. void readNormalVector(Point3F *vec, S32 bitCount);
  142. void clearCompressionPoint();
  143. void setCompressionPoint(const Point3F& p);
  144. // Matching calls to these compression methods must, of course,
  145. // have matching scale values.
  146. void writeCompressedPoint(const Point3F& p,F32 scale = 0.001f);
  147. void readCompressedPoint(Point3F* p,F32 scale = 0.001f);
  148. // Uses the above method to reduce the precision of a normal vector so the server can
  149. // determine exactly what is on the client. (Pre-dumbing the vector before sending
  150. // to the client can result in precision errors...)
  151. static Point3F dumbDownNormal(const Point3F& vec, S32 bitCount);
  152. /// Writes a compressed vector as separate magnitude and
  153. /// normal components. The final space used depends on the
  154. /// content of the vector.
  155. ///
  156. /// - 1 bit is used to skip over zero length vectors.
  157. /// - 1 bit is used to mark if the magnitude exceeds max.
  158. /// - The magnitude as:
  159. /// a. magBits if less than maxMag.
  160. /// b. a full 32bit value if greater than maxMag.
  161. /// - The normal as a phi and theta sized normalBits+1 and normalBits.
  162. ///
  163. void writeVector( Point3F vec, F32 maxMag, S32 magBits, S32 normalBits );
  164. /// Reads a compressed vector.
  165. /// @see writeVector
  166. void readVector( Point3F *outVec, F32 maxMag, S32 magBits, S32 normalBits );
  167. // writes an affine transform (full precision version)
  168. void writeAffineTransform(const MatrixF&);
  169. void readAffineTransform(MatrixF*);
  170. /// Writes a quaternion in a lossy compressed format that
  171. /// is ( bitCount * 3 ) + 1 bits in size.
  172. ///
  173. /// @param quat The normalized quaternion to write.
  174. /// @param bitCount The the storage space for the xyz component of
  175. /// the quaternion.
  176. ///
  177. void writeQuat( const QuatF& quat, U32 bitCount = 9 );
  178. /// Reads a quaternion written with writeQuat.
  179. ///
  180. /// @param quat The normalized quaternion to write.
  181. /// @param bitCount The the storage space for the xyz component of
  182. /// the quaternion. Must match the bitCount at write.
  183. /// @see writeQuat
  184. ///
  185. void readQuat( QuatF *outQuat, U32 bitCount = 9 );
  186. virtual void writeBits(S32 bitCount, const void *bitPtr);
  187. virtual void readBits(S32 bitCount, void *bitPtr);
  188. virtual bool writeFlag(bool val);
  189. inline bool writeFlag(U32 val)
  190. {
  191. return writeFlag(val != 0);
  192. }
  193. inline bool writeFlag(void *val)
  194. {
  195. return writeFlag(val != 0);
  196. }
  197. virtual bool readFlag();
  198. void writeBits(const BitVector &bitvec);
  199. void readBits(BitVector *bitvec);
  200. void setBit(S32 bitCount, bool set);
  201. bool testBit(S32 bitCount);
  202. bool isFull() { return bitNum > (bufSize << 3); }
  203. bool isValid() { return !error; }
  204. bool _read (const U32 size,void* d);
  205. bool _write(const U32 size,const void* d);
  206. void readString(char stringBuf[256]);
  207. void writeString(const char *stringBuf, S32 maxLen=255);
  208. bool hasCapability(const Capability) const { return true; }
  209. U32 getPosition() const;
  210. bool setPosition(const U32 in_newPosition);
  211. U32 getStreamSize();
  212. };
  213. class ResizeBitStream : public BitStream
  214. {
  215. protected:
  216. U32 mMinSpace;
  217. public:
  218. ResizeBitStream(U32 minSpace = 1500, U32 initialSize = 0);
  219. void validate();
  220. ~ResizeBitStream();
  221. };
  222. /// This class acts to provide an "infinitely extending" stream.
  223. ///
  224. /// Basically, it does what ResizeBitStream does, but it validates
  225. /// on every write op, so that you never have to worry about overwriting
  226. /// the buffer.
  227. class InfiniteBitStream : public ResizeBitStream
  228. {
  229. public:
  230. InfiniteBitStream();
  231. ~InfiniteBitStream();
  232. /// Ensure we have space for at least upcomingBytes more bytes in the stream.
  233. void validate(U32 upcomingBytes);
  234. /// Reset the stream to zero length (but don't clean memory).
  235. void reset();
  236. /// Shrink the buffer down to match the actual size of the data.
  237. void compact();
  238. /// Write us out to a stream... Results in last byte getting padded!
  239. void writeToStream(Stream &s);
  240. virtual void writeBits(S32 bitCount, const void *bitPtr)
  241. {
  242. validate((bitCount >> 3) + 1); // Add a little safety.
  243. BitStream::writeBits(bitCount, bitPtr);
  244. }
  245. virtual bool writeFlag(bool val)
  246. {
  247. validate(1); // One bit will at most grow our buffer by a byte.
  248. return BitStream::writeFlag(val);
  249. }
  250. const U32 getCRC()
  251. {
  252. // This could be kinda inefficient - BJG
  253. return CRC::calculateCRC(getBuffer(), getStreamSize());
  254. }
  255. };
  256. //------------------------------------------------------------------------------
  257. //-------------------------------------- INLINES
  258. //
  259. inline S32 BitStream::getCurPos() const
  260. {
  261. return bitNum;
  262. }
  263. inline void BitStream::setCurPos(const U32 in_position)
  264. {
  265. AssertFatal(in_position < (U32)(bufSize << 3), "Out of range bitposition");
  266. bitNum = S32(in_position);
  267. }
  268. inline bool BitStream::readFlag()
  269. {
  270. if(bitNum > maxReadBitNum)
  271. {
  272. error = true;
  273. AssertFatal(false, "Out of range read");
  274. return false;
  275. }
  276. S32 mask = 1 << (bitNum & 0x7);
  277. bool ret = (*(dataPtr + (bitNum >> 3)) & mask) != 0;
  278. bitNum++;
  279. return ret;
  280. }
  281. inline void BitStream::writeRangedU32(U32 value, U32 rangeStart, U32 rangeEnd)
  282. {
  283. AssertFatal(value >= rangeStart && value <= rangeEnd, "Out of bounds value!");
  284. AssertFatal(rangeEnd >= rangeStart, "error, end of range less than start");
  285. U32 rangeSize = rangeEnd - rangeStart + 1;
  286. U32 rangeBits = getBinLog2(getNextPow2(rangeSize));
  287. writeInt(S32(value - rangeStart), S32(rangeBits));
  288. }
  289. inline U32 BitStream::readRangedU32(U32 rangeStart, U32 rangeEnd)
  290. {
  291. AssertFatal(rangeEnd >= rangeStart, "error, end of range less than start");
  292. U32 rangeSize = rangeEnd - rangeStart + 1;
  293. U32 rangeBits = getBinLog2(getNextPow2(rangeSize));
  294. U32 val = U32(readInt(S32(rangeBits)));
  295. return val + rangeStart;
  296. }
  297. inline void BitStream::writeRangedS32( S32 value, S32 min, S32 max )
  298. {
  299. value = mClamp( value, min, max );
  300. writeRangedU32( ( value - min ), 0, ( max - min ) );
  301. }
  302. inline S32 BitStream::readRangedS32( S32 min, S32 max )
  303. {
  304. return readRangedU32( 0, ( max - min ) ) + min;
  305. }
  306. inline void BitStream::writeRangedF32( F32 value, F32 min, F32 max, U32 numBits )
  307. {
  308. value = ( mClampF( value, min, max ) - min ) / ( max - min );
  309. writeInt( (S32)mFloor(value * F32( (1 << numBits) - 1 )), numBits );
  310. }
  311. inline F32 BitStream::readRangedF32( F32 min, F32 max, U32 numBits )
  312. {
  313. F32 value = (F32)readInt( numBits );
  314. value /= F32( ( 1 << numBits ) - 1 );
  315. return min + value * ( max - min );
  316. }
  317. #endif //_BITSTREAM_H_