wxArray<T> macros have been changed to fix runtime problems under 64 bit
architectures. The base class is now implemented once for each needed primitive type in order to avoid invalid reference casts. Macros are provided to implement new arrays using these primitive base arrays. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14458 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -45,225 +45,256 @@
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxBaseArray - dynamice array of 'long's
|
||||
// wxBaseArray - dynamic array of 'T's
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ctor
|
||||
wxBaseArray::wxBaseArray()
|
||||
{
|
||||
m_nSize =
|
||||
m_nCount = 0;
|
||||
m_pItems = (long *) NULL;
|
||||
#define _DECLARE_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() \
|
||||
{ \
|
||||
/* only do it if no more place */ \
|
||||
if( m_nCount == m_nSize ) { \
|
||||
if( m_nSize == 0 ) { \
|
||||
/* was empty, alloc some memory */ \
|
||||
m_pItems = new T[WX_ARRAY_DEFAULT_INITIAL_SIZE]; \
|
||||
/* only grow if allocation succeeded */ \
|
||||
if ( m_pItems ) { \
|
||||
m_nSize = WX_ARRAY_DEFAULT_INITIAL_SIZE; \
|
||||
} \
|
||||
} \
|
||||
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; \
|
||||
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 *)&lItem, (const void *)&(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) \
|
||||
{ \
|
||||
Grow(); \
|
||||
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) \
|
||||
{ \
|
||||
wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArray::Insert") ); \
|
||||
\
|
||||
Grow(); \
|
||||
\
|
||||
memmove(&m_pItems[nIndex + 1], &m_pItems[nIndex], \
|
||||
(m_nCount - nIndex)*sizeof(T)); \
|
||||
m_pItems[nIndex] = lItem; \
|
||||
m_nCount++; \
|
||||
} \
|
||||
\
|
||||
/* removes item from array (by index) */ \
|
||||
void name::RemoveAt(size_t nIndex) \
|
||||
{ \
|
||||
wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArray::RemoveAt") ); \
|
||||
\
|
||||
memmove(&m_pItems[nIndex], &m_pItems[nIndex + 1], \
|
||||
(m_nCount - nIndex - 1)*sizeof(T)); \
|
||||
m_nCount--; \
|
||||
} \
|
||||
\
|
||||
/* 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); \
|
||||
}
|
||||
|
||||
// copy ctor
|
||||
wxBaseArray::wxBaseArray(const wxBaseArray& src)
|
||||
{
|
||||
m_nSize = // not src.m_nSize to save memory
|
||||
m_nCount = src.m_nCount;
|
||||
_DECLARE_BASEARRAY(void *, wxBaseArrayPtrVoid)
|
||||
_DECLARE_BASEARRAY(short, wxBaseArrayShort)
|
||||
_DECLARE_BASEARRAY(int, wxBaseArrayInt)
|
||||
_DECLARE_BASEARRAY(long, wxBaseArrayLong)
|
||||
_DECLARE_BASEARRAY(double, wxBaseArrayDouble)
|
||||
|
||||
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)
|
||||
{
|
||||
wxDELETEA(m_pItems);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dtor
|
||||
wxBaseArray::~wxBaseArray()
|
||||
{
|
||||
wxDELETEA(m_pItems);
|
||||
}
|
||||
|
||||
// clears the list
|
||||
void wxBaseArray::Clear()
|
||||
{
|
||||
m_nSize =
|
||||
m_nCount = 0;
|
||||
|
||||
wxDELETEA(m_pItems);
|
||||
}
|
||||
|
||||
// pre-allocates memory (frees the previous data!)
|
||||
void wxBaseArray::Alloc(size_t nSize)
|
||||
{
|
||||
// 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 a place to insert an item into a sorted array (binary search)
|
||||
size_t wxBaseArray::IndexForInsert(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 {
|
||||
lo = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lo;
|
||||
}
|
||||
|
||||
// search for an item in a sorted array (binary search)
|
||||
int wxBaseArray::Index(long 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 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)
|
||||
{
|
||||
Insert(lItem, IndexForInsert(lItem, fnCompare));
|
||||
}
|
||||
|
||||
// add item at the given position
|
||||
void wxBaseArray::Insert(long lItem, size_t nIndex)
|
||||
{
|
||||
wxCHECK_RET( nIndex <= m_nCount, wxT("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::RemoveAt(size_t nIndex)
|
||||
{
|
||||
wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArray::RemoveAt") );
|
||||
|
||||
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,
|
||||
wxT("removing inexistent item in wxArray::Remove") );
|
||||
|
||||
RemoveAt((size_t)iIndex);
|
||||
}
|
||||
|
||||
// sort array elements using passed comparaison function
|
||||
void wxBaseArray::Sort(CMPFUNC fCmp)
|
||||
{
|
||||
qsort(m_pItems, m_nCount, sizeof(long), fCmp);
|
||||
}
|
||||
|
Reference in New Issue
Block a user