diff --git a/core/ADTFactory.cpp b/core/ADTFactory.cpp index 4a41ddae..c9185662 100644 --- a/core/ADTFactory.cpp +++ b/core/ADTFactory.cpp @@ -58,3 +58,8 @@ void BaseTrie::Destroy() { delete this; } + +bool BaseTrie::Replace(const char *key, void *value) +{ + return sm_trie_replace(m_pTrie, key, value); +} diff --git a/core/ADTFactory.h b/core/ADTFactory.h index 08d8b83a..aeb6b242 100644 --- a/core/ADTFactory.h +++ b/core/ADTFactory.h @@ -10,6 +10,7 @@ public: BaseTrie(); virtual ~BaseTrie(); virtual bool Insert(const char *key, void *value); + virtual bool Replace(const char *key, void *value); virtual bool Retrieve(const char *key, void **value); virtual bool Delete(const char *key); virtual void Clear(); diff --git a/core/GameConfigs.cpp b/core/GameConfigs.cpp index e30d6aa9..58590a7b 100644 --- a/core/GameConfigs.cpp +++ b/core/GameConfigs.cpp @@ -190,11 +190,11 @@ SMCParseResult CGameConfig::ReadSMC_KeyValue(const char *key, const char *value, strncopy(m_prop, value, sizeof(m_prop)); } else if (strcmp(key, PLATFORM_NAME) == 0) { int val = atoi(value); - sm_trie_insert(m_pOffsets, m_offset, (void *)val); + sm_trie_replace(m_pOffsets, m_offset, (void *)val); } } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { int id = m_pStrings->AddString(value); - sm_trie_insert(m_pKeys, key, (void *)id); + sm_trie_replace(m_pKeys, key, (void *)id); } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { if (strcmp(key, "game") == 0 && strcmp(value, g_mod) == 0) @@ -249,8 +249,8 @@ SMCParseResult CGameConfig::ReadSMC_LeavingSection() if (pProp) { int val = pProp->GetOffset(); - sm_trie_insert(m_pOffsets, m_offset, (void *)val); - sm_trie_insert(m_pProps, m_offset, pProp); + sm_trie_replace(m_pOffsets, m_offset, (void *)val); + sm_trie_replace(m_pProps, m_offset, pProp); } else { /* Check if it's a non-default game and no offsets exist */ if (((strcmp(m_mod, "*") != 0) && strcmp(m_mod, "#default") != 0) @@ -383,7 +383,7 @@ SMCParseResult CGameConfig::ReadSMC_LeavingSection() #if defined PLATFORM_LINUX skip_find: #endif - sm_trie_insert(m_pSigs, m_offset, final_addr); + sm_trie_replace(m_pSigs, m_offset, final_addr); m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; break; diff --git a/core/sm_trie.cpp b/core/sm_trie.cpp index c7dbfa4e..df61a740 100644 --- a/core/sm_trie.cpp +++ b/core/sm_trie.cpp @@ -388,7 +388,7 @@ bool sm_trie_retrieve(Trie *trie, const char *key, void **value) return true; } -bool sm_trie_insert(Trie *trie, const char *key, void *value) +bool sm_trie_add(Trie *trie, const char *key, void *value, bool replace_allowed) { unsigned int lastidx = 1; /* the last node index */ unsigned int curidx; /* current node index */ @@ -803,7 +803,7 @@ bool sm_trie_insert(Trie *trie, const char *key, void *value) */ assert(node->mode == Node_Arc); - if (!node->valset) + if (!node->valset || replace_allowed) { /* Insert is only possible if we have no production */ node->valset = true; @@ -813,3 +813,13 @@ bool sm_trie_insert(Trie *trie, const char *key, void *value) return false; } + +bool sm_trie_insert(Trie *trie, const char *key, void *value) +{ + return sm_trie_add(trie, key, value, false); +} + +bool sm_trie_replace(Trie *trie, const char *key, void *value) +{ + return sm_trie_add(trie, key, value, true); +} diff --git a/core/sm_trie.h b/core/sm_trie.h index 2e7ddf37..b3162f27 100644 --- a/core/sm_trie.h +++ b/core/sm_trie.h @@ -20,6 +20,7 @@ struct Trie; Trie *sm_trie_create(); void sm_trie_destroy(Trie *trie); bool sm_trie_insert(Trie *trie, const char *key, void *value); +bool sm_trie_replace(Trie *trie, const char *key, void *value); bool sm_trie_retrieve(Trie *trie, const char *key, void **value); bool sm_trie_delete(Trie *trie, const char *key); void sm_trie_clear(Trie *trie); diff --git a/public/IADTFactory.h b/public/IADTFactory.h index ce03c223..126c86f8 100644 --- a/public/IADTFactory.h +++ b/public/IADTFactory.h @@ -4,7 +4,7 @@ #include #define SMINTERFACE_ADTFACTORY_NAME "IADTFactory" -#define SMINTERFACE_ADTFACTORY_VERSION 1 +#define SMINTERFACE_ADTFACTORY_VERSION 2 /** * @file IADTFactory.h @@ -55,6 +55,16 @@ namespace SourceMod * memory. */ virtual void Destroy() =0; + + /** + * @brief Inserts a key/value pair, replacing an old inserted + * value if it already exists. + * + * @param key Key string (null terminated). + * @param value Value pointer (may be anything). + * @return True on success, false on failure. + */ + virtual bool Replace(const char *key, void *value) =0; }; class IADTFactory : public SMInterface