////////////////////////////////////////////////////////////////////////////
// class CArray<TYPE, ARG_TYPE> - an array containing 'TYPE' elements,
// passed in parameters as ARG_TYPE
//
// NOTE: ARG_TYPE must be either an lvalue or a reference type; no pointers;
// that is, the type of &ARG_TYPE must be the same as &TYPE.
//
////////////////////////////////////////////////////////////////////////////
//$DECLARE_TEMPLATE
////////////////////////////////////////////////////////////////////////////
template<class TYPE, class ARG_TYPE>
class FAR CArray
{
public:
// Construction
CArray(DWORD memctx = MEMCTX_SAME) : m_afv(memctx, sizeof(TYPE)) { }
~CArray() { }
// Attributes
int GetSize() const
{ return m_afv.GetSize(); }
int GetUpperBound() const
{ return m_afv.GetSize()-1; }
BOOL SetSize(int nNewSize, int nGrowBy = -1)
{ return m_afv.SetSize(nNewSize, nGrowBy); }
int GetSizeValue() const
{ return m_afv.GetSizeValue(); }
// Operations
// Clean up
void FreeExtra()
{ m_afv.FreeExtra(); }
void RemoveAll()
{ m_afv.SetSize(0); }
// return pointer to element; index must be in range
TYPE GetAt(int nIndex) const
{ return *(TYPE FAR*)m_afv.GetAt(nIndex); }
TYPE FAR& ElementAt(int nIndex)
{ return (TYPE FAR&)*(TYPE FAR*)m_afv.GetAt(nIndex); }
// overloaded operator helpers
TYPE operator[](int nIndex) const
{ return GetAt(nIndex); }
TYPE FAR& operator[](int nIndex)
{ return ElementAt(nIndex); }
// set element; index must be in range
void SetAt(int nIndex, ARG_TYPE value)
{ m_afv.SetAt(nIndex, (LPVOID)&value); }
// find element given part of one; offset is offset into value; returns
// -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
// will be optimized for appropriate value size and param combinations
int IndexOf(LPVOID pData, UINT cbData, UINT offset)
{ return m_afv.IndexOf(pData, cbData, offset); }
// set/add element; Potentially growing the array; return FALSE/-1 if
// not possible (due to OOM)
BOOL SetAtGrow(int nIndex, ARG_TYPE value)
{ return m_afv.SetAtGrow(nIndex, (LPVOID)&value); }
int Add(ARG_TYPE value)
{ int nIndex = GetSize();
return SetAtGrow(nIndex, value) ? nIndex : -1;
}
// Operations that move elements around
BOOL InsertAt(int nIndex, ARG_TYPE value, int nCount = 1)
{ return m_afv.InsertAt(nIndex, (LPVOID)&value, nCount); }
void RemoveAt(int nIndex, int nCount = 1)
{ m_afv.RemoveAt(nIndex, nCount); }
void AssertValid() const
{ m_afv.AssertValid(); }
// Implementation
private:
CArrayFValue m_afv;
};