Introduce NameHashSet (bug 5884 part 1, r=ds).
authorDavid Anderson <dvander@alliedmods.net>
Sun Aug 25 11:59:44 2013 -0700 (2013-08-25)
changeset 40637b7372572e85
parent 4062 29aae8f2113a
child 4064 d7ca1e28949d
Introduce NameHashSet (bug 5884 part 1, r=ds).
core/logic/GameConfigs.cpp
core/logic/GameConfigs.h
public/amtl/am-hashset.h
public/sm_namehashset.h
     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_