Skip to content

Instantly share code, notes, and snippets.

@sylveon
Created November 26, 2021 23:49
Show Gist options
  • Save sylveon/a0e0d356fc97e068e4ee5c430158ad03 to your computer and use it in GitHub Desktop.
Save sylveon/a0e0d356fc97e068e4ee5c430158ad03 to your computer and use it in GitHub Desktop.
struct FilenameHash
{
using transparent_key_equal = FilenameEqual;
std::size_t operator()(std::wstring_view k) const
{
std::size_t hash = Util::INITIAL_HASH_VALUE;
for (std::size_t i = 0; i < k.length(); ++i)
{
if (Util::IsAscii(k[i]))
{
// if the string is all ascii characters, avoid API calls
// this is much faster due to being branchless code
Util::HashCharacter(hash, Util::AsciiToUpper(k[i]));
}
else
{
// when we encounter a non-ascii character, call an API to hash the rest and break out
SlowHash(hash, k.substr(i));
break;
}
}
return hash;
}
private:
inline static void SlowHash(std::size_t &hash, std::wstring_view k)
{
fmt::wmemory_buffer buf;
buf.resize(k.length());
const int result = LCMapStringEx(
LOCALE_NAME_INVARIANT, LCMAP_UPPERCASE,
k.data(), wil::safe_cast<int>(k.length()),
buf.data(), wil::safe_cast<int>(buf.size()),
nullptr, nullptr, 0
);
if (result)
{
buf.resize(result);
for (const wchar_t &c : buf)
{
Util::HashCharacter(hash, c);
}
}
else
{
throw std::system_error(static_cast<int>(GetLastError()), std::system_category(), "Failed to hash string");
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment