X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c86f1403c3737c07d58676a203f4707942684a01..878711c01c1b9ad5b97d35f379a048b8ce1bfb49:/src/common/dynarray.cpp?ds=inline diff --git a/src/common/dynarray.cpp b/src/common/dynarray.cpp index eb2b4e6be9..012c6077a3 100644 --- a/src/common/dynarray.cpp +++ b/src/common/dynarray.cpp @@ -6,7 +6,7 @@ // Created: 12.09.97 // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -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,222 +50,311 @@ // ============================================================================ // ---------------------------------------------------------------------------- -// wxBaseArray - dynamice array of 'long's +// wxBaseArray - dynamic array of 'T's // ---------------------------------------------------------------------------- -// ctor -wxBaseArray::wxBaseArray() -{ - m_uiSize = - m_uiCount = 0; - m_pItems = NULL; -} - -// copy ctor -wxBaseArray::wxBaseArray(const wxBaseArray& src) -{ - m_uiSize = // not src.m_uiSize to save memory - m_uiCount = src.m_uiCount; - - if ( m_uiSize != 0 ) { - m_pItems = new long[m_uiSize]; - memcpy(m_pItems, src.m_pItems, m_uiCount*sizeof(long)); - } - else - m_pItems = NULL; -} - -// assignment operator -wxBaseArray& wxBaseArray::operator=(const wxBaseArray& src) -{ - wxDELETEA(m_pItems); - - m_uiSize = // not src.m_uiSize to save memory - m_uiCount = src.m_uiCount; - - if ( m_uiSize != 0 ) { - m_pItems = new long[m_uiSize]; - memcpy(m_pItems, src.m_pItems, m_uiCount*sizeof(long)); - } - else - m_pItems = NULL; - - return *this; -} - -// grow the array -void wxBaseArray::Grow() -{ - // only do it if no more place - if( m_uiCount == m_uiSize ) { - if( m_uiSize == 0 ) { - // was empty, alloc some memory - m_uiSize = WX_ARRAY_DEFAULT_INITIAL_SIZE; - m_pItems = new long[m_uiSize]; - } - else - { - // add 50% but not too much - size_t uiIncrement = m_uiSize < WX_ARRAY_DEFAULT_INITIAL_SIZE - ? WX_ARRAY_DEFAULT_INITIAL_SIZE : m_uiSize >> 1; - if ( uiIncrement > ARRAY_MAXSIZE_INCREMENT ) - uiIncrement = ARRAY_MAXSIZE_INCREMENT; - m_uiSize += uiIncrement; - long *pNew = new long[m_uiSize]; - - // copy data to new location - memcpy(pNew, m_pItems, m_uiCount*sizeof(long)); - delete [] m_pItems; - m_pItems = pNew; - } - } -} - -// dtor -wxBaseArray::~wxBaseArray() -{ - wxDELETEA(m_pItems); -} - -// clears the list -void wxBaseArray::Clear() -{ - m_uiSize = - m_uiCount = 0; - - wxDELETEA(m_pItems); -} - -// pre-allocates memory (frees the previous data!) -void wxBaseArray::Alloc(size_t uiSize) -{ - wxASSERT( uiSize > 0 ); - - // only if old buffer was not big enough - if ( uiSize > m_uiSize ) { - wxDELETEA(m_pItems); - m_pItems = new long[uiSize]; - m_uiSize = uiSize; - } - - m_uiCount = 0; -} - -// searches the array for an item (forward or backwards) -int wxBaseArray::Index(long lItem, bool bFromEnd) const -{ - if ( bFromEnd ) { - if ( m_uiCount > 0 ) { - size_t ui = m_uiCount; - do { - if ( m_pItems[--ui] == lItem ) - return ui; - } - while ( ui != 0 ); - } - } - else { - for( size_t ui = 0; ui < m_uiCount; ui++ ) { - if( m_pItems[ui] == lItem ) - return ui; - } - } - - return NOT_FOUND; +#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; \ +} \ + \ +/* 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 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; \ + 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); \ +} \ + \ +/* 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; \ + \ + /* update the size of the new block */ \ + m_nSize = m_nCount; \ + } \ + /* else: don't do anything, better keep old memory block! */ \ + } \ +} \ + \ +/* 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 && \ + (*fnCompare)((const void *)(long)lItem, \ + ((const void *)(long)m_pItems[n])) ? (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); \ } -// 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_uiCount; - int res; +_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) - 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 NOT_FOUND; -} -// add item at the end -void wxBaseArray::Add(long lItem) -{ - Grow(); - m_pItems[m_uiCount++] = 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_uiCount; - 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 uiIndex) -{ - wxCHECK_RET( uiIndex <= m_uiCount, _("bad index in wxArray::Insert") ); - - Grow(); - - memmove(&m_pItems[uiIndex + 1], &m_pItems[uiIndex], - (m_uiCount - uiIndex)*sizeof(long)); - m_pItems[uiIndex] = lItem; - m_uiCount++; -} - -// removes item from array (by index) -void wxBaseArray::Remove(size_t uiIndex) -{ - wxCHECK_RET( uiIndex <= m_uiCount, _("bad index in wxArray::Remove") ); - - memmove(&m_pItems[uiIndex], &m_pItems[uiIndex + 1], - (m_uiCount - uiIndex - 1)*sizeof(long)); - m_uiCount--; -} - -// removes item from array (by value) -void wxBaseArray::Remove(long lItem) -{ - int iIndex = Index(lItem); - - wxCHECK_RET( iIndex != NOT_FOUND, - _("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_uiCount, sizeof(long), fCmp); -}