Diligent Engine API Reference: D:/GitHub/DiligentEngine/DiligentCore/Common/interface/HashUtils.h Source File

Diligent Engine API Reference

HashUtils.h
1 /* Copyright 2015-2018 Egor Yusov
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12 *
13 * In no event and under no legal theory, whether in tort (including negligence),
14 * contract, or otherwise, unless required by applicable law (such as deliberate
15 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16 * liable for any damages, including any direct, indirect, special, incidental,
17 * or consequential damages of any character arising as a result of this License or
18 * out of the use or inability to use the software (including but not limited to damages
19 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20 * all other commercial damages or losses), even if such Contributor has been advised
21 * of the possibility of such damages.
22 */
23
24 #pragma once
25
26 #include <functional>
27 #include <memory>
28
29 #include "Errors.h"
30
31 #define LOG_HASH_CONFLICTS 1
32
33 namespace Diligent
34 {
35 // http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html
36 template<typename T>
37 void HashCombine(std::size_t &Seed, const T& Val)
38 {
39 Seed ^= std::hash<T>()(Val) + 0x9e3779b9 + (Seed << 6) + (Seed >> 2);
40 }
41
42 template<typename FirstArgType, typename... RestArgsType>
43 void HashCombine( std::size_t &Seed, const FirstArgType& FirstArg, const RestArgsType&... RestArgs )
44 {
45 HashCombine( Seed, FirstArg );
46 HashCombine( Seed, RestArgs... ); // recursive call using pack expansion syntax
47 }
48
49 template<typename... ArgsType>
50 std::size_t ComputeHash( const ArgsType&... Args )
51 {
52 std::size_t Seed = 0;
53 HashCombine( Seed, Args... );
54 return Seed;
55 }
56
57 template<typename CharType>
58 struct CStringHash
59 {
60 size_t operator()( const CharType *str ) const
61 {
62 // http://www.cse.yorku.ca/~oz/hash.html
63 std::size_t Seed = 0;
64 while( size_t Ch = *(str++) )
65 Seed = Seed * 65599 + Ch;
66 return Seed;
67 }
68 };
69
70 template<typename CharType>
71 struct CStringCompare
72 {
73 bool operator()( const CharType *str1, const CharType *str2 )const
74 {
75 UNSUPPORTED( "Template specialization is not implemented" );
76 return false;
77 }
78 };
79
80 template<>
81 struct CStringCompare<Char>
82 {
83 bool operator()( const Char *str1, const Char *str2 )const
84 {
85 return strcmp( str1, str2 ) == 0;
86 }
87 };
88
93 struct HashMapStringKey
94 {
95 public:
96 // This constructor can perform implicit const Char* -> HashMapStringKey
97 // conversion without copying the string
98 HashMapStringKey(const Char* Str, bool bMakeCopy = false) :
99 StrPtr(nullptr),
100 Hash(0)
101 {
102 VERIFY( Str, "String pointer cannot be null" );
103 if( bMakeCopy )
104 {
105 MakeCopy( Str );
106 }
107 else
108 {
109 StrPtr = Str;
110 }
111 }
112
113 explicit // Make this constructor explicit to avoid unintentional string copies
114 HashMapStringKey(const String &Str) :
115 StrPtr( nullptr ),
116 Hash(0)
117 {
118 MakeCopy( Str.c_str() );
119 }
120
121 HashMapStringKey(HashMapStringKey &&Key) :
122 StringBuff( std::move(Key.StringBuff) ),
123 StrPtr( std::move(Key.StrPtr) ),
124 Hash(0)
125 {
126 Key.StrPtr = nullptr;
127 Key.Hash = 0;
128 }
129
130 // Disable copy constuctor and assignments. The struct is designed
131 // to be initialized at creation time only
132 HashMapStringKey( const HashMapStringKey& ) = delete;
133 HashMapStringKey& operator = ( const HashMapStringKey& ) = delete;
134 HashMapStringKey& operator = ( HashMapStringKey&& ) = delete;
135
136 // Comparison operator
137 bool operator == (const HashMapStringKey& RHS)const
138 {
139 if( StrPtr == RHS.StrPtr )
140 return true;
141
142 // Hash member might not have been initialized
143 if( (Hash != 0 && RHS.Hash !=0 && Hash != RHS.Hash) || StrPtr == nullptr || RHS.StrPtr == nullptr )
144 return false;
145
146 bool IsEqual = strcmp( StrPtr, RHS.StrPtr ) == 0;
147
148 #if LOG_HASH_CONFLICTS
149 if( Hash != 0 && RHS.Hash !=0 && Hash == RHS.Hash && !IsEqual )
150 {
151 LOG_WARNING_MESSAGE("Unequal strings \"", StrPtr, "\" and \"", RHS.StrPtr, "\" hashed to the same bucket. "
152 "You may want to use better hash function. You may disable this warning by defining LOG_HASH_CONFLICTS to 0");
153 }
154 #endif
155 return IsEqual;
156 }
157
158 size_t GetHash()const
159 {
160 if( Hash == 0 )
161 Hash = CStringHash<Char>()(StrPtr);
162
163 return Hash;
164 }
165
166 const Char* GetStr()const{ return StrPtr; }
167
168 private:
169 void MakeCopy( const Char* Str )
170 {
171 auto LenWithZeroTerm = strlen( Str ) + 1;
172 StringBuff.reset( new char[ LenWithZeroTerm ] );
173 memcpy( StringBuff.get(), Str, LenWithZeroTerm );
174 StrPtr = StringBuff.get();
175 }
176
177 // !!! WARNING !!!
178 // We can't use String to store the buffer, because String default
179 // constructor always allocates memory even when the string is empty,
180 // nor can we use vector for the same reason
181 std::unique_ptr< Char[] > StringBuff; // Must be declared first
182 const Char* StrPtr;// Must be declared after StringBuff
183 mutable size_t Hash;
184 };
185 }
186
187 namespace std
188 {
189 template<>
190 struct hash<Diligent::HashMapStringKey>
191 {
192 size_t operator()( const Diligent::HashMapStringKey &Key ) const
193 {
194 return Key.GetHash();
195 }
196 };
197 }
Diligent
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
std
Definition: AdvancedMath.h:316
Diligent::HashMapStringKey
This helper structure is intended to facilitate using strings as a hash table key. It provides constructors that can make a copy of the source string or just keep pointer to it, which enables searching in the hash using raw const Char* pointers.
Definition: HashUtils.h:93