diff --git a/docs/doxygen/mainpages/cat_classes.h b/docs/doxygen/mainpages/cat_classes.h index f48a4b032a..81c1dc06e3 100644 --- a/docs/doxygen/mainpages/cat_classes.h +++ b/docs/doxygen/mainpages/cat_classes.h @@ -632,13 +632,13 @@ these classes provide a subset or almost complete STL API. Related Overviews: @ref overview_container -@li wxArray: A type-safe dynamic array implementation (macro based) +@li wxArray: Legacy dynamic array, use srd::vector or wxVector instead. @li wxArrayString: An efficient container for storing wxString objects @li wxHashMap: A type-safe hash map implementation (macro based) @li wxHashSet: A type-safe hash set implementation(macro based) @li wxHashTable: A simple hash table implementation (deprecated, use wxHashMap) @li wxList: A type-safe linked list implementation (macro based) -@li wxVector: Template base vector implementation identical to std::vector +@li wxVector: Template base vector implementation identical to std::vector. diff --git a/include/wx/arrimpl.cpp b/include/wx/arrimpl.cpp index 0ef9e74890..020280ea38 100644 --- a/include/wx/arrimpl.cpp +++ b/include/wx/arrimpl.cpp @@ -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) * * * @@ -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() \ +#undef WX_DEFINE_OBJARRAY +#define WX_DEFINE_OBJARRAY(name) \ +name::value_type* \ +wxObjectArrayTraitsFor##name::Clone(const name::value_type& item) \ { \ - Empty(); \ + return new name::value_type(item); \ } \ \ -void name::DoCopy(const name& src) \ +void wxObjectArrayTraitsFor##name::Free(name::value_type* p) \ { \ - 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) \ -{ \ - 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); \ -} \ - \ -void name::Insert(const T& item, size_t uiIndex, size_t nInsert) \ -{ \ - 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(ui); \ - ui--; \ - } \ - while ( ui != 0 ); \ - } \ - } \ - else { \ - for( size_t ui = 0; ui < size(); ui++ ) { \ - if( (T*)base_array::operator[](ui) == &item ) \ - return static_cast(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) diff --git a/include/wx/arrstr.h b/include/wx/arrstr.h index 42fa401ca9..89dbf5316d 100644 --- a/include/wx/arrstr.h +++ b/include/wx/arrstr.h @@ -13,6 +13,7 @@ #include "wx/defs.h" #include "wx/string.h" +#include "wx/dynarray.h" #if wxUSE_STD_CONTAINERS_COMPATIBLY #include @@ -49,15 +50,9 @@ wxDictionaryStringSortDescending(const wxString& s1, const wxString& s2) #if wxUSE_STD_CONTAINERS -#include "wx/dynarray.h" - typedef int (wxCMPFUNC_CONV *CMPFUNCwxString)(wxString*, wxString*); -typedef wxString _wxArraywxBaseArrayStringBase; -_WX_DECLARE_BASEARRAY_2(_wxArraywxBaseArrayStringBase, wxBaseArrayStringBase, - wxArray_SortFunction, - class WXDLLIMPEXP_BASE); WX_DEFINE_USER_EXPORTED_TYPEARRAY(wxString, wxArrayStringBase, - wxBaseArrayStringBase, WXDLLIMPEXP_BASE); + wxARRAY_DUMMY_BASE, WXDLLIMPEXP_BASE); class WXDLLIMPEXP_BASE wxArrayString : public wxArrayStringBase { @@ -86,7 +81,7 @@ public: }; _WX_DEFINE_SORTED_TYPEARRAY_2(wxString, wxSortedArrayStringBase, - wxBaseArrayStringBase, = wxStringSortAscending, + wxArrayStringBase, = wxStringSortAscending, class WXDLLIMPEXP_BASE, wxArrayString::CompareFunction); class WXDLLIMPEXP_BASE wxSortedArrayString : public wxSortedArrayStringBase diff --git a/include/wx/dynarray.h b/include/wx/dynarray.h index a15936c394..fa52765dd3 100644 --- a/include/wx/dynarray.h +++ b/include/wx/dynarray.h @@ -13,46 +13,16 @@ #include "wx/defs.h" -#if wxUSE_STD_CONTAINERS - #include "wx/beforestd.h" - #include - #include - #include "wx/afterstd.h" -#endif +#include "wx/vector.h" /* - This header defines the dynamic arrays and object arrays (i.e. arrays which - own their elements). Dynamic means that the arrays grow automatically as - needed. + This header defines legacy dynamic arrays and object arrays (i.e. arrays + which own their elements) classes. - These macros are ugly (especially if you look in the sources ;-), but they - allow us to define "template" classes without actually using templates and so - this works with all compilers (and may be also much faster to compile even - with a compiler which does support templates). The arrays defined with these - macros are type-safe. - - Range checking is performed in debug build for both arrays and objarrays but - not in release build - so using an invalid index will just lead to a crash - then. - - Note about memory usage: arrays never shrink automatically (although you may - use Shrink() function explicitly), they only grow, so loading 10 millions in - an array only to delete them 2 lines below might be a bad idea if the array - object is not going to be destroyed soon. However, as it does free memory - when destroyed, it is ok if the array is a local variable. + Do *NOT* use them in the new code, these classes exist for compatibility + only. Simply use standard container, e.g. std::vector<>, in your own code. */ -// ---------------------------------------------------------------------------- -// constants -// ---------------------------------------------------------------------------- - -/* - The initial size by which an array grows when an element is added default - value avoids allocate one or two bytes when the array is created which is - rather inefficient -*/ -#define WX_ARRAY_DEFAULT_INITIAL_SIZE (16) - #define _WX_ERROR_REMOVE "removing inexistent element in wxArray::Remove" // ---------------------------------------------------------------------------- @@ -71,17 +41,9 @@ typedef int (wxCMPFUNC_CONV *CMPFUNC)(const void* pItem1, const void* pItem2); } // ---------------------------------------------------------------------------- -// Base class managing data having size of type 'long' (not used directly) -// -// NB: for efficiency this often used class has no virtual functions (hence no -// virtual table), even dtor is *not* virtual. If used as expected it -// won't create any problems because ARRAYs from DEFINE_ARRAY have no dtor -// at all, so it's not too important if it's not called (this happens when -// you cast "SomeArray *" as "BaseArray *" and then delete it) +// Array class providing legacy dynamic arrays API on top of wxVector<> // ---------------------------------------------------------------------------- -#if wxUSE_STD_CONTAINERS - template class wxArray_SortFunction { @@ -95,11 +57,11 @@ private: CMPFUNC m_f; }; -template +template class wxSortedArray_SortFunction { public: - typedef F CMPFUNC; + typedef int (wxCMPFUNC_CONV *CMPFUNC)(T, T); wxSortedArray_SortFunction(CMPFUNC f) : m_f(f) { } bool operator()(const T& i1, const T& i2) @@ -108,526 +70,367 @@ private: CMPFUNC m_f; }; -#define _WX_DECLARE_BASEARRAY(T, name, classexp) \ - typedef int (wxCMPFUNC_CONV *CMPFUN##name)(T pItem1, T pItem2); \ - typedef wxSortedArray_SortFunction name##_Predicate; \ - _WX_DECLARE_BASEARRAY_2(T, name, name##_Predicate, classexp) +template +class wxBaseArray : public wxVector +{ + typedef wxSortedArray_SortFunction Predicate; + typedef int (wxCMPFUNC_CONV *SCMPFUNC)(T, T); -#define _WX_DECLARE_BASEARRAY_2(T, name, predicate, classexp) \ -class name : public std::vector \ -{ \ - typedef predicate Predicate; \ - typedef predicate::CMPFUNC SCMPFUNC; \ -public: \ - typedef wxArray_SortFunction::CMPFUNC CMPFUNC; \ - \ -public: \ - typedef T base_type; \ - \ - name() : std::vector() { } \ - name(size_type n) : std::vector(n) { } \ - name(size_type n, const_reference v) : std::vector(n, v) { } \ - template \ - name(InputIterator first, InputIterator last) : std::vector(first, last) { } \ - \ - void Empty() { clear(); } \ - void Clear() { clear(); } \ - void Alloc(size_t uiSize) { reserve(uiSize); } \ - void Shrink() { name tmp(*this); swap(tmp); } \ - \ - size_t GetCount() const { return size(); } \ - void SetCount(size_t n, T v = T()) { resize(n, v); } \ - bool IsEmpty() const { return empty(); } \ - size_t Count() const { return size(); } \ - \ - T& Item(size_t uiIndex) const \ - { wxASSERT( uiIndex < size() ); return (T&)operator[](uiIndex); } \ - T& Last() const { return Item(size() - 1); } \ - \ - int Index(T item, bool bFromEnd = false) const \ - { \ - if ( bFromEnd ) \ - { \ - const const_reverse_iterator b = rbegin(), \ - e = rend(); \ - for ( const_reverse_iterator i = b; i != e; ++i ) \ - if ( *i == item ) \ - return (int)(e - i - 1); \ - } \ - else \ - { \ - const const_iterator b = begin(), \ - e = end(); \ - for ( const_iterator i = b; i != e; ++i ) \ - if ( *i == item ) \ - return (int)(i - b); \ - } \ - \ - return wxNOT_FOUND; \ - } \ - int Index(T lItem, CMPFUNC fnCompare) const \ - { \ - Predicate p((SCMPFUNC)fnCompare); \ - const_iterator i = std::lower_bound(begin(), end(), lItem, p);\ - return i != end() && !p(lItem, *i) ? (int)(i - begin()) \ - : wxNOT_FOUND; \ - } \ - size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const \ - { \ - Predicate p((SCMPFUNC)fnCompare); \ - const_iterator i = std::lower_bound(begin(), end(), lItem, p);\ - return i - begin(); \ - } \ - void Add(T lItem, size_t nInsert = 1) \ - { insert(end(), nInsert, lItem); } \ - size_t Add(T lItem, CMPFUNC fnCompare) \ - { \ - size_t n = IndexForInsert(lItem, fnCompare); \ - Insert(lItem, n); \ - return n; \ - } \ - void Insert(T lItem, size_t uiIndex, size_t nInsert = 1) \ - { insert(begin() + uiIndex, nInsert, lItem); } \ - void Remove(T lItem) \ - { \ - int n = Index(lItem); \ - wxCHECK_RET( n != wxNOT_FOUND, _WX_ERROR_REMOVE ); \ - RemoveAt((size_t)n); \ - } \ - void RemoveAt(size_t uiIndex, size_t nRemove = 1) \ - { erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \ - \ - void Sort(CMPFUNC fCmp) \ - { \ - wxArray_SortFunction p(fCmp); \ - std::sort(begin(), end(), p); \ - } \ -} +public: + typedef typename wxArray_SortFunction::CMPFUNC CMPFUNC; -#else // if !wxUSE_STD_CONTAINERS + typedef wxVector base_vec; -#define _WX_DECLARE_BASEARRAY(T, name, classexp) \ -classexp name \ -{ \ - typedef CMPFUNC SCMPFUNC; /* for compatibility wuth wxUSE_STD_CONTAINERS */ \ -public: \ - name(); \ - name(const name& array); \ - name& operator=(const name& src); \ - ~name(); \ - \ - void Empty() { m_nCount = 0; } \ - void Clear(); \ - void Alloc(size_t n) { if ( n > m_nSize ) Realloc(n); } \ - void Shrink(); \ - \ - size_t GetCount() const { return m_nCount; } \ - void SetCount(size_t n, T defval = T()); \ - bool IsEmpty() const { return m_nCount == 0; } \ - size_t Count() const { return m_nCount; } \ - \ - typedef T base_type; \ - \ -protected: \ - T& Item(size_t uiIndex) const \ - { wxASSERT( uiIndex < m_nCount ); return m_pItems[uiIndex]; } \ - T& operator[](size_t uiIndex) const { return Item(uiIndex); } \ - \ - int Index(T lItem, bool bFromEnd = false) const; \ - int Index(T lItem, CMPFUNC fnCompare) const; \ - size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const; \ - void Add(T lItem, size_t nInsert = 1); \ - size_t Add(T lItem, CMPFUNC fnCompare); \ - void Insert(T lItem, size_t uiIndex, size_t nInsert = 1); \ - void Remove(T lItem); \ - void RemoveAt(size_t uiIndex, size_t nRemove = 1); \ - \ - void Sort(CMPFUNC fnCompare); \ - \ - /* *minimal* STL-ish interface, for derived classes */ \ - typedef T value_type; \ - typedef value_type* iterator; \ - typedef const value_type* const_iterator; \ - typedef value_type& reference; \ - typedef const value_type& const_reference; \ - typedef ptrdiff_t difference_type; \ - typedef size_t size_type; \ - \ - void assign(const_iterator first, const_iterator last); \ - void assign(size_type n, const_reference v); \ - size_type capacity() const { return m_nSize; } \ - iterator erase(iterator first, iterator last) \ - { \ - size_type idx = first - begin(); \ - RemoveAt(idx, last - first); \ - return begin() + idx; \ - } \ - iterator erase(iterator it) { return erase(it, it + 1); } \ - void insert(iterator it, size_type n, const value_type& v) \ - { Insert(v, it - begin(), n); } \ - iterator insert(iterator it, const value_type& v = value_type()) \ - { \ - size_type idx = it - begin(); \ - Insert(v, idx); \ - return begin() + idx; \ - } \ - void insert(iterator it, const_iterator first, const_iterator last);\ - void pop_back() { RemoveAt(size() - 1); } \ - void push_back(const value_type& v) { Add(v); } \ - void reserve(size_type n) { Alloc(n); } \ - void resize(size_type count, value_type defval = value_type()) \ - { \ - if ( count < m_nCount ) \ - m_nCount = count; \ - else \ - SetCount(count, defval); \ - } \ - \ - iterator begin() { return m_pItems; } \ - iterator end() { return m_pItems + m_nCount; } \ - const_iterator begin() const { return m_pItems; } \ - const_iterator end() const { return m_pItems + m_nCount; } \ - \ - void swap(name& other) \ - { \ - wxSwap(m_nSize, other.m_nSize); \ - wxSwap(m_nCount, other.m_nCount); \ - wxSwap(m_pItems, other.m_pItems); \ - } \ - \ - /* the following functions may be made directly public because */ \ - /* they don't use the type of the elements at all */ \ -public: \ - void clear() { Clear(); } \ - bool empty() const { return IsEmpty(); } \ - size_type max_size() const { return INT_MAX; } \ - size_type size() const { return GetCount(); } \ - \ -private: \ - void Grow(size_t nIncrement = 0); \ - bool Realloc(size_t nSize); \ - \ - size_t m_nSize, \ - m_nCount; \ - \ - T *m_pItems; \ -} + typedef typename base_vec::value_type value_type; + typedef typename base_vec::reference reference; + typedef typename base_vec::const_reference const_reference; + typedef typename base_vec::iterator iterator; + typedef typename base_vec::const_iterator const_iterator; + typedef typename base_vec::const_reverse_iterator const_reverse_iterator; + typedef typename base_vec::difference_type difference_type; + typedef typename base_vec::size_type size_type; -#endif // !wxUSE_STD_CONTAINERS +public: + typedef T base_type; + + wxBaseArray() : base_vec() { } + explicit wxBaseArray(size_t n) : base_vec(n) { } + wxBaseArray(size_t n, const_reference v) : base_vec(n, v) { } + + template + wxBaseArray(InputIterator first, InputIterator last) + : base_vec(first, last) + { } + + void Empty() { this->clear(); } + void Clear() { this->clear(); } + void Alloc(size_t uiSize) { this->reserve(uiSize); } + + void Shrink() + { +#if !wxUSE_STD_CONTAINERS || __cplusplus >= 201103L || wxCHECK_VISUALC_VERSION(10) + this->shrink_to_fit(); +#else + base_vec tmp(*this); + this->swap(tmp); +#endif + } + + size_t GetCount() const { return this->size(); } + void SetCount(size_t n, T v = T()) { this->resize(n, v); } + bool IsEmpty() const { return this->empty(); } + size_t Count() const { return this->size(); } + + T& Item(size_t uiIndex) const + { + wxASSERT( uiIndex < this->size() ); + return const_cast((*this)[uiIndex]); + } + + T& Last() const { return Item(this->size() - 1); } + + int Index(T item, bool bFromEnd = false) const + { + if ( bFromEnd ) + { + const const_reverse_iterator b = this->rbegin(), + e = this->rend(); + for ( const_reverse_iterator i = b; i != e; ++i ) + if ( *i == item ) + return (int)(e - i - 1); + } + else + { + const const_iterator b = this->begin(), + e = this->end(); + for ( const_iterator i = b; i != e; ++i ) + if ( *i == item ) + return (int)(i - b); + } + + return wxNOT_FOUND; + } + + int Index(T lItem, CMPFUNC fnCompare) const + { + Predicate p((SCMPFUNC)fnCompare); + const_iterator i = std::lower_bound(this->begin(), this->end(), lItem, p); + return i != this->end() && !p(lItem, *i) ? (int)(i - this->begin()) + : wxNOT_FOUND; + } + + size_t IndexForInsert(T lItem, CMPFUNC fnCompare) const + { + Predicate p((SCMPFUNC)fnCompare); + const_iterator i = std::lower_bound(this->begin(), this->end(), lItem, p); + return i - this->begin(); + } + + void Add(T lItem, size_t nInsert = 1) + { + this->insert(this->end(), nInsert, lItem); + } + + size_t Add(T lItem, CMPFUNC fnCompare) + { + size_t n = IndexForInsert(lItem, fnCompare); + Insert(lItem, n); + return n; + } + + void Insert(T lItem, size_t uiIndex, size_t nInsert = 1) + { + this->insert(this->begin() + uiIndex, nInsert, lItem); + } + + void Remove(T lItem) + { + int n = Index(lItem); + wxCHECK_RET( n != wxNOT_FOUND, _WX_ERROR_REMOVE ); + RemoveAt((size_t)n); + } + + void RemoveAt(size_t uiIndex, size_t nRemove = 1) + { + this->erase(this->begin() + uiIndex, this->begin() + uiIndex + nRemove); + } + + void Sort(CMPFUNC fCmp) + { + wxArray_SortFunction p(fCmp); + std::sort(this->begin(), this->end(), p); + } +}; // ============================================================================ // The private helper macros containing the core of the array classes // ============================================================================ -// Implementation notes: -// -// JACS: Salford C++ doesn't like 'var->operator=' syntax, as in: -// { ((wxBaseArray *)this)->operator=((const wxBaseArray&)src); -// so using a temporary variable instead. -// -// The classes need a (even trivial) ~name() to link under Mac X - -// ---------------------------------------------------------------------------- -// _WX_DEFINE_TYPEARRAY: array for simple types -// ---------------------------------------------------------------------------- - -#if wxUSE_STD_CONTAINERS - -// in STL case we don't need the entire base arrays hack as standard container -// don't suffer from alignment/storage problems as our home-grown do -#define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \ - _WX_DECLARE_BASEARRAY(T, name, classexp) - -#define _WX_DEFINE_TYPEARRAY_PTR(T, name, base, classexp) \ - _WX_DEFINE_TYPEARRAY(T, name, base, classexp) - -#else // if !wxUSE_STD_CONTAINERS - -// common declaration used by both _WX_DEFINE_TYPEARRAY and -// _WX_DEFINE_TYPEARRAY_PTR -#define _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, classexp, ptrop) \ -wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \ - TypeTooBigToBeStoredIn##base, \ - name); \ -typedef int (CMPFUNC_CONV *CMPFUNC##T)(T *pItem1, T *pItem2); \ -classexp name : public base \ -{ \ -public: \ - name() { } \ - ~name() { } \ - \ - 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[](GetCount() - 1)); } \ - \ - int Index(T lItem, bool bFromEnd = false) const \ - { return base::Index((base_type)lItem, bFromEnd); } \ - \ - void Add(T lItem, size_t nInsert = 1) \ - { base::Add((base_type)lItem, nInsert); } \ - void Insert(T lItem, size_t uiIndex, size_t nInsert = 1) \ - { base::Insert((base_type)lItem, uiIndex, nInsert) ; } \ - \ - void RemoveAt(size_t uiIndex, size_t nRemove = 1) \ - { base::RemoveAt(uiIndex, nRemove); } \ - void Remove(T lItem) \ - { int iIndex = Index(lItem); \ - wxCHECK_RET( iIndex != wxNOT_FOUND, _WX_ERROR_REMOVE); \ - base::RemoveAt((size_t)iIndex); } \ - \ - void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC)fCmp); } \ - \ - /* STL-like interface */ \ -private: \ - typedef base::iterator biterator; \ - typedef base::const_iterator bconst_iterator; \ - typedef base::value_type bvalue_type; \ - typedef base::const_reference bconst_reference; \ -public: \ - typedef T value_type; \ - typedef value_type* pointer; \ - typedef const value_type* const_pointer; \ - typedef value_type* iterator; \ - typedef const value_type* const_iterator; \ - typedef value_type& reference; \ - typedef const value_type& const_reference; \ - typedef base::difference_type difference_type; \ - typedef base::size_type size_type; \ - \ - class reverse_iterator \ - { \ - typedef T value_type; \ - typedef value_type& reference; \ - typedef value_type* pointer; \ - typedef reverse_iterator itor; \ - friend inline itor operator+(int o, const itor& it) \ - { return it.m_ptr - o; } \ - friend inline itor operator+(const itor& it, int o) \ - { return it.m_ptr - o; } \ - friend inline itor operator-(const itor& it, int o) \ - { return it.m_ptr + o; } \ - friend inline difference_type operator-(const itor& i1, \ - const itor& i2) \ - { return i1.m_ptr - i2.m_ptr; } \ - \ - public: \ - pointer m_ptr; \ - reverse_iterator() : m_ptr(NULL) { } \ - reverse_iterator(pointer ptr) : m_ptr(ptr) { } \ - reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } \ - reference operator*() const { return *m_ptr; } \ - ptrop \ - itor& operator++() { --m_ptr; return *this; } \ - const itor operator++(int) \ - { reverse_iterator tmp = *this; --m_ptr; return tmp; } \ - itor& operator--() { ++m_ptr; return *this; } \ - const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; }\ - bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; }\ - bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; }\ - }; \ - \ - class const_reverse_iterator \ - { \ - typedef T value_type; \ - typedef const value_type& reference; \ - typedef const value_type* pointer; \ - typedef const_reverse_iterator itor; \ - friend inline itor operator+(int o, const itor& it) \ - { return it.m_ptr - o; } \ - friend inline itor operator+(const itor& it, int o) \ - { return it.m_ptr - o; } \ - friend inline itor operator-(const itor& it, int o) \ - { return it.m_ptr + o; } \ - friend inline difference_type operator-(const itor& i1, \ - const itor& i2) \ - { return i1.m_ptr - i2.m_ptr; } \ - \ - public: \ - pointer m_ptr; \ - const_reverse_iterator() : m_ptr(NULL) { } \ - const_reverse_iterator(pointer ptr) : m_ptr(ptr) { } \ - const_reverse_iterator(const itor& it) : m_ptr(it.m_ptr) { } \ - const_reverse_iterator(const reverse_iterator& it) : m_ptr(it.m_ptr) { }\ - reference operator*() const { return *m_ptr; } \ - ptrop \ - itor& operator++() { --m_ptr; return *this; } \ - const itor operator++(int) \ - { itor tmp = *this; --m_ptr; return tmp; } \ - itor& operator--() { ++m_ptr; return *this; } \ - const itor operator--(int) { itor tmp = *this; ++m_ptr; return tmp; }\ - bool operator ==(const itor& it) const { return m_ptr == it.m_ptr; }\ - bool operator !=(const itor& it) const { return m_ptr != it.m_ptr; }\ - }; \ - \ - name(size_type n) { assign(n, value_type()); } \ - name(size_type n, const_reference v) { assign(n, v); } \ - name(const_iterator first, const_iterator last) \ - { assign(first, last); } \ - void assign(const_iterator first, const_iterator last) \ - { base::assign((bconst_iterator)first, (bconst_iterator)last); } \ - void assign(size_type n, const_reference v) \ - { base::assign(n, (bconst_reference)v); } \ - reference back() { return *(end() - 1); } \ - const_reference back() const { return *(end() - 1); } \ - iterator begin() { return (iterator)base::begin(); } \ - const_iterator begin() const { return (const_iterator)base::begin(); }\ - size_type capacity() const { return base::capacity(); } \ - iterator end() { return (iterator)base::end(); } \ - const_iterator end() const { return (const_iterator)base::end(); } \ - iterator erase(iterator first, iterator last) \ - { return (iterator)base::erase((biterator)first, (biterator)last); }\ - iterator erase(iterator it) \ - { return (iterator)base::erase((biterator)it); } \ - reference front() { return *begin(); } \ - const_reference front() const { return *begin(); } \ - void insert(iterator it, size_type n, const_reference v) \ - { base::insert((biterator)it, n, (bconst_reference)v); } \ - iterator insert(iterator it, const_reference v = value_type()) \ - { return (iterator)base::insert((biterator)it, (bconst_reference)v); }\ - void insert(iterator it, const_iterator first, const_iterator last) \ - { base::insert((biterator)it, (bconst_iterator)first, \ - (bconst_iterator)last); } \ - void pop_back() { base::pop_back(); } \ - void push_back(const_reference v) \ - { base::push_back((bconst_reference)v); } \ - reverse_iterator rbegin() { return reverse_iterator(end() - 1); } \ - const_reverse_iterator rbegin() const; \ - reverse_iterator rend() { return reverse_iterator(begin() - 1); } \ - const_reverse_iterator rend() const; \ - void reserve(size_type n) { base::reserve(n); } \ - void resize(size_type n, value_type v = value_type()) \ - { base::resize(n, v); } \ - void swap(name& other) { base::swap(other); } \ -} - -#define _WX_PTROP pointer operator->() const { return m_ptr; } -#define _WX_PTROP_NONE - -#define _WX_DEFINE_TYPEARRAY(T, name, base, classexp) \ - _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, classexp, _WX_PTROP) -#define _WX_DEFINE_TYPEARRAY_PTR(T, name, base, classexp) \ - _WX_DEFINE_TYPEARRAY_HELPER(T, name, base, classexp, _WX_PTROP_NONE) - -#endif // !wxUSE_STD_CONTAINERS - // ---------------------------------------------------------------------------- // _WX_DEFINE_SORTED_TYPEARRAY: sorted array for simple data types // cannot handle types with size greater than pointer because of sorting // ---------------------------------------------------------------------------- #define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp, comptype)\ -wxCOMPILE_TIME_ASSERT2(sizeof(T) <= sizeof(base::base_type), \ - TypeTooBigToBeStoredInSorted##base, \ - name); \ -classexp name : public base \ -{ \ - typedef comptype SCMPFUNC; \ -public: \ - name(comptype fn defcomp) { m_fnCompare = fn; } \ - \ - name& operator=(const name& src) \ - { base* temp = (base*) this; \ - (*temp) = ((const base&)src); \ - m_fnCompare = src.m_fnCompare; \ - return *this; } \ - \ - 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(T lItem) const \ - { return base::Index(lItem, (CMPFUNC)m_fnCompare); } \ - \ - size_t IndexForInsert(T lItem) const \ - { return base::IndexForInsert(lItem, (CMPFUNC)m_fnCompare); } \ - \ - void AddAt(T item, size_t index) \ - { base::insert(begin() + index, item); } \ - \ - size_t Add(T lItem) \ - { return base::Add(lItem, (CMPFUNC)m_fnCompare); } \ - void push_back(T lItem) \ - { Add(lItem); } \ - \ - void RemoveAt(size_t uiIndex, size_t nRemove = 1) \ - { base::erase(begin() + uiIndex, begin() + uiIndex + nRemove); } \ - void Remove(T lItem) \ - { int iIndex = Index(lItem); \ - wxCHECK_RET( iIndex != wxNOT_FOUND, _WX_ERROR_REMOVE ); \ - base::erase(begin() + iIndex); } \ - \ -private: \ - comptype m_fnCompare; \ -} + typedef wxBaseSortedArray wxBaseSortedArrayFor##name; \ + classexp name : public wxBaseSortedArrayFor##name \ + { \ + public: \ + name(comptype fn defcomp) : wxBaseSortedArrayFor##name(fn) { } \ + } + + +template +class wxBaseSortedArray : public wxBaseArray +{ + typedef typename wxBaseArray::CMPFUNC CMPFUNC; + +public: + explicit wxBaseSortedArray(Cmp fn) : m_fnCompare(fn) { } + + wxBaseSortedArray& operator=(const wxBaseSortedArray& src) + { + wxBaseArray::operator=(src); + m_fnCompare = src.m_fnCompare; + return *this; + } + + size_t IndexForInsert(T item) const + { + return this->wxBaseArray::IndexForInsert(item, (CMPFUNC)m_fnCompare); + } + + void AddAt(T item, size_t index) + { + this->insert(this->begin() + index, item); + } + + size_t Add(T item) + { + return this->wxBaseArray::Add(item, (CMPFUNC)m_fnCompare); + } + + void push_back(T item) + { + Add(item); + } + +private: + Cmp m_fnCompare; +}; // ---------------------------------------------------------------------------- // _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 +class wxBaseObjectArray : private wxBaseArray +{ + typedef wxBaseArray 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(ui); + ui--; + } + while ( ui != 0 ); + } + } + else + { + for ( size_t ui = 0; ui < size(); ++ui ) + { + if( base::operator[](ui) == &item ) + return static_cast(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(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 @@ -648,26 +451,27 @@ private: \ #define wxARRAY_DEFAULT_EXPORT // ---------------------------------------------------------------------------- -// WX_DECLARE_BASEARRAY(T, name) declare an array class named "name" containing -// the elements of type T +// WX_DECLARE_BASEARRAY(T, name): now is the same as WX_DEFINE_TYPEARRAY() +// below, only preserved for compatibility. // ---------------------------------------------------------------------------- +#define wxARRAY_DUMMY_BASE + #define WX_DECLARE_BASEARRAY(T, name) \ - WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, wxARRAY_DEFAULT_EXPORT) + WX_DEFINE_TYPEARRAY(T, name) #define WX_DECLARE_EXPORTED_BASEARRAY(T, name) \ - WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, WXDLLIMPEXP_CORE) + WX_DEFINE_EXPORTED_TYPEARRAY(T, name, WXDLLIMPEXP_CORE) #define WX_DECLARE_USER_EXPORTED_BASEARRAY(T, name, expmode) \ - typedef T _wxArray##name; \ - _WX_DECLARE_BASEARRAY(_wxArray##name, name, class expmode) + WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, wxARRAY_DUMMY_BASE, class expmode) // ---------------------------------------------------------------------------- -// WX_DEFINE_TYPEARRAY(T, name, base) define an array class named "name" deriving -// from class "base" containing the elements of type T -// -// Note that the class defined has only inline function and doesn't take any -// space at all so there is no size penalty for defining multiple array classes +// WX_DEFINE_TYPEARRAY(T, name, base) define an array class named "name" +// containing the elements of type T. Note that the argument "base" is unused +// and is preserved for compatibility only. Also, macros with and without +// "_PTR" suffix are identical, and the latter ones are also kept only for +// compatibility. // ---------------------------------------------------------------------------- #define WX_DEFINE_TYPEARRAY(T, name, base) \ @@ -688,13 +492,35 @@ private: \ #define WX_DEFINE_USER_EXPORTED_TYPEARRAY_PTR(T, name, base, expdecl) \ WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, base, class expdecl) -#define WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, classdecl) \ - typedef T _wxArray##name; \ - _WX_DEFINE_TYPEARRAY(_wxArray##name, name, base, classdecl) +// This is the only non-trivial macro, which actually defines the array class +// with the given name containing the elements of the specified type. +// +// Note that "name" must be a class and not just a typedef because it can be +// (and is) forward declared in the existing code. +// +// As mentioned above, "base" is unused and so is "classdecl" as this class has +// only inline methods and so never needs to be exported from MSW DLLs. +// +// Note about apparently redundant wxBaseArray##name typedef: this is needed to +// avoid clashes between T and symbols defined in wxBaseArray<> scope, e.g. if +// we didn't do this, we would have compilation problems with arrays of type +// "Item" (which is also the name of a method in wxBaseArray<>). +#define WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, classdecl) \ + typedef wxBaseArray wxBaseArrayFor##name; \ + class name : public wxBaseArrayFor##name \ + { \ + typedef wxBaseArrayFor##name Base; \ + public: \ + name() : Base() { } \ + explicit name(size_t n) : Base(n) { } \ + name(size_t n, Base::const_reference v) : Base(n, v) { } \ + template \ + name(InputIterator first, InputIterator last) : Base(first, last) { } \ + } + #define WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, base, classdecl) \ - typedef T _wxArray##name; \ - _WX_DEFINE_TYPEARRAY_PTR(_wxArray##name, name, base, classdecl) + WX_DEFINE_TYPEARRAY_WITH_DECL(T, name, base, classdecl) // ---------------------------------------------------------------------------- // WX_DEFINE_SORTED_TYPEARRAY: this is the same as the previous macro, but it @@ -814,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 \ + 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) @@ -1025,32 +864,34 @@ WX_DEFINE_USER_EXPORTED_ARRAY_LONG(long, wxArrayLong, class WXDLLIMPEXP_BASE); WX_DEFINE_USER_EXPORTED_ARRAY_PTR(void *, wxArrayPtrVoid, class WXDLLIMPEXP_BASE); // ----------------------------------------------------------------------------- -// convenience macros +// convenience functions: they used to be macros, hence the naming convention // ----------------------------------------------------------------------------- // prepend all element of one array to another one; e.g. if first array contains // elements X,Y,Z and the second contains A,B,C (in those orders), then the // first array will be result as A,B,C,X,Y,Z -#define WX_PREPEND_ARRAY(array, other) \ - { \ - size_t wxAAcnt = (other).size(); \ - (array).reserve(wxAAcnt); \ - for ( size_t wxAAn = 0; wxAAn < wxAAcnt; wxAAn++ ) \ - { \ - (array).Insert((other)[wxAAn], wxAAn); \ - } \ +template +inline void WX_PREPEND_ARRAY(A1& array, const A2& other) +{ + const size_t size = other.size(); + array.reserve(size); + for ( size_t n = 0; n < size; n++ ) + { + array.Insert(other[n], n); } +} // append all element of one array to another one -#define WX_APPEND_ARRAY(array, other) \ - { \ - size_t wxAAcnt = (other).size(); \ - (array).reserve(wxAAcnt); \ - for ( size_t wxAAn = 0; wxAAn < wxAAcnt; wxAAn++ ) \ - { \ - (array).push_back((other)[wxAAn]); \ - } \ +template +inline void WX_APPEND_ARRAY(A1& array, const A2& other) +{ + size_t size = other.size(); + array.reserve(size); + for ( size_t n = 0; n < size; n++ ) + { + array.push_back(other[n]); } +} // delete all array elements // @@ -1058,15 +899,16 @@ WX_DEFINE_USER_EXPORTED_ARRAY_PTR(void *, wxArrayPtrVoid, class WXDLLIMPEXP_BASE // place where you use this macro, otherwise the proper destructor may not // be called (a decent compiler should give a warning about it, but don't // count on it)! -#define WX_CLEAR_ARRAY(array) \ - { \ - size_t wxAAcnt = (array).size(); \ - for ( size_t wxAAn = 0; wxAAn < wxAAcnt; wxAAn++ ) \ - { \ - delete (array)[wxAAn]; \ - } \ - \ - (array).clear(); \ +template +inline void WX_CLEAR_ARRAY(A& array) +{ + size_t size = array.size(); + for ( size_t n = 0; n < size; n++ ) + { + delete array[n]; } + array.clear(); +} + #endif // _DYNARRAY_H diff --git a/interface/wx/dynarray.h b/interface/wx/dynarray.h index 876cbb139c..548a5c8b6a 100644 --- a/interface/wx/dynarray.h +++ b/interface/wx/dynarray.h @@ -6,6 +6,8 @@ ///////////////////////////////////////////////////////////////////////////// /** + The legacy dynamic array class, existing for compatibility only and @e NOT + to be used in the new code. This section describes the so called @e "dynamic arrays". This is a C array-like type safe data structure i.e. the member access time is constant diff --git a/src/common/dynarray.cpp b/src/common/dynarray.cpp index be01a4b840..241c55450e 100644 --- a/src/common/dynarray.cpp +++ b/src/common/dynarray.cpp @@ -24,368 +24,7 @@ #include "wx/intl.h" #endif //WX_PRECOMP -#include -#include // for memmove - -#if !wxUSE_STD_CONTAINERS - -// we cast the value to long from which we cast it to void * in IndexForInsert: -// this can't work if the pointers are not big enough -wxCOMPILE_TIME_ASSERT( sizeof(wxUIntPtr) <= sizeof(void *), - wxArraySizeOfPtrLessSizeOfLong ); // < 32 symbols - -// ============================================================================ -// constants -// ============================================================================ - -// size increment = max(50% of current size, ARRAY_MAXSIZE_INCREMENT) -#define ARRAY_MAXSIZE_INCREMENT 4096 - -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// wxBaseArray - dynamic array of 'T's -// ---------------------------------------------------------------------------- - -#define _WX_DEFINE_BASEARRAY(T, name) \ -/* searches the array for an item (forward or backwards) */ \ -int name::Index(T lItem, bool bFromEnd) const \ -{ \ - if ( bFromEnd ) { \ - if ( size() > 0 ) { \ - size_t n = size(); \ - do { \ - if ( (*this)[--n] == lItem ) \ - return n; \ - } \ - while ( n != 0 ); \ - } \ - } \ - else { \ - for( size_t n = 0; n < size(); n++ ) { \ - if( (*this)[n] == lItem ) \ - return n; \ - } \ - } \ - \ - return wxNOT_FOUND; \ -} \ - \ -/* add item assuming the array is sorted with fnCompare function */ \ -size_t name::Add(T lItem, CMPFUNC fnCompare) \ -{ \ - size_t idx = IndexForInsert(lItem, fnCompare); \ - Insert(lItem, idx); \ - return idx; \ -} \ - \ -/* ctor */ \ -name::name() \ -{ \ - m_nSize = \ - m_nCount = 0; \ - m_pItems = NULL; \ -} \ - \ -/* copy ctor */ \ -name::name(const name& src) \ -{ \ - m_nSize = /* not src.m_nSize to save memory */ \ - m_nCount = src.m_nCount; \ - \ - if ( m_nSize != 0 ) { \ - m_pItems = new T[m_nSize]; \ - /* only copy if allocation succeeded */ \ - if ( m_pItems ) { \ - memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(T)); \ - } \ - else { \ - m_nSize = 0; \ - } \ - } \ - else \ - m_pItems = NULL; \ -} \ - \ -/* assignment operator */ \ -name& name::operator=(const name& src) \ -{ \ - wxDELETEA(m_pItems); \ - \ - m_nSize = /* not src.m_nSize to save memory */ \ - m_nCount = src.m_nCount; \ - \ - if ( m_nSize != 0 ){ \ - m_pItems = new T[m_nSize]; \ - /* only copy if allocation succeeded */ \ - if ( m_pItems ) { \ - memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(T)); \ - } \ - else { \ - m_nSize = 0; \ - } \ - } \ - else \ - m_pItems = NULL; \ - \ - return *this; \ -} \ - \ -/* allocate new buffer of the given size and move our data to it */ \ -bool name::Realloc(size_t nSize) \ -{ \ - T *pNew = new T[nSize]; \ - /* only grow if allocation succeeded */ \ - if ( !pNew ) \ - return false; \ - \ - m_nSize = nSize; \ - /* copy data to new location */ \ - memcpy(pNew, m_pItems, m_nCount*sizeof(T)); \ - delete [] m_pItems; \ - m_pItems = pNew; \ - \ - return true; \ -} \ - \ -/* grow the array */ \ -void name::Grow(size_t nIncrement) \ -{ \ - /* only do it if no more place */ \ - if( (m_nCount == m_nSize) || ((m_nSize - m_nCount) < nIncrement) ) { \ - if( m_nSize == 0 ) { \ - /* was empty, determine initial size */ \ - size_t sz = WX_ARRAY_DEFAULT_INITIAL_SIZE; \ - if (sz < nIncrement) sz = nIncrement; \ - /* allocate some memory */ \ - m_pItems = new T[sz]; \ - /* only grow if allocation succeeded */ \ - if ( m_pItems ) { \ - m_nSize = sz; \ - } \ - } \ - else \ - { \ - /* add at least 50% but not too much */ \ - size_t ndefIncrement = m_nSize < WX_ARRAY_DEFAULT_INITIAL_SIZE \ - ? WX_ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1; \ - if ( ndefIncrement > ARRAY_MAXSIZE_INCREMENT ) \ - ndefIncrement = ARRAY_MAXSIZE_INCREMENT; \ - if ( nIncrement < ndefIncrement ) \ - nIncrement = ndefIncrement; \ - Realloc(m_nSize + nIncrement); \ - } \ - } \ -} \ - \ -/* make sure that the array has at least count elements */ \ -void name::SetCount(size_t count, T defval) \ -{ \ - if ( m_nSize < count ) \ - { \ - /* need to realloc memory: don't overallocate it here as if */ \ - /* SetCount() is called, it probably means that the caller */ \ - /* knows in advance how many elements there will be in the */ \ - /* array and so it won't be necessary to realloc it later */ \ - if ( !Realloc(count) ) \ - { \ - /* out of memory -- what can we do? */ \ - return; \ - } \ - } \ - \ - /* add new elements if we extend the array */ \ - while ( m_nCount < count ) \ - { \ - m_pItems[m_nCount++] = defval; \ - } \ -} \ - \ -/* dtor */ \ -name::~name() \ -{ \ - wxDELETEA(m_pItems); \ -} \ - \ -/* clears the list */ \ -void name::Clear() \ -{ \ - m_nSize = \ - m_nCount = 0; \ - \ - wxDELETEA(m_pItems); \ -} \ - \ -/* minimizes the memory usage by freeing unused memory */ \ -void name::Shrink() \ -{ \ - /* only do it if we have some memory to free */ \ - if( m_nCount < m_nSize ) { \ - /* allocates exactly as much memory as we need */ \ - T *pNew = new T[m_nCount]; \ - /* only shrink if allocation succeeded */ \ - if ( pNew ) { \ - /* copy data to new location */ \ - memcpy(pNew, m_pItems, m_nCount*sizeof(T)); \ - delete [] m_pItems; \ - m_pItems = pNew; \ - \ - /* update the size of the new block */ \ - m_nSize = m_nCount; \ - } \ - /* else: don't do anything, better keep old memory block! */ \ - } \ -} \ - \ -/* add item at the end */ \ -void name::Add(T lItem, size_t nInsert) \ -{ \ - if (nInsert == 0) \ - return; \ - Grow(nInsert); \ - for (size_t i = 0; i < nInsert; i++) \ - m_pItems[m_nCount++] = lItem; \ -} \ - \ -/* add item at the given position */ \ -void name::Insert(T lItem, size_t nIndex, size_t nInsert) \ -{ \ - wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArray::Insert") ); \ - wxCHECK_RET( m_nCount <= m_nCount + nInsert, \ - wxT("array size overflow in wxArray::Insert") ); \ - \ - if (nInsert == 0) \ - return; \ - Grow(nInsert); \ - \ - memmove(&m_pItems[nIndex + nInsert], &m_pItems[nIndex], \ - (m_nCount - nIndex)*sizeof(T)); \ - for (size_t i = 0; i < nInsert; i++) \ - m_pItems[nIndex + i] = lItem; \ - m_nCount += nInsert; \ -} \ - \ -/* search for a place to insert item into sorted array (binary search) */ \ -size_t name::IndexForInsert(T lItem, CMPFUNC fnCompare) const \ -{ \ - size_t i, \ - lo = 0, \ - hi = m_nCount; \ - int res; \ - \ - while ( lo < hi ) { \ - i = (lo + hi)/2; \ - \ - res = (*fnCompare)((const void *)(wxUIntPtr)lItem, \ - (const void *)(wxUIntPtr)(m_pItems[i])); \ - if ( res < 0 ) \ - hi = i; \ - else if ( res > 0 ) \ - lo = i + 1; \ - else { \ - lo = i; \ - break; \ - } \ - } \ - \ - return lo; \ -} \ - \ -/* search for an item in a sorted array (binary search) */ \ -int name::Index(T lItem, CMPFUNC fnCompare) const \ -{ \ - size_t n = IndexForInsert(lItem, fnCompare); \ - \ - return (n >= m_nCount || \ - (*fnCompare)((const void *)(wxUIntPtr)lItem, \ - ((const void *)(wxUIntPtr)m_pItems[n]))) \ - ? wxNOT_FOUND \ - : (int)n; \ -} \ - \ -/* removes item from array (by index) */ \ -void name::RemoveAt(size_t nIndex, size_t nRemove) \ -{ \ - wxCHECK_RET( nIndex < m_nCount, wxT("bad index in wxArray::RemoveAt") ); \ - wxCHECK_RET( nIndex + nRemove <= m_nCount, \ - wxT("removing too many elements in wxArray::RemoveAt") ); \ - \ - memmove(&m_pItems[nIndex], &m_pItems[nIndex + nRemove], \ - (m_nCount - nIndex - nRemove)*sizeof(T)); \ - m_nCount -= nRemove; \ -} \ - \ -/* removes item from array (by value) */ \ -void name::Remove(T lItem) \ -{ \ - int iIndex = Index(lItem); \ - \ - wxCHECK_RET( iIndex != wxNOT_FOUND, \ - wxT("removing inexistent item in wxArray::Remove") ); \ - \ - RemoveAt((size_t)iIndex); \ -} \ - \ -/* sort array elements using passed comparaison function */ \ -void name::Sort(CMPFUNC fCmp) \ -{ \ - qsort(m_pItems, m_nCount, sizeof(T), fCmp); \ -} \ - \ -void name::assign(const_iterator first, const_iterator last) \ -{ \ - clear(); \ - reserve(last - first); \ - for(; first != last; ++first) \ - push_back(*first); \ -} \ - \ -void name::assign(size_type n, const_reference v) \ -{ \ - clear(); \ - reserve(n); \ - for( size_type i = 0; i < n; ++i ) \ - push_back(v); \ -} \ - \ -void name::insert(iterator it, const_iterator first, const_iterator last) \ -{ \ - size_t nInsert = last - first, nIndex = it - begin(); \ - if (nInsert == 0) \ - return; \ - Grow(nInsert); \ - \ - /* old iterator could have been invalidated by Grow(). */ \ - it = begin() + nIndex; \ - \ - memmove(&m_pItems[nIndex + nInsert], &m_pItems[nIndex], \ - (m_nCount - nIndex)*sizeof(T)); \ - for (size_t i = 0; i < nInsert; ++i, ++it, ++first) \ - *it = *first; \ - m_nCount += nInsert; \ -} - -#ifdef __INTELC__ - #pragma warning(push) - #pragma warning(disable: 1684) - #pragma warning(disable: 1572) -#endif - -_WX_DEFINE_BASEARRAY(const void *, wxBaseArrayPtrVoid) -_WX_DEFINE_BASEARRAY(char, wxBaseArrayChar) -_WX_DEFINE_BASEARRAY(short, wxBaseArrayShort) -_WX_DEFINE_BASEARRAY(int, wxBaseArrayInt) -_WX_DEFINE_BASEARRAY(long, wxBaseArrayLong) -_WX_DEFINE_BASEARRAY(size_t, wxBaseArraySizeT) -_WX_DEFINE_BASEARRAY(double, wxBaseArrayDouble) - -#ifdef __INTELC__ - #pragma warning(pop) -#endif - -#else // wxUSE_STD_CONTAINERS +#if wxUSE_STD_CONTAINERS #include "wx/arrstr.h" @@ -493,4 +132,4 @@ int wxSortedArrayString::Index(const wxString& str, return it - begin(); } -#endif // !wxUSE_STD_CONTAINERS/wxUSE_STD_CONTAINERS +#endif // wxUSE_STD_CONTAINERS