/**
 * @file Hash.h
 * @author apio (cloudapio.eu)
 * @brief Common hash functions for use in hash tables.
 *
 * @copyright Copyright (c) 2023, the Luna authors.
 *
 */

#pragma once
#include <luna/Types.h>

/**
 * @brief Calculate the hash of an area of memory.
 *
 * @param mem A pointer to the memory to hash.
 * @param size The amount of bytes to use.
 * @param salt A randomly generated salt to vary the output and avoid hash table attacks.
 * @return u64 The calculated hash.
 */
u64 hash_memory(const void* mem, usize size, u64 salt);

/**
 * @brief Calculate the hash of a value.
 *
 * The default implementation simply hashes the raw memory representation of the value. This may not be suitable for
 * some types, so those can define a template specialization of this function to do their own hashing.
 *
 * @tparam T The type of the value to hash.
 * @param value The value to hash.
 * @param salt A randomly generated salt to vary the output and avoid hash table attacks.
 * @return u64 The calculated hash.
 */
template <typename T> u64 hash(const T& value, u64 salt)
{
    return hash_memory(&value, sizeof(value), salt);
}

/**
 * @brief Template specialization of hash() for C-strings.
 *
 * This function hashes the actual string instead of the pointer value.
 *
 * @param value The C-string to hash.
 * @param salt A randomly generated salt to vary the output and avoid hash table attacks.
 * @return u64 The calculated hash.
 */
template <> u64 hash(const char* const& value, u64 salt);

/**
 * @brief Swap two values of the same type.
 *
 * FIXME: This function should be moved to a more appropriate header.
 *
 * @tparam T The type of the values to swap.
 * @param a The first value to swap.
 * @param b The second value to swap.
 */
template <typename T> static void swap(T* a, T* b)
{
    char* x = (char*)a;
    char* y = (char*)b;

    usize size = sizeof(T);

    while (size--)
    {
        char t = *x;
        *x = *y;
        *y = t;
        x += 1;
        y += 1;
    }
}