| 1 | |
| 2 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
| 3 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
| 4 | #pragma once |
| 5 | |
| 6 | #include "Prerequisites/BsPrerequisitesUtil.h" |
| 7 | #include "Math/BsMath.h" |
| 8 | #include "Math/BsQuaternion.h" |
| 9 | #include "Math/BsVector3.h" |
| 10 | #include "Utility/BsBitwise.h" |
| 11 | |
| 12 | namespace bs |
| 13 | { |
| 14 | /** @addtogroup General |
| 15 | * @{ |
| 16 | */ |
| 17 | |
| 18 | /** |
| 19 | * Allows encoding/decoding of types into a stream of bits. Supports various methods of storing data in a compact form. |
| 20 | * The bitstream can manage its internal memory or a user can provide an external source of data. If using internal |
| 21 | * memory the bitstream will automatically grow the memory storage as needed. |
| 22 | * |
| 23 | * The stream keeps an internal cursor that represents the bit at which to perform read & write operations. |
| 24 | * Read & write operations will operate at the current cursor location and the cursor will be advanced by the number of |
| 25 | * bits read or written. If writing outside of range the internal memory buffer will be automatically expanded, except |
| 26 | * when external memory buffer is used, in which case it is undefined behaviour. Reading outside of range is always |
| 27 | * undefined behaviour. |
| 28 | */ |
| 29 | class Bitstream |
| 30 | { |
| 31 | using QuantType = uint8_t; |
| 32 | public: |
| 33 | /** |
| 34 | * Initializes an empty bitstream. As data is written the stream will grow its internal memory storage |
| 35 | * automatically. |
| 36 | */ |
| 37 | Bitstream() = default; |
| 38 | |
| 39 | /** |
| 40 | * Initializes a bitstream with some initial capacity. If more bytes than capacity is written, the bitstream will |
| 41 | * grow its internal memory storage. |
| 42 | * |
| 43 | * @param[in] capacity Number of bytes to initially allocate for the internal memory storage. |
| 44 | */ |
| 45 | Bitstream(uint32_t capacity); |
| 46 | |
| 47 | /** |
| 48 | * Initializes a bitstream with external data storage. The bitstream will not manage internal memory and will not |
| 49 | * grow memory storage if capacity is exceeded. The user is responsible for keeping track and not writing outside |
| 50 | * of buffer range. |
| 51 | * |
| 52 | * @param[in] data Address of the external memory buffer. The user is responsible of keeping this memory alive |
| 53 | * for the lifetime of the bitstream, as well as releasing it. Must have enough capacity to |
| 54 | * store @p count bits. |
| 55 | * @param[in] count Size of the provided data, in bits. |
| 56 | */ |
| 57 | Bitstream(QuantType* data, uint32_t count); |
| 58 | |
| 59 | ~Bitstream(); |
| 60 | |
| 61 | /** |
| 62 | * Writes bits from the provided buffer into the stream at the current cursor location and advances the cursor. |
| 63 | * |
| 64 | * @param[in] data Buffer to write the data from. Must have enough capacity to store @p count bits. |
| 65 | * @param[in] count Number of bits to write. |
| 66 | */ |
| 67 | void writeBits(const QuantType* data, uint32_t count); |
| 68 | |
| 69 | /** |
| 70 | * Reads bits from the stream into the provided buffer from the current cursor location and advances the cursor. |
| 71 | * |
| 72 | * @param[out] data Buffer to read the data from. Must have enough capacity to store @p count bits. |
| 73 | * @param[in] count Number of bits to read. |
| 74 | */ |
| 75 | void readBits(QuantType* data, uint32_t count); |
| 76 | |
| 77 | /** |
| 78 | * Writes the provided data into the stream at the current cursor location and advances the cursor. |
| 79 | * |
| 80 | * @param[in] value Data to write. |
| 81 | */ |
| 82 | template<class T> |
| 83 | void write(const T& value); |
| 84 | |
| 85 | /** |
| 86 | * Reads bits from the stream and writes them into the provided object. Data is read from the current cursor |
| 87 | * location and advances the cursor. |
| 88 | * |
| 89 | * @param[out] value Object to initialize with the read bits. |
| 90 | */ |
| 91 | template<class T> |
| 92 | void read(T& value); |
| 93 | |
| 94 | /** @copydoc write(const T&) */ |
| 95 | void write(const bool& value); |
| 96 | |
| 97 | /** @copydoc read(T&) */ |
| 98 | void read(bool& value); |
| 99 | |
| 100 | /** @copydoc write(const T&) */ |
| 101 | void write(const String& value); |
| 102 | |
| 103 | /** @copydoc read(T&) */ |
| 104 | void read(String& value); |
| 105 | |
| 106 | /** |
| 107 | * Checks if the provided value differs from the last provided value, and if they are equivalent writes just a |
| 108 | * single bit signifying no change. Otherwise the value is encoded as if calling write(). |
| 109 | */ |
| 110 | template<class T> |
| 111 | void writeDelta(const T& value, const T& lastValue); |
| 112 | |
| 113 | /** Reads the data written by writeDelta() from the current cursor location and advances the cursor. */ |
| 114 | template<class T> |
| 115 | void readDelta(T& value, const T& lastValue); |
| 116 | |
| 117 | /** @copydoc writeDelta(const T&, const T&) */ |
| 118 | void writeDelta(bool value, bool lastValue); |
| 119 | |
| 120 | /** @copydoc readDelta(T&, const T&) */ |
| 121 | void readDelta(bool& value, bool lastValue); |
| 122 | |
| 123 | /** |
| 124 | * Encodes a 32-bit integer value as a base-128 varint and writes it to the stream. Write is performed at the |
| 125 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 126 | * more bytes, where smaller values use less bytes. |
| 127 | */ |
| 128 | void writeVarInt(uint32_t value); |
| 129 | |
| 130 | /** |
| 131 | * Encodes a 32-bit integer value as a base-128 varint and writes it to the stream. Write is performed at the |
| 132 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 133 | * more bytes, where smaller values use less bytes. |
| 134 | */ |
| 135 | void writeVarInt(int32_t value); |
| 136 | |
| 137 | /** |
| 138 | * Encodes a 64-bit integer value as a base-128 varint and writes it to the stream. Write is performed at the |
| 139 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 140 | * more bytes, where smaller values use less bytes. |
| 141 | */ |
| 142 | void writeVarInt(uint64_t value); |
| 143 | |
| 144 | /** |
| 145 | * Encodes a 64-bit integer value as a base-128 varint and writes it to the stream. Write is performed at the |
| 146 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 147 | * more bytes, where smaller values use less bytes. |
| 148 | */ |
| 149 | void writeVarInt(int64_t value); |
| 150 | |
| 151 | /** |
| 152 | * Decodes a 32-bit integer value encoded as a base-128 varint from the stream. Read is performed at the |
| 153 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 154 | * more bytes, where smaller values use less bytes. |
| 155 | */ |
| 156 | void readVarInt(uint32_t& value); |
| 157 | |
| 158 | /** |
| 159 | * Decodes a 32-bit integer value encoded as a base-128 varint from the stream. Read is performed at the |
| 160 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 161 | * more bytes, where smaller values use less bytes. |
| 162 | */ |
| 163 | void readVarInt(int32_t& value); |
| 164 | |
| 165 | /** |
| 166 | * Decodes a 32-bit integer value encoded as a base-128 varint from the stream. Read is performed at the |
| 167 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 168 | * more bytes, where smaller values use less bytes. |
| 169 | */ |
| 170 | void readVarInt(uint64_t& value); |
| 171 | |
| 172 | /** |
| 173 | * Decodes a 32-bit integer value encoded as a base-128 varint from the stream. Read is performed at the |
| 174 | * current cursor location and advances the cursor. Varints are a method of serializing integers using one or |
| 175 | * more bytes, where smaller values use less bytes. |
| 176 | */ |
| 177 | void readVarInt(int64_t& value); |
| 178 | |
| 179 | /** |
| 180 | * Checks if the provided value differs from the last provided value, and if they are equivalent writes just a |
| 181 | * single bit signifying no change. Otherwise the value is encoded as if calling writeVarInt(). |
| 182 | */ |
| 183 | template<class T> |
| 184 | void writeVarIntDelta(const T& value, const T& lastValue); |
| 185 | |
| 186 | /** Reads the data written by writeVarIntDelta() from the current cursor location and advances the cursor. */ |
| 187 | template<class T> |
| 188 | void readVarIntDelta(T& value, const T& lastValue); |
| 189 | |
| 190 | /** |
| 191 | * Encodes a float in range [0, 1] into a fixed point representation using a specific number of bits, and writes it |
| 192 | * to the stream. Write is performed at the current cursor location and advances the cursor. |
| 193 | */ |
| 194 | void writeNorm(float value, uint32_t bits = 16); |
| 195 | |
| 196 | /** |
| 197 | * Decodes a float encoded using writeNorm(float, uint32_t). Read is performed at the current cursor location and |
| 198 | * advances the cursor. Same number of bits need to be used as when the float was encoded. |
| 199 | */ |
| 200 | void readNorm(float& value, uint32_t bits = 16); |
| 201 | |
| 202 | /** |
| 203 | * Encodes a 3D vector with individual components in range [-1, 1] into a fixed point representation where each |
| 204 | * component uses a specific number of bits, and writes it to the stream. Write is performed at the current cursor |
| 205 | * location and advances the cursor. |
| 206 | */ |
| 207 | void writeNorm(const Vector3& value, uint32_t bits = 16); |
| 208 | |
| 209 | /** |
| 210 | * Decodes a 3D vector encoded using writeNorm(Vector3, uint32_t). Read is performed at the current cursor location |
| 211 | * and advances the cursor. Same number of bits need to be used as when the float was encoded. |
| 212 | */ |
| 213 | void readNorm(Vector3& value, uint32_t bits = 16); |
| 214 | |
| 215 | /** |
| 216 | * Encodes a quaternion with individual components in range [-1, 1] into a fixed point representation where each |
| 217 | * component uses a specific number of bits, and writes it to the stream. Write is performed at the current cursor |
| 218 | * location and advances the cursor. |
| 219 | */ |
| 220 | void writeNorm(const Quaternion& value, uint32_t bits = 16); |
| 221 | |
| 222 | /** |
| 223 | * Decodes a quaternion encoded using writeNorm(Quaternion, uint32_t). Read is performed at the current cursor |
| 224 | * location and advances the cursor. Same number of bits need to be used as when the float was encoded. |
| 225 | */ |
| 226 | void readNorm(Quaternion& value, uint32_t bits = 16); |
| 227 | |
| 228 | /** |
| 229 | * Checks if the provided value differs from the last provided value, and if they are equivalent writes just a |
| 230 | * single bit signifying no change. Otherwise the value is encoded as if calling writeNorm(). |
| 231 | */ |
| 232 | template<class T> |
| 233 | void writeNormDelta(const T& value, const T& lastValue, uint32_t bits = 16); |
| 234 | |
| 235 | /** Reads the data written by writeNormDelta() from the current cursor location and advances the cursor. */ |
| 236 | template<class T> |
| 237 | void readNormDelta(T& value, const T& lastValue, uint32_t bits = 16); |
| 238 | |
| 239 | /** |
| 240 | * Encodes an integer in a specific range, using the range the reduce the number of bits required, and writes it |
| 241 | * to the stream. Write is performed at the current cursor location and advances the cursor. |
| 242 | */ |
| 243 | template<class T> |
| 244 | void writeRange(const T& value, const T& min, const T& max); |
| 245 | |
| 246 | /** |
| 247 | * Decodes an integer encoded using writeRange(const T&, const T&, const T&). Read is performed at the current |
| 248 | * cursor location and advances the cursor. Same needs to be used as when the value was encoded. |
| 249 | */ |
| 250 | template<class T> |
| 251 | void readRange(T& value, const T& min, const T& max); |
| 252 | |
| 253 | /** |
| 254 | * Checks if the provided value differs from the last provided value, and if they are equivalent writes just a |
| 255 | * single bit signifying no change. Otherwise the value is encoded as if calling |
| 256 | * writeRange(const T&, const T&, const T&). |
| 257 | */ |
| 258 | template<class T> |
| 259 | void writeRangeDelta(const T& value, const T& lastValue, const T& min, const T& max); |
| 260 | |
| 261 | /** |
| 262 | * Reads the data written by writeRangeDelta(const T&, const T&, const T&, const T&) from the current cursor |
| 263 | * location and advances the cursor. |
| 264 | */ |
| 265 | template<class T> |
| 266 | void readRangeDelta(T& value, const T& lastValue, const T& min, const T& max); |
| 267 | |
| 268 | /** |
| 269 | * Encodes a float in a specific range into a fixed point representation using a specific number of bits, and |
| 270 | * writes it to the stream. Write is performed at the current cursor location and advances the cursor. |
| 271 | */ |
| 272 | void writeRange(float value, float min, float max, uint32_t bits = 16); |
| 273 | |
| 274 | /** |
| 275 | * Decodes a float encoded using writeRange(float, float, float, uint32_t). Read is performed at the current cursor |
| 276 | * location and advances the cursor. Same number of bits, and the same range needs to be used as when the float was |
| 277 | * encoded. |
| 278 | */ |
| 279 | void readRange(float& value, float min, float max, uint32_t bits = 16); |
| 280 | |
| 281 | /** |
| 282 | * Checks if the provided value differs from the last provided value, and if they are equivalent writes just a |
| 283 | * single bit signifying no change. Otherwise the value is encoded as if calling |
| 284 | * writeRange(float, float, float, uint32_t). |
| 285 | */ |
| 286 | void writeRangeDelta(float value, float lastValue, float min, float max, uint32_t bits = 16); |
| 287 | |
| 288 | /** |
| 289 | * Reads the data written by writeRangeDelta(float, float, float, float, uint32_t) from the current cursor |
| 290 | * location and advances the cursor. |
| 291 | */ |
| 292 | void readRangeDelta(float& value, float lastValue, float min, float max, uint32_t bits = 16); |
| 293 | |
| 294 | /** |
| 295 | * Skip a defined number of bits, moving the read/write cursor by this amount. This can also be a negative value, |
| 296 | * in which case the file pointer rewinds a defined number of bits. Note the cursor can never skip past the |
| 297 | * capacity of the buffer, and will be clamped. |
| 298 | */ |
| 299 | void skip(int32_t count); |
| 300 | |
| 301 | /** |
| 302 | * Repositions the read/write cursor to the specified bit. Note the cursor can never skip past the capacity |
| 303 | * of the buffer, and will be clamped. |
| 304 | */ |
| 305 | void seek(uint32_t pos); |
| 306 | |
| 307 | /** |
| 308 | * Aligns the read/write cursor to a byte boundary. @p count determines the alignment in bytes. Note the |
| 309 | * requested alignment might not be achieved if count > 1 and it would move the cursor past the capacity of the |
| 310 | * buffer, as the cursor will be clamped to buffer end regardless of alignment. |
| 311 | */ |
| 312 | void align(uint32_t count = 1); |
| 313 | |
| 314 | /** Returns the current read/write cursor position, in bits. */ |
| 315 | uint32_t tell() const { return mCursor; } |
| 316 | |
| 317 | /** Returns true if the stream has reached the end. */ |
| 318 | bool eof() const { return mCursor >= mNumBits; } |
| 319 | |
| 320 | /** Returns the total number of bits available in the stream. */ |
| 321 | uint32_t size() const { return mNumBits; } |
| 322 | |
| 323 | /** Returns the total number of bits the stream can store without needing to allocate more memory. */ |
| 324 | uint32_t capacity() const { return mMaxBits; } |
| 325 | |
| 326 | /** Returns the internal data buffer. */ |
| 327 | QuantType* data() const { return mData; } |
| 328 | |
| 329 | private: |
| 330 | static constexpr uint32_t BYTES_PER_QUANT = sizeof(QuantType); |
| 331 | static constexpr uint32_t BITS_PER_QUANT = BYTES_PER_QUANT * 8; |
| 332 | static constexpr uint32_t BITS_PER_QUANT_LOG2 = Bitwise::bitsLog2(BITS_PER_QUANT); |
| 333 | |
| 334 | /** Checks if the internal memory buffer needs to grow in order to accomodate @p numBits bits. */ |
| 335 | void reallocIfNeeded(uint32_t numBits); |
| 336 | |
| 337 | /** Reallocates the internal buffer making enough room for @p numBits (rounded to a multiple of BYTES_PER_QUANT. */ |
| 338 | void realloc(uint32_t numBits); |
| 339 | |
| 340 | QuantType* mData = nullptr; |
| 341 | uint32_t mMaxBits = 0; |
| 342 | uint32_t mNumBits = 0; |
| 343 | bool mOwnsMemory = true; |
| 344 | |
| 345 | uint32_t mCursor = 0; |
| 346 | }; |
| 347 | |
| 348 | /** @} */ |
| 349 | |
| 350 | /** @addtogroup Implementation |
| 351 | * @{ |
| 352 | */ |
| 353 | |
| 354 | inline Bitstream::Bitstream(uint32_t capacity) |
| 355 | { |
| 356 | realloc(capacity * 8); |
| 357 | } |
| 358 | |
| 359 | inline Bitstream::Bitstream(QuantType* data, uint32_t count) |
| 360 | : mData(data), mMaxBits(count), mNumBits(count), mOwnsMemory(false) { } |
| 361 | |
| 362 | inline Bitstream::~Bitstream() |
| 363 | { |
| 364 | if (mData && mOwnsMemory) |
| 365 | bs_free(mData); |
| 366 | } |
| 367 | |
| 368 | inline void Bitstream::writeBits(const QuantType* data, uint32_t count) |
| 369 | { |
| 370 | if (count == 0) |
| 371 | return; |
| 372 | |
| 373 | uint32_t newCursor = mCursor + count; |
| 374 | reallocIfNeeded(newCursor); |
| 375 | |
| 376 | uint32_t destBitsMod = mCursor & (BITS_PER_QUANT - 1); |
| 377 | uint32_t destQuant = mCursor >> BITS_PER_QUANT_LOG2; |
| 378 | uint32_t destMask = (1 << destBitsMod) - 1; |
| 379 | |
| 380 | // If destination is aligned, memcpy everything except the last quant (unless it is also aligned) |
| 381 | if (destBitsMod == 0) |
| 382 | { |
| 383 | uint32_t numQuants = count >> BITS_PER_QUANT_LOG2; |
| 384 | memcpy(&mData[destQuant], data, numQuants * BYTES_PER_QUANT); |
| 385 | |
| 386 | data += numQuants; |
| 387 | count -= numQuants * BITS_PER_QUANT; |
| 388 | destQuant += numQuants; |
| 389 | } |
| 390 | |
| 391 | // Write remaining bits (or all bits if destination wasn't aligned) |
| 392 | while (count > 0) |
| 393 | { |
| 394 | QuantType quant = *data; |
| 395 | data++; |
| 396 | |
| 397 | mData[destQuant] = (quant << destBitsMod) | (mData[destQuant] & destMask); |
| 398 | |
| 399 | uint32_t writtenBits = BITS_PER_QUANT - destBitsMod; |
| 400 | if (count > writtenBits) |
| 401 | mData[destQuant + 1] = (quant >> writtenBits) | (mData[destQuant + 1] & ~destMask); |
| 402 | |
| 403 | destQuant++; |
| 404 | count -= std::min(BITS_PER_QUANT, count); |
| 405 | } |
| 406 | |
| 407 | mCursor = newCursor; |
| 408 | mNumBits = std::max(mNumBits, newCursor); |
| 409 | } |
| 410 | |
| 411 | inline void Bitstream::readBits(QuantType* data, uint32_t count) |
| 412 | { |
| 413 | if (count == 0) |
| 414 | return; |
| 415 | |
| 416 | assert((mCursor + count) <= mNumBits); |
| 417 | |
| 418 | uint32_t newCursor = mCursor + count; |
| 419 | uint32_t srcBitsMod = mCursor & (BITS_PER_QUANT - 1); |
| 420 | uint32_t srcQuant = mCursor >> BITS_PER_QUANT_LOG2; |
| 421 | |
| 422 | // If source is aligned, memcpy everything except the last quant (unless it is also aligned) |
| 423 | if (srcBitsMod == 0) |
| 424 | { |
| 425 | uint32_t numQuants = count >> BITS_PER_QUANT_LOG2; |
| 426 | memcpy(data, &mData[srcQuant], numQuants * BYTES_PER_QUANT); |
| 427 | |
| 428 | data += numQuants; |
| 429 | count -= numQuants * BITS_PER_QUANT; |
| 430 | srcQuant += numQuants; |
| 431 | } |
| 432 | |
| 433 | // Read remaining bits (or all bits if source wasn't aligned) |
| 434 | while (count > 0) |
| 435 | { |
| 436 | QuantType& quant = *data; |
| 437 | data++; |
| 438 | |
| 439 | quant = 0; |
| 440 | quant |= mData[srcQuant] >> srcBitsMod; |
| 441 | |
| 442 | uint32_t readBits = BITS_PER_QUANT - srcBitsMod; |
| 443 | if (count > readBits) |
| 444 | quant |= mData[srcQuant + 1] << readBits; |
| 445 | |
| 446 | srcQuant++; |
| 447 | count -= std::min(BITS_PER_QUANT, count); |
| 448 | } |
| 449 | |
| 450 | mCursor = newCursor; |
| 451 | } |
| 452 | |
| 453 | template <class T> |
| 454 | void Bitstream::write(const T& value) |
| 455 | { |
| 456 | writeBits((QuantType*)&value, sizeof(value) * 8); |
| 457 | } |
| 458 | |
| 459 | template <class T> |
| 460 | void Bitstream::read(T& value) |
| 461 | { |
| 462 | QuantType* temp = (QuantType*)&value; |
| 463 | readBits(temp, sizeof(value) * 8); |
| 464 | } |
| 465 | |
| 466 | inline void Bitstream::write(const bool& value) |
| 467 | { |
| 468 | reallocIfNeeded(mCursor + 1); |
| 469 | |
| 470 | uint32_t destBitsMod = mCursor & (BITS_PER_QUANT - 1); |
| 471 | uint32_t destQuant = mCursor >> BITS_PER_QUANT_LOG2; |
| 472 | |
| 473 | if (value) |
| 474 | mData[destQuant] |= 1U << destBitsMod; |
| 475 | else |
| 476 | mData[destQuant] &= ~(1U << destBitsMod); |
| 477 | |
| 478 | mCursor++; |
| 479 | mNumBits = std::max(mNumBits, mCursor); |
| 480 | } |
| 481 | |
| 482 | inline void Bitstream::read(bool& value) |
| 483 | { |
| 484 | assert((mCursor + 1) <= mNumBits); |
| 485 | |
| 486 | uint32_t srcBitsMod = mCursor & (BITS_PER_QUANT - 1); |
| 487 | uint32_t srcQuant = mCursor >> BITS_PER_QUANT_LOG2; |
| 488 | |
| 489 | value = (mData[srcQuant] >> srcBitsMod) & 0x1; |
| 490 | mCursor++; |
| 491 | } |
| 492 | |
| 493 | inline void Bitstream::write(const String& value) |
| 494 | { |
| 495 | uint32_t length = (uint32_t)value.size(); |
| 496 | writeVarInt(length); |
| 497 | writeBits((QuantType*)value.data(), length * 8); |
| 498 | } |
| 499 | |
| 500 | inline void Bitstream::read(String& value) |
| 501 | { |
| 502 | uint32_t length; |
| 503 | readVarInt(length); |
| 504 | |
| 505 | value.resize(length); |
| 506 | |
| 507 | QuantType* temp = (QuantType*)value.data(); |
| 508 | readBits(temp, length * 8); |
| 509 | } |
| 510 | |
| 511 | template <class T> |
| 512 | void Bitstream::writeDelta(const T& value, const T& lastValue) |
| 513 | { |
| 514 | if(value == lastValue) |
| 515 | write(true); |
| 516 | else |
| 517 | { |
| 518 | write(false); |
| 519 | write(value); |
| 520 | } |
| 521 | } |
| 522 | |
| 523 | template <class T> |
| 524 | void Bitstream::readDelta(T& value, const T& lastValue) |
| 525 | { |
| 526 | bool clean; |
| 527 | read(clean); |
| 528 | |
| 529 | if(clean) |
| 530 | value = lastValue; |
| 531 | else |
| 532 | read(value); |
| 533 | } |
| 534 | |
| 535 | inline void Bitstream::writeDelta(bool value, bool lastValue) |
| 536 | { |
| 537 | write(value); |
| 538 | } |
| 539 | |
| 540 | inline void Bitstream::readDelta(bool& value, bool lastValue) |
| 541 | { |
| 542 | read(value); |
| 543 | } |
| 544 | |
| 545 | inline void Bitstream::writeVarInt(uint32_t value) |
| 546 | { |
| 547 | uint8_t output[5]; |
| 548 | uint32_t count = Bitwise::encodeVarInt(value, output); |
| 549 | |
| 550 | writeBits(output, count * 8); |
| 551 | } |
| 552 | |
| 553 | inline void Bitstream::writeVarInt(int32_t value) |
| 554 | { |
| 555 | uint8_t output[5]; |
| 556 | uint32_t count = Bitwise::encodeVarInt(value, output); |
| 557 | |
| 558 | writeBits(output, count * 8); |
| 559 | } |
| 560 | |
| 561 | inline void Bitstream::writeVarInt(uint64_t value) |
| 562 | { |
| 563 | uint8_t output[10]; |
| 564 | uint32_t count = Bitwise::encodeVarInt(value, output); |
| 565 | |
| 566 | writeBits(output, count * 8); |
| 567 | } |
| 568 | |
| 569 | inline void Bitstream::writeVarInt(int64_t value) |
| 570 | { |
| 571 | uint8_t output[10]; |
| 572 | uint32_t count = Bitwise::encodeVarInt(value, output); |
| 573 | |
| 574 | writeBits(output, count * 8); |
| 575 | } |
| 576 | |
| 577 | inline void Bitstream::readVarInt(uint32_t& value) |
| 578 | { |
| 579 | uint8_t output[5]; |
| 580 | for(uint32_t i = 0; i < 5; i++) |
| 581 | { |
| 582 | readBits(&output[i], 8); |
| 583 | if((output[i] & 0x80) == 0) |
| 584 | break; |
| 585 | } |
| 586 | |
| 587 | Bitwise::decodeVarInt(value, output, 5); |
| 588 | } |
| 589 | |
| 590 | inline void Bitstream::readVarInt(int32_t& value) |
| 591 | { |
| 592 | uint8_t output[5]; |
| 593 | for(uint32_t i = 0; i < 5; i++) |
| 594 | { |
| 595 | readBits(&output[i], 8); |
| 596 | if((output[i] & 0x80) == 0) |
| 597 | break; |
| 598 | } |
| 599 | |
| 600 | Bitwise::decodeVarInt(value, output, 5); |
| 601 | } |
| 602 | |
| 603 | inline void Bitstream::readVarInt(uint64_t& value) |
| 604 | { |
| 605 | uint8_t output[10]; |
| 606 | for(uint32_t i = 0; i < 10; i++) |
| 607 | { |
| 608 | readBits(&output[i], 8); |
| 609 | if((output[i] & 0x80) == 0) |
| 610 | break; |
| 611 | } |
| 612 | |
| 613 | Bitwise::decodeVarInt(value, output, 10); |
| 614 | } |
| 615 | |
| 616 | inline void Bitstream::readVarInt(int64_t& value) |
| 617 | { |
| 618 | uint8_t output[10]; |
| 619 | for(uint32_t i = 0; i < 10; i++) |
| 620 | { |
| 621 | readBits(&output[i], 8); |
| 622 | if((output[i] & 0x80) == 0) |
| 623 | break; |
| 624 | } |
| 625 | |
| 626 | Bitwise::decodeVarInt(value, output, 10); |
| 627 | } |
| 628 | |
| 629 | template <class T> |
| 630 | void Bitstream::writeVarIntDelta(const T& value, const T& lastValue) |
| 631 | { |
| 632 | if(value == lastValue) |
| 633 | write(true); |
| 634 | else |
| 635 | { |
| 636 | write(false); |
| 637 | writeVarInt(value); |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | template <class T> |
| 642 | void Bitstream::readVarIntDelta(T& value, const T& lastValue) |
| 643 | { |
| 644 | bool clean; |
| 645 | read(clean); |
| 646 | |
| 647 | if(clean) |
| 648 | value = lastValue; |
| 649 | else |
| 650 | readVarInt(value); |
| 651 | } |
| 652 | |
| 653 | inline void Bitstream::writeNorm(float value, uint32_t bits) |
| 654 | { |
| 655 | uint32_t encodedVal = Bitwise::unormToUint(value, bits); |
| 656 | writeBits((QuantType*)&encodedVal, bits); |
| 657 | } |
| 658 | |
| 659 | inline void Bitstream::readNorm(float& value, uint32_t bits) |
| 660 | { |
| 661 | uint32_t encodedVal = 0; |
| 662 | readBits((QuantType*)&encodedVal, bits); |
| 663 | value = Bitwise::uintToUnorm(encodedVal, bits); |
| 664 | } |
| 665 | |
| 666 | inline void Bitstream::writeNorm(const Vector3& value, uint32_t bits) |
| 667 | { |
| 668 | writeRange(value.x, -1.0f, 1.0f, bits); |
| 669 | writeRange(value.y, -1.0f, 1.0f, bits); |
| 670 | writeRange(value.z, -1.0f, 1.0f, bits); |
| 671 | } |
| 672 | |
| 673 | inline void Bitstream::readNorm(Vector3& value, uint32_t bits) |
| 674 | { |
| 675 | readRange(value.x, -1.0f, 1.0f, bits); |
| 676 | readRange(value.y, -1.0f, 1.0f, bits); |
| 677 | readRange(value.z, -1.0f, 1.0f, bits); |
| 678 | } |
| 679 | |
| 680 | inline void Bitstream::writeNorm(const Quaternion& value, uint32_t bits) |
| 681 | { |
| 682 | writeRange(value.x, -1.0f, 1.0f, bits); |
| 683 | writeRange(value.y, -1.0f, 1.0f, bits); |
| 684 | writeRange(value.z, -1.0f, 1.0f, bits); |
| 685 | writeRange(value.w, -1.0f, 1.0f, bits); |
| 686 | } |
| 687 | |
| 688 | inline void Bitstream::readNorm(Quaternion& value, uint32_t bits) |
| 689 | { |
| 690 | readRange(value.x, -1.0f, 1.0f, bits); |
| 691 | readRange(value.y, -1.0f, 1.0f, bits); |
| 692 | readRange(value.z, -1.0f, 1.0f, bits); |
| 693 | readRange(value.w, -1.0f, 1.0f, bits); |
| 694 | } |
| 695 | |
| 696 | template <class T> |
| 697 | void Bitstream::writeNormDelta(const T& value, const T& lastValue, uint32_t bits) |
| 698 | { |
| 699 | if(value == lastValue) |
| 700 | write(true); |
| 701 | else |
| 702 | { |
| 703 | write(false); |
| 704 | writeNorm(value, bits); |
| 705 | } |
| 706 | } |
| 707 | |
| 708 | template <class T> |
| 709 | void Bitstream::readNormDelta(T& value, const T& lastValue, uint32_t bits) |
| 710 | { |
| 711 | bool clean; |
| 712 | read(clean); |
| 713 | |
| 714 | if(clean) |
| 715 | value = lastValue; |
| 716 | else |
| 717 | readNorm(value, bits); |
| 718 | } |
| 719 | |
| 720 | |
| 721 | template <class T> |
| 722 | void Bitstream::writeRange(const T& value, const T& min, const T& max) |
| 723 | { |
| 724 | T range = max - min; |
| 725 | uint32_t bits = Bitwise::mostSignificantBit(range) + 1; |
| 726 | |
| 727 | T rangeVal = value - min; |
| 728 | writeBits((QuantType*)&rangeVal, bits); |
| 729 | } |
| 730 | |
| 731 | template <class T> |
| 732 | void Bitstream::readRange(T& value, const T& min, const T& max) |
| 733 | { |
| 734 | T range = max - min; |
| 735 | uint32_t bits = Bitwise::mostSignificantBit(range) + 1; |
| 736 | |
| 737 | value = 0; |
| 738 | readBits((QuantType*)&value, bits); |
| 739 | value += min; |
| 740 | } |
| 741 | |
| 742 | template <class T> |
| 743 | void Bitstream::writeRangeDelta(const T& value, const T& lastValue, const T& min, const T& max) |
| 744 | { |
| 745 | if(value == lastValue) |
| 746 | write(true); |
| 747 | else |
| 748 | { |
| 749 | write(false); |
| 750 | writeRange(value, min, max); |
| 751 | } |
| 752 | } |
| 753 | |
| 754 | template <class T> |
| 755 | void Bitstream::readRangeDelta(T& value, const T& lastValue, const T& min, const T& max) |
| 756 | { |
| 757 | bool clean; |
| 758 | read(clean); |
| 759 | |
| 760 | if(clean) |
| 761 | value = lastValue; |
| 762 | else |
| 763 | readRange(value, min, max); |
| 764 | } |
| 765 | |
| 766 | inline void Bitstream::writeRange(float value, float min, float max, uint32_t bits) |
| 767 | { |
| 768 | float pct = Math::clamp01((value - min)/(max - min)); |
| 769 | writeNorm(pct, bits); |
| 770 | } |
| 771 | |
| 772 | inline void Bitstream::readRange(float& value, float min, float max, uint32_t bits) |
| 773 | { |
| 774 | float pct; |
| 775 | readNorm(pct, bits); |
| 776 | |
| 777 | value = min + (max - min) * pct; |
| 778 | } |
| 779 | |
| 780 | inline void Bitstream::writeRangeDelta(float value, float lastValue, float min, float max, uint32_t bits) |
| 781 | { |
| 782 | if(value == lastValue) |
| 783 | write(true); |
| 784 | else |
| 785 | { |
| 786 | write(false); |
| 787 | writeRange(value, min, max, bits); |
| 788 | } |
| 789 | } |
| 790 | |
| 791 | inline void Bitstream::readRangeDelta(float& value, float lastValue, float min, float max, uint32_t bits) |
| 792 | { |
| 793 | bool clean; |
| 794 | read(clean); |
| 795 | |
| 796 | if(clean) |
| 797 | value = lastValue; |
| 798 | else |
| 799 | readRange(value, min, max, bits); |
| 800 | } |
| 801 | |
| 802 | inline void Bitstream::skip(int32_t count) |
| 803 | { |
| 804 | mCursor = (uint32_t)Math::clamp((int32_t)mCursor + count, 0, (int32_t)mMaxBits); |
| 805 | } |
| 806 | |
| 807 | inline void Bitstream::seek(uint32_t pos) |
| 808 | { |
| 809 | mCursor = std::min(pos, mMaxBits); |
| 810 | } |
| 811 | |
| 812 | inline void Bitstream::align(uint32_t count) |
| 813 | { |
| 814 | if (count == 0) |
| 815 | return; |
| 816 | |
| 817 | uint32_t bits = count * 8; |
| 818 | skip(bits - (((mCursor - 1) & (bits - 1)) + 1)); |
| 819 | } |
| 820 | |
| 821 | inline void Bitstream::reallocIfNeeded(uint32_t numBits) |
| 822 | { |
| 823 | if (numBits > mMaxBits) |
| 824 | { |
| 825 | if (mOwnsMemory) |
| 826 | { |
| 827 | // Grow |
| 828 | const uint32_t newMaxBits = numBits + 4 * BITS_PER_QUANT + numBits / 2; |
| 829 | realloc(newMaxBits); |
| 830 | } |
| 831 | else |
| 832 | { |
| 833 | // Caller accessing bits outside of external memory range |
| 834 | assert(false); |
| 835 | } |
| 836 | } |
| 837 | } |
| 838 | |
| 839 | inline void Bitstream::realloc(uint32_t numBits) |
| 840 | { |
| 841 | numBits = Math::divideAndRoundUp(numBits, BITS_PER_QUANT) * BITS_PER_QUANT; |
| 842 | |
| 843 | if (numBits != mMaxBits) |
| 844 | { |
| 845 | assert(numBits > mMaxBits); |
| 846 | |
| 847 | const uint32_t numQuants = Math::divideAndRoundUp(numBits, BITS_PER_QUANT); |
| 848 | |
| 849 | // Note: Eventually add support for custom allocators |
| 850 | auto buffer = bs_allocN<uint8_t>(numQuants); |
| 851 | if (mData) |
| 852 | { |
| 853 | const uint32_t numBytes = Math::divideAndRoundUp(mMaxBits, BITS_PER_QUANT) * BYTES_PER_QUANT; |
| 854 | memcpy(buffer, mData, numBytes); |
| 855 | bs_free(mData); |
| 856 | } |
| 857 | |
| 858 | mData = buffer; |
| 859 | mMaxBits = numBits; |
| 860 | } |
| 861 | } |
| 862 | } |
| 863 | |