// Copyright 2014 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_huffman_decoder.h"

#include "core/fxcodec/jbig2/jbig2_define.h"
#include "core/fxcrt/fx_safe_types.h"

CJBig2_HuffmanDecoder::CJBig2_HuffmanDecoder(CJBig2_BitStream* pStream)
    : stream_(pStream) {}

CJBig2_HuffmanDecoder::~CJBig2_HuffmanDecoder() = default;

int CJBig2_HuffmanDecoder::DecodeAValue(const CJBig2_HuffmanTable* pTable,
                                        int* nResult) {
  FX_SAFE_INT32 nSafeVal = 0;
  int nBits = 0;
  while (true) {
    uint32_t nTmp;
    if (stream_->read1Bit(&nTmp) == -1) {
      break;
    }

    nSafeVal <<= 1;
    if (!nSafeVal.IsValid()) {
      break;
    }

    nSafeVal |= nTmp;
    ++nBits;
    const int32_t nVal = nSafeVal.ValueOrDie();
    for (uint32_t i = 0; i < pTable->Size(); ++i) {
      const JBig2HuffmanCode& code = pTable->GetCODES()[i];
      if (code.codelen != nBits || code.code != nVal) {
        continue;
      }

      if (pTable->IsHTOOB() && i == pTable->Size() - 1) {
        return kJBig2OOB;
      }

      if (stream_->readNBits(pTable->GetRANGELEN()[i], &nTmp) == -1) {
        return -1;
      }

      uint32_t offset = pTable->IsHTOOB() ? 3 : 2;
      if (i == pTable->Size() - offset) {
        *nResult = pTable->GetRANGELOW()[i] - nTmp;
      } else {
        *nResult = pTable->GetRANGELOW()[i] + nTmp;
      }
      return 0;
    }
  }
  return -1;
}
