From 610b85245172f42d812b86fa87129a40b0230a79 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Sat, 10 Aug 2019 00:22:03 +0200 Subject: [PATCH] [ATL] Add a minimal CAtlArray implementation --- modules/rostests/apitests/atl/CMakeLists.txt | 1 + modules/rostests/apitests/atl/testlist.c | 2 + sdk/lib/atl/atlcoll.h | 249 ++++++++++++++++++- 3 files changed, 251 insertions(+), 1 deletion(-) diff --git a/modules/rostests/apitests/atl/CMakeLists.txt b/modules/rostests/apitests/atl/CMakeLists.txt index 7ff83d6691d..8bbd802c4a5 100644 --- a/modules/rostests/apitests/atl/CMakeLists.txt +++ b/modules/rostests/apitests/atl/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl) list(APPEND SOURCE atltypes.cpp CAtlFileMapping.cpp + CAtlArray.cpp CAtlList.cpp CComBSTR.cpp CComHeapPtr.cpp diff --git a/modules/rostests/apitests/atl/testlist.c b/modules/rostests/apitests/atl/testlist.c index 73546673240..d9a88545f2c 100644 --- a/modules/rostests/apitests/atl/testlist.c +++ b/modules/rostests/apitests/atl/testlist.c @@ -3,6 +3,7 @@ extern void func_atltypes(void); extern void func_CAtlFileMapping(void); +extern void func_CAtlArray(void); extern void func_CAtlList(void); extern void func_CComBSTR(void); extern void func_CComHeapPtr(void); @@ -19,6 +20,7 @@ const struct test winetest_testlist[] = { { "atltypes", func_atltypes }, { "CAtlFileMapping", func_CAtlFileMapping }, + { "CAtlArray", func_CAtlArray }, { "CAtlList", func_CAtlList }, { "CComBSTR", func_CComBSTR }, { "CComHeapPtr", func_CComHeapPtr }, diff --git a/sdk/lib/atl/atlcoll.h b/sdk/lib/atl/atlcoll.h index ae47ff7887f..73feb751645 100644 --- a/sdk/lib/atl/atlcoll.h +++ b/sdk/lib/atl/atlcoll.h @@ -5,6 +5,15 @@ #include "atlbase.h" #include "atlexcept.h" +// FIXME: We need to include for placement new, but that would mean everyone using atl +// would also need to set the option 'WITH_STL'.. +// For now we just copy the definition here, under a guard.. +#ifndef _NEW +inline void* operator new (size_t size, void* ptr) throw() { return ptr; } +inline void operator delete (void* ptr, void* voidptr2) throw() { } +#endif + + struct __POSITION { }; @@ -90,7 +99,7 @@ public: _In_reads_(NumElements) T* Source, _In_ size_t NumElements) { - memmove_s(Dest, NumElements * sizeof(T), Source, NumElements * sizeof(T)); + memmove(Dest, Source, NumElements * sizeof(T)); } }; @@ -136,6 +145,244 @@ class CElementTraits : { }; + +template > +class CAtlArray +{ +public: + typedef typename ETraits::INARGTYPE INARGTYPE; + typedef typename ETraits::OUTARGTYPE OUTARGTYPE; + +private: + E* m_pData; + size_t m_Size; + size_t m_AllocatedSize; + size_t m_GrowBy; + + +#pragma push_macro("new") +#undef new + + void CreateItems(E* pData, size_t Size) + { + for (size_t n = 0; n < Size; ++n) + { + ::new (pData + n) E; + } + } + +#pragma pop_macro("new") + + void DestructItems(E* pData, size_t Size) + { + for (size_t n = 0; n < Size; ++n) + { + pData[n].~E(); + } + } + + bool GrowAllocatedData(size_t nNewSize) + { + if (m_pData) + { + size_t addSize = m_GrowBy > 0 ? m_GrowBy : m_AllocatedSize / 2; + size_t allocSize = m_AllocatedSize + addSize; + if (allocSize < nNewSize) + allocSize = nNewSize; + + E* pData = (E*)malloc(nNewSize * sizeof(E)); + + if (pData == NULL) + { + return false; + } + + // Copy the objects over (default implementation will just move them without calling anything + ETraits::RelocateElements(pData, m_pData, m_Size); + + free(m_pData); + m_pData = pData; + m_AllocatedSize = nNewSize; + } + else + { + // We need to allocate a new buffer + size_t allocSize = m_GrowBy > nNewSize ? m_GrowBy : nNewSize; + m_pData = (E*)malloc(allocSize * sizeof(E)); + if (m_pData == NULL) + { + return false; + } + m_AllocatedSize = allocSize; + } + return true; + } + + /* The CAtlArray class does not support construction by copy */ +private: + CAtlArray(_In_ const CAtlArray&); + CAtlArray& operator=(_In_ const CAtlArray&); + +public: + CAtlArray(); + ~CAtlArray(); + + size_t Add(INARGTYPE element); + size_t Add(); + + bool SetCount(size_t nNewSize, int nGrowBy = - 1); + size_t GetCount() const; + + E& operator[](size_t ielement); + const E& operator[](size_t ielement) const; + + E& GetAt(size_t iElement); + const E& GetAt(size_t iElement) const; + + //FIXME: Most of this class is missing! +}; + +// +// CAtlArray public methods +// + +template +CAtlArray< E, ETraits >::CAtlArray() + : m_pData(NULL) + , m_Size(0) + , m_AllocatedSize(0) + , m_GrowBy(0) +{ +} + +template +CAtlArray< E, ETraits >::~CAtlArray() +{ + // Destroy all items + SetCount(0, -1); +} + +#pragma push_macro("new") +#undef new + +template +size_t CAtlArray::Add(INARGTYPE element) +{ + if (m_Size >= m_AllocatedSize) + { + if (!GrowAllocatedData(m_Size + 1)) + { + AtlThrow(E_OUTOFMEMORY); + } + } + + ::new (m_pData + m_Size) E(element); + m_Size++; + + return m_Size - 1; +} + +#pragma pop_macro("new") + +template +size_t CAtlArray::Add() +{ + if (!SetCount(m_Size + 1)) + { + AtlThrow(E_OUTOFMEMORY); + } + + return m_Size - 1; +} + +template +bool CAtlArray::SetCount(size_t nNewSize, int nGrowBy /*= -1*/) +{ + + if (nGrowBy > -1) + { + m_GrowBy = (size_t)nGrowBy; + } + + if (nNewSize == m_Size) + { + // Do nothing + } + else if (nNewSize == 0) + { + if (m_pData) + { + DestructItems(m_pData, m_Size); + m_pData = NULL; + } + m_Size = m_AllocatedSize = NULL; + } + else if (nNewSize < m_AllocatedSize) + { + if (nNewSize > m_Size) + { + CreateItems(m_pData + m_Size, nNewSize - m_Size); + } + else + { + DestructItems(m_pData + nNewSize, m_Size - nNewSize); + } + m_Size = nNewSize; + } + else + { + if (!GrowAllocatedData(nNewSize)) + { + return false; + } + + CreateItems(m_pData + m_Size, nNewSize - m_Size); + m_Size = nNewSize; + } + + return true; +} + +template +size_t CAtlArray::GetCount() const +{ + return m_Size; +} + +template +E& CAtlArray::operator[](size_t iElement) +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +const E& CAtlArray::operator[](size_t iElement) const +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +E& CAtlArray::GetAt(size_t iElement) +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +const E& CAtlArray::GetAt(size_t iElement) const +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + + + template > class CAtlList {