1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcrt/cfx_bitstream.h"
8 
9 #include <limits>
10 
11 #include "core/fxcrt/fx_memory.h"
12 #include "core/fxcrt/fx_system.h"
13 
CFX_BitStream(pdfium::span<const uint8_t> pData)14 CFX_BitStream::CFX_BitStream(pdfium::span<const uint8_t> pData)
15     : m_BitPos(0), m_BitSize(pData.size() * 8), m_pData(pData.data()) {
16   ASSERT(pData.size() <= std::numeric_limits<uint32_t>::max() / 8);
17 }
18 
19 CFX_BitStream::~CFX_BitStream() = default;
20 
ByteAlign()21 void CFX_BitStream::ByteAlign() {
22   m_BitPos = FxAlignToBoundary<8>(m_BitPos);
23 }
24 
GetBits(uint32_t nBits)25 uint32_t CFX_BitStream::GetBits(uint32_t nBits) {
26   ASSERT(nBits > 0);
27   ASSERT(nBits <= 32);
28   if (nBits > m_BitSize || m_BitPos > m_BitSize - nBits)
29     return 0;
30 
31   const uint32_t bit_pos = m_BitPos % 8;
32   uint32_t byte_pos = m_BitPos / 8;
33   const uint8_t* data = m_pData.Get();
34   uint8_t current_byte = data[byte_pos];
35 
36   if (nBits == 1) {
37     int bit = (current_byte & (1 << (7 - bit_pos))) ? 1 : 0;
38     m_BitPos++;
39     return bit;
40   }
41 
42   uint32_t bit_left = nBits;
43   uint32_t result = 0;
44   if (bit_pos) {
45     uint32_t bits_readable = 8 - bit_pos;
46     if (bits_readable >= bit_left) {
47       result = (current_byte & (0xff >> bit_pos)) >> (bits_readable - bit_left);
48       m_BitPos += bit_left;
49       return result;
50     }
51     bit_left -= bits_readable;
52     result = (current_byte & ((1 << bits_readable) - 1)) << bit_left;
53     ++byte_pos;
54   }
55   while (bit_left >= 8) {
56     bit_left -= 8;
57     result |= data[byte_pos++] << bit_left;
58   }
59   if (bit_left)
60     result |= data[byte_pos] >> (8 - bit_left);
61   m_BitPos += nBits;
62   return result;
63 }
64