1// Copyright 2015 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/fxcodec/jbig2/JBig2_BitStream.h"
8
9#include <algorithm>
10
11#include "core/fpdfapi/parser/cpdf_stream.h"
12#include "core/fpdfapi/parser/cpdf_stream_acc.h"
13
14CJBig2_BitStream::CJBig2_BitStream(const RetainPtr<CPDF_StreamAcc>& pSrcStream)
15    : m_pBuf(pSrcStream->GetData()),
16      m_dwLength(pSrcStream->GetSize()),
17      m_dwByteIdx(0),
18      m_dwBitIdx(0),
19      m_dwObjNum(pSrcStream->GetStream() ? pSrcStream->GetStream()->GetObjNum()
20                                         : 0) {
21  if (m_dwLength > 256 * 1024 * 1024) {
22    m_dwLength = 0;
23    m_pBuf = nullptr;
24  }
25}
26
27CJBig2_BitStream::~CJBig2_BitStream() {}
28
29int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, uint32_t* dwResult) {
30  if (!IsInBounds())
31    return -1;
32
33  uint32_t dwBitPos = getBitPos();
34  if (dwBitPos > LengthInBits())
35    return -1;
36
37  *dwResult = 0;
38  if (dwBitPos + dwBits <= LengthInBits())
39    dwBitPos = dwBits;
40  else
41    dwBitPos = LengthInBits() - dwBitPos;
42
43  for (; dwBitPos > 0; --dwBitPos) {
44    *dwResult =
45        (*dwResult << 1) | ((m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01);
46    AdvanceBit();
47  }
48  return 0;
49}
50
51int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, int32_t* nResult) {
52  if (!IsInBounds())
53    return -1;
54
55  uint32_t dwBitPos = getBitPos();
56  if (dwBitPos > LengthInBits())
57    return -1;
58
59  *nResult = 0;
60  if (dwBitPos + dwBits <= LengthInBits())
61    dwBitPos = dwBits;
62  else
63    dwBitPos = LengthInBits() - dwBitPos;
64
65  for (; dwBitPos > 0; --dwBitPos) {
66    *nResult =
67        (*nResult << 1) | ((m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01);
68    AdvanceBit();
69  }
70  return 0;
71}
72
73int32_t CJBig2_BitStream::read1Bit(uint32_t* dwResult) {
74  if (!IsInBounds())
75    return -1;
76
77  *dwResult = (m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01;
78  AdvanceBit();
79  return 0;
80}
81
82int32_t CJBig2_BitStream::read1Bit(bool* bResult) {
83  if (!IsInBounds())
84    return -1;
85
86  *bResult = (m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01;
87  AdvanceBit();
88  return 0;
89}
90
91int32_t CJBig2_BitStream::read1Byte(uint8_t* cResult) {
92  if (!IsInBounds())
93    return -1;
94
95  *cResult = m_pBuf[m_dwByteIdx];
96  ++m_dwByteIdx;
97  return 0;
98}
99
100int32_t CJBig2_BitStream::readInteger(uint32_t* dwResult) {
101  if (m_dwByteIdx + 3 >= m_dwLength)
102    return -1;
103
104  *dwResult = (m_pBuf[m_dwByteIdx] << 24) | (m_pBuf[m_dwByteIdx + 1] << 16) |
105              (m_pBuf[m_dwByteIdx + 2] << 8) | m_pBuf[m_dwByteIdx + 3];
106  m_dwByteIdx += 4;
107  return 0;
108}
109
110int32_t CJBig2_BitStream::readShortInteger(uint16_t* dwResult) {
111  if (m_dwByteIdx + 1 >= m_dwLength)
112    return -1;
113
114  *dwResult = (m_pBuf[m_dwByteIdx] << 8) | m_pBuf[m_dwByteIdx + 1];
115  m_dwByteIdx += 2;
116  return 0;
117}
118
119void CJBig2_BitStream::alignByte() {
120  if (m_dwBitIdx != 0) {
121    ++m_dwByteIdx;
122    m_dwBitIdx = 0;
123  }
124}
125
126uint8_t CJBig2_BitStream::getCurByte() const {
127  return IsInBounds() ? m_pBuf[m_dwByteIdx] : 0;
128}
129
130void CJBig2_BitStream::incByteIdx() {
131  if (IsInBounds())
132    ++m_dwByteIdx;
133}
134
135uint8_t CJBig2_BitStream::getCurByte_arith() const {
136  return IsInBounds() ? m_pBuf[m_dwByteIdx] : 0xFF;
137}
138
139uint8_t CJBig2_BitStream::getNextByte_arith() const {
140  return m_dwByteIdx + 1 < m_dwLength ? m_pBuf[m_dwByteIdx + 1] : 0xFF;
141}
142
143uint32_t CJBig2_BitStream::getOffset() const {
144  return m_dwByteIdx;
145}
146
147void CJBig2_BitStream::setOffset(uint32_t dwOffset) {
148  m_dwByteIdx = std::min(dwOffset, m_dwLength);
149}
150
151uint32_t CJBig2_BitStream::getBitPos() const {
152  return (m_dwByteIdx << 3) + m_dwBitIdx;
153}
154
155void CJBig2_BitStream::setBitPos(uint32_t dwBitPos) {
156  m_dwByteIdx = dwBitPos >> 3;
157  m_dwBitIdx = dwBitPos & 7;
158}
159
160const uint8_t* CJBig2_BitStream::getBuf() const {
161  return m_pBuf;
162}
163
164const uint8_t* CJBig2_BitStream::getPointer() const {
165  return m_pBuf + m_dwByteIdx;
166}
167
168void CJBig2_BitStream::offset(uint32_t dwOffset) {
169  m_dwByteIdx += dwOffset;
170}
171
172uint32_t CJBig2_BitStream::getByteLeft() const {
173  return m_dwLength - m_dwByteIdx;
174}
175
176void CJBig2_BitStream::AdvanceBit() {
177  if (m_dwBitIdx == 7) {
178    ++m_dwByteIdx;
179    m_dwBitIdx = 0;
180  } else {
181    ++m_dwBitIdx;
182  }
183}
184
185bool CJBig2_BitStream::IsInBounds() const {
186  return m_dwByteIdx < m_dwLength;
187}
188
189uint32_t CJBig2_BitStream::LengthInBits() const {
190  return m_dwLength << 3;
191}
192
193uint32_t CJBig2_BitStream::getObjNum() const {
194  return m_dwObjNum;
195}
196