Introduce NameHashSet (bug 5884 part 1, r=ds).
1.1 --- a/core/logic/GameConfigs.cpp Sun Aug 25 11:26:37 2013 -0700
1.2 +++ b/core/logic/GameConfigs.cpp Sun Aug 25 11:59:44 2013 -0700
1.3 @@ -981,12 +981,10 @@
1.4
1.5 SendProp *CGameConfig::GetSendProp(const char *key)
1.6 {
1.7 - SendProp **pProp;
1.8 -
1.9 - if ((pProp = m_Props.retrieve(key)) == NULL)
1.10 + SendProp *prop;
1.11 + if (!m_Props.retrieve(key, &prop))
1.12 return NULL;
1.13 -
1.14 - return *pProp;
1.15 + return prop;
1.16 }
1.17
1.18 bool CGameConfig::GetMemSig(const char *key, void **addr)
1.19 @@ -1042,11 +1040,9 @@
1.20 #endif
1.21
1.22 CGameConfig *pConfig;
1.23 - CGameConfig **ppConfig;
1.24
1.25 - if ((ppConfig = m_Lookup.retrieve(file)) != NULL)
1.26 + if (m_Lookup.retrieve(file, &pConfig))
1.27 {
1.28 - pConfig = *ppConfig;
1.29 pConfig->AddRef();
1.30 *_pConfig = pConfig;
1.31 return true;
2.1 --- a/core/logic/GameConfigs.h Sun Aug 25 11:26:37 2013 -0700
2.2 +++ b/core/logic/GameConfigs.h Sun Aug 25 11:59:44 2013 -0700
2.3 @@ -39,6 +39,7 @@
2.4 #include <sm_trie_tpl.h>
2.5 #include <am-refcounting.h>
2.6 #include <sm_stringhashmap.h>
2.7 +#include <sm_namehashset.h>
2.8
2.9 using namespace SourceMod;
2.10 using namespace SourceHook;
2.11 @@ -69,12 +70,17 @@
2.12 SendProp *GetSendProp(const char *key);
2.13 bool GetMemSig(const char *key, void **addr);
2.14 bool GetAddress(const char *key, void **addr);
2.15 +public: //NameHashSet
2.16 + static inline bool matches(const char *key, const CGameConfig *value)
2.17 + {
2.18 + return strcmp(key, value->m_File) == 0;
2.19 + }
2.20 private:
2.21 ke::AutoPtr<BaseStringTable> m_pStrings;
2.22 char m_File[PLATFORM_MAX_PATH];
2.23 char m_CurFile[PLATFORM_MAX_PATH];
2.24 StringHashMap<int> m_Offsets;
2.25 - KTrie<SendProp *> m_Props;
2.26 + StringHashMap<SendProp *> m_Props;
2.27 StringHashMap<int> m_Keys;
2.28 StringHashMap<void *> m_Sigs;
2.29 /* Parse states */
2.30 @@ -139,7 +145,7 @@
2.31 public:
2.32 void RemoveCachedConfig(CGameConfig *config);
2.33 private:
2.34 - KTrie<CGameConfig *> m_Lookup;
2.35 + NameHashSet<CGameConfig *> m_Lookup;
2.36 public:
2.37 StringHashMap<ITextListener_SMC *> m_customHandlers;
2.38 };
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/public/amtl/am-hashset.h Sun Aug 25 11:59:44 2013 -0700
3.3 @@ -0,0 +1,126 @@
3.4 +// vim: set sts=8 ts=2 sw=2 tw=99 et:
3.5 +//
3.6 +// Copyright (C) 2013, David Anderson and AlliedModders LLC
3.7 +// All rights reserved.
3.8 +//
3.9 +// Redistribution and use in source and binary forms, with or without
3.10 +// modification, are permitted provided that the following conditions are met:
3.11 +//
3.12 +// * Redistributions of source code must retain the above copyright notice, this
3.13 +// list of conditions and the following disclaimer.
3.14 +// * Redistributions in binary form must reproduce the above copyright notice,
3.15 +// this list of conditions and the following disclaimer in the documentation
3.16 +// and/or other materials provided with the distribution.
3.17 +// * Neither the name of AlliedModders LLC nor the names of its contributors
3.18 +// may be used to endorse or promote products derived from this software
3.19 +// without specific prior written permission.
3.20 +//
3.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3.22 +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3.23 +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3.24 +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
3.25 +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3.26 +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3.27 +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3.28 +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3.29 +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3.30 +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3.31 +// POSSIBILITY OF SUCH DAMAGE.
3.32 +
3.33 +#ifndef _include_amtl_hashmap_h_
3.34 +#define _include_amtl_hashmap_h_
3.35 +
3.36 +#include <am-hashtable.h>
3.37 +
3.38 +namespace ke {
3.39 +
3.40 +// Template parameters:
3.41 +//
3.42 +// K - Key type.
3.43 +// HashPolicy - A struct with a hash and comparator function for each lookup type:
3.44 +// static uint32_t hash(const Type &value);
3.45 +// static bool matches(const Type &value, const K &key);
3.46 +//
3.47 +// Like HashMap and HashTable, init() must be called to construct the set.
3.48 +template <typename K,
3.49 + typename HashPolicy,
3.50 + typename AllocPolicy = SystemAllocatorPolicy>
3.51 +class HashSet : public AllocPolicy
3.52 +{
3.53 + struct Policy {
3.54 + typedef K Payload;
3.55 +
3.56 + template <typename Lookup>
3.57 + static uint32_t hash(const Lookup &key) {
3.58 + return HashPolicy::hash(key);
3.59 + }
3.60 +
3.61 + template <typename Lookup>
3.62 + static bool matches(const Lookup &key, const Payload &payload) {
3.63 + return HashPolicy::matches(key, payload);
3.64 + }
3.65 + };
3.66 +
3.67 + typedef HashTable<Policy, AllocPolicy> Internal;
3.68 +
3.69 + public:
3.70 + HashSet(AllocPolicy ap = AllocPolicy())
3.71 + : table_(ap)
3.72 + {
3.73 + }
3.74 +
3.75 + // capacity must be a power of two.
3.76 + bool init(size_t capacity = 16) {
3.77 + return table_.init(capacity);
3.78 + }
3.79 +
3.80 + typedef typename Internal::Result Result;
3.81 + typedef typename Internal::Insert Insert;
3.82 +
3.83 + template <typename Lookup>
3.84 + Result find(const Lookup &key) {
3.85 + return table_.find(key);
3.86 + }
3.87 +
3.88 + template <typename Lookup>
3.89 + Insert findForAdd(const Lookup &key) {
3.90 + return table_.findForAdd(key);
3.91 + }
3.92 +
3.93 + template <typename Lookup>
3.94 + void removeIfExists(const Lookup &key) {
3.95 + return table_.remove(key);
3.96 + }
3.97 +
3.98 + void remove(Result &r) {
3.99 + table_.remove(r);
3.100 + }
3.101 +
3.102 + // The map must not have been mutated in between findForAdd() and add().
3.103 + // The Insert object is still valid after add() returns, however.
3.104 + bool add(Insert &i, const K &key) {
3.105 + return table_.add(i, key);
3.106 + }
3.107 +
3.108 + // This can be used to avoid compiler constructed temporaries, since AMTL
3.109 + // does not yet support move semantics. If you use this, the key and value
3.110 + // must be set after.
3.111 + bool add(Insert &i) {
3.112 + return table_.add(i);
3.113 + }
3.114 +
3.115 + void clear() {
3.116 + table_.clear();
3.117 + }
3.118 +
3.119 + size_t estimateMemoryUse() const {
3.120 + return table_.estimateMemoryUse();
3.121 + }
3.122 +
3.123 + private:
3.124 + Internal table_;
3.125 +};
3.126 +
3.127 +}
3.128 +
3.129 +#endif // _include_amtl_hashset_h_
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/public/sm_namehashset.h Sun Aug 25 11:59:44 2013 -0700
4.3 @@ -0,0 +1,143 @@
4.4 +/**
4.5 + * vim: set ts=4 sw=4 tw=99 noet :
4.6 + * =============================================================================
4.7 + * SourceMod
4.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
4.9 + * =============================================================================
4.10 + *
4.11 + * This program is free software; you can redistribute it and/or modify it under
4.12 + * the terms of the GNU General Public License, version 3.0, as published by the
4.13 + * Free Software Foundation.
4.14 + *
4.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
4.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
4.18 + * details.
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License along with
4.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
4.22 + *
4.23 + * As a special exception, AlliedModders LLC gives you permission to link the
4.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
4.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
4.26 + * by the Valve Corporation. You must obey the GNU General Public License in
4.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
4.28 + * this exception to all derivative works. AlliedModders LLC defines further
4.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
4.30 + * or <http://www.sourcemod.net/license.php>.
4.31 + *
4.32 + * Version: $Id$
4.33 + */
4.34 +
4.35 +#ifndef _include_sourcemod_namehashset_h_
4.36 +#define _include_sourcemod_namehashset_h_
4.37 +
4.38 +/**
4.39 + * @file sm_namehashset.h
4.40 + *
4.41 + * @brief Stores a set of uniquely named objects.
4.42 + */
4.43 +
4.44 +#include <am-allocator-policies.h>
4.45 +#include <am-hashmap.h>
4.46 +#include <am-string.h>
4.47 +#include "sm_stringhashmap.h"
4.48 +
4.49 +namespace SourceMod
4.50 +{
4.51 +
4.52 +// The HashPolicy type must have this method:
4.53 +// static bool matches(const char *key, const T &value);
4.54 +//
4.55 +// Depending on what lookup types are used.
4.56 +//
4.57 +// If these members are available on T, then the HashPolicy type can be left
4.58 +// default. It is okay to use |T *|, the functions will still be looked up
4.59 +// on |T|.
4.60 +template <typename T, typename KeyPolicy = T>
4.61 +class NameHashSet : public SystemAllocatorPolicy
4.62 +{
4.63 + typedef detail::CharsAndLength CharsAndLength;
4.64 +
4.65 + // Default policy type: the two types are different. Use them directly.
4.66 + template <typename KeyType, typename KeyPolicyType>
4.67 + struct Policy {
4.68 + typedef KeyType Payload;
4.69 +
4.70 + static uint32_t hash(const CharsAndLength &key)
4.71 + {
4.72 + return key.hash();
4.73 + }
4.74 +
4.75 + static bool matches(const CharsAndLength &key, const KeyType &value)
4.76 + {
4.77 + return KeyPolicyType::matches(key.chars(), value);
4.78 + }
4.79 + };
4.80 +
4.81 + // Specialization: the types are equal, and T is a pointer. Strip the
4.82 + // pointer off so we can access T:: for match functions.
4.83 + template <typename KeyType>
4.84 + struct Policy<KeyType *, KeyType *>
4.85 + {
4.86 + typedef KeyType *Payload;
4.87 +
4.88 + static uint32_t hash(const detail::CharsAndLength &key)
4.89 + {
4.90 + return key.hash();
4.91 + }
4.92 +
4.93 + static bool matches(const CharsAndLength &key, const KeyType *value)
4.94 + {
4.95 + return KeyType::matches(key.chars(), value);
4.96 + }
4.97 + };
4.98 +
4.99 + typedef HashTable<Policy<T, KeyPolicy>, SystemAllocatorPolicy> Internal;
4.100 +
4.101 +public:
4.102 + NameHashSet()
4.103 + {
4.104 + if (!table_.init())
4.105 + this->reportOutOfMemory();
4.106 + }
4.107 +
4.108 + typedef typename Internal::Result Result;
4.109 + typedef typename Internal::Insert Insert;
4.110 +
4.111 + bool retrieve(const char *aKey, T *value)
4.112 + {
4.113 + CharsAndLength key(aKey);
4.114 + Result r = table_.find(aKey);
4.115 + if (!r.found())
4.116 + return false;
4.117 + *value = *r;
4.118 + return true;
4.119 + }
4.120 +
4.121 + bool insert(const char *aKey, const T &value)
4.122 + {
4.123 + CharsAndLength key(aKey);
4.124 + Insert i = table_.findForAdd(key);
4.125 + if (i.found())
4.126 + return false;
4.127 + return table_.add(i, value);
4.128 + }
4.129 +
4.130 + bool remove(const char *aKey)
4.131 + {
4.132 + CharsAndLength key(aKey);
4.133 + Result r = table_.find(key);
4.134 + if (!r.found())
4.135 + return false;
4.136 + table_.remove(r);
4.137 + return true;
4.138 + }
4.139 +
4.140 +private:
4.141 + Internal table_;
4.142 +};
4.143 +
4.144 +}
4.145 +
4.146 +#endif // _include_sourcemod_namehashset_h_