1*07fb1d06SElliott Hughes // Copyright 2017 The ChromiumOS Authors 2*07fb1d06SElliott Hughes // Use of this source code is governed by a BSD-style license that can be 3*07fb1d06SElliott Hughes // found in the LICENSE file. 4*07fb1d06SElliott Hughes 5*07fb1d06SElliott Hughes #include "puffin/src/bit_reader.h" 6*07fb1d06SElliott Hughes 7*07fb1d06SElliott Hughes #include "puffin/src/logging.h" 8*07fb1d06SElliott Hughes 9*07fb1d06SElliott Hughes namespace puffin { 10*07fb1d06SElliott Hughes CacheBits(size_t nbits)11*07fb1d06SElliott Hughesbool BufferBitReader::CacheBits(size_t nbits) { 12*07fb1d06SElliott Hughes if ((in_size_ - index_) * 8 + in_cache_bits_ < nbits) { 13*07fb1d06SElliott Hughes return false; 14*07fb1d06SElliott Hughes } 15*07fb1d06SElliott Hughes if (nbits > sizeof(in_cache_) * 8) { 16*07fb1d06SElliott Hughes return false; 17*07fb1d06SElliott Hughes } 18*07fb1d06SElliott Hughes while (in_cache_bits_ < nbits) { 19*07fb1d06SElliott Hughes in_cache_ |= in_buf_[index_++] << in_cache_bits_; 20*07fb1d06SElliott Hughes in_cache_bits_ += 8; 21*07fb1d06SElliott Hughes } 22*07fb1d06SElliott Hughes return true; 23*07fb1d06SElliott Hughes } 24*07fb1d06SElliott Hughes ReadBits(size_t nbits)25*07fb1d06SElliott Hughesuint32_t BufferBitReader::ReadBits(size_t nbits) { 26*07fb1d06SElliott Hughes return in_cache_ & ((1U << nbits) - 1); 27*07fb1d06SElliott Hughes } 28*07fb1d06SElliott Hughes DropBits(size_t nbits)29*07fb1d06SElliott Hughesvoid BufferBitReader::DropBits(size_t nbits) { 30*07fb1d06SElliott Hughes in_cache_ >>= nbits; 31*07fb1d06SElliott Hughes in_cache_bits_ -= nbits; 32*07fb1d06SElliott Hughes } 33*07fb1d06SElliott Hughes ReadBoundaryBits()34*07fb1d06SElliott Hughesuint8_t BufferBitReader::ReadBoundaryBits() { 35*07fb1d06SElliott Hughes return in_cache_ & ((1 << (in_cache_bits_ & 7)) - 1); 36*07fb1d06SElliott Hughes } 37*07fb1d06SElliott Hughes SkipBoundaryBits()38*07fb1d06SElliott Hughessize_t BufferBitReader::SkipBoundaryBits() { 39*07fb1d06SElliott Hughes size_t nbits = in_cache_bits_ & 7; 40*07fb1d06SElliott Hughes in_cache_ >>= nbits; 41*07fb1d06SElliott Hughes in_cache_bits_ -= nbits; 42*07fb1d06SElliott Hughes return nbits; 43*07fb1d06SElliott Hughes } 44*07fb1d06SElliott Hughes GetByteReaderFn(size_t length,std::function<bool (uint8_t *,size_t)> * read_fn)45*07fb1d06SElliott Hughesbool BufferBitReader::GetByteReaderFn( 46*07fb1d06SElliott Hughes size_t length, std::function<bool(uint8_t*, size_t)>* read_fn) { 47*07fb1d06SElliott Hughes index_ -= (in_cache_bits_ + 7) / 8; 48*07fb1d06SElliott Hughes in_cache_ = 0; 49*07fb1d06SElliott Hughes in_cache_bits_ = 0; 50*07fb1d06SElliott Hughes TEST_AND_RETURN_FALSE(length <= in_size_ - index_); 51*07fb1d06SElliott Hughes *read_fn = [this, length](uint8_t* buffer, size_t count) mutable { 52*07fb1d06SElliott Hughes TEST_AND_RETURN_FALSE(count <= length); 53*07fb1d06SElliott Hughes if (buffer != nullptr) { 54*07fb1d06SElliott Hughes memcpy(buffer, &in_buf_[index_], count); 55*07fb1d06SElliott Hughes } 56*07fb1d06SElliott Hughes index_ += count; 57*07fb1d06SElliott Hughes length -= count; 58*07fb1d06SElliott Hughes return true; 59*07fb1d06SElliott Hughes }; 60*07fb1d06SElliott Hughes return true; 61*07fb1d06SElliott Hughes } 62*07fb1d06SElliott Hughes Offset() const63*07fb1d06SElliott Hughessize_t BufferBitReader::Offset() const { 64*07fb1d06SElliott Hughes return index_ - in_cache_bits_ / 8; 65*07fb1d06SElliott Hughes } 66*07fb1d06SElliott Hughes OffsetInBits() const67*07fb1d06SElliott Hughesuint64_t BufferBitReader::OffsetInBits() const { 68*07fb1d06SElliott Hughes return (index_ * 8) - in_cache_bits_; 69*07fb1d06SElliott Hughes } 70*07fb1d06SElliott Hughes BitsRemaining() const71*07fb1d06SElliott Hughesuint64_t BufferBitReader::BitsRemaining() const { 72*07fb1d06SElliott Hughes return ((in_size_ - index_) * 8) + in_cache_bits_; 73*07fb1d06SElliott Hughes } 74*07fb1d06SElliott Hughes 75*07fb1d06SElliott Hughes } // namespace puffin 76