#pragma once #include #ifdef malloc #pragma push_macro("malloc") #undef malloc #define pop_malloc #endif #ifdef realloc #pragma push_macro("realloc") #undef realloc #define pop_realloc #endif #ifdef free #pragma push_macro("free") #undef free #define pop_free #endif #ifdef new #pragma push_macro("new") #undef new #define pop_new #endif // Template class helpers with functions for comparing elements // Override if using complex types without operator== template class CListCtrlArrayEqualHelper { public: static bool IsEqual(const T & t1, const T & t2) { return (t1 == t2); } }; template > class CListCtrlArray { public: // Construction / destruction CListCtrlArray() : m_aT(nullptr), m_nSize(0), m_nAllocSize(0) { } ~CListCtrlArray() { RemoveAll(); } CListCtrlArray(const CListCtrlArray & src) : m_aT(nullptr), m_nSize(0), m_nAllocSize(0) { m_aT = (T *)malloc(src.GetSize() * sizeof(T)); if (m_aT != nullptr) { m_nAllocSize = src.GetSize(); for (int i = 0; i < src.GetSize(); i++) Add(src[i]); } } CListCtrlArray & operator=(const CListCtrlArray & src) { if (GetSize() != src.GetSize()) { RemoveAll(); m_aT = (T *)malloc(src.GetSize() * sizeof(T)); if (m_aT != nullptr) m_nAllocSize = src.GetSize(); } else { for (int i = GetSize(); i > 0; i--) RemoveAt(i - 1); } for (int i = 0; i < src.GetSize(); i++) Add(src[i]); return *this; } // Operations int GetSize() const { return m_nSize; } BOOL Add(const T & t) { if (m_nSize == m_nAllocSize) { T * aT; int nNewAllocSize = (m_nAllocSize == 0) ? 1 : (m_nSize * 2); aT = (T *)realloc(m_aT, nNewAllocSize * sizeof(T)); if (aT == nullptr) return FALSE; m_nAllocSize = nNewAllocSize; m_aT = aT; } InternalSetAtIndex(m_nSize, t); m_nSize++; return TRUE; } BOOL AddAt(const T & t, int index) { if (m_nSize == m_nAllocSize) { T * aT; int nNewAllocSize = (m_nAllocSize == 0) ? 1 : (m_nSize * 2); aT = (T *)realloc(m_aT, nNewAllocSize * sizeof(T)); if (aT == nullptr) return FALSE; m_nAllocSize = nNewAllocSize; m_aT = aT; } int NewItem = (m_nSize - index); if (NewItem > 0) { memmove(&m_aT[index + 1], &m_aT[index], NewItem * sizeof(T)); } InternalSetAtIndex(index, t); m_nSize++; return TRUE; } BOOL Remove(const T & t) { int nIndex = Find(t); if (nIndex == -1) return FALSE; return RemoveAt(nIndex); } BOOL RemoveAt(int nIndex) { ATLASSERT(nIndex >= 0 && nIndex < m_nSize); if (nIndex < 0 || nIndex >= m_nSize) return FALSE; m_aT[nIndex].~T(); if (nIndex != (m_nSize - 1)) memmove((void *)(m_aT + nIndex), (void *)(m_aT + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(T)); m_nSize--; return TRUE; } void RemoveAll() { if (m_aT != nullptr) { for (int i = 0; i < m_nSize; i++) m_aT[i].~T(); free(m_aT); m_aT = nullptr; } m_nSize = 0; m_nAllocSize = 0; } const T & operator[](int nIndex) const { ATLASSERT(nIndex >= 0 && nIndex < m_nSize); if (nIndex < 0 || nIndex >= m_nSize) { RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_NONCONTINUABLE, 0, nullptr); } return m_aT[nIndex]; } T & operator[](int nIndex) { ATLASSERT(nIndex >= 0 && nIndex < m_nSize); if (nIndex < 0 || nIndex >= m_nSize) { RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_NONCONTINUABLE, 0, nullptr); } return m_aT[nIndex]; } T * GetData() const { return m_aT; } int Find(const T & t) const { for (int i = 0; i < m_nSize; i++) { if (TEqual::IsEqual(m_aT[i], t)) return i; } return -1; // Not found } BOOL SetAtIndex(int nIndex, const T & t) { if (nIndex < 0 || nIndex >= m_nSize) return FALSE; InternalSetAtIndex(nIndex, t); return TRUE; } // Implementation class Wrapper { public: Wrapper(const T & _t) : t(_t) { } template void * __cdecl operator new(size_t, _Ty * p) { return p; } template void __cdecl operator delete(void * /* pv */, _Ty * /* p */) { } T t; }; // Implementation void InternalSetAtIndex(int nIndex, const T & t) { new (m_aT + nIndex) Wrapper(t); } typedef T _ArrayElementType; T * m_aT; int m_nSize; int m_nAllocSize; }; #ifdef pop_new #pragma pop_macro("new") #endif #ifdef pop_free #pragma pop_macro("free") #endif #ifdef pop_realloc #pragma pop_macro("realloc") #endif #ifdef pop_malloc #pragma pop_macro("malloc") #endif