|
|
#ifndef __VPTRARRAY_HPP
#define __VPTRARRAY_HPP
#include "vStandard.h"
#define VPTRARRAY_ELEMENT ULONG_PTR
// <VDOC<CLASS=VPtrArray><DESC=Collection of unknown 4 byte types (FAR pointers)><FAMILY=Collections><AUTHOR=Todd Osborne ([email protected])>VDOC>
class VPtrArray { public: VPtrArray() { m_lpData = NULL; m_nSize = 0; }
virtual ~VPtrArray() { RemoveAll(); } // Same as At(nIndex)
LPVOID operator [] (int nIndex) { return At(nIndex); } // Same as Add()
int operator + (LPVOID lpData) { return Add(lpData); }
// Same as FindAndRemove()
int operator - (LPVOID lpData) { return FindAndRemove(lpData); }
// Add a new element at the end of the array. Returns index into array on success, -1 on failure
int Add(LPVOID lpData) { if ( AllocCopy(m_nSize + 1, -1, -1) ) { m_lpData[m_nSize - 1] = (VPTRARRAY_ELEMENT)lpData; return m_nSize - 1; }
return -1; }
// Return element at given index
LPVOID At(int nIndex) { assert(nIndex >= 0 && nIndex < m_nSize); return (LPVOID)m_lpData[nIndex]; } // Set element at given index. This does not allocate memory, that must already have been done by Add(), Size(), or +
void At(int nIndex, LPVOID lpData) { assert(nIndex >= 0 && nIndex < m_nSize); m_lpData[nIndex] = (VPTRARRAY_ELEMENT)lpData; }
// Return the index into array for first occurence of lpData, or -1 if not found
int Find(LPVOID lpData) { int nResult = -1;
for ( int i = 0; i < m_nSize; i++ ) { if ( m_lpData[i] == (VPTRARRAY_ELEMENT)lpData ) { nResult = i; break; } }
return nResult; }
// Find and remove element from array. Returns TRUE on success, FALSE on failure
BOOL FindAndRemove(LPVOID lpData) { int nIndex = Find(lpData); return (nIndex != -1) ? RemoveAt(nIndex) : FALSE; }
// Insert a new element into the array at specified index, moving everything after
// it further into the array. Returns index on success, -1 on failure
int InsertAt(int nIndex, LPVOID lpData) { assert(nIndex <= m_nSize); // Add item first to end
if ( Add(lpData) != - 1 ) { if ( nIndex < m_nSize - 1 ) { // Shift memory up in array
MoveMemory( &m_lpData[nIndex + 1], &m_lpData[nIndex], sizeof(VPTRARRAY_ELEMENT) * (m_nSize - nIndex - 1)); // Set lpData where told to
m_lpData[nIndex] = (VPTRARRAY_ELEMENT)lpData; }
return nIndex; }
return -1; }
// Remove all elements from array
void RemoveAll() { delete [] m_lpData; m_lpData = NULL; m_nSize = 0; }
// Remove a single element from the array. All other elements will be shifted down one slot
BOOL RemoveAt(int nIndex) { return RemoveRange(nIndex, nIndex); }
// Remove multiple elements from the array. All other elements will be shifted down by the number of elements removed
BOOL RemoveRange(int nIndexStart, int nIndexEnd) { assert(nIndexStart >= 0 && nIndexStart < m_nSize && nIndexEnd >= nIndexStart); int nSize = m_nSize; return (AllocCopy(m_nSize - ((nIndexEnd - nIndexStart) + 1), nIndexStart, nIndexEnd) && m_nSize != nSize) ? TRUE : FALSE; }
// Get / Set the size of the array (number of elements). Returns TRUE on success, FALSE on failure
// Elements currently in array will be preserved, unless array is skrinking, in which
// case element(s) at the end of the current array will be truncated
BOOL Size(int nSize) { assert(nSize >= 0); return AllocCopy(nSize , -1, -1); }
int Size() { return m_nSize; }
protected: // Internal function to work with private data
BOOL AllocCopy(int nNewSize, int nSkipIndexStart, int nSkipIndexEnd) { VPTRARRAY_ELEMENT* lpNewData = (nNewSize) ? new VPTRARRAY_ELEMENT[nNewSize] : NULL;
// If memory allocation was required and did not succeed, exit now with error
if ( nNewSize && !lpNewData ) return FALSE;
if ( lpNewData ) { #ifdef _DEBUG
// Data but no size!
if ( m_lpData ) assert(m_nSize); #endif
// Clear new memory
ZeroMemory(lpNewData, nNewSize * sizeof(VPTRARRAY_ELEMENT));
// Copy any previous memory
if ( m_nSize ) { // There must be data!
assert(m_lpData);
// If either skip index is -1, we will copy everything
// -1 is used internally as a flag to indicate no exclusions
if ( nSkipIndexStart == -1 || nSkipIndexEnd == -1 ) CopyMemory(lpNewData, m_lpData, min(m_nSize, nNewSize) * sizeof(VPTRARRAY_ELEMENT)); else { // Copy up to nSkipIndexStart
if ( nSkipIndexStart ) CopyMemory(&lpNewData[0], &m_lpData[0], nSkipIndexStart * sizeof(VPTRARRAY_ELEMENT));
// Copy from nSkipIndexEnd + 1 to end
CopyMemory( &lpNewData [nSkipIndexStart], &m_lpData [nSkipIndexEnd + 1], (m_nSize * sizeof(VPTRARRAY_ELEMENT)) - ((nSkipIndexEnd + 1) * sizeof(VPTRARRAY_ELEMENT))); } } }
// Kill any current memory
delete [] m_lpData;
// Make new assignments
m_lpData = lpNewData; m_nSize = nNewSize;
return TRUE; }
private: // Embedded Members
VPTRARRAY_ELEMENT* m_lpData; int m_nSize; };
#endif // __VPTRARRAY_HPP
|