CompileTimeHash.h#

Parent directory (strings)

Hash functions inmplementations.

Detailed Description#

PowerVR by Imagination, Developer Technology Team.

Copyright (c) Imagination Technologies Limited.

Includes#

Included By#

Namespaces#

Classes#

Functions#

Source Code#

#pragma once
#include "PVRCore/Utils.h"
#include <string>
#include <cwchar>
#pragma warning(push)
#pragma warning(disable : 4307)

namespace pvr {
template<typename T1_>
inline uint32_t hash32_32(const T1_& t)
{
    uint32_t a = utils::reinterpretBits<uint32_t>(t);
    a = (a + 0x7ed55d16) + (a << 12);
    a = (a ^ 0xc761c23c) ^ (a >> 19);
    a = (a + 0x165667b1) + (a << 5);
    a = (a + 0xd3a2646c) ^ (a << 9);
    a = (a + 0xfd7046c5) + (a << 3);
    a = (a ^ 0xb55a4f09) ^ (a >> 16);
    return a;
}

inline uint32_t hash32_bytes(const void* bytes, size_t count)
{
    // IF THIS ALGORITHM IS CHANGED, THE ALGORITHM IN THE BOTTOM OF THE PAGE MUST BE CHANGED
    // AS IT IS AN INDEPENDENT COMPILE TIME IMPLEMENTATION OF TTHIS ALGORITHM.

    uint32_t hashValue = 2166136261U;
    const unsigned char* current = static_cast<const unsigned char*>(bytes);
    const unsigned char* end = current + count;
    while (current < end)
    {
        hashValue = (hashValue * 16777619U) ^ *current;
        ++current;
    }
    return hashValue;
}

template<typename T>
struct hash
{};

template<>
struct hash<uint32_t>
{
    uint32_t operator()(uint32_t value) { return hash32_32(value); }
};

template<>
struct hash<int32_t>
{
    uint32_t operator()(int32_t value) { return hash32_32(value); }
};

template<>
struct hash<uint64_t>
{
    uint32_t operator()(uint64_t value)
    {
        uint32_t a = static_cast<uint32_t>((value >> 32) | (value & 0x00000000FFFFFFFFull));
        return hash32_32(a);
    }
};

template<>
struct hash<int64_t>
{
    uint32_t operator()(int64_t value)
    {
        uint32_t a = static_cast<uint32_t>((value >> 32) | (value & 0x00000000FFFFFFFFull));
        return hash32_32(a);
    }
};

template<typename T>
struct hash<std::basic_string<T>>
{
    uint32_t operator()(const std::string& t) const { return hash32_bytes(t.data(), sizeof(T) * t.size()); }
};

// Compile time hashing - warning this must give the same results as the hash 32 bytes alogithm otherwise classes around the framework may break. This is used to optimise compiler time switch statements
template<uint32_t hashvalue, unsigned char... dummy>
class hasher_helper;

template<uint32_t hashvalue, unsigned char first>
class hasher_helper<hashvalue, first>
{
public:
    static const uint32_t value = hashvalue * 16777619U ^ first;
};

template<uint32_t hashvalue, unsigned char first, unsigned char... dummy>
class hasher_helper<hashvalue, first, dummy...>
{
public:
    static const uint32_t value = hasher_helper<hashvalue * 16777619U ^ first, dummy...>::value;
};

template<unsigned char... chars>
class HashCompileTime
{
public:
    static const uint32_t value = hasher_helper<2166136261U, chars...>::value;
};
} // namespace pvr
#pragma warning(pop)