https://git.reactos.org/?p=reactos.git;a=commitdiff;h=610b85245172f42d812b8…
commit 610b85245172f42d812b86fa87129a40b0230a79
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sat Aug 10 00:22:03 2019 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sun Aug 11 21:46:07 2019 +0200
[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 <new> 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<typename E, class ETraits = CElementTraits<E> >
+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<typename E, class ETraits>
+CAtlArray< E, ETraits >::CAtlArray()
+ : m_pData(NULL)
+ , m_Size(0)
+ , m_AllocatedSize(0)
+ , m_GrowBy(0)
+{
+}
+
+template<typename E, class ETraits>
+CAtlArray< E, ETraits >::~CAtlArray()
+{
+ // Destroy all items
+ SetCount(0, -1);
+}
+
+#pragma push_macro("new")
+#undef new
+
+template<typename E, class ETraits>
+size_t CAtlArray<E, ETraits>::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<typename E, class ETraits>
+size_t CAtlArray<E, ETraits>::Add()
+{
+ if (!SetCount(m_Size + 1))
+ {
+ AtlThrow(E_OUTOFMEMORY);
+ }
+
+ return m_Size - 1;
+}
+
+template<typename E, class ETraits>
+bool CAtlArray<E, ETraits>::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<typename E, class ETraits>
+size_t CAtlArray<E, ETraits>::GetCount() const
+{
+ return m_Size;
+}
+
+template<typename E, class ETraits>
+E& CAtlArray<E, ETraits>::operator[](size_t iElement)
+{
+ ATLASSERT(iElement < m_Size);
+
+ return m_pData[iElement];
+}
+
+template<typename E, class ETraits>
+const E& CAtlArray<E, ETraits>::operator[](size_t iElement) const
+{
+ ATLASSERT(iElement < m_Size);
+
+ return m_pData[iElement];
+}
+
+template<typename E, class ETraits>
+E& CAtlArray<E, ETraits>::GetAt(size_t iElement)
+{
+ ATLASSERT(iElement < m_Size);
+
+ return m_pData[iElement];
+}
+
+template<typename E, class ETraits>
+const E& CAtlArray<E, ETraits>::GetAt(size_t iElement) const
+{
+ ATLASSERT(iElement < m_Size);
+
+ return m_pData[iElement];
+}
+
+
+
template<typename E, class ETraits = CElementTraits<E> >
class CAtlList
{