Extended Map Class

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
dirkmausf
In need of some credit
In need of some credit
Posts: 7
Joined: Tue May 15, 2007 9:05 pm
Location: Freiburg
Contact:

Extended Map Class

Post by dirkmausf » Sat Jan 01, 2011 12:34 pm

Hi all!


This is my effort to create an "Extended Map" for wxWidgets classes.

It has the ability to lookup ids & pointers, to sort etc. It is based on my previos posted classes wxCArray and wxCMap.

I hope you like it.

Have fun...


Happy new Year!


Code: Select all



#ifndef EXTMAP_H
#define EXTMAP_H
#pragma once

#include "./wxArray.h"
#include "./wxMap.h"


template<class KEY, class ARG_KEY>
class wxExtMapElement
{

public:
	bool m_bSortDirection;
	int  m_iSortIndex;

public:
	wxExtMapElement() {m_bSortDirection= true; m_iSortIndex=0;};
	virtual ~wxExtMapElement() {};

	virtual int SortCompare(wxExtMapElement<KEY, ARG_KEY>* in_pElement) = NULL;
	virtual BOOL IsEqual(wxExtMapElement<KEY, ARG_KEY>* in_pElement) = NULL;
	virtual KEY GetUniqueID() = NULL;
};



template<class KEY, class ARG_KEY>
class wxExtMap
{
	typedef wxCMap<KEY, ARG_KEY, int, int> wxExtMapID_t;
	typedef wxCMap<void*, void*, int, int> wxExtMapAddress_t;
	typedef wxCArray<wxExtMapElement<KEY, ARG_KEY>*> wxExtMapArray_t;
protected:
	wxExtMapID_t		m_MapID;
	wxExtMapAddress_t	m_MapAddress;
	wxExtMapArray_t		m_Array;

	bool m_bSortDirection;
	int  m_iSortIndex;

public:
	wxExtMap();
	virtual ~wxExtMap();

	int	InsertAt(int in_iIndex, wxExtMapElement<KEY, ARG_KEY>* in_pElement);
	int	Add(wxExtMapElement<KEY, ARG_KEY>* in_pElement);

	wxExtMapElement<KEY, ARG_KEY>* GetAt(int in_iIndex);
	wxExtMapElement<KEY, ARG_KEY>* GetByID(ARG_KEY in_pszID);
	int							   GetPos(ARG_KEY in_pszID);
	wxExtMapElement<KEY, ARG_KEY>* GetByAddress(void* in_pAddress);

	wxExtMapElement<KEY, ARG_KEY>* RemoveAt(int in_iIndex);
	wxExtMapElement<KEY, ARG_KEY>* RemoveByID(ARG_KEY in_pszID);
	wxExtMapElement<KEY, ARG_KEY>* RemoveByAddress(void* in_pAddress);
	void			       RemoveAll();
		
	bool RemoveAndDeleteAt(int in_iIndex);
	bool RemoveAndDeleteByID(ARG_KEY in_pszID);
	bool RemoveAndDeleteByAddress(void* in_pAddress);
	void RemoveAndDeleteAll();

	int GetCount();

	void Sort(bool in_bSortDirection, int in_iSortIndex);

	static int __cdecl CompareExtMapElements(const void * in_pElement1, const void *in_pElement2);

protected:
	bool bSearch(wxExtMapElement<KEY, ARG_KEY>* in_pElement, int& out_iIndex);
	void RebuildMaps(int iIndex=0);
	
};


template<class KEY, class ARG_KEY>
wxExtMap<KEY, ARG_KEY>::wxExtMap()
{
	m_bSortDirection = true;
	m_iSortIndex     = -1;
}

template<class KEY, class ARG_KEY>
wxExtMap<KEY, ARG_KEY>::~wxExtMap()
{
	RemoveAll();
}

template<class KEY, class ARG_KEY>
int	wxExtMap<KEY, ARG_KEY>::InsertAt(int in_iIndex, wxExtMapElement<KEY, ARG_KEY>* in_pElement)
{
	int iRet;

	if ( (in_iIndex < 0) || (in_iIndex >= m_Array.GetCount()))
	{
		iRet = m_Array.Add(in_pElement);
		m_MapID.SetAt(in_pElement->GetUniqueID(), iRet);
		m_MapAddress.SetAt(in_pElement, iRet);
		return iRet;
	}

	m_Array.InsertAt(in_iIndex, in_pElement);
	RebuildMaps(in_iIndex);
	return in_iIndex;
}


template<class KEY, class ARG_KEY>
int	wxExtMap<KEY, ARG_KEY>::Add(wxExtMapElement<KEY, ARG_KEY>* in_pElement)
{
	int iIndex = -1;

	if (m_iSortIndex >= 0)
	{
		in_pElement->m_bSortDirection = m_bSortDirection;
		in_pElement->m_iSortIndex     = m_iSortIndex;

		if (bSearch(in_pElement, iIndex))
		{
			if (in_pElement->IsEqual(GetAt(iIndex)))
			{
			return -1;
			}
		}
	}

	return InsertAt(iIndex, in_pElement);
}


template<class KEY, class ARG_KEY>
wxExtMapElement<KEY, ARG_KEY>* wxExtMap<KEY, ARG_KEY>::GetAt(int in_iIndex)
{
	if ( (in_iIndex < 0) || (in_iIndex >= m_Array.GetCount()))
	{
		return NULL;
	}
	
	return m_Array.GetAt(in_iIndex);
}


template<class KEY, class ARG_KEY>
wxExtMapElement<KEY, ARG_KEY>* wxExtMap<KEY, ARG_KEY>::GetByID(ARG_KEY in_pszID)
{
	int iIndex = -1;
	if (!m_MapID.Lookup(in_pszID, iIndex))
	{
		return NULL;
	}

	return GetAt(iIndex);
}

template<class KEY, class ARG_KEY>
int wxExtMap<KEY, ARG_KEY>::GetPos(ARG_KEY in_pszID)
{
	int iIndex = -1;
	if (!m_MapID.Lookup(in_pszID, iIndex))
	{
		return NULL;
	}

	return iIndex;
}

template<class KEY, class ARG_KEY>
wxExtMapElement<KEY, ARG_KEY>* wxExtMap<KEY, ARG_KEY>::GetByAddress(void* in_pAddress)
{
	int iIndex = -1;
	if (!m_MapAddress.Lookup(in_pAddress, iIndex))
	{
		return NULL;
	}

	return GetAt(iIndex);
}

template<class KEY, class ARG_KEY>
wxExtMapElement<KEY, ARG_KEY>* wxExtMap<KEY, ARG_KEY>::RemoveAt(int in_iIndex)
{
	wxExtMapElement<KEY, ARG_KEY>* pRet = NULL;
	if ( (in_iIndex < 0) || (in_iIndex >= m_Array.GetCount()))
	{
		return NULL;
	}
	pRet = m_Array.GetAt(in_iIndex);
	m_Array.RemoveAt(in_iIndex);
	m_MapID.RemoveKey(pRet->GetUniqueID());
	m_MapAddress.RemoveKey(pRet);
	RebuildMaps(in_iIndex);
	return pRet;
}

template<class KEY, class ARG_KEY>
wxExtMapElement<KEY, ARG_KEY>* wxExtMap<KEY, ARG_KEY>::RemoveByID(ARG_KEY in_pszID)
{
	int iIndex = -1;
	if (!m_MapID.Lookup(in_pszID, iIndex))
	{
		return NULL;
	}

	return RemoveAt(iIndex);
}

template<class KEY, class ARG_KEY>
wxExtMapElement<KEY, ARG_KEY>* wxExtMap<KEY, ARG_KEY>::RemoveByAddress(void* in_pAddress)
{
	int iIndex = -1;
	if (!m_MapAddress.Lookup(in_pAddress, iIndex))
	{
		return NULL;
	}

	return RemoveAt(iIndex);
}

template<class KEY, class ARG_KEY>
void wxExtMap<KEY, ARG_KEY>::RemoveAll()
{
	m_Array.RemoveAll();
	m_MapID.RemoveAll();
	m_MapAddress.RemoveAll();
}
		
template<class KEY, class ARG_KEY>
bool wxExtMap<KEY, ARG_KEY>::RemoveAndDeleteAt(int in_iIndex)
{
	wxExtMapElement<KEY, ARG_KEY>* pElement = RemoveAt(in_iIndex);
	if (!pElement)
	{
		return false;
	}
	delete pElement;
	return true;
}

template<class KEY, class ARG_KEY>
bool wxExtMap<KEY, ARG_KEY>::RemoveAndDeleteByID(ARG_KEY in_pszID)
{
	wxExtMapElement<KEY, ARG_KEY>* pElement = RemoveByID(in_pszID);
	if (!pElement)
	{
		return false;
	}
	delete pElement;
	return true;
}

template<class KEY, class ARG_KEY>
bool wxExtMap<KEY, ARG_KEY>::RemoveAndDeleteByAddress(void* in_pAddress)
{
	wxExtMapElement<KEY, ARG_KEY>* pElement = RemoveByAddress(in_pAddress);
	if (!pElement)
	{
		return false;
	}
	delete pElement;
	return true;
}

template<class KEY, class ARG_KEY>
void wxExtMap<KEY, ARG_KEY>::RemoveAndDeleteAll()
{
	int i;
	for (i=0; i<m_Array.GetCount(); i++)
	{
		delete m_Array[i];
	}
	RemoveAll();
}


template<class KEY, class ARG_KEY>
int __cdecl wxExtMap<KEY, ARG_KEY>::CompareExtMapElements(const void * in_pElement1, const void *in_pElement2)
{
	return ((*((wxExtMapElement<KEY, ARG_KEY>**)in_pElement1))->SortCompare((*((wxExtMapElement<KEY, ARG_KEY>**) in_pElement2))));
}

template<class KEY, class ARG_KEY>
void wxExtMap<KEY, ARG_KEY>::Sort(bool in_bSortDirection, int in_iSortIndex)
{
	int i;
	m_bSortDirection = in_bSortDirection;
	m_iSortIndex = in_iSortIndex;

	for (i=0; i<m_Array.GetCount(); i++)
	{
		m_Array[i]->m_bSortDirection = in_bSortDirection;
		m_Array[i]->m_iSortIndex   = in_iSortIndex;
	}

	qsort(m_Array.GetData(), m_Array.GetCount(), sizeof(wxExtMap*), CompareExtMapElements);
	RebuildMaps();
}

template<class KEY, class ARG_KEY>
int wxExtMap<KEY, ARG_KEY>::GetCount()
{
	return m_Array.GetCount();
}

template<class KEY, class ARG_KEY>
void wxExtMap<KEY, ARG_KEY>::RebuildMaps(int iIndex/*=0*/)
{
	for (; iIndex<m_Array.GetCount(); iIndex++)
	{
		m_MapID.SetAt(m_Array[iIndex]->GetUniqueID(), iIndex);
		m_MapAddress.SetAt(m_Array[iIndex], iIndex);
	}
}

template<class KEY, class ARG_KEY>
bool wxExtMap<KEY, ARG_KEY>::bSearch(wxExtMapElement<KEY, ARG_KEY>* in_pElement, int& out_iIndex)
{
	int iStart = 0;
	int iEnd = m_Array.GetCount();
	int iIndex = (iStart+iEnd)/2;
	bool bContinue = true;
	
	while(bContinue && iStart < iEnd)
	{
		iIndex = (iStart+iEnd)/2;

		int iCmp = in_pElement->SortCompare(m_Array.GetAt(iIndex));

		if(iCmp < 0)
		{
			iEnd = iIndex-1;
		}
		else if(iCmp > 0)
		{
			iStart = iIndex+1;
		}
		else
		{
			out_iIndex = iIndex;
			return true;
		}
	}
	out_iIndex = iStart >= 0 ? iStart : 0;
	return false;
}

#endif


Greetings,

Dirk

Post Reply