summaryrefslogtreecommitdiff
path: root/source/core/slang-hash.h
blob: 08a40491ceea1e8806731b8035e1d81ec678f12f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#ifndef SLANG_CORE_HASH_H
#define SLANG_CORE_HASH_H

#include "slang-math.h"
#include <string.h>
#include <type_traits>

namespace Slang
{
    typedef int HashCode;

	inline int GetHashCode(double key)
	{
		return FloatAsInt((float)key);
	}
	inline int GetHashCode(float key)
	{
		return FloatAsInt(key);
	}
	inline int GetHashCode(const char * buffer)
	{
		if (!buffer)
			return 0;
		int hash = 0;
		int c;
		auto str = buffer;
		c = *str++;
		while (c)
		{
			hash = c + (hash << 6) + (hash << 16) - hash;
			c = *str++;
		}
		return hash;
	}
	inline int GetHashCode(char * buffer)
	{
		return GetHashCode(const_cast<const char *>(buffer));
	}
    inline int GetHashCode(const char * buffer, size_t numChars)
    {
        int hash = 0;
        for (size_t i = 0; i < numChars; ++i)
        {      
            hash = int(buffer[i]) + (hash << 6) + (hash << 16) - hash;
        }
        return hash;
    }

    inline uint64_t GetHashCode64(const char * buffer, size_t numChars)
    {
        // Use uints because hash requires wrap around behavior and int is undefined on over/underflows
        uint64_t hash = 0;
        for (size_t i = 0; i < numChars; ++i)
        {
            hash = uint64_t(int64_t(buffer[i])) + (hash << 6) + (hash << 16) - hash;
        }
        return hash;
    }

	template<int IsInt>
	class Hash
	{
	public:
	};
	template<>
	class Hash<1>
	{
	public:
		template<typename TKey>
		static int GetHashCode(TKey & key)
		{
			return (int)key;
		}
	};
	template<>
	class Hash<0>
	{
	public:
		template<typename TKey>
		static int GetHashCode(TKey & key)
		{
			return int(key.GetHashCode());
		}
	};
	template<int IsPointer>
	class PointerHash
	{};
	template<>
	class PointerHash<1>
	{
	public:
		template<typename TKey>
		static int GetHashCode(TKey const& key)
		{
			return (int)((PtrInt)key) / 16; // sizeof(typename std::remove_pointer<TKey>::type);
		}
	};
	template<>
	class PointerHash<0>
	{
	public:
		template<typename TKey>
		static int GetHashCode(TKey & key)
		{
			return Hash<std::is_integral<TKey>::value || std::is_enum<TKey>::value>::GetHashCode(key);
		}
	};

	template<typename TKey>
	int GetHashCode(const TKey & key)
	{
		return PointerHash<std::is_pointer<TKey>::value>::GetHashCode(key);
	}

	template<typename TKey>
	int GetHashCode(TKey & key)
	{
		return PointerHash<std::is_pointer<TKey>::value>::GetHashCode(key);
	}

    inline int combineHash(int left, int right)
    {
        return (left * 16777619) ^ right;
    }

    struct Hasher
    {
    public:
        Hasher() {}

        template<typename T>
        void hashValue(T const& value)
        {
            m_hashCode = combineHash(m_hashCode, GetHashCode(value));
        }

        template<typename T>
        void hashObject(T const& object)
        {
            m_hashCode = combineHash(m_hashCode, object->GetHashCode());
        }

        HashCode getResult() const
        {
            return m_hashCode;
        }

    private:
        HashCode m_hashCode = 0;
    };
}

#endif