Fix inserting an element of wxArrayString itself back into it.

Do the insertion/addition before deallocating the old memory to allow things
like array.Add(array[0]) to work correctly.

Closes #2290.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76909 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2014-07-13 14:30:22 +00:00
parent 86e587a096
commit 45adc64f9f
3 changed files with 28 additions and 10 deletions

View File

@ -364,7 +364,10 @@ protected:
CompareFunction m_compareFunction; // set only from wxSortedArrayString
private:
void Grow(size_t nIncrement = 0); // makes array bigger if needed
// Allocate the new buffer big enough to hold m_nCount + nIncrement items and
// return the pointer to the old buffer, which must be deleted by the caller
// (if the old buffer is big enough, just return NULL).
wxString *Grow(size_t nIncrement);
size_t m_nSize, // current size of the array
m_nCount; // current number of elements

View File

@ -20,6 +20,7 @@
#endif
#include "wx/arrstr.h"
#include "wx/scopedarray.h"
#include "wx/beforestd.h"
#include <algorithm>
@ -107,10 +108,14 @@ void wxArrayString::Copy(const wxArrayString& src)
}
// grow the array
void wxArrayString::Grow(size_t nIncrement)
wxString *wxArrayString::Grow(size_t nIncrement)
{
// only do it if no more place
if ( (m_nSize - m_nCount) < nIncrement ) {
if ( (m_nSize - m_nCount) >= nIncrement )
{
// We already have enough space.
return NULL;
}
// if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would
// be never resized!
#if ARRAY_DEFAULT_INITIAL_SIZE == 0
@ -123,6 +128,9 @@ void wxArrayString::Grow(size_t nIncrement)
if (m_nSize < nIncrement)
m_nSize = nIncrement;
m_pItems = new wxString[m_nSize];
// Nothing to free, we hadn't had any memory before.
return NULL;
}
else {
// otherwise when it's called for the first time, nIncrement would be 0
@ -141,12 +149,12 @@ void wxArrayString::Grow(size_t nIncrement)
for ( size_t j = 0; j < m_nCount; j++ )
pNew[j] = m_pItems[j];
// delete old memory (but do not release the strings!)
delete [] m_pItems;
wxString* const pItemsOld = m_pItems;
m_pItems = pNew;
return pItemsOld;
}
}
}
// deletes all the strings from the list
@ -289,7 +297,10 @@ size_t wxArrayString::Add(const wxString& str, size_t nInsert)
return (size_t)lo;
}
else {
Grow(nInsert);
// Now that we must postpone freeing the old memory until we don't need it
// any more, i.e. don't reference "str" which could be a reference to one
// of our own strings.
wxScopedArray<wxString> oldStrings(Grow(nInsert));
for (size_t i = 0; i < nInsert; i++)
{
@ -309,7 +320,7 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert)
wxCHECK_RET( m_nCount <= m_nCount + nInsert,
wxT("array size overflow in wxArrayString::Insert") );
Grow(nInsert);
wxScopedArray<wxString> oldStrings(Grow(nInsert));
for (int j = m_nCount - nIndex - 1; j >= 0; j--)
m_pItems[nIndex + nInsert + j] = m_pItems[nIndex + j];
@ -328,7 +339,7 @@ wxArrayString::insert(iterator it, const_iterator first, const_iterator last)
const int idx = it - begin();
// grow it once
Grow(last - first);
wxScopedArray<wxString> oldStrings(Grow(last - first));
// reset "it" since it can change inside Grow()
it = begin() + idx;

View File

@ -346,6 +346,10 @@ void ArraysTestCase::wxStringArrayTest()
a5.resize(3);
CPPUNIT_ASSERT_EQUAL( 3, a5.size() );
CPPUNIT_ASSERT_EQUAL( "Foo", a5[2] );
wxArrayString a6;
a6.Add("Foo");
a6.Insert(a6[0], 1, 100);
}
void ArraysTestCase::SortedArray()