bitStream.h 13 KB

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