/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#pragma once

#include <cstdint>
#include <functional>
#include <string_view>

namespace facebook::react {

/**
 * FNV-1a hash function implementation.
 * Implemented as described in http://www.isthe.com/chongo/tech/comp/fnv/.
 *
 * Please use std::hash if possible. `fnv1a` should only be used in cases
 * when std::hash does not provide the needed functionality. For example,
 * constexpr.
 */
template <typename CharTransformT = std::identity>
constexpr uint32_t fnv1a(std::string_view string) noexcept {
  constexpr uint32_t offset_basis = 2166136261;

  uint32_t hash = offset_basis;

  for (const auto& c : string) {
    hash ^= static_cast<int8_t>(CharTransformT{}(c));
    // Using shifts and adds instead of multiplication with a prime number.
    // This is faster when compiled with optimizations.
    hash +=
        (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
  }

  return hash;
}

constexpr uint32_t fnv1aLowercase(std::string_view string) {
  struct LowerCaseTransform {
    constexpr char operator()(char c) const {
      if (c >= 'A' && c <= 'Z') {
        return c + static_cast<char>('a' - 'A');
      }
      return c;
    }
  };

  return fnv1a<LowerCaseTransform>(string);
}

} // namespace facebook::react
