/*========================================================================== * * Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved. * * File: OrderedArray.h * Content: COrderedArray / COrderedPtrArray Declarations * * History: * Date By Reason * ====== == ====== * 12-12-2001 simonpow Created ***************************************************************************/ #ifndef __ORDEREDARRAY_H__ #define __ORDEREDARRAY_H__ #include "AutoArray.h" /* * COrderedArray * Maintains an array of elements that can be inserted into and removed * from whilst maintaining element order. i.e. List like semantics * This class is useful when you want to maintain a list of items in * order and scan the data far more often than you modify the list. * If you perform lots of insert/remove operations, then a linked * list is probably more efficient. * Memory management is handled through CAutoArray so see comments * in that header for more information * * If you need an array of pointers use the specialisation COrderedPtrArray * declared below the COrderedArray class. */ template class COrderedArray { public: //provides the type of entries held typedef T Entry; //array starts 0 zero and by default grows in multiples //of 16 elements at a time COrderedArray(DWORD dwSizeMultiple=16) : m_data(dwSizeMultiple), m_dwTopFreeSlot(0) { }; //standard d'tor ~COrderedArray() {}; /* * Memory Management */ //Delete existing contents and reset the size multiplier //Pass 0 for size multiplier to retain the existing value void Reset(DWORD dwSizeMultiple=16) { m_data.Reset(dwSizeMultiple); m_dwTopFreeSlot=0; }; //ensure that there is enough space in the array to hold at least //'numElements' without needing to re-create and copy the data //returns FALSE if fails due to memory allocation failure BOOL AllocAtLeast(DWORD dwNumElements) { return m_data.AllocAtLeast(dwNumElements); }; //ensure there is enough space in the array to hold at least an //extra 'numElements' without needing to re-create and copy the data //returns FALSE if fails due to memory allocation failure BOOL AllocExtra(DWORD dwNumElements) { return m_data.AllocAtLeast(dwNumElements+m_dwTopFreeSlot); }; /* * Adding/Modifying Elements */ //add an entry to end of array //returns FALSE if fails due to memory allocation failure BOOL AddElement(const T& elem) { return m_data.SetElement(m_dwTopFreeSlot++, elem); }; //add a number of elements to the end of the array //N.B. Don't pass pointers into data in this array as 'pElem'! //e.g. Don't do array.AddElements(array.GetAllElements, array.GetNumElements()); //returns FALSE if fails due to memory allocation failure BOOL AddElements(const T * pElem, DWORD dwNumElem); //add the entries from another ordered array to the end of this one //N.B. Don't pass array to itself (e.g. Don't do array.AddElements(array); ) //returns FALSE if fails due to memory allocation failure BOOL AddElements(const COrderedArray& array); //set the element at 'dwIndex' to 'elem. Upto caller to //ensure this doesn't create a hole in array (i.e. dwIndex must be<=Num Entries) //returns FALSE if fails due to memory allocation failure inline BOOL SetElement(DWORD dwIndex, const T& elem); //set 'dwNumElem' from 'dwIndex' to values specified by 'pElem' //Upto caller to ensure this doesn't create a hole in array //(i.e. dwIndex must be<=Num Entries) //N.B. Don't pass pointers into data in this array as 'pElem'! //e.g. Don't do array.SetElements(x, array.GetAllElements, array.GetNumElements()); //returns FALSE if fails due to memory allocation failure inline BOOL SetElements(DWORD dwIndex, const T * pElem, DWORD dwNumElem); //insert element 'elem' at index 'dwIndex, shifting up //elements after 'dwIndex' if necessary //Upto caller to ensure this doesn't create a hole in the array //i.e. dwIndex is within the current range //returns FALSE if fails due to memory allocation failure BOOL InsertElement(DWORD dwIndex, const T& elem); //insert 'dwNumElem' elements pointed to be 'pElems' into array //at index 'dwIndex', shifting up any existing elements if necessary //Upto caller to ensure this doesn't create a hole in the array //i.e. dwIndex is within the current range //N.B. Don't pass pointers into data in this array as 'pElem'! //e.g. Don't do array.InsertElements(x, array.GetAllElements, array.GetNumElements()); //returns FALSE if fails due to memory allocation failure BOOL InsertElements(DWORD dwIndex, const T * pElems, DWORD dwNumElem); /* * Removing Entries */ //remove the single entry at 'dwIndex', shifting all the entries //between 'index'+1 and the last entry down by one. //Upto caller to ensure dwIndex falls within the current array range inline void RemoveElementByIndex(DWORD dwIndex); //remove a block of 'dwNumElem' elements starting at 'dwIndex', moving //down all entries between 'index'+1 and the last entry by 'dwNumElem'. //Upto caller to ensure specified block falls within the current array range inline void RemoveElementsByIndex(DWORD dwIndex, DWORD dwNumElem); //remove first entry in array that matches 'elem' //returns TRUE if a match is found and FALSE otherwise BOOL RemoveElementByValue(const T& elem); //remove all the current entries in the array void RemoveAll() { m_dwTopFreeSlot=0; }; /* * Accessing the array data * N.B. Treat any pointers into array contents very carefully. * Adding new elements to the array or using the Alloc* methods * can cause them to become invalid */ //returns the number of entries DWORD GetNumElements() const { return m_dwTopFreeSlot; }; //returns TRUE if array is empty BOOL IsEmpty() const { return (m_dwTopFreeSlot==0); }; //return value at a specific index T GetElementValue(DWORD dwIndex) const { return m_data.GetElementValue(dwIndex); }; //return reference to an element at specific index T& GetElementRef(DWORD dwIndex) { return m_data.GetElementRef(dwIndex); }; //return constant reference to an element at specific index const T& GetElementRef(DWORD dwIndex) const { return m_data.GetElementRef(dwIndex); }; //return a pointer to an element T * GetElementPtr(DWORD dwIndex) { return m_data.GetElementPtr(dwIndex); }; //returns pointer to array of all elements T * GetAllElements() { return m_data.GetAllElements(); }; /* * Searching Array */ //find an instance of 'elem' in array. If found returns TRUE //and sets 'pdwIndex' to index of element BOOL FindElement(const T& elem, DWORD * pdwIndex) const; //returns TRUE if 'elem' is present in bag BOOL IsElementPresent(const T& elem) const { DWORD dwIndex; return (FindElement(elem, &dwIndex)); }; protected: CAutoArray m_data; DWORD m_dwTopFreeSlot; }; /* * Specialisation of COrderedArray for handling pointers * If you ever need to declare an ordered array of pointers (e.g. char *) * declare it as an COrderedPtrArray (e.g. COrderedPtrArray). * This specilisation uses a COrderedArray underneath and hence * re-uses the same code between all types of COrderedPtrArray. */ template class COrderedPtrArray : public COrderedArray { public: typedef T Entry; typedef COrderedArray Base; COrderedPtrArray(DWORD dwSizeMultiple=16) : COrderedArray(dwSizeMultiple) { }; BOOL AddElement(T elem) { return Base::AddElement((void * ) elem); }; BOOL AddElements(const T * pElem, DWORD dwNumElem) { return Base::AddElements((void **) pElem, dwNumElem); }; BOOL AddElements(const COrderedArray& array) { return Base::AddElements((COrderedArray&) array); }; BOOL SetElement(DWORD dwIndex, T elem) { return Base::SetElement(dwIndex, (void * ) elem); }; BOOL SetElements(DWORD dwIndex, T * pElem, DWORD dwNumElem) { return Base::SetElements(dwIndex, (void**) pElem, dwNumElem); }; BOOL InsertElement(DWORD dwIndex, T elem) { return Base::InsertElement(dwIndex, (void * ) elem); }; BOOL InsertElements(DWORD dwIndex, const T * pElems, DWORD dwNumElem) { return Base::InsertElements(dwIndex, (void **) pElems, dwNumElem); }; BOOL RemoveElementByValue(T elem) { return Base::RemoveElementByValue((void *) elem); }; T GetElementValue(DWORD dwIndex) const { return (T) m_data.GetElementValue(dwIndex); }; T& GetElementRef(DWORD dwIndex) { return (T&) m_data.GetElementRef(dwIndex); }; const T& GetElementRef(DWORD dwIndex) const { return (const T&) m_data.GetElementRef(dwIndex); }; T * GetElementPtr(DWORD dwIndex) { return (T*) m_data.GetElementPtr(dwIndex); }; T * GetAllElements() { return (T*) m_data.GetAllElements(); }; BOOL FindElement(T elem, DWORD * pdwIndex) const { return Base::FindElement((void * ) elem, pdwIndex); }; BOOL IsElementPresent(T elem) const { DWORD dwIndex; return (Base::FindElement((void * ) elem, &dwIndex)); }; }; /* * COrderedArray inline methods */ template BOOL COrderedArray::AddElements(const T * pElem, DWORD dwNumElem) { //ensure pointer passed isn't into this arrays contents DNASSERT(!(pElem>=m_data.GetAllElements() && pElem BOOL COrderedArray::SetElement(DWORD dwIndex, const T& elem) { DNASSERT(dwIndex<=m_dwTopFreeSlot); if (dwIndex==m_dwTopFreeSlot) return m_data.SetElement(m_dwTopFreeSlot++, elem); m_data.SetExistingElement(dwIndex, elem); return TRUE; } template BOOL COrderedArray::SetElements(DWORD dwIndex, const T * pElem, DWORD dwNumElem) { //ensure pointer passed isn't into this arrays contents DNASSERT(!(pElem>=m_data.GetAllElements() && pElemm_dwTopFreeSlot ? dwIndex : m_dwTopFreeSlot; return TRUE; } template void COrderedArray::RemoveElementByIndex(DWORD dwIndex) { DNASSERT(dwIndex void COrderedArray::RemoveElementsByIndex(DWORD dwIndex, DWORD dwNumElem) { DNASSERT(dwIndex+dwNumElem<=m_dwTopFreeSlot); m_data.MoveElements(dwIndex+dwNumElem, m_dwTopFreeSlot-dwIndex-dwNumElem, dwIndex, FALSE); m_dwTopFreeSlot-=dwNumElem; } /* * If not building with explicit template instantiation then also * include all other methods for COrderedArray */ #ifndef DPNBUILD_EXPLICIT_TEMPLATES #include "OrderedArray.inl" #endif #endif //#ifndef __ORDEREDARRAY_H__