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:
Gilles Depeyrot
2002-03-06 06:31:34 +00:00
parent 434005ca85
commit 5a1cad6ea4
8 changed files with 614 additions and 480 deletions

View File

@@ -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);
}