libraries/ltkutils/inc/stringhash.h
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Sat, 31 Jul 2010 19:07:57 +0100
changeset 23 092bcc217d9d
parent 0 7f656887cf89
permissions -rw-r--r--
Tidied iocli exports, build macro tweaks. Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll. fixed builds on platforms that don't support btrace or any form of tracing.

// 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