1. fixed wxVector<T> iterators to actually point to what they're supposed to point to instead of crashing on any use

2. don't allocate memory for every element on the heap, store elements directly in the array instead of storing pointers to them

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48298 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2007-08-21 15:47:47 +00:00
parent b667edaecd
commit 0516de2cdb

View File

@@ -28,13 +28,14 @@ public:
typedef size_t size_type; typedef size_t size_type;
typedef T value_type; typedef T value_type;
typedef value_type* iterator; typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef value_type& reference; typedef value_type& reference;
wxVector() : m_allocsize(16), m_size(0), m_capacity(0), m_objects(0) {} wxVector() : m_size(0), m_capacity(0), m_values(NULL) {}
wxVector(const wxVector& c) wxVector(const wxVector& c)
{ {
wxCHECK2(Copy(c), return); Copy(c);
} }
~wxVector() ~wxVector()
@@ -44,19 +45,35 @@ public:
void clear() void clear()
{ {
for (size_type i = 0; i < size(); i++) delete[] m_values;
delete m_objects[i]; m_values = NULL;
free(m_objects);
m_objects = 0;
m_size = m_capacity = 0; m_size = m_capacity = 0;
} }
void reserve(size_type n) void reserve(size_type n)
{ {
if ( !Alloc(n) ) if ( n <= m_capacity )
return;
// increase the size twice, unless we're already too big or unless
// more is requested
const size_type increment = (m_size > 0)
? wxMin(m_size, ALLOC_MAX_SIZE)
: ALLOC_INITIAL_SIZE;
if ( m_capacity + increment > n )
n = m_capacity + increment;
value_type *mem = new value_type[n];
if ( m_values )
{ {
wxFAIL_MSG( _T("out of memory in wxVector::reserve()") ); for ( size_type i = 0; i < m_size; ++i )
mem[i] = m_values[i];
delete[] m_values;
} }
m_values = mem;
m_capacity = n;
} }
size_type size() const size_type size() const
@@ -76,31 +93,31 @@ public:
wxVector& operator=(const wxVector& vb) wxVector& operator=(const wxVector& vb)
{ {
wxCHECK(Copy(vb), *this); Copy(vb);
return *this; return *this;
} }
void push_back(const value_type& o) void push_back(const value_type& v)
{ {
wxCHECK2(Alloc(size() + 1), return); reserve(size() + 1);
Append(new value_type(o)); m_values[m_size++] = v;
} }
void pop_back() void pop_back()
{ {
RemoveAt(size() - 1); erase(end() - 1);
} }
const value_type& at(size_type idx) const const value_type& at(size_type idx) const
{ {
wxASSERT(idx < m_size); wxASSERT(idx < m_size);
return *m_objects[idx]; return m_values[idx];
} }
value_type& at(size_type idx) value_type& at(size_type idx)
{ {
wxASSERT(idx < m_size); wxASSERT(idx < m_size);
return *m_objects[idx]; return m_values[idx];
} }
const value_type& operator[](size_type idx) const { return at(idx); } const value_type& operator[](size_type idx) const { return at(idx); }
@@ -110,128 +127,83 @@ public:
const value_type& back() const { return at(size() - 1); } const value_type& back() const { return at(size() - 1); }
value_type& back() { return at(size() - 1); } value_type& back() { return at(size() - 1); }
iterator begin() { return m_objects[0]; } const_iterator begin() const { return m_values; }
iterator end() { return m_objects[size()]; } iterator begin() { return m_values; }
const_iterator end() const { return m_values + size(); }
iterator end() { return m_values + size(); }
iterator insert(iterator it, const value_type& v = value_type())
{
size_t idx = it - begin();
reserve(size() + 1);
// unless we're inserting at the end, move following values out of
// the way:
for ( size_t n = m_size; n != idx; --n )
m_values[n] = m_values[n-1];
m_values[idx] = v;
m_size++;
return begin() + idx;
}
iterator erase(iterator it)
{
return erase(it, it + 1);
}
iterator erase(iterator first, iterator last) iterator erase(iterator first, iterator last)
{ {
size_type idx = first - begin(); if ( first == last )
RemoveAt(idx, last - first); return first;
return begin() + idx; wxASSERT( first < end() && last <= end() );
}
iterator erase(iterator it) size_type index = first - begin();
{ size_type count = last - first;
size_type idx = it - begin();
RemoveAt(idx); // move the remaining values over to the freed space:
return begin() + idx; for ( iterator i = last; i < end(); ++i )
*(i - count) = *i;
// erase items behind the new end of m_values:
for ( iterator i = end() - count; i < end(); ++i )
*i = value_type();
m_size -= count;
return begin() + index;
} }
#if WXWIN_COMPATIBILITY_2_8 #if WXWIN_COMPATIBILITY_2_8
wxDEPRECATED( size_type erase(size_type n) ); wxDEPRECATED( size_type erase(size_type n) );
#endif // WXWIN_COMPATIBILITY_2_8 #endif // WXWIN_COMPATIBILITY_2_8
iterator insert(iterator it, const value_type& v = value_type())
{
wxCHECK2(Alloc(size() + 1), return 0);
size_type idx = it - begin();
InsertAt(new value_type(v), idx);
return begin() + idx;
}
private: private:
bool Alloc(size_type sz) static const size_type ALLOC_INITIAL_SIZE = 16;
{ static const size_type ALLOC_MAX_SIZE = 4096;
// work in multiples of m_allocsize;
sz = (sz / m_allocsize + 1) * m_allocsize;
if (sz <= m_capacity)
return true;
// try to realloc void Copy(const wxVector& vb)
void *mem = realloc(m_objects, sizeof(value_type*) * sz);
if (! mem)
return false; // failed
// success
m_objects = (value_type **) mem;
m_capacity = sz;
return true;
}
void Append(value_type *obj)
{
wxASSERT(m_size < m_capacity);
m_objects[m_size] = obj;
m_size++;
}
void InsertAt(size_type idx, value_type *obj)
{
wxASSERT(idx <= m_size);
wxASSERT(m_size < m_capacity);
if (idx < m_size)
memmove(
m_objects + idx + 1,
m_objects + idx,
( m_size - idx ) * sizeof(value_type*) );
m_size++;
}
void RemoveAt(size_type idx)
{
wxASSERT(idx < m_size);
delete m_objects[idx];
if (idx < m_size - 1)
memcpy(
m_objects + idx,
m_objects + idx + 1,
( m_size - idx - 1 ) * sizeof(value_type*) );
m_size--;
}
void RemoveAt(size_type idx, size_type count)
{
if (count == 0)
return;
wxASSERT(idx < m_size);
size_type i;
for (i = 0; i < count; i++)
delete m_objects[idx+1];
if (idx < m_size - count)
memcpy(
m_objects + idx,
m_objects + idx + count,
( m_size - idx - count ) * sizeof(value_type*) );
m_size -= count;
}
bool Copy(const wxVector& vb)
{ {
clear(); clear();
if (! Alloc(vb.size())) reserve(vb.size());
return false;
for (size_type i = 0; i < vb.size(); i++) for ( const_iterator i = vb.begin(); i != vb.end(); ++i )
{ push_back(*i);
value_type *o = new value_type(vb.at(i));
if (! o)
return false;
Append(o);
}
return true;
} }
private: private:
size_type m_allocsize;
size_type m_size, size_type m_size,
m_capacity; m_capacity;
value_type **m_objects; value_type *m_values;
}; };
#if WXWIN_COMPATIBILITY_2_8 #if WXWIN_COMPATIBILITY_2_8
template<typename T> template<typename T>
typename wxVector<T>::size_type wxVector<T>::erase(size_type n) typename wxVector<T>::size_type wxVector<T>::erase(size_type n)
{ {
RemoveAt(n); erase(begin() + n);
return n; return n;
} }
#endif // WXWIN_COMPATIBILITY_2_8 #endif // WXWIN_COMPATIBILITY_2_8