CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
StringID.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2023 Rogiel Sulzbach. All rights reserved.
6//
7
8// NOTE: Based on https://github.com/foonathan/string_id
9
10#pragma once
11
12#include "Exception.hpp"
13#include "Hash.hpp"
14#include "String.hpp"
15#include "Container/Atomic.hpp"
16
18
20
21#include <atomic>
22#include <cstdint>
23#include <cstring>
24#include <exception>
25#include <functional>
26#include <memory>
27#include <utility>
28
29namespace CeresEngine {
30
31 class StringDatabase;
32
37 class StringID {
38 public:
40 using Hash = UInt64;
41
43 enum class Status {
46
49
52 };
53
54 private:
55 Hash mID = 0;
57
58 public:
61 StringID() = default;
62
68 explicit StringID(StringView string);
69
76
81 StringID(const StringID& prefix, StringView string);
82
90
97 StringID(const StringID& prefix, StringView string, Status& status);
98
99 public:
102
105
106 public: // Comparison
111 [[nodiscard]] friend bool operator==(const StringID a, const StringID b) noexcept { return a.mDatabase == b.mDatabase && a.mID == b.mID; }
112 [[nodiscard]] friend bool operator==(const StringID::Hash a, const StringID& b) noexcept { return a == b.mID; }
113 [[nodiscard]] friend bool operator==(const StringID& a, const StringID::Hash b) noexcept { return a.mID == b; }
114 [[nodiscard]] friend bool operator!=(const StringID& a, const StringID& b) noexcept { return !(a == b); }
115 [[nodiscard]] friend bool operator!=(const StringID::Hash a, const StringID& b) noexcept { return !(a == b); }
116 [[nodiscard]] friend bool operator!=(const StringID& a, const StringID::Hash b) noexcept { return !(a == b); }
117
118 public: // Collision handler
125
128
131 };
132
133 namespace literals {
139 constexpr StringID::Hash operator""_id(const char* string, const std::size_t length) { return staticHash64(StringView(string, length)); }
140 } // namespace literals
141
144 public:
148 virtual ~StringDatabase() = default;
149
150 protected:
151 StringDatabase() = default;
152
153 public:
164
176
184 [[nodiscard]] virtual StringView lookup(StringID::Hash hash) const noexcept = 0;
185
186 public:
189 };
190
206
209 public:
211 explicit MapStringDatabase(std::size_t size = 1024, double maxLoadFactor = 1.0);
212 ~MapStringDatabase() noexcept override;
213
215 [[nodiscard]] StringID::Status insert(StringID::Hash hash, StringView string) override;
216
218 [[nodiscard]] StringID::Status insertPrefix(StringID::Hash hash, StringID::Hash prefix, StringView string) override;
219
221 [[nodiscard]] StringView lookup(StringID::Hash hash) const noexcept override;
222
223 private:
224 void rehash();
225
226 class NodeList;
227 std::unique_ptr<NodeList[]> mBuckets;
228 std::size_t mItemCount, mBucketCount;
229 double mMaximumLoadFactor;
230 std::size_t mNextResize;
231 };
232
235 template<class Parent, typename MutexType = Mutex> class ThreadSafeStringDatabase : public Parent {
236 using super = Parent;
237
238 private:
239 mutable MutexType mMutex;
240
241 public:
242 // workaround of lacking inheriting constructors
243 template<typename... Args> explicit ThreadSafeStringDatabase(Args&&... args) : super(std::forward<Args>(args)...) {}
244
245 public:
247 [[nodiscard]] typename StringID::Status insert(StringID::Hash hash, StringView string) override {
248 Lock<MutexType> lock(mMutex);
249 return super::insert(hash, string);
250 }
251
253 [[nodiscard]] typename StringID::Status insertPrefix(StringID::Hash hash, StringID::Hash prefix, StringView string) override {
254 Lock<MutexType> lock(mMutex);
255 return super::insertPrefix(hash, prefix, string);
256 }
257
259 [[nodiscard]] StringView lookup(StringID::Hash hash) const noexcept override {
260 Lock<MutexType> lock(mMutex);
261 return super::lookup(hash);
262 }
263 };
264
268
271 private:
272 String mFirstString, mSecondString;
274
275 public:
278 : RuntimeError("CollisionError: strings {0} and {1} are both producing the value {2}", a, b, hash), mFirstString(a), mSecondString(b),
279 mHashCode(hash) {}
280
281 public:
283 StringView getFirstString() const noexcept { return mFirstString; }
284
286 StringView getSecondString() const noexcept { return mSecondString; }
287
289 StringID::Hash getHashCode() const noexcept { return mHashCode; }
290 };
291
292} // namespace CeresEngine
293
295template<> struct std::hash<CeresEngine::StringID> {
296 size_t operator()(const CeresEngine::StringID& arg) const noexcept { return static_cast<size_t>(arg.getHashCode()); }
297};
A database that doesn't store the string-values.
Definition StringID.hpp:195
StringID::Status insertPrefix(StringID::Hash, StringID::Hash, StringView) override
Inserts a hash-string-pair with given prefix into the internal database.
Definition StringID.hpp:201
StringView lookup(StringID::Hash) const noexcept override
Returns the string stored with a given hash.
Definition StringID.hpp:204
StringID::Status insert(StringID::Hash, StringView) override
Inserts a new hash-string-pair with prefix (optional) into the internal database.
Definition StringID.hpp:198
The class Lock is a mutex wrapper that provides a convenient RAII-style mechanism for owning one or m...
Definition Threading.hpp:246
A database that uses a highly optimized hash table.
Definition StringID.hpp:208
~MapStringDatabase() noexcept override
MapStringDatabase(std::size_t size=1024, double maxLoadFactor=1.0)
Creates a new database with given number of buckets and maximum load factor.
Definition Exception.hpp:115
The interface for all databases. You can derive own databases from it.
Definition StringID.hpp:143
virtual ~StringDatabase()=default
StringDatabase(StringDatabase &&)=delete
StringDatabase(const StringDatabase &)=delete
virtual StringView lookup(StringID::Hash hash) const noexcept=0
Returns the string stored with a given hash.
virtual StringID::Status insertPrefix(StringID::Hash hash, StringID::Hash prefix, StringView string)
Inserts a hash-string-pair with given prefix into the internal database.
static StringDatabase & getDefault() noexcept
virtual StringID::Status insert(StringID::Hash hash, StringView string)=0
Inserts a new hash-string-pair with prefix (optional) into the internal database.
The exception class thrown by the default CollisionHandler.
Definition StringID.hpp:270
StringID::Hash mHashCode
Definition StringID.hpp:273
StringIDCollisionError(StringID::Hash hash, StringView a, StringView b)
Creates a new exception, same parameter as CollisionError.
Definition StringID.hpp:277
StringID::Hash getHashCode() const noexcept
Returns the hash code of the collided strings.
Definition StringID.hpp:289
StringView getFirstString() const noexcept
Returns the first string that collided.
Definition StringID.hpp:283
StringView getSecondString() const noexcept
Returns the second string that collided.
Definition StringID.hpp:286
String mFirstString
Definition StringID.hpp:272
The string identifier class.
Definition StringID.hpp:37
StringID()=default
Constructs a new empty StringID.
StringDatabase * mDatabase
Definition StringID.hpp:56
StringID(StringDatabase &database, StringView string, Status &status)
Same as other constructors versions but instead of calling the CollisionHandler, they set the output ...
friend bool operator!=(const StringID &a, const StringID &b) noexcept
Definition StringID.hpp:114
UInt64 Hash
The type of a hashed string.
Definition StringID.hpp:40
Hash mID
Definition StringID.hpp:55
friend bool operator==(const StringID &a, const StringID::Hash b) noexcept
Definition StringID.hpp:113
friend bool operator==(const StringID::Hash a, const StringID &b) noexcept
Definition StringID.hpp:112
StringID(const StringID &prefix, StringView string, Status &status)
Same as other constructors versions but instead of calling the CollisionHandler, they set the output ...
StringID(StringDatabase &database, StringView string)
Creates a new id by hashing a given string.
StringView getString() const noexcept
StringID(StringView string)
Creates a new id by hashing a given string.
friend bool operator!=(const StringID::Hash a, const StringID &b) noexcept
Definition StringID.hpp:115
StringID::Hash getHashCode() const noexcept
Definition StringID.hpp:101
static CollisionHandler getCollisionHandler()
Returns the current CollisionHandler.
static CollisionHandler setCollisionHandler(CollisionHandler h)
Exchanges the CollisionHandler.
StringID(const StringID &prefix, StringView string)
Creates a new id with a given prefix.
Status
The status of an insert operation.
Definition StringID.hpp:43
@ Collision
Two different strings collide on the same value.
@ OldString
The string already existed inside the database.
@ NewString
A new string was inserted.
void(*)(StringID::Hash hash, StringView a, StringView b) CollisionHandler
The type of the collision handler.
Definition StringID.hpp:124
friend bool operator!=(const StringID &a, const StringID::Hash b) noexcept
Definition StringID.hpp:116
A thread-safe database adapter.
Definition StringID.hpp:235
StringView lookup(StringID::Hash hash) const noexcept override
Returns the string stored with a given hash.
Definition StringID.hpp:259
MutexType mMutex
Definition StringID.hpp:239
ThreadSafeStringDatabase(Args &&... args)
Definition StringID.hpp:243
Parent super
Definition StringID.hpp:236
StringID::Status insertPrefix(StringID::Hash hash, StringID::Hash prefix, StringView string) override
Inserts a hash-string-pair with given prefix into the internal database.
Definition StringID.hpp:253
StringID::Status insert(StringID::Hash hash, StringView string) override
Inserts a new hash-string-pair with prefix (optional) into the internal database.
Definition StringID.hpp:247
Definition Application.hpp:19
std::uint64_t UInt64
Definition DataTypes.hpp:26
decltype(auto) lock(Func &&func, Ts &... objects)
Definition Threading.hpp:667
BasicStringView< char > StringView
Narrow string view used for handling narrow encoded text in UTF-8.
Definition String.hpp:190
constexpr UInt64 staticHash64(BasicStringView< T > string, const UInt64 value=0xcbf29ce484222325) noexcept
Definition Hash.hpp:82
std::mutex Mutex
The Mutex class is a synchronization primitive that can be used to protect shared data from being sim...
Definition Threading.hpp:73
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition Span.hpp:668