Merge branch '1.9-dev' of https://github.com/alliedmodders/sourcemod into 1.9-dev

This commit is contained in:
Nick Hastings 2018-10-05 07:12:14 -04:00
commit 92e9ca7153
21 changed files with 191 additions and 49 deletions

View File

@ -43,6 +43,7 @@
#include <compat_wrappers.h> #include <compat_wrappers.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include <sm_stringhashmap.h>
using namespace SourceHook; using namespace SourceHook;
@ -67,6 +68,10 @@ struct ConVarInfo
{ {
return strcmp(name, info->pVar->GetName()) == 0; return strcmp(name, info->pVar->GetName()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
/** /**

View File

@ -77,6 +77,10 @@ struct EventHook
{ {
return strcmp(name, hook->name.chars()) == 0; return strcmp(name, hook->name.chars()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
enum EventHookMode enum EventHookMode

View File

@ -92,12 +92,20 @@ struct DataTableInfo
{ {
return strcmp(name, info.prop->GetName()) == 0; return strcmp(name, info.prop->GetName()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
static inline bool matches(const char *name, const DataTableInfo *info) static inline bool matches(const char *name, const DataTableInfo *info)
{ {
return strcmp(name, info->sc->GetName()) == 0; return strcmp(name, info->sc->GetName()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
DataTableInfo(ServerClass *sc) DataTableInfo(ServerClass *sc)
: sc(sc) : sc(sc)
@ -114,6 +122,10 @@ struct DataMapCachePolicy
{ {
return strcmp(name, info.prop->fieldName) == 0; return strcmp(name, info.prop->fieldName) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache; typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;

View File

@ -82,6 +82,10 @@ struct AuthMethod
{ {
return strcmp(name, method->name.c_str()) == 0; return strcmp(name, method->name.c_str()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
struct UserAuth struct UserAuth

View File

@ -72,6 +72,10 @@ public: //NameHashSet
{ {
return strcmp(key, value->m_File) == 0; return strcmp(key, value->m_File) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
private: private:
char m_File[PLATFORM_MAX_PATH]; char m_File[PLATFORM_MAX_PATH];
char m_CurFile[PLATFORM_MAX_PATH]; char m_CurFile[PLATFORM_MAX_PATH];

View File

@ -110,6 +110,10 @@ struct QHandleType
{ {
return type->name && type->name->compare(key) == 0; return type->name && type->name->compare(key) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
typedef ke::Lambda<void(const char *)> HandleReporter; typedef ke::Lambda<void(const char *)> HandleReporter;

View File

@ -36,6 +36,7 @@
#include <am-string.h> #include <am-string.h>
#include <am-utility.h> #include <am-utility.h>
#include <am-refcounting.h> #include <am-refcounting.h>
#include <sm_stringhashmap.h>
#include "common_logic.h" #include "common_logic.h"
class CNativeOwner; class CNativeOwner;
@ -93,6 +94,10 @@ struct Native : public ke::Refcounted<Native>
{ {
return strcmp(name, entry->name()) == 0; return strcmp(name, entry->name()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };

View File

@ -31,7 +31,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h>
#include "PluginSys.h" #include "PluginSys.h"
#include "ShareSys.h" #include "ShareSys.h"
#include <ILibrarySys.h> #include <ILibrarySys.h>
@ -47,7 +46,6 @@
#include "frame_tasks.h" #include "frame_tasks.h"
#include <amtl/am-string.h> #include <amtl/am-string.h>
#include <amtl/am-linkedlist.h> #include <amtl/am-linkedlist.h>
#include <amtl/am-uniqueptr.h>
#include <bridge/include/IVEngineServerBridge.h> #include <bridge/include/IVEngineServerBridge.h>
#include <bridge/include/CoreProvider.h> #include <bridge/include/CoreProvider.h>
@ -934,38 +932,16 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
libsys->CloseDirectory(dir); libsys->CloseDirectory(dir);
} }
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
char *strdup_tolower(const char *input)
{
char *str = strdup(input);
for (char *c = str; *c; c++)
{
*c = tolower((unsigned char)*c);
}
return str;
}
#endif
LoadRes CPluginManager::LoadPlugin(CPlugin **aResult, const char *path, bool debug, PluginType type) LoadRes CPluginManager::LoadPlugin(CPlugin **aResult, const char *path, bool debug, PluginType type)
{ {
if (m_LoadingLocked) if (m_LoadingLocked)
return LoadRes_NeverLoad; return LoadRes_NeverLoad;
/* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
ke::UniquePtr<char> finalPath = ke::UniquePtr<char>(strdup_tolower(path));
#else
ke::UniquePtr<char> finalPath = ke::UniquePtr<char>(strdup(path));
#endif
/** /**
* Does this plugin already exist? * Does this plugin already exist?
*/ */
CPlugin *pPlugin; CPlugin *pPlugin;
if (m_LoadLookup.retrieve(finalPath.get(), &pPlugin)) if (m_LoadLookup.retrieve(path, &pPlugin))
{ {
/* Check to see if we should try reloading it */ /* Check to see if we should try reloading it */
if (pPlugin->GetStatus() == Plugin_BadLoad if (pPlugin->GetStatus() == Plugin_BadLoad
@ -978,12 +954,11 @@ LoadRes CPluginManager::LoadPlugin(CPlugin **aResult, const char *path, bool deb
{ {
if (aResult) if (aResult)
*aResult = pPlugin; *aResult = pPlugin;
return LoadRes_AlreadyLoaded; return LoadRes_AlreadyLoaded;
} }
} }
CPlugin *plugin = CompileAndPrep(finalPath.get()); CPlugin *plugin = CompileAndPrep(path);
// Assign our outparam so we can return early. It must be set. // Assign our outparam so we can return early. It must be set.
*aResult = plugin; *aResult = plugin;

View File

@ -143,11 +143,6 @@ public:
*/ */
static CPlugin *Create(const char *file); static CPlugin *Create(const char *file);
static inline bool matches(const char *file, const CPlugin *plugin)
{
return strcmp(plugin->m_filename, file) == 0;
}
public: public:
// Evicts the plugin from memory and sets an error state. // Evicts the plugin from memory and sets an error state.
void EvictWithError(PluginStatus status, const char *error_fmt, ...); void EvictWithError(PluginStatus status, const char *error_fmt, ...);
@ -483,7 +478,54 @@ private:
typedef decltype(m_listeners)::iterator ListenerIter; typedef decltype(m_listeners)::iterator ListenerIter;
typedef decltype(m_plugins)::iterator PluginIter; typedef decltype(m_plugins)::iterator PluginIter;
NameHashSet<CPlugin *> m_LoadLookup; struct CPluginPolicy
{
static inline uint32_t hash(const detail::CharsAndLength &key)
{
/* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
const char *original = key.chars();
char *copy = strdup(original);
for (size_t i = 0; copy[i]; ++i)
{
copy[i] = tolower(copy[i]);
}
uint32_t hash = detail::CharsAndLength(copy).hash();
free(copy);
return hash;
#else
return key.hash();
#endif
}
static inline bool matches(const char *file, const CPlugin *plugin)
{
const char *pluginFile = const_cast<CPlugin*>(plugin)->GetFilename();
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
size_t fileLen = strlen(file);
if (fileLen != strlen(pluginFile))
{
return false;
}
for (size_t i = 0; i < fileLen; ++i)
{
if (tolower(file[i]) != tolower(pluginFile[i]))
{
return false;
}
}
return true;
#else
return strcmp(pluginFile, file) == 0;
#endif
}
};
NameHashSet<CPlugin *, CPluginPolicy> m_LoadLookup;
bool m_AllPluginsLoaded; bool m_AllPluginsLoaded;
IdentityToken_t *m_MyIdent; IdentityToken_t *m_MyIdent;

View File

@ -46,6 +46,10 @@ struct ConsoleEntry
{ {
return strcmp(name, entry->command.c_str()) == 0; return strcmp(name, entry->command.c_str()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
class RootConsoleMenu : class RootConsoleMenu :

View File

@ -58,6 +58,10 @@ struct maplist_info_t
{ {
return strcmp(value->name, key) == 0; return strcmp(value->name, key) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
#define MAPLIST_FLAG_MAPSFOLDER (1<<0) /**< On failure, use all maps in the maps folder. */ #define MAPLIST_FLAG_MAPSFOLDER (1<<0) /**< On failure, use all maps in the maps folder. */

View File

@ -184,6 +184,10 @@ private:
{ {
return strcmp(name, base->GetName()) == 0; return strcmp(name, base->GetName()) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
NameHashSet<ConCommandBase *, ConCommandPolicy> m_CmdFlags; NameHashSet<ConCommandBase *, ConCommandPolicy> m_CmdFlags;
} s_CommandFlagsHelper; } s_CommandFlagsHelper;

View File

@ -96,6 +96,10 @@ struct Cookie
{ {
return strcmp(name, cookie->name) == 0; return strcmp(name, cookie->name) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
class CookieManager : public IClientListener, public IPluginsListener class CookieManager : public IClientListener, public IPluginsListener

View File

@ -126,7 +126,7 @@ DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
} }
#endif #endif
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) #if SOURCE_ENGINE != SE_CSGO
DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason) DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
{ {
if (g_pIgnoreTerminateDetour) if (g_pIgnoreTerminateDetour)
@ -135,20 +135,31 @@ DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason); DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
return; return;
} }
#elif !defined(WIN32)
DETOUR_DECL_MEMBER4(DetourTerminateRound, void, float, delay, int, reason, int, unknown, int, unknown2)
{
if (g_pIgnoreTerminateDetour)
{
g_pIgnoreTerminateDetour = false;
DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason, unknown, unknown2);
return;
}
#else #else
//Windows CSGO //Windows CSGO
//char __userpurge TerminateRound(int a1@<ecx>, float a2@<xmm1>, int *a3) //char __userpurge TerminateRound(int a1@<ecx>, float a2@<xmm1>, int *a3)
// a1 - this // a1 - this
// a2 - delay // a2 - delay
// a3 - reason // a3 - reason
DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason) // a4 - unknown
// a5 - unknown
DETOUR_DECL_MEMBER3(DetourTerminateRound, void, int, reason, int, unknown, int, unknown2)
{ {
float delay; float delay;
if (g_pIgnoreTerminateDetour) if (g_pIgnoreTerminateDetour)
{ {
g_pIgnoreTerminateDetour = false; g_pIgnoreTerminateDetour = false;
return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason, unknown, unknown2);
} }
//Save the delay //Save the delay
@ -178,11 +189,16 @@ DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason)
reason++; reason++;
#endif #endif
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) #if SOURCE_ENGINE != SE_CSGO
if (result == Pl_Changed) if (result == Pl_Changed)
return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason);
#elif !defined(WIN32)
if (result == Pl_Changed)
return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason, unknown, unknown2);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason, unknown, unknown2);
#else #else
if (result == Pl_Changed) if (result == Pl_Changed)
{ {
@ -190,13 +206,13 @@ DETOUR_DECL_MEMBER1(DetourTerminateRound, void, int, reason)
{ {
movss xmm1, delay movss xmm1, delay
} }
return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(reason, unknown, unknown2);
} }
__asm __asm
{ {
movss xmm1, orgdelay movss xmm1, orgdelay
} }
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgreason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgreason, unknown, unknown2);
#endif #endif
} }

View File

@ -314,7 +314,7 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
reason++; reason++;
#endif #endif
#if SOURCE_ENGINE != SE_CSGO || !defined(WIN32) #if SOURCE_ENGINE != SE_CSGO
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
@ -342,6 +342,45 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
vptr += sizeof(float); vptr += sizeof(float);
*(int*)vptr = reason; *(int*)vptr = reason;
pWrapper->Execute(vstk, NULL);
#elif !defined(WIN32)
static ICallWrapper *pWrapper = NULL;
if (!pWrapper)
{
REGISTER_NATIVE_ADDR("TerminateRound",
PassInfo pass[4]; \
pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \
pass[0].size = sizeof(float); \
pass[1].flags = PASSFLAG_BYVAL; \
pass[1].type = PassType_Basic; \
pass[1].size = sizeof(int); \
pass[2].flags = PASSFLAG_BYVAL; \
pass[2].type = PassType_Basic; \
pass[2].size = sizeof(int); \
pass[3].flags = PASSFLAG_BYVAL; \
pass[3].type = PassType_Basic; \
pass[3].size = sizeof(int); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 4))
}
if (params[3] == 1 && g_pTerminateRoundDetoured)
g_pIgnoreTerminateDetour = true;
unsigned char vstk[sizeof(void *) + sizeof(float) + (sizeof(int)*3)];
unsigned char *vptr = vstk;
*(void **)vptr = gamerules;
vptr += sizeof(void *);
*(float *)vptr = sp_ctof(params[1]);
vptr += sizeof(float);
*(int*)vptr = reason;
vptr += sizeof(int);
*(int*)vptr = 0;
vptr += sizeof(int);
*(int*)vptr = 0;
pWrapper->Execute(vstk, NULL); pWrapper->Execute(vstk, NULL);
#else #else
static void *addr = NULL; static void *addr = NULL;
@ -358,6 +397,8 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
__asm __asm
{ {
push 0
push 0
push reason push reason
movss xmm1, delay movss xmm1, delay
mov ecx, gamerules mov ecx, gamerules

View File

@ -336,7 +336,7 @@ SMCSWeapon GetWeaponIdFromDefIdx(uint16_t iDefIdx)
SMCSWeapon_AUG, SMCSWeapon_AWP, SMCSWeapon_FAMAS, SMCSWeapon_G3SG1, SMCSWeapon_AUG, SMCSWeapon_AWP, SMCSWeapon_FAMAS, SMCSWeapon_G3SG1,
SMCSWeapon_NONE, SMCSWeapon_GALILAR, SMCSWeapon_M249, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_GALILAR, SMCSWeapon_M249, SMCSWeapon_NONE,
SMCSWeapon_M4A1, SMCSWeapon_MAC10, SMCSWeapon_NONE, SMCSWeapon_P90, SMCSWeapon_M4A1, SMCSWeapon_MAC10, SMCSWeapon_NONE, SMCSWeapon_P90,
SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_NONE, SMCSWeapon_MP5NAVY,
SMCSWeapon_UMP45, SMCSWeapon_XM1014, SMCSWeapon_BIZON, SMCSWeapon_MAG7, SMCSWeapon_UMP45, SMCSWeapon_XM1014, SMCSWeapon_BIZON, SMCSWeapon_MAG7,
SMCSWeapon_NEGEV, SMCSWeapon_SAWEDOFF, SMCSWeapon_TEC9, SMCSWeapon_TASER, SMCSWeapon_NEGEV, SMCSWeapon_SAWEDOFF, SMCSWeapon_TEC9, SMCSWeapon_TASER,
SMCSWeapon_HKP2000, SMCSWeapon_MP7, SMCSWeapon_MP9, SMCSWeapon_NOVA, SMCSWeapon_HKP2000, SMCSWeapon_MP7, SMCSWeapon_MP9, SMCSWeapon_NOVA,

View File

@ -77,6 +77,10 @@ struct topmenu_object_t
{ {
return strcmp(name, topmenu->name) == 0; return strcmp(name, topmenu->name) == 0;
} }
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
}; };
struct topmenu_category_t struct topmenu_category_t

View File

@ -102,6 +102,10 @@
"plugin_33a4351dd2b9350d6f2b21dab68f7d9e" "" /* [CS:GO] Komutcu Daire System (Sourceless distro) - Version 1.0 */ "plugin_33a4351dd2b9350d6f2b21dab68f7d9e" "" /* [CS:GO] Komutcu Daire System (Sourceless distro) - Version 1.0 */
"plugin_0f9828ea5fe6900981137f3c6fb9d70b" "" /* token changer (Adi) - Version 1.1.2 */ "plugin_0f9828ea5fe6900981137f3c6fb9d70b" "" /* token changer (Adi) - Version 1.1.2 */
"plugin_267929e572d647c43e54ab7aa921174d" "" /* Playwire MOTD (Playwire Media) - Version 1.1.0 */ "plugin_267929e572d647c43e54ab7aa921174d" "" /* Playwire MOTD (Playwire Media) - Version 1.1.0 */
"plugin_f9874d362c5c8142037045a0a2c6249c" "" /* [AnoX]A-Nox Core (A-Nox dev.) - Version 3.1a */
"plugin_eae8ed2c593591814f9e6bfa73000d85" "" /* Unknown VIP plugin with fake myinfo */
"plugin_da0e76b67029c12eb5c1995df4fa4f89" "" /* token changer (Adi) - Version 1.3.9 */
"plugin_514efe1f39061e7365a31fc21d452a79" "" /* Token Auto Updater (Phoenix) - Version 1.4 */
} }
} }
} }

View File

@ -145,7 +145,7 @@
"SetClanTag" "SetClanTag"
{ {
"library" "server" "library" "server"
"windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x2A\x8D\x81\x44\x25\x00\x00" "windows" "\x55\x8B\xEC\x8B\x55\x08\x85\xD2\x74\x2A\x8D\x81\x48\x25\x00\x00"
"linux" "\x55\x89\xE5\x83\xEC\x18\x8B\x45\x0C\x85\xC0\x74\x2A\x89\x44\x24\x04\x8B\x45\x08\xC7\x44\x24\x08\x10\x00\x00\x00" "linux" "\x55\x89\xE5\x83\xEC\x18\x8B\x45\x0C\x85\xC0\x74\x2A\x89\x44\x24\x04\x8B\x45\x08\xC7\x44\x24\x08\x10\x00\x00\x00"
} }
"SetModelFromClass" "SetModelFromClass"

View File

@ -152,6 +152,10 @@ enum CSWeaponID
CSWeapon_KNIFE_SURVIVAL_BOWIE = 514, CSWeapon_KNIFE_SURVIVAL_BOWIE = 514,
CSWeapon_KNIFE_BUTTERFLY = 515, CSWeapon_KNIFE_BUTTERFLY = 515,
CSWeapon_KNIFE_PUSH = 516, CSWeapon_KNIFE_PUSH = 516,
CSWeapon_KNIFE_URSUS = 519,
CSWeapon_KNIFE_GYPSY_JACKKNIFE = 520,
CSWeapon_KNIFE_STILETTO = 522,
CSWeapon_KNIFE_WIDOWMAKER = 523,
CSWeapon_MAX_WEAPONS //THIS MUST BE LAST, EASY WAY TO CREATE LOOPS. When looping, do CS_IsValidWeaponID(i), to check. CSWeapon_MAX_WEAPONS //THIS MUST BE LAST, EASY WAY TO CREATE LOOPS. When looping, do CS_IsValidWeaponID(i), to check.
}; };

View File

@ -48,10 +48,12 @@
namespace SourceMod namespace SourceMod
{ {
// The HashPolicy type must have this method: // The HashPolicy type must have these methods:
// static bool matches(const char *key, const T &value); // static bool matches(const char *key, const T &value);
// static uint32_t hash(const CharsAndLength &key);
// //
// Depending on what lookup types are used. // Depending on what lookup types are used, and how hashing should be done.
// Most of the time, key hashing will just call the key's hash() method.
// //
// If these members are available on T, then the HashPolicy type can be left // If these members are available on T, then the HashPolicy type can be left
// default. It is okay to use |T *|, the functions will still be looked up // default. It is okay to use |T *|, the functions will still be looked up
@ -69,7 +71,7 @@ class NameHashSet : public ke::SystemAllocatorPolicy
static uint32_t hash(const CharsAndLength &key) static uint32_t hash(const CharsAndLength &key)
{ {
return key.hash(); return KeyPolicyType::hash(key);
} }
static bool matches(const CharsAndLength &key, const KeyType &value) static bool matches(const CharsAndLength &key, const KeyType &value)
@ -85,9 +87,9 @@ class NameHashSet : public ke::SystemAllocatorPolicy
{ {
typedef KeyType *Payload; typedef KeyType *Payload;
static uint32_t hash(const detail::CharsAndLength &key) static uint32_t hash(const CharsAndLength &key)
{ {
return key.hash(); return KeyType::hash(key);
} }
static bool matches(const CharsAndLength &key, const KeyType *value) static bool matches(const CharsAndLength &key, const KeyType *value)