git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@754 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
289 lines
6.3 KiB
C++
289 lines
6.3 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: dynarray.cpp
|
|
// Purpose: implementation of wxBaseArray class
|
|
// Author: Vadim Zeitlin
|
|
// Modified by:
|
|
// Created: 12.09.97
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
|
// Licence: wxWindows license
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// headers
|
|
// ============================================================================
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "dynarray.h"
|
|
#endif
|
|
|
|
#include <wx/wxprec.h>
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#include "wx/dynarray.h"
|
|
#include <wx/intl.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h> // for memmove
|
|
|
|
#ifndef max
|
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
// ============================================================================
|
|
// constants
|
|
// ============================================================================
|
|
|
|
// size increment = max(50% of current size, ARRAY_MAXSIZE_INCREMENT)
|
|
#define ARRAY_MAXSIZE_INCREMENT 4096
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxBaseArray - dynamice array of 'long'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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
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 NOT_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 NOT_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, "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, "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 != 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_nCount, sizeof(long), fCmp);
|
|
}
|