libraries/ltkutils/inc/stringhash.h
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/ltkutils/inc/stringhash.h	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,280 @@
+// stringhash.h
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+#ifndef FSHELL_STRINGHASH_H
+#define FSHELL_STRINGHASH_H
+
+#include <e32hashtab.h>
+
+namespace LtkUtils
+	{
+	template <typename T> class TStringHashIter;
+	template <typename T> struct SHashVal { HBufC* iKey; T iValue; };
+	
+	template <typename T>
+	class RStringHash
+		{
+	public: // RHashMap-style
+		inline RStringHash();
+		inline T* Find(const TDesC& aKey);
+		inline T FindPtr(const TDesC& aKey); // Only use if T is a pointer
+		inline T& FindL(const TDesC& aKey);
+		inline T const* Find(const TDesC& aKey) const;
+		inline T const FindPtr(const TDesC& aKey) const; // Only use if T is a pointer
+		inline T const& FindL(const TDesC& aKey) const;
+		inline TInt Insert(const TDesC& aKey, const T& aValue);
+		inline void InsertL(const TDesC& aKey, const T& aValue);
+		inline TInt Remove(const TDesC& aKey);
+
+		inline TInt Count() const;
+		inline TInt Reserve(TInt aCount);
+		inline void ReserveL(TInt aCount);
+		inline void Close();
+
+	protected:
+		inline SHashVal<T>* DoFind(const TDesC& aKey);
+		inline SHashVal<T> const* DoFind(const TDesC& aKey) const;
+		friend class TStringHashIter<T>;
+
+		RHashMap<TDesC*, SHashVal<T> > iHash;
+		TAny* iSpare;
+		TAny* iSpare2;
+		};
+
+	template <typename T>
+	class TStringHashIter
+		{
+	public:
+		inline TStringHashIter(const RStringHash<T>& aHash);
+		inline const TDesC* CurrentKey() const;
+		inline const TDesC* NextKey();
+		inline T* CurrentValue();
+		inline const T* NextValue();
+		inline void RemoveCurrent();
+
+	private:
+		THashMapIter<TDesC*, SHashVal<T> > iIter;
+		};
+
+	inline TUint32 HashFn(TDesC* const& aKey);
+	inline TBool IdFn(TDesC* const& aFirst, TDesC* const& aSecond);
+	}
+
+
+// Nothing to see here, move along move along
+
+template <typename T>
+LtkUtils::RStringHash<T>::RStringHash()
+	: iHash(THashFunction32<TDesC*>(&HashFn), TIdentityRelation<TDesC*>(&IdFn)), iSpare(NULL), iSpare2(NULL)
+	{
+	}
+
+inline TUint32 LtkUtils::HashFn(TDesC* const& aKey)
+	{
+	return DefaultHash::Des16(*aKey);
+	}
+
+inline TBool LtkUtils::IdFn(TDesC* const& aFirst, TDesC* const& aSecond)
+	{
+	return DefaultIdentity::Des16(*aFirst, *aSecond);
+	}
+
+template <typename T>
+inline T* LtkUtils::RStringHash<T>::Find(const TDesC& aKey)
+	{
+	SHashVal<T>* res = DoFind(aKey);
+	if (res) return &res->iValue;
+	else return NULL;
+	}
+
+
+template <typename T>
+inline T LtkUtils::RStringHash<T>::FindPtr(const TDesC& aKey)
+	{
+	T* res = Find(aKey);
+	if (res) return *res;
+	else return NULL;
+	}
+
+
+template <typename T>
+inline T const* LtkUtils::RStringHash<T>::Find(const TDesC& aKey) const
+	{
+	SHashVal<T> const* res = DoFind(aKey);
+	if (res) return &res->iValue;
+	else return NULL;
+	}
+
+template <typename T>
+inline T const LtkUtils::RStringHash<T>::FindPtr(const TDesC& aKey) const
+	{
+	T const* res = Find(aKey);
+	if (res) return *res;
+	else return NULL;
+	}
+
+template <typename T>
+inline T& LtkUtils::RStringHash<T>::FindL(const TDesC& aKey)
+	{
+	T* res = Find(aKey);
+	if (!res) User::Leave(KErrNotFound);
+	return *res;
+	}
+
+template <typename T>
+inline T const& LtkUtils::RStringHash<T>::FindL(const TDesC& aKey) const
+	{
+	T const* res = Find(aKey);
+	if (!res) User::Leave(KErrNotFound);
+	return *res;
+	}
+
+template <typename T>
+TInt LtkUtils::RStringHash<T>::Insert(const TDesC& aKey, const T& aValue)
+	{
+	SHashVal<T>* valPtr = DoFind(aKey);
+	if (valPtr)
+		{
+		// Just update the value, no need to realloc anything
+		memcpy(&valPtr->iValue, &aValue, sizeof(T));
+		return KErrNone;
+		}
+
+	HBufC* buf = aKey.Alloc();
+	if (!buf) return KErrNoMemory;
+	// Avoid declaring an SHashVal<T> as that requires T to have a default constructor
+	TUint8 valBuf[sizeof(SHashVal<T>)];
+	SHashVal<T>& val = *reinterpret_cast<SHashVal<T>*>(valBuf);
+	val.iKey = buf;
+	memcpy(&val.iValue, &aValue, sizeof(T));
+	TInt err = iHash.Insert(buf, val);
+	if (err)
+		{
+		delete buf;
+		}
+	return err;
+	}
+
+template <typename T>
+inline TInt LtkUtils::RStringHash<T>::Remove(const TDesC& aKey)
+	{
+	SHashVal<T>* valPtr = DoFind(aKey);
+	if (valPtr)
+		{
+		HBufC* key = valPtr->iKey;
+		iHash.Remove(key);
+		delete key;
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+template <typename T>
+inline void LtkUtils::RStringHash<T>::Close()
+	{
+	THashMapIter<TDesC*, SHashVal<T> > iter(iHash);
+	while (iter.NextValue() != NULL)
+		{
+		SHashVal<T>* current = const_cast<SHashVal<T>*>(iter.CurrentValue()); // const_cast not needed except on 9.1
+		HBufC* key = current->iKey;
+		iter.RemoveCurrent();
+		delete key;
+		}
+	iHash.Close();
+	}
+
+template <typename T>
+inline void LtkUtils::RStringHash<T>::InsertL(const TDesC& aKey, const T& aValue)
+	{
+	User::LeaveIfError(Insert(aKey, aValue));
+	}
+
+template <typename T>
+inline TInt LtkUtils::RStringHash<T>::Count() const
+	{
+	return iHash.Count();
+	}
+
+template <typename T>
+inline TInt LtkUtils::RStringHash<T>::Reserve(TInt aCount)
+	{
+	return iHash.Reserve(aCount);
+	}
+
+template <typename T>
+inline void LtkUtils::RStringHash<T>::ReserveL(TInt aCount)
+	{
+	User::LeaveIfError(Reserve(aCount));
+	}
+
+template <typename T>
+inline LtkUtils::SHashVal<T>* LtkUtils::RStringHash<T>::DoFind(const TDesC& aKey)
+	{
+	return iHash.Find(const_cast<TDesC*>(&aKey));
+	}
+
+template <typename T>
+inline LtkUtils::SHashVal<T> const* LtkUtils::RStringHash<T>::DoFind(const TDesC& aKey) const
+	{
+	return iHash.Find(const_cast<TDesC*>(&aKey));
+	}
+
+/// Iterator support
+
+template <typename T>
+inline const TDesC* LtkUtils::TStringHashIter<T>::CurrentKey() const
+	{
+	return *const_cast<TDesC**>(iIter.CurrentKey());
+	}
+
+template <typename T>
+inline const TDesC* LtkUtils::TStringHashIter<T>::NextKey()
+	{
+	return *const_cast<TDesC**>(iIter.NextKey());
+	}
+
+template <typename T>
+inline T* LtkUtils::TStringHashIter<T>::CurrentValue()
+	{
+	SHashVal<T>* val = const_cast<SHashVal<T>*>(iIter.CurrentValue()); // The const_cast isn't needed, except on 9.1
+	if (val) return &val->iValue;
+	return NULL;
+	}
+
+template <typename T>
+inline const T* LtkUtils::TStringHashIter<T>::NextValue()
+	{
+	const SHashVal<T>* val = iIter.NextValue();
+	if (val) return &val->iValue;
+	return NULL;
+	}
+
+template <typename T>
+inline void LtkUtils::TStringHashIter<T>::RemoveCurrent()
+	{
+	SHashVal<T>* val = iIter.CurrentValue();
+	if (val)
+		{
+		HBufC* key = val->iKey;
+		iIter.RemoveCurrent();
+		delete key;
+		}
+	}
+
+template <typename T>
+inline LtkUtils::TStringHashIter<T>::TStringHashIter(const RStringHash<T>& aHash)
+	: iIter(aHash.iHash)
+	{}
+
+#endif