X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/509201463dbd3bce8aff762c664b111a8f2c3412..008a56c968ed7e0694e32e93c2dbf95dde2ba5c8:/src/common/dynarray.cpp?ds=sidebyside diff --git a/src/common/dynarray.cpp b/src/common/dynarray.cpp index 07d31a52ae..4d0ee51d28 100644 --- a/src/common/dynarray.cpp +++ b/src/common/dynarray.cpp @@ -17,14 +17,14 @@ #pragma implementation "dynarray.h" #endif -#include +#include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include "wx/dynarray.h" -#include +#include "wx/intl.h" #include #include // for memmove @@ -33,6 +33,11 @@ #define max(a, b) (((a) > (b)) ? (a) : (b)) #endif +// 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(long) <= sizeof(void *), + wxArraySizeOfPtrLessSizeOfLong ); // < 32 symbols + // ============================================================================ // constants // ============================================================================ @@ -45,244 +50,272 @@ // ============================================================================ // ---------------------------------------------------------------------------- -// wxBaseArray - dynamice array of 'long's +// wxBaseArray - dynamic array of 'T's // ---------------------------------------------------------------------------- -// ctor -wxBaseArray::wxBaseArray() -{ - m_nSize = - m_nCount = 0; - m_pItems = (long *) NULL; -} - -// copy ctor -wxBaseArray::wxBaseArray(const wxBaseArray& src) -{ - m_nSize = // not src.m_nSize to save memory - m_nCount = src.m_nCount; - - if ( m_nSize != 0 ) { - m_pItems = new long[m_nSize]; - memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(long)); - } - else - m_pItems = (long *) NULL; -} - -// assignment operator -wxBaseArray& wxBaseArray::operator=(const wxBaseArray& src) -{ -#if 0 - wxDELETEA(m_pItems); -#else - if ( (m_pItems)) { - delete (m_pItems); - (m_pItems) = 0; - } -#endif - - m_nSize = // not src.m_nSize to save memory - m_nCount = src.m_nCount; - - if ( m_nSize != 0 ) { - m_pItems = new long[m_nSize]; - memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(long)); - } - else - m_pItems = (long *) NULL; - - return *this; -} - -// grow the array -void wxBaseArray::Grow() -{ - // only do it if no more place - if( m_nCount == m_nSize ) { - if( m_nSize == 0 ) { - // was empty, alloc some memory - m_nSize = WX_ARRAY_DEFAULT_INITIAL_SIZE; - m_pItems = new long[m_nSize]; - } - else - { - // add 50% but not too much - size_t nIncrement = m_nSize < WX_ARRAY_DEFAULT_INITIAL_SIZE - ? WX_ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1; - if ( nIncrement > ARRAY_MAXSIZE_INCREMENT ) - nIncrement = ARRAY_MAXSIZE_INCREMENT; - m_nSize += nIncrement; - long *pNew = new long[m_nSize]; - - // copy data to new location - memcpy(pNew, m_pItems, m_nCount*sizeof(long)); - delete [] m_pItems; - m_pItems = pNew; - } - } +#define _WX_DEFINE_BASEARRAY(T, name) \ +/* ctor */ \ +name::name() \ +{ \ + m_nSize = \ + m_nCount = 0; \ + m_pItems = (T *)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 = (T *) 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 = (T *) NULL; \ + \ + return *this; \ +} \ + \ +/* 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 size = WX_ARRAY_DEFAULT_INITIAL_SIZE; \ + if (size < nIncrement) size = nIncrement; \ + /* allocate some memory */ \ + m_pItems = new T[size]; \ + /* only grow if allocation succeeded */ \ + if ( m_pItems ) { \ + m_nSize = size; \ + } \ + } \ + 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; \ + T *pNew = new T[m_nSize + nIncrement]; \ + /* only grow if allocation succeeded */ \ + if ( pNew ) { \ + m_nSize += nIncrement; \ + /* copy data to new location */ \ + memcpy(pNew, m_pItems, m_nCount*sizeof(T)); \ + delete [] m_pItems; \ + m_pItems = pNew; \ + } \ + } \ + } \ +} \ + \ +/* dtor */ \ +name::~name() \ +{ \ + wxDELETEA(m_pItems); \ +} \ + \ +/* clears the list */ \ +void name::Clear() \ +{ \ + m_nSize = \ + m_nCount = 0; \ + \ + wxDELETEA(m_pItems); \ +} \ + \ +/* pre-allocates memory (frees the previous data!) */ \ +void name::Alloc(size_t nSize) \ +{ \ + /* only if old buffer was not big enough */ \ + if ( nSize > m_nSize ) { \ + wxDELETEA(m_pItems); \ + m_nSize = 0; \ + m_pItems = new T[nSize]; \ + /* only alloc if allocation succeeded */ \ + if ( m_pItems ) { \ + m_nSize = nSize; \ + } \ + } \ + \ + m_nCount = 0; \ +} \ + \ +/* 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; \ + } \ + } \ +} \ + \ +/* searches the array for an item (forward or backwards) */ \ +int name::Index(T lItem, bool bFromEnd) const \ +{ \ + if ( bFromEnd ) { \ + if ( m_nCount > 0 ) { \ + size_t n = m_nCount; \ + do { \ + if ( m_pItems[--n] == lItem ) \ + return n; \ + } \ + while ( n != 0 ); \ + } \ + } \ + else { \ + for( size_t n = 0; n < m_nCount; n++ ) { \ + if( m_pItems[n] == lItem ) \ + return n; \ + } \ + } \ + \ + return wxNOT_FOUND; \ +} \ + \ +/* 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 *)(long)lItem, \ + (const void *)(long)(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 && m_pItems[n] == lItem ? (int)n : wxNOT_FOUND; \ +} \ + \ +/* 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 assuming the array is sorted with fnCompare function */ \ +void name::Add(T lItem, CMPFUNC fnCompare) \ +{ \ + Insert(lItem, IndexForInsert(lItem, fnCompare)); \ +} \ + \ +/* 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; \ +} \ + \ +/* 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); \ } -// dtor -wxBaseArray::~wxBaseArray() -{ - wxDELETEA(m_pItems); -} - -// clears the list -void wxBaseArray::Clear() -{ - m_nSize = - m_nCount = 0; - - wxDELETEA(m_pItems); -} +_WX_DEFINE_BASEARRAY(const void *, wxBaseArrayPtrVoid) +_WX_DEFINE_BASEARRAY(short, wxBaseArrayShort) +_WX_DEFINE_BASEARRAY(int, wxBaseArrayInt) +_WX_DEFINE_BASEARRAY(long, wxBaseArrayLong) +//_WX_DEFINE_BASEARRAY(double, wxBaseArrayDouble) -// pre-allocates memory (frees the previous data!) -void wxBaseArray::Alloc(size_t nSize) -{ - wxASSERT( nSize > 0 ); - - // only if old buffer was not big enough - if ( nSize > m_nSize ) { - wxDELETEA(m_pItems); - m_pItems = new long[nSize]; - m_nSize = nSize; - } - - m_nCount = 0; -} - -// minimizes the memory usage by freeing unused memory -void wxBaseArray::Shrink() -{ - // only do it if we have some memory to free - if( m_nCount < m_nSize ) { - // allocates exactly as much memory as we need - long *pNew = new long[m_nCount]; - - // copy data to new location - memcpy(pNew, m_pItems, m_nCount*sizeof(long)); - delete [] m_pItems; - m_pItems = pNew; - } -} - -// searches the array for an item (forward or backwards) -int wxBaseArray::Index(long lItem, bool bFromEnd) const -{ - if ( bFromEnd ) { - if ( m_nCount > 0 ) { - size_t n = m_nCount; - do { - if ( m_pItems[--n] == lItem ) - return n; - } - while ( n != 0 ); - } - } - else { - for( size_t n = 0; n < m_nCount; n++ ) { - if( m_pItems[n] == lItem ) - return n; - } - } - - return wxNOT_FOUND; -} - -// search for an item in a sorted array (binary search) -int wxBaseArray::Index(long 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 *)lItem, (const void *)m_pItems[i]); - if ( res < 0 ) - hi = i; - else if ( res > 0 ) - lo = i + 1; - else - return i; - } - - return wxNOT_FOUND; -} -// add item at the end -void wxBaseArray::Add(long lItem) -{ - Grow(); - m_pItems[m_nCount++] = lItem; -} - -// add item assuming the array is sorted with fnCompare function -void wxBaseArray::Add(long lItem, CMPFUNC fnCompare) -{ - size_t i, - lo = 0, - hi = m_nCount; - int res; - - while ( lo < hi ) { - i = (lo + hi)/2; - - res = (*fnCompare)((const void *)lItem, (const void *)m_pItems[i]); - if ( res < 0 ) - hi = i; - else if ( res > 0 ) - lo = i + 1; - else { - lo = hi = i; - break; - } - } - - wxASSERT( lo == hi ); // I hope I got binary search right :-) - - Insert(lItem, lo); -} - -// add item at the given position -void wxBaseArray::Insert(long lItem, size_t nIndex) -{ - wxCHECK_RET( nIndex <= m_nCount, _T("bad index in wxArray::Insert") ); - - Grow(); - - memmove(&m_pItems[nIndex + 1], &m_pItems[nIndex], - (m_nCount - nIndex)*sizeof(long)); - m_pItems[nIndex] = lItem; - m_nCount++; -} - -// removes item from array (by index) -void wxBaseArray::Remove(size_t nIndex) -{ - wxCHECK_RET( nIndex <= m_nCount, _T("bad index in wxArray::Remove") ); - - memmove(&m_pItems[nIndex], &m_pItems[nIndex + 1], - (m_nCount - nIndex - 1)*sizeof(long)); - m_nCount--; -} - -// removes item from array (by value) -void wxBaseArray::Remove(long lItem) -{ - int iIndex = Index(lItem); - - wxCHECK_RET( iIndex != wxNOT_FOUND, - _T("removing inexistent item in wxArray::Remove") ); - - Remove((size_t)iIndex); -} - -// sort array elements using passed comparaison function -void wxBaseArray::Sort(CMPFUNC fCmp) -{ - qsort(m_pItems, m_nCount, sizeof(long), fCmp); -}