Recenter Han emblem logo slightly and fix the name.
[0ad.git] / source / ps / CStrIntern.cpp
blob079eab998f7c8cc0df79b3db0361c8b6363476bd
1 /* Copyright (C) 2021 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "CStrIntern.h"
22 #include "lib/fnv_hash.h"
23 #include "ps/CLogger.h"
24 #include "ps/ThreadUtil.h"
26 #include <unordered_map>
28 class CStrInternInternals
30 public:
31 CStrInternInternals(const char* str, size_t len)
32 : data(str, str+len), hash(fnv_hash(str, len))
34 // LOGWARNING("New interned string '%s'", data.c_str());
37 bool operator==(const CStrInternInternals& b) const
39 // Compare hash first for quick rejection of inequal strings
40 return (hash == b.hash && data == b.data);
43 const std::string data;
44 const u32 hash; // fnv_hash of data
46 private:
47 CStrInternInternals& operator=(const CStrInternInternals&);
50 // Interned strings are stored in a hash table, indexed by string:
52 using StringsKey = std::string;
54 struct StringsKeyHash
56 size_t operator()(const StringsKey& key) const
58 return fnv_hash(key.c_str(), key.length());
62 // To avoid std::string memory allocations when GetString does lookups in the
63 // hash table of interned strings, we make use of std::unordered_map's ability
64 // to do lookups with a functionally equivalent proxy object:
66 struct StringsKeyProxy
68 const char* str;
69 size_t len;
72 struct StringsKeyProxyHash
74 size_t operator()(const StringsKeyProxy& key) const
76 return fnv_hash(key.str, key.len);
80 struct StringsKeyProxyEq
82 bool operator()(const StringsKeyProxy& proxy, const StringsKey& key) const
84 return (proxy.len == key.length() && memcmp(proxy.str, key.c_str(), proxy.len) == 0);
88 static std::unordered_map<StringsKey, std::shared_ptr<CStrInternInternals>, StringsKeyHash> g_Strings;
90 #define X(id) CStrIntern str_##id(#id);
91 #define X2(id, str) CStrIntern str_##id(str);
92 #include "CStrInternStatic.h"
93 #undef X
94 #undef X2
96 static CStrInternInternals* GetString(const char* str, size_t len)
98 // g_Strings is not thread-safe, so complain if anyone is using this
99 // type in non-main threads. (If that's desired, g_Strings should be changed
100 // to be thread-safe, preferably without sacrificing performance.)
101 ENSURE(Threading::IsMainThread());
103 std::unordered_map<StringsKey, std::shared_ptr<CStrInternInternals> >::iterator it = g_Strings.find(str);
105 if (it != g_Strings.end())
106 return it->second.get();
108 std::shared_ptr<CStrInternInternals> internals = std::make_shared<CStrInternInternals>(str, len);
109 g_Strings.insert(std::make_pair(internals->data, internals));
110 return internals.get();
113 CStrIntern::CStrIntern()
115 *this = str__emptystring;
118 CStrIntern::CStrIntern(const char* str)
120 m = GetString(str, strlen(str));
123 CStrIntern::CStrIntern(const std::string& str)
125 m = GetString(str.c_str(), str.length());
128 u32 CStrIntern::GetHash() const
130 return m->hash;
133 const char* CStrIntern::c_str() const
135 return m->data.c_str();
138 size_t CStrIntern::length() const
140 return m->data.length();
143 bool CStrIntern::empty() const
145 return m->data.empty();
148 const std::string& CStrIntern::string() const
150 return m->data;