From cdc7d550eb4c1c9f261ec7c8f1ca0388b6d52535 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Mon, 19 Jan 2015 19:17:41 +0100 Subject: [PATCH] Cvars: Rearrange a bit some code Changed class CCVar -> struct CvarInfo Added CvarManager class and moved some code there Code of registering a cvar is rewritten Cvars datas are stored in a hashtable for fast lookup For natives compatibility, an inline list is kept (though CList -> ke::InlineList) Replace some CVAR_GET/SEt_ by FindVar --- amxmodx/amxmodx.cpp | 161 ++++++++++++++++--------------- amxmodx/amxmodx.h | 1 - amxmodx/cvars.cpp | 192 +++++++++++++++++++++++++++++++++++-- amxmodx/cvars.h | 73 +++++++------- amxmodx/meta_api.cpp | 6 +- amxmodx/srvcmd.cpp | 27 +----- plugins/multilingual.sma | 4 +- public/sm_namehashset.h | 201 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 511 insertions(+), 154 deletions(-) create mode 100644 public/sm_namehashset.h diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 10c8ab9c..752a30ff 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -1923,11 +1923,15 @@ static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params) static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params) /* 3 param */ { - int ilen; - char* sptemp = get_amxstring(amx, params[1], 0, ilen); + int length; + const char* name = get_amxstring(amx, params[1], 0, length); - const char *value = CVAR_GET_STRING(sptemp); - return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3] + 1); // + EOS + cvar_t* var = g_CvarManager.FindCvar(name); + + const char *value = var ? var->string : ""; + length = var ? strlen(value) : 0; + + return set_amxstring_utf8(amx, params[2], value, length, params[3] + 1); // + EOS } static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params) @@ -1939,18 +1943,17 @@ static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params) return 0; } - REAL val = (REAL)ptr->value; - - return amx_ftoc(val); + return amx_ftoc(ptr->value); } static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params) /* 1 param */ { - int ilen; + int length; + const char* name = get_amxstring(amx, params[1], 0, length); - REAL pFloat = CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen)); - - return amx_ftoc(pFloat); + cvar_t* var = g_CvarManager.FindCvar(name); + + return var ? amx_ftoc(var->value) : 0; } static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params) @@ -1962,16 +1965,25 @@ static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params) return 0; } - UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%f",amx_ctof(params[2])); - (*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]); + UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2])); + CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]); + return 1; } static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params) /* 2 param */ { - int ilen; - CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), amx_ctof(params[2])); - + int length; + const char* name = get_amxstring(amx, params[1], 0, length); + + cvar_t* var = g_CvarManager.FindCvar(name); + + if (var) + { + UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2])); + CVAR_DIRECTSET(var, &CVarTempBuffer[0]); + } + return 1; } @@ -1989,8 +2001,13 @@ static cell AMX_NATIVE_CALL get_pcvar_num(AMX *amx, cell *params) static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params) /* 1 param */ { - int ilen; - return (int)CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen)); + int length; + const char* name = get_amxstring(amx, params[1], 0, length); + + cvar_t* var = g_CvarManager.FindCvar(name); + + return var ? (int)var->value : 0; + } static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params) @@ -2003,27 +2020,40 @@ static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params) } UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%d",params[2]); - (*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]); + CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]); return 1; } static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params) /* 2 param */ { - int ilen; - CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), (float)params[2]); - + int length; + const char* name = get_amxstring(amx, params[1], 0, length); + int value = params[2]; + + cvar_t* var = g_CvarManager.FindCvar(name); + + if (var) + { + UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%d", value); + CVAR_DIRECTSET(var, &CVarTempBuffer[0]); + } + return 1; } static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params) /* 2 param */ { - int ilen; - char* sptemp = get_amxstring(amx, params[1], 0, ilen); - char* szValue = get_amxstring(amx, params[2], 1, ilen); - - CVAR_SET_STRING(sptemp, szValue); + int length; + const char* name = get_amxstring(amx, params[1], 0, length); + cvar_t* var = g_CvarManager.FindCvar(name); + + if (var) + { + CVAR_DIRECTSET(var, get_amxstring(amx, params[2], 1, length)); + } + return 1; } @@ -2038,7 +2068,7 @@ static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params) /* 2 param int len; - (*g_engfuncs.pfnCvar_DirectSet)(ptr, get_amxstring(amx,params[2],0,len)); + CVAR_DIRECTSET(ptr, get_amxstring(amx,params[2],0,len)); return 1; } @@ -2598,40 +2628,28 @@ static cell AMX_NATIVE_CALL task_exists(AMX *amx, cell *params) /* 1 param */ static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params) /* 1 param */ { int ilen; - return (CVAR_GET_POINTER(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0); + return (g_CvarManager.FindCvar(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0); } static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params) /* 3 param */ { - int i; - char* temp = get_amxstring(amx, params[1], 0, i); + int length; + const char* name = get_amxstring(amx, params[1], 0, length); + const char* value = get_amxstring(amx, params[2], 1, length); + + int flags = params[3]; + float fvalue = amx_ctof(params[4]); + CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx); - if (CheckBadConList(temp, 0)) + if (CheckBadConList(name, 0)) { plugin->AddToFailCounter(1); } - if (!g_cvars.find(temp)) - { - CCVar* cvar = new CCVar(temp, plugin->getName(), params[3], amx_ctof(params[4])); + cvar_t* var = g_CvarManager.CreateCvar(name, value, fvalue, flags, plugin->getName(), plugin->getId()); - cvar->plugin_id = plugin->getId(); - - g_cvars.put(cvar); - - if (CVAR_GET_POINTER(temp) == 0) - { - static cvar_t cvar_reg_helper; - cvar_reg_helper = *(cvar->getCvar()); - CVAR_REGISTER(&cvar_reg_helper); - } - - CVAR_SET_STRING(temp, get_amxstring(amx, params[2], 1, i)); - return reinterpret_cast(CVAR_GET_POINTER(temp)); - } - - return reinterpret_cast(CVAR_GET_POINTER(temp)); + return reinterpret_cast(var); } static cell AMX_NATIVE_CALL get_user_ping(AMX *amx, cell *params) /* 3 param */ @@ -3022,29 +3040,16 @@ static cell AMX_NATIVE_CALL remove_quotes(AMX *amx, cell *params) /* 1 param */ //native get_plugins_cvar(id, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0); static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params) { - int id = params[1]; - int iter_id = 0; + CvarInfo* info = g_CvarManager.FindCvar(params[1]); - for (CList::iterator iter=g_cvars.begin(); iter; ++iter) + if (info) { - if (id == iter_id) - { - CCVar *var = &(*iter); - set_amxstring(amx, params[2], var->getName(), params[3]); - cvar_t *ptr = CVAR_GET_POINTER(var->getName()); - if (!ptr) - { - return 0; - } - cell *addr = get_amxaddr(amx, params[4]); - *addr = ptr->flags; - addr = get_amxaddr(amx, params[5]); - *addr = var->plugin_id; - addr = get_amxaddr(amx, params[6]); - *addr = (cell)ptr; - return 1; - } - iter_id++; + set_amxstring(amx, params[2], info->name.chars(), params[3]); + *get_amxaddr(amx, params[4]) = info->var->flags; + *get_amxaddr(amx, params[5]) = info->pluginId; + *get_amxaddr(amx, params[6]) = reinterpret_cast(info->var); + + return 1; } return 0; @@ -3053,7 +3058,7 @@ static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params) //native get_plugins_cvarsnum(); static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params) { - return g_cvars.size(); + return g_CvarManager.GetRegCvarsCount(); } static cell AMX_NATIVE_CALL get_user_aiming(AMX *amx, cell *params) /* 4 param */ @@ -3107,7 +3112,7 @@ static cell AMX_NATIVE_CALL remove_cvar_flags(AMX *amx, cell *params) if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats")) return 0; - cvar_t* pCvar = CVAR_GET_POINTER(sCvar); + cvar_t* pCvar = g_CvarManager.FindCvar(sCvar); if (pCvar) { @@ -3135,7 +3140,7 @@ static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params) int ilen; char* sCvar = get_amxstring(amx, params[1], 0, ilen); - cvar_t* pCvar = CVAR_GET_POINTER(sCvar); + cvar_t* pCvar = g_CvarManager.FindCvar(sCvar); return pCvar ? pCvar->flags : 0; } @@ -3162,7 +3167,7 @@ static cell AMX_NATIVE_CALL set_cvar_flags(AMX *amx, cell *params) if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats")) return 0; - cvar_t* pCvar = CVAR_GET_POINTER(sCvar); + cvar_t* pCvar = g_CvarManager.FindCvar(sCvar); if (pCvar) { @@ -4448,9 +4453,9 @@ static cell AMX_NATIVE_CALL DestroyForward(AMX *amx, cell *params) static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params) { int len; - char *temp = get_amxstring(amx, params[1], 0, len); + char *name = get_amxstring(amx, params[1], 0, len); - cvar_t *ptr = CVAR_GET_POINTER(temp); + cvar_t *ptr = g_CvarManager.FindCvar(name); return reinterpret_cast(ptr); } diff --git a/amxmodx/amxmodx.h b/amxmodx/amxmodx.h index 76efc850..3a96630f 100755 --- a/amxmodx/amxmodx.h +++ b/amxmodx/amxmodx.h @@ -162,7 +162,6 @@ extern CTaskMngr g_tasksMngr; extern CPlayer g_players[33]; extern CPlayer* mPlayer; extern CmdMngr g_commands; -extern CList g_cvars; extern CList g_forcemodels; extern CList g_forcesounds; extern CList g_forcegeneric; diff --git a/amxmodx/cvars.cpp b/amxmodx/cvars.cpp index 6f7a8c43..1d18dc04 100644 --- a/amxmodx/cvars.cpp +++ b/amxmodx/cvars.cpp @@ -11,25 +11,52 @@ #include "amxmodx.h" #include -CDetour *Cvar_DirectSetDetour; +CvarManager g_CvarManager; DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value) { - if (var && value) + static bool calledFromCallback = false; + + if (!calledFromCallback && var && value) { if (strcmp(var->string, value) != 0) { + calledFromCallback = true; + if (executeForwards(FF_CvarChanged, reinterpret_cast(var), var->string, value, var->name) > 0) { - return; + //return; } + + calledFromCallback = false; } } DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value); } -void CreateCvarHook(void) +CvarManager::CvarManager() : m_AmxmodxCvars(0), m_HookDetour(nullptr) +{ +} + +CvarManager::~CvarManager() +{ + CvarsList::iterator iter = m_Cvars.begin(); + + while (iter != m_Cvars.end()) + { + CvarInfo* info = (*iter); + + iter = m_Cvars.erase(iter); + + delete info; + } + + m_Cache.clear(); + m_HookDetour->Destroy(); +} + +void CvarManager::CreateCvarHook(void) { // void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet // { @@ -69,11 +96,160 @@ void CreateCvarHook(void) if (functionAddress) { - CDetour *Cvar_DirectSetDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress); + m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress); - if (Cvar_DirectSetDetour) + if (m_HookDetour) { - Cvar_DirectSetDetour->EnableDetour(); + m_HookDetour->EnableDetour(); } } -} \ No newline at end of file +} + +cvar_t* CvarManager::CreateCvar(const char* name, const char* value, float fvalue, int flags, const char* plugin, int plugnId) +{ + cvar_t* var = nullptr; + CvarInfo* info = nullptr; + + // Is cvar already cached ? + if (!m_Cache.retrieve(name, &info)) + { + // Not cached - Is cvar already exist? + var = CVAR_GET_POINTER(name); + + // Whether it exists, we need to prepare a new entry. + info = new CvarInfo(); + + // Shared datas. + info->name = name; + info->plugin = plugin; + info->pluginId = plugnId; + + if (var) + { + // Cvar already exists. Just copy. + // "string" will be set after. "value" and "next" are automatically set. + info->var = var; + info->defaultval = var->string; + info->amxmodx = false; + } + else + { + // Registers a new cvar. + static cvar_t cvar_reg_helper; + + // "string" will be set after. "value" and "next" are automatically set. + cvar_reg_helper.name = info->name.chars(); + cvar_reg_helper.string = ""; + cvar_reg_helper.flags = flags; + + // Adds cvar to global list. + CVAR_REGISTER(&cvar_reg_helper); + + // Registering can fail if name is already a registered command. + var = CVAR_GET_POINTER(name); + + // If so, we can't go further. + if (!var) + { + delete info; + return nullptr; + } + + // If ok, we got a valid pointer, we can copy. + info->var = var; + info->defaultval = value; + info->amxmodx = true; + + // Keeps track count of cvars registered by AMXX. + ++m_AmxmodxCvars; + } + + // Add a new entry in the caches. + m_Cvars.append(info); + m_Cache.insert(name, info); + + // Make sure that whether an existing or new cvar is set to the given value. + CVAR_DIRECTSET(var, value); + } + + return info->var; +} + +cvar_t* CvarManager::FindCvar(const char* name) +{ + cvar_t* var = nullptr; + CvarInfo* info = nullptr; + + // Do we have already cvar in cache? + if (m_Cache.retrieve(name, &info)) + { + return info->var; + } + + // Cvar doesn't exist. + if (!(var = CVAR_GET_POINTER(name))) + { + return nullptr; + } + + // Create a new entry. + info = new CvarInfo(); + info->var = var; + info->name = name; + info->plugin = ""; + info->pluginId = -1; + info->amxmodx = false; + + // Add entry in the caches. + m_Cvars.append(info); + m_Cache.insert(name, info); + + return var; +} + +CvarInfo* CvarManager::FindCvar(size_t index) +{ + // Used by get_plugins_cvar native. + // For compatibility, only cvars registered by AMXX are concerned. + + size_t iter_id = 0; + + for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++) + { + if (iter->amxmodx && iter_id++ == index) + { + return *(iter); + } + } + + return nullptr; +} + +size_t CvarManager::GetRegCvarsCount() +{ + return m_AmxmodxCvars; +} + +void CvarManager::OnConsoleCommand() +{ + print_srvconsole("Registered cvars:\n"); + print_srvconsole(" %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin"); + + size_t index = 0; + ke::AString pluginName; + + if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin + { + pluginName = CMD_ARGV(2); + } + + for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++) + { + CvarInfo* ci = (*iter); + + if (ci->amxmodx && (!pluginName.length() || strncmp(ci->name.chars(), pluginName.chars(), pluginName.length()) == 0)) + { + print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++index, ci->name.chars(), ci->var->string, ci->plugin.chars()); + } + } +} diff --git a/amxmodx/cvars.h b/amxmodx/cvars.h index 9d29bc9d..e4b71891 100644 --- a/amxmodx/cvars.h +++ b/amxmodx/cvars.h @@ -11,50 +11,53 @@ #define CVARS_H #include "cvardef.h" -#include +#include +#include class CDetour; -class CCVar +struct CvarInfo : public ke::InlineListNode { - cvar_t cvar; - ke::AString name; - ke::AString plugin; + cvar_t* var; + ke::AString name; + ke::AString defaultval; + ke::AString plugin; + int pluginId; + bool amxmodx; -public: - CCVar(const char* pname, const char* pplugin, int pflags, float pvalue) : name(pname), plugin(pplugin) + static inline bool matches(const char *name, const CvarInfo* info) { - cvar.name = name.chars(); - cvar.flags = pflags; - cvar.string = ""; - cvar.value = pvalue; + return strcmp(name, info->var->name) == 0; } - - inline cvar_t* getCvar() - { - return &cvar; - } - - inline const char* getPluginName() - { - return plugin.chars(); - } - - inline const char* getName() - { - return name.chars(); - } - - inline bool operator == (const char* string) - { - return name.compare(string) == 0; - } - - int plugin_id; }; -void CreateCvarHook(void); +typedef NameHashSet CvarsCache; +typedef ke::InlineList CvarsList; -extern CDetour *Cvar_DirectSetDetour; +class CvarManager +{ + public: + + CvarManager(); + ~CvarManager(); + + public: + + void CreateCvarHook(); + cvar_t* CreateCvar(const char* name, const char* value, float fvalue, int flags, const char* plugin, int plugnId); + cvar_t* FindCvar(const char* name); + CvarInfo* FindCvar(size_t index); + size_t GetRegCvarsCount(); + void OnConsoleCommand(); + + private: + + CvarsCache m_Cache; + CvarsList m_Cvars; + size_t m_AmxmodxCvars; + CDetour* m_HookDetour; +}; + +extern CvarManager g_CvarManager; #endif // CVARS_H diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 7e4ad667..9908738f 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -64,7 +64,6 @@ extern CVector DynamicAdmins; CLog g_log; CForwardMngr g_forwards; CList g_auth; -CList g_cvars; CList g_forcemodels; CList g_forcesounds; CList g_forcegeneric; @@ -122,7 +121,7 @@ cvar_t init_amxmodx_modules = {"amxmodx_modules", "", FCVAR_SPONLY}; cvar_t init_amxmodx_debug = {"amx_debug", "1", FCVAR_SPONLY}; cvar_t init_amxmodx_mldebug = {"amx_mldebug", "", FCVAR_SPONLY}; cvar_t init_amxmodx_language = {"amx_language", "en", FCVAR_SERVER}; -cvar_t init_amxmodx_cl_langs = {"amx_client_languages", "", FCVAR_SERVER}; +cvar_t init_amxmodx_cl_langs = {"amx_client_languages", "1", FCVAR_SERVER}; cvar_t* amxmodx_version = NULL; cvar_t* amxmodx_modules = NULL; cvar_t* amxmodx_language = NULL; @@ -1492,7 +1491,7 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m FlagMan.SetFile("cmdaccess.ini"); - CreateCvarHook(); + g_CvarManager.CreateCvarHook(); return (TRUE); } @@ -1522,7 +1521,6 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) g_vault.clear(); g_xvars.clear(); g_plugins.clear(); - g_cvars.clear(); g_langMngr.Clear(); ClearMessages(); diff --git a/amxmodx/srvcmd.cpp b/amxmodx/srvcmd.cpp index 91e264ef..847b7f28 100755 --- a/amxmodx/srvcmd.cpp +++ b/amxmodx/srvcmd.cpp @@ -111,32 +111,7 @@ void amx_command() } else if (!strcmp(cmd, "cvars")) { - print_srvconsole("Registered cvars:\n"); - print_srvconsole(" %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin"); - - int ammount = 0; - - if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin - { - const char* targetname = CMD_ARGV(2); - size_t len = strlen(targetname); - for (CList::iterator a = g_cvars.begin(); a; ++a) - { - if (strncmp((*a).getPluginName(), targetname, len) == 0) - { - print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++ammount, (*a).getName(), CVAR_GET_STRING((*a).getName()), (*a).getPluginName()); - } - } - } - else // No search - { - for (CList::iterator a = g_cvars.begin(); a; ++a) - { - print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++ammount, (*a).getName(), CVAR_GET_STRING((*a).getName()), (*a).getPluginName()); - } - } - - print_srvconsole("%d cvars\n", ammount); + g_CvarManager.OnConsoleCommand(); } else if (!strcmp(cmd, "cmds")) { diff --git a/plugins/multilingual.sma b/plugins/multilingual.sma index 28dbc721..6c41a2fe 100755 --- a/plugins/multilingual.sma +++ b/plugins/multilingual.sma @@ -28,9 +28,9 @@ public plugin_init() register_dictionary("multilingual.txt") register_dictionary("common.txt") register_dictionary("languages.txt") - - g_cvarClientLanguages = register_cvar("amx_client_languages", "1") + g_cvarDisplayClientMessage = register_cvar("amx_language_display_msg", "1") + g_cvarClientLanguages = get_cvar_pointer("amx_client_languages") g_cvarServerLanguage = get_cvar_pointer("amx_language"); register_clcmd("amx_langmenu", "cmdLangMenu", ADMIN_ALL) diff --git a/public/sm_namehashset.h b/public/sm_namehashset.h new file mode 100644 index 00000000..9524987b --- /dev/null +++ b/public/sm_namehashset.h @@ -0,0 +1,201 @@ +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _include_sourcemod_namehashset_h_ +#define _include_sourcemod_namehashset_h_ + +/** + * @file sm_namehashset.h + * + * @brief Stores a set of uniquely named objects. + */ + +#include +#include +#include +#include + +//namespace SourceMod +//{ + +// The HashPolicy type must have this method: +// static bool matches(const char *key, const T &value); +// +// Depending on what lookup types are used. +// +// 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 +// on |T|. +template +class NameHashSet : public ke::SystemAllocatorPolicy +{ + typedef detail::CharsAndLength CharsAndLength; + + // Default policy type: the two types are different. Use them directly. + template + struct Policy + { + typedef KeyType Payload; + + static uint32_t hash(const CharsAndLength &key) + { + return key.hash(); + } + + static bool matches(const CharsAndLength &key, const KeyType &value) + { + return KeyPolicyType::matches(key.chars(), value); + } + }; + + // Specialization: the types are equal, and T is a pointer. Strip the + // pointer off so we can access T:: for match functions. + template + struct Policy + { + typedef KeyType *Payload; + + static uint32_t hash(const detail::CharsAndLength &key) + { + return key.hash(); + } + + static bool matches(const CharsAndLength &key, const KeyType *value) + { + return KeyType::matches(key.chars(), value); + } + }; + + typedef ke::HashTable, ke::SystemAllocatorPolicy> Internal; + +public: + NameHashSet() + { + if (!table_.init()) + this->reportOutOfMemory(); + } + + typedef typename Internal::Result Result; + typedef typename Internal::Insert Insert; + typedef typename Internal::iterator iterator; + + Result find(const char *aKey) + { + return table_.find(aKey); + } + + Insert findForAdd(const char *aKey) + { + return table_.findForAdd(aKey); + } + + void add(Insert &i, const T &value) + { + return table_.add(i, value); + } + + void add(Insert &i, T &&value) + { + return table_.add(i, value); + } + + bool retrieve(const char *aKey, T *value) + { + CharsAndLength key(aKey); + Result r = table_.find(aKey); + if (!r.found()) + return false; + *value = *r; + return true; + } + + bool insert(const char *aKey, const T &value) + { + CharsAndLength key(aKey); + Insert i = table_.findForAdd(key); + if (i.found()) + return false; + return table_.add(i, value); + } + + bool insert(const char *aKey, T &&value) + { + CharsAndLength key(aKey); + Insert i = table_.findForAdd(key); + if (i.found()) + return false; + return table_.add(i, value); + } + + bool contains(const char *aKey) + { + CharsAndLength key(aKey); + Result r = table_.find(aKey); + return r.found(); + } + + bool remove(const char *aKey) + { + CharsAndLength key(aKey); + Result r = table_.find(key); + if (!r.found()) + return false; + table_.remove(r); + return true; + } + + void remove(Result &r) + { + table_.remove(r); + } + + void clear() + { + table_.clear(); + } + + size_t mem_usage() const + { + return table_.estimateMemoryUse(); + } + + iterator iter() + { + return iterator(&table_); + } + +private: + Internal table_; +}; + +//} + +#endif // _include_sourcemod_namehashset_h_