StringHash.h#

Parent directory (strings)

A hashed std::string with functionality for fast compares.

Includes#

  • PVRCore/Errors.h

  • PVRCore/strings/CompileTimeHash.h

  • PVRCore/strings/StringFunctions.h

  • functional

Included By#

Namespaces#

Classes#

Source Code#

#pragma once
#include "PVRCore/strings/CompileTimeHash.h"
#include "PVRCore/strings/StringFunctions.h"
#include "PVRCore/Errors.h"
#include <functional>

namespace pvr {
class StringHash
{
    typedef hash<std::string> HashFn;

public:
    StringHash(const char* str) : _String(str), _Hash(HashFn()(_String)) {}

    StringHash(const std::string& right) : _String(right), _Hash(HashFn()(_String)) {}

    operator const std::string&() const { return _String; }

    StringHash() : _String(""), _Hash(HashFn()(_String)) {}

    StringHash(const StringHash& other)
    {
        _String = other._String;
        _Hash = other._Hash;
    }

    ~StringHash() {}

    StringHash& operator=(const StringHash other)
    {
        _String = other._String;
        _Hash = other._Hash;
        return *this;
    }

    StringHash& append(const char* ptr)
    {
        _String.append(ptr);
        _Hash = HashFn()(_String);
        return *this;
    }

    StringHash& append(const std::string& str)
    {
        _String.append(str);
        _Hash = HashFn()(_String);
        return *this;
    }

    StringHash& assign(const char* ptr)
    {
        _String.assign(ptr);
        _Hash = HashFn()(_String);
        return *this;
    }

    StringHash& assign(const std::string& str)
    {
        _String = str;
        _Hash = HashFn()(_String);
        return *this;
    }

    size_t size() const { return _String.size(); }

    size_t length() const { return _String.length(); }

    bool empty() const { return _String.empty(); }

    void clear() { assign(std::string()); }

    bool operator==(const StringHash& str) const
    {
#ifdef DEBUG // Collision detection
        if (_Hash == str.getHash() && _String != str._String)
        {
            throw InvalidDataError(strings::createFormatted("***** STRING HASH COLLISION DETECTED ********************\n"
                                                            "** String [%s] collides with std::string [%s] \n"
                                                            "*********************************************************",
                _String.c_str(), str._String.c_str()));
        }
#endif

#ifndef PVR_STRING_HASH_STRONG_COMPARISONS
        return (_Hash == str.getHash());
#else
        return (_Hash == str.getHash()) && _String == str._String;
#endif
    }

    bool operator==(const char* str) const { return (_String.compare(str) == 0); }

    bool operator==(const std::string& str) const { return _String == str; }

    bool operator!=(const StringHash& str) const { return !(*this == str); }

    bool operator<(const StringHash& str) const
    {
#ifdef DEBUG // Collision detection
        if (_Hash == str.getHash() && _String != str._String)
        { throw InvalidDataError(strings::createFormatted("HASH COLLISION DETECTED with %s and %s", _String.c_str(), str._String.c_str()).c_str()); }
        #endif
        return _Hash < str.getHash() || (_Hash == str.getHash() && _String < str._String);
    }

    bool operator>(const StringHash& str) const { return str < *this; }

    bool operator<=(const StringHash& str) const { return !(str > *this); }

    bool operator>=(const StringHash& str) const { return !(str < *this); }

    const std::string& str() const { return _String; }

    std::size_t getHash() const { return _Hash; }

    const char* c_str() const { return _String.c_str(); }

private:
    std::string _String;
    std::size_t _Hash;
};
} // namespace pvr