// Copyright 2017 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/fpdfapi/font/cpdf_tounicodemap.h"

#include <algorithm>
#include <utility>
#include <variant>

#include "core/fpdfapi/font/cpdf_cid2unicodemap.h"
#include "core/fpdfapi/font/cpdf_fontglobals.h"
#include "core/fpdfapi/parser/cpdf_simple_parser.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_safe_types.h"

namespace {

constexpr uint32_t kCidLimit = 0xffff;

// Per spec, bfchar and bfrange sections should have at most 100 entries. Some
// PDFs violate this part of the spec and other PDF parsers tolerate it. So set
// an artificially high limit that should be good enough for PDFs in the wild,
// but not too high to prevent fuzzers from slowing down fuzzing.
constexpr int kOutOfSpecBFLimit = 160000;

WideString StringDataAdd(WideString str) {
  WideString ret;
  wchar_t value = 1;
  for (size_t i = str.GetLength(); i > 0; --i) {
    wchar_t ch = str[i - 1] + value;
    if (ch < str[i - 1]) {
      ret.InsertAtFront(0);
    } else {
      ret.InsertAtFront(ch);
      value = 0;
    }
  }
  if (value) {
    ret.InsertAtFront(value);
  }
  return ret;
}

}  // namespace

CPDF_ToUnicodeMap::CPDF_ToUnicodeMap(RetainPtr<const CPDF_Stream> pStream) {
  Load(std::move(pStream));
}

CPDF_ToUnicodeMap::~CPDF_ToUnicodeMap() = default;

WideString CPDF_ToUnicodeMap::Lookup(uint32_t charcode) const {
  auto it = map_.find(charcode);
  if (it == map_.end()) {
    if (!base_map_) {
      return WideString();
    }
    return WideString(
        base_map_->UnicodeFromCID(static_cast<uint16_t>(charcode)));
  }

  uint32_t value = it->second;
  wchar_t unicode = static_cast<wchar_t>(value & 0xffff);
  if (unicode != 0xffff) {
    return WideString(unicode);
  }

  size_t index = value >> 16;
  return index < multi_char_vec_.size() ? multi_char_vec_[index] : WideString();
}

uint32_t CPDF_ToUnicodeMap::ReverseLookup(wchar_t unicode) const {
  auto it = reverse_map_.find(unicode);
  return it != reverse_map_.end() ? it->second : 0;
}

size_t CPDF_ToUnicodeMap::GetUnicodeCountByCharcodeForTesting(
    uint32_t charcode) const {
  return std::ranges::count_if(reverse_map_, [charcode](const auto& entry) {
    return entry.second == charcode;
  });
}

// static
std::optional<uint32_t> CPDF_ToUnicodeMap::StringToCode(ByteStringView str) {
  size_t len = str.GetLength();
  if (len <= 2 || str[0] != '<' || str[len - 1] != '>') {
    return std::nullopt;
  }

  FX_SAFE_UINT32 code = 0;
  for (char c : str.Substr(1, len - 2)) {
    // Ignore whitespace https://crbug.com/42271078
    if (PDFCharIsWhitespace(c)) {
      continue;
    }
    if (!FXSYS_IsHexDigit(c)) {
      return std::nullopt;
    }

    code = code * 16 + FXSYS_HexCharToInt(c);
    if (!code.IsValid()) {
      return std::nullopt;
    }
  }
  return std::optional<uint32_t>(code.ValueOrDie());
}

// static
WideString CPDF_ToUnicodeMap::StringToWideString(ByteStringView str) {
  size_t len = str.GetLength();
  if (len <= 2 || str[0] != '<' || str[len - 1] != '>') {
    return WideString();
  }

  WideString result;
  int byte_pos = 0;
  wchar_t ch = 0;
  for (char c : str.Substr(1, len - 2)) {
    // Ignore whitespace https://crbug.com/42270019
    if (PDFCharIsWhitespace(c)) {
      continue;
    }
    if (!FXSYS_IsHexDigit(c)) {
      break;
    }

    ch = ch * 16 + FXSYS_HexCharToInt(c);
    byte_pos++;
    if (byte_pos == 4) {
      result += ch;
      byte_pos = 0;
      ch = 0;
    }
  }
  return result;
}

void CPDF_ToUnicodeMap::Load(RetainPtr<const CPDF_Stream> pStream) {
  CIDSet cid_set = CIDSet::kUnknown;
  auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pStream));
  pAcc->LoadAllDataFiltered();
  CPDF_SimpleParser parser(pAcc->GetSpan());
  ByteStringView previous_word;
  while (true) {
    ByteStringView word = parser.GetWord();
    if (word.IsEmpty()) {
      break;
    }

    if (word == "beginbfchar") {
      word = HandleBeginBFChar(parser, previous_word);
    } else if (word == "beginbfrange") {
      word = HandleBeginBFRange(parser, previous_word);
    } else if (word == "/Adobe-Korea1-UCS2") {
      cid_set = CIDSet::kKorea1;
    } else if (word == "/Adobe-Japan1-UCS2") {
      cid_set = CIDSet::kJapan1;
    } else if (word == "/Adobe-CNS1-UCS2") {
      cid_set = CIDSet::kCNS1;
    } else if (word == "/Adobe-GB1-UCS2") {
      cid_set = CIDSet::kGB1;
    }

    previous_word = word;
  }
  if (cid_set != CIDSet::kUnknown) {
    base_map_ = CPDF_FontGlobals::GetInstance()->GetCID2UnicodeMap(cid_set);
  }
}

ByteStringView CPDF_ToUnicodeMap::HandleBeginBFChar(
    CPDF_SimpleParser& parser,
    ByteStringView previous_word) {
  struct CodeWord {
    uint32_t code;
    ByteStringView word;
  };
  std::vector<CodeWord> code_words;

  const int raw_count = StringToInt(previous_word);
  bool is_valid = raw_count >= 0 && raw_count <= kOutOfSpecBFLimit;
  const size_t expected_count = is_valid ? static_cast<size_t>(raw_count) : 0;
  code_words.reserve(expected_count);

  ByteStringView word;
  while (true) {
    word = parser.GetWord();
    if (word.IsEmpty() || word == "endbfchar") {
      break;
    }
    if (!is_valid) {
      continue;  // Keep consuming words. Do nothing else.
    }

    std::optional<uint32_t> code = StringToCode(word);
    if (!code.has_value() || code.value() > kCidLimit) {
      is_valid = false;
      continue;
    }

    word = parser.GetWord();
    code_words.emplace_back(CodeWord{code.value(), word});

    if (code_words.size() > expected_count) {
      is_valid = false;
    }
  }

  if (is_valid && code_words.size() == expected_count) {
    for (const auto& entry : code_words) {
      SetCode(entry.code, StringToWideString(entry.word));
    }
  }
  return word;
}

ByteStringView CPDF_ToUnicodeMap::HandleBeginBFRange(
    CPDF_SimpleParser& parser,
    ByteStringView previous_word) {
  struct CodeWordRange {
    uint32_t low_code;
    std::vector<ByteStringView> code_words;
  };
  struct MultimapSingleDestRange {
    uint32_t low_code;
    uint32_t high_code;
    uint32_t start_value;
  };
  struct MultimapMultiDestRange {
    uint32_t low_code;
    std::vector<WideString> retcodes;
  };
  using Range = std::variant<CodeWordRange, MultimapSingleDestRange,
                             MultimapMultiDestRange>;
  std::vector<Range> ranges;

  const int raw_count = StringToInt(previous_word);
  bool is_valid = raw_count >= 0 && raw_count <= kOutOfSpecBFLimit;
  const size_t expected_count = is_valid ? static_cast<size_t>(raw_count) : 0;
  ranges.reserve(expected_count);

  ByteStringView word;
  while (true) {
    word = parser.GetWord();
    if (word.IsEmpty() || word == "endbfrange") {
      break;
    }
    if (!is_valid) {
      continue;  // Keep consuming words. Do nothing else.
    }

    std::optional<uint32_t> lowcode_opt = StringToCode(word);
    if (!lowcode_opt.has_value()) {
      is_valid = false;
      continue;
    }

    word = parser.GetWord();
    std::optional<uint32_t> highcode_opt = StringToCode(word);
    if (!highcode_opt.has_value()) {
      is_valid = false;
      continue;
    }

    uint32_t lowcode = lowcode_opt.value();
    uint32_t highcode = (lowcode & 0xffffff00) | (highcode_opt.value() & 0xff);
    if (lowcode > kCidLimit || highcode > kCidLimit || lowcode > highcode) {
      is_valid = false;
      continue;
    }

    word = parser.GetWord();
    ByteStringView start = word;
    if (start == "[") {
      CodeWordRange range;
      range.low_code = lowcode;
      range.code_words.reserve(1 + highcode - lowcode);
      for (uint32_t code = lowcode; code <= highcode; ++code) {
        word = parser.GetWord();
        range.code_words.push_back(word);
      }
      ranges.push_back(std::move(range));

      if (ranges.size() > expected_count) {
        is_valid = false;
        continue;
      }

      word = parser.GetWord();
      if (word != "]") {
        is_valid = false;
      }
      continue;
    }

    WideString destcode = StringToWideString(start);
    if (destcode.GetLength() == 1) {
      uint32_t start_value = pdfium::checked_cast<uint32_t>(destcode.Front());
      CHECK_LE(start_value, 0xffff);
      ranges.push_back(MultimapSingleDestRange{.low_code = lowcode,
                                               .high_code = highcode,
                                               .start_value = start_value});
    } else {
      MultimapMultiDestRange range;
      range.low_code = lowcode;
      range.retcodes.reserve(1 + highcode - lowcode);
      range.retcodes.push_back(destcode);
      for (uint32_t code = lowcode + 1; code <= highcode; ++code) {
        WideString retcode = StringDataAdd(range.retcodes.back());
        range.retcodes.push_back(std::move(retcode));
      }
      ranges.push_back(std::move(range));
    }

    if (ranges.size() > expected_count) {
      is_valid = false;
    }
  }

  if (is_valid && ranges.size() == expected_count) {
    for (const auto& entry : ranges) {
      if (std::holds_alternative<CodeWordRange>(entry)) {
        const auto& range = std::get<CodeWordRange>(entry);
        uint32_t code = range.low_code;
        for (const auto& code_word : range.code_words) {
          SetCode(code, StringToWideString(code_word));
          ++code;
        }
      } else if (std::holds_alternative<MultimapSingleDestRange>(entry)) {
        const auto& range = std::get<MultimapSingleDestRange>(entry);
        uint32_t value = range.start_value;
        for (uint32_t code = range.low_code; code <= range.high_code; ++code) {
          InsertIntoMaps(code, value++);
        }
      } else {
        CHECK(std::holds_alternative<MultimapMultiDestRange>(entry));
        const auto& range = std::get<MultimapMultiDestRange>(entry);
        uint32_t code = range.low_code;
        for (const auto& retcode : range.retcodes) {
          InsertIntoMaps(code, GetMultiCharIndexIndicator());
          multi_char_vec_.push_back(retcode);
          ++code;
        }
      }
    }
  }
  return word;
}

uint32_t CPDF_ToUnicodeMap::GetMultiCharIndexIndicator() const {
  FX_SAFE_UINT32 uni = multi_char_vec_.size();
  uni = uni * 0x10000 + 0xffff;
  return uni.ValueOrDefault(0);
}

void CPDF_ToUnicodeMap::SetCode(uint32_t srccode, WideString destcode) {
  size_t len = destcode.GetLength();
  if (len == 0) {
    return;
  }
  if (len == 1) {
    InsertIntoMaps(srccode, destcode.Front());
  } else {
    InsertIntoMaps(srccode, GetMultiCharIndexIndicator());
    multi_char_vec_.push_back(destcode);
  }
}

void CPDF_ToUnicodeMap::InsertIntoMaps(uint32_t code, uint32_t destcode) {
  auto [it, inserted] = map_.insert({code, destcode});
  if (!inserted) {
    it->second = std::min(it->second, destcode);
  }

  auto [reverse_it, reverse_inserted] = reverse_map_.insert({destcode, code});
  if (!reverse_inserted) {
    reverse_it->second = std::min(reverse_it->second, code);
  }
}
