tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BitWriter.cpp (3294B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "BitWriter.h"
      6 
      7 #include <stdint.h>
      8 
      9 #include "MediaData.h"
     10 #include "mozilla/MathAlgorithms.h"
     11 
     12 namespace mozilla {
     13 
     14 constexpr uint8_t golombLen[256] = {
     15    1,  3,  3,  5,  5,  5,  5,  7,  7,  7,  7,  7,  7,  7,  7,  9,  9,  9,  9,
     16    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  11, 11, 11, 11, 11, 11, 11,
     17    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
     18    11, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
     19    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
     20    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
     21    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
     22    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
     23    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
     24    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
     25    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
     26    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
     27    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
     28    15, 15, 15, 15, 15, 15, 15, 15, 17,
     29 };
     30 
     31 BitWriter::BitWriter(MediaByteBuffer* aBuffer) : mBuffer(aBuffer) {}
     32 
     33 BitWriter::~BitWriter() = default;
     34 
     35 void BitWriter::WriteBits(uint64_t aValue, size_t aBits) {
     36  MOZ_ASSERT(aBits <= sizeof(uint64_t) * 8);
     37 
     38  while (aBits) {
     39    if (mBitIndex == 0) {
     40      mBuffer->AppendElement(0);
     41    }
     42 
     43    const uint8_t clearMask = ~(~0u << (8 - mBitIndex));
     44    uint8_t mask = 0;
     45 
     46    if (mBitIndex + aBits > 8) {
     47      // Not enough bits in the current byte to write all the bits
     48      // required, we'll process what we can and continue with the left over.
     49      const uint8_t leftOverBits = mBitIndex + aBits - 8;
     50      const uint64_t leftOver = aValue & (~uint64_t(0) >> (8 - mBitIndex));
     51      mask = aValue >> leftOverBits;
     52 
     53      mBitIndex = 8;
     54      aValue = leftOver;
     55      aBits = leftOverBits;
     56    } else {
     57      const uint8_t offset = 8 - mBitIndex - aBits;
     58      mask = aValue << offset;
     59 
     60      mBitIndex += aBits;
     61      aBits = 0;
     62    }
     63 
     64    mBuffer->ElementAt(mPosition) |= mask & clearMask;
     65 
     66    if (mBitIndex == 8) {
     67      mPosition++;
     68      mBitIndex = 0;
     69    }
     70  }
     71 }
     72 
     73 void BitWriter::WriteUE(uint32_t aValue) {
     74  MOZ_ASSERT(aValue <= (UINT32_MAX - 1));
     75 
     76  if (aValue < 256) {
     77    WriteBits(aValue + 1, golombLen[aValue]);
     78  } else {
     79    const uint32_t e = FloorLog2(aValue + 1);
     80    WriteBits(aValue + 1, e * 2 + 1);
     81  }
     82 }
     83 
     84 void BitWriter::WriteULEB128(uint64_t aValue) {
     85  // See https://en.wikipedia.org/wiki/LEB128#Encode_unsigned_integer
     86  do {
     87    uint8_t byte = aValue & 0x7F;
     88    aValue >>= 7;
     89    WriteBit(aValue != 0);
     90    WriteBits(byte, 7);
     91  } while (aValue != 0);
     92 }
     93 
     94 void BitWriter::CloseWithRbspTrailing() {
     95  WriteBit(true);
     96  WriteBits(0, (8 - mBitIndex) & 7);
     97 }
     98 
     99 void BitWriter::AdvanceBytes(uint32_t aByteOffset) {
    100  MOZ_DIAGNOSTIC_ASSERT(mBitIndex == 0);
    101  mPosition += aByteOffset;
    102 }
    103 
    104 }  // namespace mozilla