// Copyright 2015 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fxcodec/jbig2/JBig2_BitStream.h"

#include <algorithm>

#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/numerics/safe_conversions.h"

namespace {

pdfium::span<const uint8_t> ValidatedSpan(pdfium::span<const uint8_t> sp) {
  if (sp.size() > 256 * 1024 * 1024) {
    return {};
  }
  return sp;
}

}  // namespace

CJBig2_BitStream::CJBig2_BitStream(pdfium::span<const uint8_t> pSrcStream,
                                   uint64_t key)
    : span_(ValidatedSpan(pSrcStream)), key_(key) {}

CJBig2_BitStream::~CJBig2_BitStream() = default;

int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, uint32_t* dwResult) {
  if (!IsInBounds()) {
    return -1;
  }

  uint32_t dwBitPos = getBitPos();
  if (dwBitPos > LengthInBits()) {
    return -1;
  }

  *dwResult = 0;
  if (dwBitPos + dwBits <= LengthInBits()) {
    dwBitPos = dwBits;
  } else {
    dwBitPos = LengthInBits() - dwBitPos;
  }

  for (; dwBitPos > 0; --dwBitPos) {
    *dwResult =
        (*dwResult << 1) | ((span_[byte_idx_] >> (7 - bit_idx_)) & 0x01);
    AdvanceBit();
  }
  return 0;
}

int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, int32_t* nResult) {
  if (!IsInBounds()) {
    return -1;
  }

  uint32_t dwBitPos = getBitPos();
  if (dwBitPos > LengthInBits()) {
    return -1;
  }

  *nResult = 0;
  if (dwBitPos + dwBits <= LengthInBits()) {
    dwBitPos = dwBits;
  } else {
    dwBitPos = LengthInBits() - dwBitPos;
  }

  for (; dwBitPos > 0; --dwBitPos) {
    *nResult = (*nResult << 1) | ((span_[byte_idx_] >> (7 - bit_idx_)) & 0x01);
    AdvanceBit();
  }
  return 0;
}

int32_t CJBig2_BitStream::read1Bit(uint32_t* dwResult) {
  if (!IsInBounds()) {
    return -1;
  }

  *dwResult = (span_[byte_idx_] >> (7 - bit_idx_)) & 0x01;
  AdvanceBit();
  return 0;
}

int32_t CJBig2_BitStream::read1Bit(bool* bResult) {
  if (!IsInBounds()) {
    return -1;
  }

  *bResult = (span_[byte_idx_] >> (7 - bit_idx_)) & 0x01;
  AdvanceBit();
  return 0;
}

int32_t CJBig2_BitStream::read1Byte(uint8_t* cResult) {
  if (!IsInBounds()) {
    return -1;
  }

  *cResult = span_[byte_idx_];
  ++byte_idx_;
  return 0;
}

int32_t CJBig2_BitStream::readInteger(uint32_t* dwResult) {
  if (byte_idx_ + 3 >= span_.size()) {
    return -1;
  }

  *dwResult = (span_[byte_idx_] << 24) | (span_[byte_idx_ + 1] << 16) |
              (span_[byte_idx_ + 2] << 8) | span_[byte_idx_ + 3];
  byte_idx_ += 4;
  return 0;
}

int32_t CJBig2_BitStream::readShortInteger(uint16_t* dwResult) {
  if (byte_idx_ + 1 >= span_.size()) {
    return -1;
  }

  *dwResult = (span_[byte_idx_] << 8) | span_[byte_idx_ + 1];
  byte_idx_ += 2;
  return 0;
}

void CJBig2_BitStream::alignByte() {
  if (bit_idx_ != 0) {
    addOffset(1);
    bit_idx_ = 0;
  }
}

uint8_t CJBig2_BitStream::getCurByte() const {
  return IsInBounds() ? span_[byte_idx_] : 0;
}

void CJBig2_BitStream::incByteIdx() {
  addOffset(1);
}

uint8_t CJBig2_BitStream::getCurByte_arith() const {
  return IsInBounds() ? span_[byte_idx_] : 0xFF;
}

uint8_t CJBig2_BitStream::getNextByte_arith() const {
  return byte_idx_ + 1 < span_.size() ? span_[byte_idx_ + 1] : 0xFF;
}

uint32_t CJBig2_BitStream::getOffset() const {
  return byte_idx_;
}

void CJBig2_BitStream::setOffset(uint32_t dwOffset) {
  byte_idx_ =
      std::min(dwOffset, pdfium::checked_cast<uint32_t>(getBufSpan().size()));
}

void CJBig2_BitStream::addOffset(uint32_t dwDelta) {
  FX_SAFE_UINT32 new_offset = byte_idx_;
  new_offset += dwDelta;
  if (new_offset.IsValid()) {
    setOffset(new_offset.ValueOrDie());
  }
}

uint32_t CJBig2_BitStream::getBitPos() const {
  return (byte_idx_ << 3) + bit_idx_;
}

void CJBig2_BitStream::setBitPos(uint32_t dwBitPos) {
  byte_idx_ = dwBitPos >> 3;
  bit_idx_ = dwBitPos & 7;
}

pdfium::span<const uint8_t> CJBig2_BitStream::getCurrentSpan(
    uint32_t size) const {
  return span_.subspan(byte_idx_, size);
}

uint32_t CJBig2_BitStream::getByteLeft() const {
  FX_SAFE_UINT32 result = getBufSpan().size();
  result -= byte_idx_;
  return result.ValueOrDie();
}

void CJBig2_BitStream::AdvanceBit() {
  if (bit_idx_ == 7) {
    ++byte_idx_;
    bit_idx_ = 0;
  } else {
    ++bit_idx_;
  }
}

bool CJBig2_BitStream::IsInBounds() const {
  return byte_idx_ < getBufSpan().size();
}

uint32_t CJBig2_BitStream::LengthInBits() const {
  FX_SAFE_UINT32 result = getBufSpan().size();
  result *= 8;
  return result.ValueOrDie();
}
