Skip to content

Commit

Permalink
Replace object array macros with template class too
Browse files Browse the repository at this point in the history
Put the code implementing object arrays, i.e. arrays owning pointers to
the objects, into wxBaseObjectArray<> instead of _WX_DECLARE_OBJARRAY
macro.

Also simplify WX_DEFINE_OBJARRAY() by leaving only the definitions of
functions creating and destroying the objects in it (they have to be
there and not in the template itself to allow using template with
incomplete classes).
  • Loading branch information
vadz committed Jun 3, 2018
1 parent aaa9c80 commit 97684a9
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 155 deletions.
102 changes: 8 additions & 94 deletions include/wx/arrimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
///////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
* Purpose: implements methods of "template" class declared in *
* Purpose: implements helper functions used by the template class used by *
* DECLARE_OBJARRAY macro and which couldn't be implemented inline *
* (because they need the full definition of type T in scope) *
* *
Expand All @@ -19,101 +19,15 @@
* 4) WX_DEFINE_OBJARRAY *
*****************************************************************************/

// needed to resolve the conflict between global T and macro parameter T

#define _WX_ERROR_REMOVE2(x) wxT("bad index in ") wxT(#x) wxT("::RemoveAt()")

// macro implements remaining (not inline) methods of template list
// (it's private to this file)
#undef _DEFINE_OBJARRAY
#define _DEFINE_OBJARRAY(T, name) \
name::~name() \
{ \
Empty(); \
} \
\
void name::DoCopy(const name& src) \
{ \
for ( size_t ui = 0; ui < src.size(); ui++ ) \
Add(src[ui]); \
} \
\
name& name::operator=(const name& src) \
{ \
Empty(); \
DoCopy(src); \
\
return *this; \
} \
\
name::name(const name& src) : wxArrayPtrVoid() \
{ \
DoCopy(src); \
} \
\
void name::DoEmpty() \
{ \
for ( size_t ui = 0; ui < size(); ui++ ) \
delete (T*)base_array::operator[](ui); \
} \
\
void name::RemoveAt(size_t uiIndex, size_t nRemove) \
{ \
wxCHECK_RET( uiIndex < size(), _WX_ERROR_REMOVE2(name) ); \
\
for (size_t i = 0; i < nRemove; i++ ) \
delete (T*)base_array::operator[](uiIndex + i); \
\
base_array::erase(begin() + uiIndex, begin() + uiIndex + nRemove); \
} \
\
void name::Add(const T& item, size_t nInsert) \
#undef WX_DEFINE_OBJARRAY
#define WX_DEFINE_OBJARRAY(name) \
name::value_type* \
wxObjectArrayTraitsFor##name::Clone(const name::value_type& item) \
{ \
if (nInsert == 0) \
return; \
T* pItem = new T(item); \
size_t nOldSize = size(); \
if ( pItem != NULL ) \
base_array::insert(end(), nInsert, pItem); \
for (size_t i = 1; i < nInsert; i++) \
base_array::operator[](nOldSize + i) = new T(item); \
return new name::value_type(item); \
} \
\
void name::Insert(const T& item, size_t uiIndex, size_t nInsert) \
void wxObjectArrayTraitsFor##name::Free(name::value_type* p) \
{ \
if (nInsert == 0) \
return; \
T* pItem = new T(item); \
if ( pItem != NULL ) \
base_array::insert(begin() + uiIndex, nInsert, pItem); \
for (size_t i = 1; i < nInsert; i++) \
base_array::operator[](uiIndex + i) = new T(item); \
} \
\
int name::Index(const T& item, bool bFromEnd) const \
{ \
if ( bFromEnd ) { \
if ( size() > 0 ) { \
size_t ui = size() - 1; \
do { \
if ( (T*)base_array::operator[](ui) == &item ) \
return static_cast<int>(ui); \
ui--; \
} \
while ( ui != 0 ); \
} \
} \
else { \
for( size_t ui = 0; ui < size(); ui++ ) { \
if( (T*)base_array::operator[](ui) == &item ) \
return static_cast<int>(ui); \
} \
} \
\
return wxNOT_FOUND; \
delete p; \
}

// redefine the macro so that now it will generate the class implementation
// old value would provoke a compile-time error if this file is not included
#undef WX_DEFINE_OBJARRAY
#define WX_DEFINE_OBJARRAY(name) _DEFINE_OBJARRAY(_wxObjArray##name, name)
245 changes: 184 additions & 61 deletions include/wx/dynarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class wxBaseSortedArray : public wxBaseArray<T>

size_t IndexForInsert(T item) const
{
return this->IndexForInsert(item, (CMPFUNC)m_fnCompare);
return this->wxBaseArray<T>::IndexForInsert(item, (CMPFUNC)m_fnCompare);
}

void AddAt(T item, size_t index)
Expand All @@ -264,63 +264,173 @@ class wxBaseSortedArray : public wxBaseArray<T>
// _WX_DECLARE_OBJARRAY: an array for pointers to type T with owning semantics
// ----------------------------------------------------------------------------

#define _WX_DECLARE_OBJARRAY(T, name, base, classexp) \
typedef int (CMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
classexp name : protected base \
{ \
typedef int (CMPFUNC_CONV *CMPFUNC##base)(void **pItem1, void **pItem2); \
typedef base base_array; \
public: \
name() { } \
name(const name& src); \
name& operator=(const name& src); \
\
~name(); \
\
void Alloc(size_t count) { base::reserve(count); } \
void reserve(size_t count) { base::reserve(count); } \
size_t GetCount() const { return base_array::size(); } \
size_t size() const { return base_array::size(); } \
bool IsEmpty() const { return base_array::empty(); } \
bool empty() const { return base_array::empty(); } \
size_t Count() const { return base_array::size(); } \
void Shrink() { base::Shrink(); } \
\
T& operator[](size_t uiIndex) const \
{ return *(T*)base::operator[](uiIndex); } \
T& Item(size_t uiIndex) const \
{ return *(T*)base::operator[](uiIndex); } \
T& Last() const \
{ return *(T*)(base::operator[](size() - 1)); } \
\
int Index(const T& lItem, bool bFromEnd = false) const; \
\
void Add(const T& lItem, size_t nInsert = 1); \
void Add(const T* pItem) \
{ base::push_back((T*)pItem); } \
void push_back(const T* pItem) \
{ base::push_back((T*)pItem); } \
void push_back(const T& lItem) \
{ Add(lItem); } \
\
void Insert(const T& lItem, size_t uiIndex, size_t nInsert = 1); \
void Insert(const T* pItem, size_t uiIndex) \
{ base::insert(begin() + uiIndex, (T*)pItem); } \
\
void Empty() { DoEmpty(); base::clear(); } \
void Clear() { DoEmpty(); base::clear(); } \
\
T* Detach(size_t uiIndex) \
{ T* p = (T*)base::operator[](uiIndex); \
base::erase(begin() + uiIndex); return p; } \
void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
\
void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC##base)fCmp); } \
\
private: \
void DoEmpty(); \
void DoCopy(const name& src); \
}
// This class must be able to be declared with incomplete types, so it doesn't
// actually use type T in its definition, and relies on a helper template
// parameter, which is declared by WX_DECLARE_OBJARRAY() and defined by
// WX_DEFINE_OBJARRAY(), for providing a way to create and destroy objects of
// type T
template <typename T, typename Traits>
class wxBaseObjectArray : private wxBaseArray<T*>
{
typedef wxBaseArray<T*> base;

public:
typedef T value_type;

typedef int (wxCMPFUNC_CONV *CMPFUNC)(T **pItem1, T **pItem2);

wxBaseObjectArray()
{
}

wxBaseObjectArray(const wxBaseObjectArray& src) : base()
{
DoCopy(src);
}

wxBaseObjectArray& operator=(const wxBaseObjectArray& src)
{
Empty();
DoCopy(src);

return *this;
}

~wxBaseObjectArray()
{
Empty();
}

void Alloc(size_t count) { base::reserve(count); }
void reserve(size_t count) { base::reserve(count); }
size_t GetCount() const { return base::size(); }
size_t size() const { return base::size(); }
bool IsEmpty() const { return base::empty(); }
bool empty() const { return base::empty(); }
size_t Count() const { return base::size(); }
void Shrink() { base::Shrink(); }

T& operator[](size_t uiIndex) const
{
return *base::operator[](uiIndex);
}

T& Item(size_t uiIndex) const
{
return *base::operator[](uiIndex);
}

T& Last() const
{
return *(base::operator[](size() - 1));
}

int Index(const T& item, bool bFromEnd = false) const
{
if ( bFromEnd )
{
if ( size() > 0 )
{
size_t ui = size() - 1;
do
{
if ( base::operator[](ui) == &item )
return static_cast<int>(ui);
ui--;
}
while ( ui != 0 );
}
}
else
{
for ( size_t ui = 0; ui < size(); ++ui )
{
if( base::operator[](ui) == &item )
return static_cast<int>(ui);
}
}

return wxNOT_FOUND;
}

void Add(const T& item, size_t nInsert = 1)
{
if ( nInsert == 0 )
return;

T* const pItem = Traits::Clone(item);

const size_t nOldSize = size();
if ( pItem != NULL )
base::insert(this->end(), nInsert, pItem);

for ( size_t i = 1; i < nInsert; i++ )
base::operator[](nOldSize + i) = Traits::Clone(item);
}

void Add(const T* pItem)
{
base::push_back(const_cast<T*>(pItem));
}

void push_back(const T* pItem) { Add(pItem); }
void push_back(const T& item) { Add(item); }

void Insert(const T& item, size_t uiIndex, size_t nInsert = 1)
{
if ( nInsert == 0 )
return;

T* const pItem = Traits::Clone(item);
if ( pItem != NULL )
base::insert(this->begin() + uiIndex, nInsert, pItem);

for ( size_t i = 1; i < nInsert; ++i )
base::operator[](uiIndex + i) = Traits::Clone(item);
}

void Insert(const T* pItem, size_t uiIndex)
{
base::insert(this->begin() + uiIndex, (T*)pItem);
}

void Empty() { DoEmpty(); base::clear(); }
void Clear() { DoEmpty(); base::clear(); }

T* Detach(size_t uiIndex)
{
T* const p = base::operator[](uiIndex);

base::erase(this->begin() + uiIndex);
return p;
}

void RemoveAt(size_t uiIndex, size_t nRemove = 1)
{
wxCHECK_RET( uiIndex < size(), "bad index in RemoveAt()" );

for ( size_t i = 0; i < nRemove; ++i )
Traits::Free(base::operator[](uiIndex + i));

base::erase(this->begin() + uiIndex, this->begin() + uiIndex + nRemove);
}

void Sort(CMPFUNC fCmp) { base::Sort(fCmp); }

private:
void DoEmpty()
{
for ( size_t n = 0; n < size(); ++n )
Traits::Free(base::operator[](n));
}

void DoCopy(const wxBaseObjectArray& src)
{
reserve(src.size());
for ( size_t n = 0; n < src.size(); ++n )
Add(src[n]);
}
};

// ============================================================================
// The public macros for declaration and definition of the dynamic arrays
Expand Down Expand Up @@ -530,9 +640,22 @@ private: \
#define WX_DECLARE_EXPORTED_OBJARRAY(T, name) \
WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_CORE)

#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, decl) \
typedef T _wxObjArray##name; \
_WX_DECLARE_OBJARRAY(_wxObjArray##name, name, wxArrayPtrVoid, decl)
#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, classdecl) \
classdecl wxObjectArrayTraitsFor##name \
{ \
public: \
static T* Clone(const T& item); \
static void Free(T* p); \
}; \
typedef wxBaseObjectArray<T, wxObjectArrayTraitsFor##name> \
wxBaseObjectArrayFor##name; \
typedef int (wxCMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
classdecl name : public wxBaseObjectArrayFor##name \
{ \
public: \
name() : wxBaseObjectArrayFor##name() { } \
name(const name& src) : wxBaseObjectArrayFor##name(src) { } \
}

#define WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, expmode) \
WX_DECLARE_OBJARRAY_WITH_DECL(T, name, class expmode)
Expand Down

0 comments on commit 97684a9

Please sign in to comment.