Improve StaticString hashing

In a lot of case the StaticString hash can be computed a compile time,
so we now take advantage of that.

Removed StaticString(const char*) ctor, and replaced it with a
StaticString::make() method.

Fixed a couple wrong uses of the old StaticString(const char*) ctor.
This commit is contained in:
Mathias Agopian
2018-12-12 13:47:28 -08:00
committed by Mathias Agopian
parent d135108763
commit 2d6b43827e
8 changed files with 76 additions and 31 deletions

View File

@@ -27,6 +27,19 @@
namespace utils {
//! \privatesection
struct hashCStrings {
typedef const char* argument_type;
typedef size_t result_type;
result_type operator()(argument_type cstr) const noexcept {
size_t hash = 5381;
while (int c = *cstr++) {
hash = (hash * 33u) ^ size_t(c);
}
return hash;
}
};
//! \privatesection
struct equalCStrings {
typedef const char* first_argument_type;
@@ -37,20 +50,6 @@ struct equalCStrings {
}
};
//! \privatesection
struct hashCStrings {
typedef const char* argument_type;
typedef size_t result_type;
result_type operator()(argument_type cstr) const noexcept {
// TODO: is this good enough?
size_t hash = 5381;
while (int c = *cstr++) {
hash = hash * 33 ^ c;
}
return hash;
}
};
//! \privatesection
struct lessCStrings {
typedef const char* first_argument_type;
@@ -80,24 +79,40 @@ public:
StaticString() noexcept = default;
// initialization from a string literal
template <size_t N>
StaticString(StringLiteral<N> const& other) noexcept // NOLINT(google-explicit-constructor)
: mString(other),
mLength(size_type(N - 1)) {
}
StaticString(const_pointer literal, size_t length) noexcept
: mString(literal),
mLength(size_type(length)) {
mLength(size_type(N - 1)),
mHash(computeHash(other)) {
}
// assignment from a string literal
template<size_t N>
StaticString& operator=(StringLiteral<N> const& other) noexcept {
mString = other;
mLength = size_type(N - 1);
mHash = computeHash(other);
return *this;
}
// helper to make a StaticString from a C string that is known to be a string literal
static constexpr StaticString make(const_pointer literal, size_t length) noexcept {
StaticString r;
r.mString = literal;
r.mLength = size_type(length);
size_type hash = 5381;
while (int c = *literal++) {
hash = (hash * 33u) ^ size_type(c);
}
r.mHash = hash;
return r;
}
static StaticString make(const_pointer literal) noexcept {
return make(literal, strlen(literal));
}
const_pointer c_str() const noexcept { return mString; }
const_pointer data() const noexcept { return mString; }
size_type size() const noexcept { return mLength; }
@@ -130,9 +145,21 @@ public:
return begin()[size() - 1];
}
size_type getHash() const noexcept { return mHash; }
private:
const_pointer mString = nullptr;
size_type mLength = 0;
size_type mHash = 0;
template<size_t N>
static constexpr size_type computeHash(StringLiteral<N> const& s) noexcept {
size_type hash = 5381;
for (size_t i = 0; i < N - 1; i++) {
hash = (hash * 33u) ^ size_type(s[i]);
}
return hash;
}
int compare(const StaticString& rhs) const noexcept;
@@ -344,9 +371,8 @@ template<>
struct hash<utils::StaticString> {
typedef utils::StaticString argument_type;
typedef size_t result_type;
utils::hashCStrings hasher;
size_t operator()(const utils::StaticString& s) const noexcept {
return hasher(s.c_str());
return s.getHash();
}
};