#endif
#include <ctype.h>
-#include <errno.h>
+
+#ifndef __WXWINCE__
+ #include <errno.h>
+#endif
+
#include <string.h>
#include <stdlib.h>
#if !wxUSE_STL
// get the pointer to writable buffer of (at least) nLen bytes
-wxChar *wxString::GetWriteBuf(size_t nLen)
+wxChar *wxString::DoGetWriteBuf(size_t nLen)
{
if ( !AllocBeforeWrite(nLen) ) {
// allocation failure handled by caller
}
// put string back in a reasonable state after GetWriteBuf
+void wxString::DoUngetWriteBuf()
+{
+ DoUngetWriteBuf(wxStrlen(m_pchData));
+}
+
+void wxString::DoUngetWriteBuf(size_t nLen)
+{
+ wxStringData * const pData = GetStringData();
+
+ wxASSERT_MSG( nLen < pData->nAllocLength, _T("buffer overrun") );
+
+ // the strings we store are always NUL-terminated
+ pData->data()[nLen] = _T('\0');
+ pData->nDataLength = nLen;
+ pData->Validate(true);
+}
+
+// deprecated compatibility code:
+#if WXWIN_COMPATIBILITY_2_8
+wxChar *wxString::GetWriteBuf(size_t nLen)
+{
+ return DoGetWriteBuf(nLen);
+}
+
void wxString::UngetWriteBuf()
{
- GetStringData()->nDataLength = wxStrlen(m_pchData);
- GetStringData()->Validate(true);
+ DoUngetWriteBuf();
}
void wxString::UngetWriteBuf(size_t nLen)
{
- GetStringData()->nDataLength = nLen;
- GetStringData()->Validate(true);
+ DoUngetWriteBuf(nLen);
}
-#endif
+#endif // WXWIN_COMPATIBILITY_2_8
+
+#endif // !wxUSE_STL
+
// ---------------------------------------------------------------------------
// data access
reverse_iterator psz = rbegin();
while ( (psz != rend()) && wxSafeIsspace(*psz) )
psz++;
-
+
// truncate at trailing space start
erase(psz.base(), end());
}
// the implementation of all the functions below is exactly the same so factor
// it out
-template <typename T>
+
+template <typename T, typename F>
bool wxStringToIntType(const wxChar *start,
T *val,
int base,
- T (*func)(const wxChar *, wxChar **, int))
+ F func)
{
wxCHECK_MSG( val, false, _T("NULL output pointer") );
wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
+#ifndef __WXWINCE__
errno = 0;
+#endif
wxChar *end;
*val = (*func)(start, &end, base);
// return true only if scan was stopped by the terminating NUL and if the
// string was not empty to start with and no under/overflow occurred
- return !*end && (end != start) && (errno != ERANGE);
+ return !*end && (end != start)
+#ifndef __WXWINCE__
+ && (errno != ERANGE)
+#endif
+ ;
}
bool wxString::ToLong(long *val, int base) const
return wxStringToIntType(c_str(), val, base, wxStrtoll);
#else
// TODO: implement this ourselves
+ wxUnusedVar(val);
+ wxUnusedVar(base);
return false;
#endif // wxHAS_STRTOLL
}
return wxStringToIntType(c_str(), val, base, wxStrtoull);
#else
// TODO: implement this ourselves
+ wxUnusedVar(val);
+ wxUnusedVar(base);
return false;
#endif
}
{
wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") );
+#ifndef __WXWINCE__
errno = 0;
+#endif
const wxChar *start = c_str();
wxChar *end;
// return true only if scan was stopped by the terminating NUL and if the
// string was not empty to start with and no under/overflow occurred
- return !*end && (end != start) && (errno != ERANGE);
+ return !*end && (end != start)
+#ifndef __WXWINCE__
+ && (errno != ERANGE)
+#endif
+ ;
}
// ---------------------------------------------------------------------------
// buffer were large enough (newer standards such as Unix98)
if ( len < 0 )
{
+#if wxUSE_WXVSNPRINTF
+ // we know that our own implementation of wxVsnprintf() returns -1
+ // only for a format error - thus there's something wrong with
+ // the user's format string
+ return -1;
+#else // assume that system version only returns error if not enough space
// still not enough, as we don't know how much we need, double the
// current size of the buffer
size *= 2;
+#endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
}
else if ( len >= size )
{
+#if wxUSE_WXVSNPRINTF
+ // we know that our own implementation of wxVsnprintf() returns
+ // size+1 when there's not enough space but that's not the size
+ // of the required buffer!
+ size *= 2; // so we just double the current size of the buffer
+#else
// some vsnprintf() implementations NUL-terminate the buffer and
// some don't in len == size case, to be safe always add 1
size = len + 1;
+#endif
}
else // ok, there was enough space
{
#define ARRAY_DEFAULT_INITIAL_SIZE (16)
#endif
-#define STRING(p) ((wxString *)(&(p)))
-
// ctor
void wxArrayString::Init(bool autoSort)
{
m_nSize =
m_nCount = 0;
- m_pItems = (wxChar **) NULL;
+ m_pItems = NULL;
m_autoSort = autoSort;
}
m_nSize = ARRAY_DEFAULT_INITIAL_SIZE;
if (m_nSize < nIncrement)
m_nSize = nIncrement;
- m_pItems = new wxChar *[m_nSize];
+ m_pItems = new wxString[m_nSize];
}
else {
// otherwise when it's called for the first time, nIncrement would be 0
if ( nIncrement < ndefIncrement )
nIncrement = ndefIncrement;
m_nSize += nIncrement;
- wxChar **pNew = new wxChar *[m_nSize];
+ wxString *pNew = new wxString[m_nSize];
// copy data to new location
- memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *));
+ for ( size_t j = 0; j < m_nCount; j++ )
+ pNew[j] = m_pItems[j];
// delete old memory (but do not release the strings!)
wxDELETEA(m_pItems);
}
}
-void wxArrayString::Free()
-{
- for ( size_t n = 0; n < m_nCount; n++ ) {
- STRING(m_pItems[n])->GetStringData()->Unlock();
- }
-}
-
// deletes all the strings from the list
void wxArrayString::Empty()
{
- Free();
-
m_nCount = 0;
}
// as Empty, but also frees memory
void wxArrayString::Clear()
{
- Free();
-
m_nSize =
m_nCount = 0;
// dtor
wxArrayString::~wxArrayString()
{
- Free();
-
wxDELETEA(m_pItems);
}
{
// only if old buffer was not big enough
if ( nSize > m_nSize ) {
- Free();
- wxDELETEA(m_pItems);
- m_pItems = new wxChar *[nSize];
+ wxString *pNew = new wxString[nSize];
+ if ( !pNew )
+ return;
+
+ for ( size_t j = 0; j < m_nCount; j++ )
+ pNew[j] = m_pItems[j];
+ delete [] m_pItems;
+
+ m_pItems = pNew;
m_nSize = nSize;
}
-
- m_nCount = 0;
}
// minimizes the memory usage by freeing unused memory
// only do it if we have some memory to free
if( m_nCount < m_nSize ) {
// allocates exactly as much memory as we need
- wxChar **pNew = new wxChar *[m_nCount];
+ wxString *pNew = new wxString[m_nCount];
// copy data to new location
- memcpy(pNew, m_pItems, m_nCount*sizeof(wxChar *));
+ for ( size_t j = 0; j < m_nCount; j++ )
+ pNew[j] = m_pItems[j];
delete [] m_pItems;
m_pItems = pNew;
}
}
-#if WXWIN_COMPATIBILITY_2_4
-
-// return a wxString[] as required for some control ctors.
-wxString* wxArrayString::GetStringArray() const
-{
- wxString *array = 0;
-
- if( m_nCount > 0 )
- {
- array = new wxString[m_nCount];
- for( size_t i = 0; i < m_nCount; i++ )
- array[i] = m_pItems[i];
- }
-
- return array;
-}
-
-void wxArrayString::Remove(size_t nIndex, size_t nRemove)
-{
- RemoveAt(nIndex, nRemove);
-}
-
-#endif // WXWIN_COMPATIBILITY_2_4
-
// searches the array for an item (forward or backwards)
int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const
{
if ( m_nCount > 0 ) {
size_t ui = m_nCount;
do {
- if ( STRING(m_pItems[--ui])->IsSameAs(sz, bCase) )
+ if ( m_pItems[--ui].IsSameAs(sz, bCase) )
return ui;
}
while ( ui != 0 );
}
else {
for( size_t ui = 0; ui < m_nCount; ui++ ) {
- if( STRING(m_pItems[ui])->IsSameAs(sz, bCase) )
+ if( m_pItems[ui].IsSameAs(sz, bCase) )
return ui;
}
}
return (size_t)lo;
}
else {
- wxASSERT( str.GetStringData()->IsValid() );
-
Grow(nInsert);
for (size_t i = 0; i < nInsert; i++)
{
- // the string data must not be deleted!
- str.GetStringData()->Lock();
-
// just append
- m_pItems[m_nCount + i] = (wxChar *)str.c_str(); // const_cast
+ m_pItems[m_nCount + i] = str;
}
size_t ret = m_nCount;
m_nCount += nInsert;
// add item at the given position
void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert)
{
- wxASSERT( str.GetStringData()->IsValid() );
-
wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") );
wxCHECK_RET( m_nCount <= m_nCount + nInsert,
wxT("array size overflow in wxArrayString::Insert") );
Grow(nInsert);
- memmove(&m_pItems[nIndex + nInsert], &m_pItems[nIndex],
- (m_nCount - nIndex)*sizeof(wxChar *));
+ for (int j = m_nCount - nIndex - 1; j >= 0; j--)
+ m_pItems[nIndex + nInsert + j] = m_pItems[nIndex + j];
for (size_t i = 0; i < nInsert; i++)
{
- str.GetStringData()->Lock();
- m_pItems[nIndex + i] = (wxChar *)str.c_str();
+ m_pItems[nIndex + i] = str;
}
m_nCount += nInsert;
}
wxString s;
while ( m_nCount < count )
- m_pItems[m_nCount++] = (wxChar *)s.c_str();
+ m_pItems[m_nCount++] = s;
}
// removes item from array (by index)
wxCHECK_RET( nIndex + nRemove <= m_nCount,
wxT("removing too many elements in wxArrayString::Remove") );
- // release our lock
- for (size_t i = 0; i < nRemove; i++)
- Item(nIndex + i).GetStringData()->Unlock();
+ for ( size_t j = 0; j < m_nCount - nIndex -nRemove; j++)
+ m_pItems[nIndex + j] = m_pItems[nIndex + nRemove + j];
- memmove(&m_pItems[nIndex], &m_pItems[nIndex + nRemove],
- (m_nCount - nIndex - nRemove)*sizeof(wxChar *));
m_nCount -= nRemove;
}
void wxArrayString::Sort(CompareFunction2 compareFunction)
{
- qsort(m_pItems, m_nCount, sizeof(wxChar *), (wxStringCompareFn)compareFunction);
+ qsort(m_pItems, m_nCount, sizeof(wxString), (wxStringCompareFn)compareFunction);
}
void wxArrayString::Sort(bool reverseOrder)
{
wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
- // just sort the pointers using qsort() - of course it only works because
- // wxString() *is* a pointer to its data
- qsort(m_pItems, m_nCount, sizeof(wxChar *), wxStringCompareFunction);
+ qsort(m_pItems, m_nCount, sizeof(wxString), wxStringCompareFunction);
}
bool wxArrayString::operator==(const wxArrayString& a) const