/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCryptoHash.h"

#include "cmAlgorithms.h"
#include "cm_kwiml.h"
#include "cm_rhash.h"
#include "cmsys/FStream.hxx"
#include <string.h>

#include <memory> // IWYU pragma: keep

static unsigned int const cmCryptoHashAlgoToId[] = {
  /* clang-format needs this comment to break after the opening brace */
  RHASH_MD5,      //
  RHASH_SHA1,     //
  RHASH_SHA224,   //
  RHASH_SHA256,   //
  RHASH_SHA384,   //
  RHASH_SHA512,   //
  RHASH_SHA3_224, //
  RHASH_SHA3_256, //
  RHASH_SHA3_384, //
  RHASH_SHA3_512
};

static int cmCryptoHash_rhash_library_initialized;

static rhash cmCryptoHash_rhash_init(unsigned int id)
{
  if (!cmCryptoHash_rhash_library_initialized) {
    cmCryptoHash_rhash_library_initialized = 1;
    rhash_library_init();
  }
  return rhash_init(id);
}

cmCryptoHash::cmCryptoHash(Algo algo)
  : Id(cmCryptoHashAlgoToId[algo])
  , CTX(cmCryptoHash_rhash_init(Id))
{
}

cmCryptoHash::~cmCryptoHash()
{
  rhash_free(this->CTX);
}

std::unique_ptr<cmCryptoHash> cmCryptoHash::New(const char* algo)
{
  if (strcmp(algo, "MD5") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoMD5);
  }
  if (strcmp(algo, "SHA1") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA1);
  }
  if (strcmp(algo, "SHA224") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA224);
  }
  if (strcmp(algo, "SHA256") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA256);
  }
  if (strcmp(algo, "SHA384") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA384);
  }
  if (strcmp(algo, "SHA512") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA512);
  }
  if (strcmp(algo, "SHA3_224") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_224);
  }
  if (strcmp(algo, "SHA3_256") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_256);
  }
  if (strcmp(algo, "SHA3_384") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_384);
  }
  if (strcmp(algo, "SHA3_512") == 0) {
    return cm::make_unique<cmCryptoHash>(AlgoSHA3_512);
  }
  return std::unique_ptr<cmCryptoHash>(nullptr);
}

bool cmCryptoHash::IntFromHexDigit(char input, char& output)
{
  if (input >= '0' && input <= '9') {
    output = char(input - '0');
    return true;
  }
  if (input >= 'a' && input <= 'f') {
    output = char(input - 'a' + 0xA);
    return true;
  }
  if (input >= 'A' && input <= 'F') {
    output = char(input - 'A' + 0xA);
    return true;
  }
  return false;
}

std::string cmCryptoHash::ByteHashToString(
  const std::vector<unsigned char>& hash)
{
  // Map from 4-bit index to hexadecimal representation.
  static char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
                                '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

  std::string res;
  for (unsigned char v : hash) {
    res.push_back(hex[v >> 4]);
    res.push_back(hex[v & 0xF]);
  }
  return res;
}

std::vector<unsigned char> cmCryptoHash::ByteHashString(
  const std::string& input)
{
  this->Initialize();
  this->Append(reinterpret_cast<unsigned char const*>(input.c_str()),
               static_cast<int>(input.size()));
  return this->Finalize();
}

std::vector<unsigned char> cmCryptoHash::ByteHashFile(const std::string& file)
{
  cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary);
  if (fin) {
    this->Initialize();
    {
      // Should be efficient enough on most system:
      KWIML_INT_uint64_t buffer[512];
      char* buffer_c = reinterpret_cast<char*>(buffer);
      unsigned char const* buffer_uc =
        reinterpret_cast<unsigned char const*>(buffer);
      // This copy loop is very sensitive on certain platforms with
      // slightly broken stream libraries (like HPUX).  Normally, it is
      // incorrect to not check the error condition on the fin.read()
      // before using the data, but the fin.gcount() will be zero if an
      // error occurred.  Therefore, the loop should be safe everywhere.
      while (fin) {
        fin.read(buffer_c, sizeof(buffer));
        if (int gcount = static_cast<int>(fin.gcount())) {
          this->Append(buffer_uc, gcount);
        }
      }
    }
    if (fin.eof()) {
      // Success
      return this->Finalize();
    }
    // Finalize anyway
    this->Finalize();
  }
  // Return without success
  return std::vector<unsigned char>();
}

std::string cmCryptoHash::HashString(const std::string& input)
{
  return ByteHashToString(this->ByteHashString(input));
}

std::string cmCryptoHash::HashFile(const std::string& file)
{
  return ByteHashToString(this->ByteHashFile(file));
}

void cmCryptoHash::Initialize()
{
  rhash_reset(this->CTX);
}

void cmCryptoHash::Append(void const* buf, size_t sz)
{
  rhash_update(this->CTX, buf, sz);
}

void cmCryptoHash::Append(std::string const& str)
{
  this->Append(str.c_str(), str.size());
}

std::vector<unsigned char> cmCryptoHash::Finalize()
{
  std::vector<unsigned char> hash(rhash_get_digest_size(this->Id), 0);
  rhash_final(this->CTX, &hash[0]);
  return hash;
}

std::string cmCryptoHash::FinalizeHex()
{
  return cmCryptoHash::ByteHashToString(this->Finalize());
}
