// Created: 29/01/98
// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
} g_strEmpty = { {-1, 0, 0}, wxT('\0') };
// empty C style string: points to 'string data' byte of g_strEmpty
-extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy;
+extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy;
// ----------------------------------------------------------------------------
// global functions
#define STATISTICS_ADD(av, val)
#endif // WXSTRING_STATISTICS
+// ===========================================================================
+// wxStringData class deallocation
+// ===========================================================================
+
+#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL)
+# pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!")
+void wxStringData::Free()
+{
+ free(this);
+}
+#endif
+
// ===========================================================================
// wxString class core
// ===========================================================================
// from multibyte string
wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
{
- // first get necessary size
- size_t nLen = psz ? conv.MB2WC((wchar_t *) NULL, psz, 0) : 0;
-
- // nLength is number of *Unicode* characters here!
- if ((nLen != (size_t)-1) && (nLen > nLength))
- nLen = nLength;
+ // first get the size of the buffer we need
+ size_t nLen;
+ if ( psz )
+ {
+ // calculate the needed size ourselves or use the provided one
+ nLen = nLength == wxSTRING_MAXLEN ? conv.MB2WC(NULL, psz, 0) : nLength;
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
- // empty?
- if ( (nLen != 0) && (nLen != (size_t)-1) ) {
- if ( !AllocBuffer(nLen) ) {
- wxFAIL_MSG( _T("out of memory in wxString::wxString") );
- return;
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !AllocBuffer(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ // MB2WC wants the buffer size, not the string length hence +1
+ nLen = conv.MB2WC(m_pchData, psz, nLen + 1);
+
+ if ( nLen != (size_t)-1 )
+ {
+ // initialized ok, set the real length as nLength specified by
+ // the caller could be greater than the real string length
+ GetStringData()->nDataLength = nLen;
+ m_pchData[nLen] = 0;
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
}
- conv.MB2WC(m_pchData, psz, nLen);
- }
- else {
+
Init();
- }
}
#else // ANSI
// from wide string
wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
{
- // first get necessary size
- size_t nLen = 0;
- if (pwz)
- {
- if (nLength == wxSTRING_MAXLEN)
- nLen = conv.WC2MB((char *) NULL, pwz, 0);
+ // first get the size of the buffer we need
+ size_t nLen;
+ if ( pwz )
+ {
+ // calculate the needed size ourselves or use the provided one
+ nLen = nLength == wxSTRING_MAXLEN ? conv.WC2MB(NULL, pwz, 0) : nLength;
+ }
else
- nLen = nLength;
- }
+ {
+ // nothing to convert
+ nLen = 0;
+ }
- // empty?
- if ( (nLen != 0) && (nLen != (size_t)-1) ) {
- if ( !AllocBuffer(nLen) ) {
- wxFAIL_MSG( _T("out of memory in wxString::wxString") );
- return;
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !AllocBuffer(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ // WC2MB wants the buffer size, not the string length
+ if ( conv.WC2MB(m_pchData, pwz, nLen + 1) != (size_t)-1 )
+ {
+ // initialized ok
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
}
- conv.WC2MB(m_pchData, pwz, nLen);
- }
- else {
+
Init();
- }
}
#endif // wxUSE_WCHAR_T
// ---------------------------------------------------------------------------
// add something to this string
-bool wxString::ConcatSelf(int nSrcLen, const wxChar *pszSrcData)
+bool wxString::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData)
{
STATISTICS_ADD(SummandLength, nSrcLen);
return res;
}
+wxString wxString::FromAscii(const char ascii)
+{
+ // What do we do with '\0' ?
+
+ wxString res;
+ res += (wchar_t)(unsigned char) ascii;
+
+ return res;
+}
+
const wxCharBuffer wxString::ToAscii() const
{
// this will allocate enough space for the terminating NUL too
}
// replace first (or all) occurences of some substring with another one
-size_t wxString::Replace(const wxChar *szOld, const wxChar *szNew, bool bReplaceAll)
+size_t
+wxString::Replace(const wxChar *szOld, const wxChar *szNew, bool bReplaceAll)
{
+ // if we tried to replace an empty string we'd enter an infinite loop below
+ wxCHECK_MSG( szOld && *szOld && szNew, 0,
+ _T("wxString::Replace(): invalid parameter") );
+
size_t uiCount = 0; // count of replacements made
size_t uiOldLen = wxStrlen(szOld);
// ArrayString
// ============================================================================
+#include "wx/arrstr.h"
+
+#if !wxUSE_STL
+
// size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT)
#define ARRAY_MAXSIZE_INCREMENT 4096
void wxArrayString::Grow(size_t nIncrement)
{
// only do it if no more place
- if ( m_nCount == m_nSize ) {
+ if ( (m_nSize - m_nCount) < nIncrement ) {
// if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would
// be never resized!
#if ARRAY_DEFAULT_INITIAL_SIZE == 0
if ( m_nSize == 0 ) {
// was empty, alloc some memory
m_nSize = ARRAY_DEFAULT_INITIAL_SIZE;
+ if (m_nSize < nIncrement)
+ m_nSize = nIncrement;
m_pItems = new wxChar *[m_nSize];
}
else {
}
}
+#if WXWIN_COMPATIBILITY_2_4
+
// return a wxString[] as required for some control ctors.
wxString* wxArrayString::GetStringArray() const
{
return array;
}
+#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
{
}
// removes item from array (by index)
-void wxArrayString::Remove(size_t nIndex, size_t nRemove)
+void wxArrayString::RemoveAt(size_t nIndex, size_t nRemove)
{
wxCHECK_RET( nIndex < m_nCount, wxT("bad index in wxArrayString::Remove") );
wxCHECK_RET( nIndex + nRemove <= m_nCount,
wxCHECK_RET( iIndex != wxNOT_FOUND,
wxT("removing inexistent element in wxArrayString::Remove") );
- Remove(iIndex);
+ RemoveAt(iIndex);
}
// ----------------------------------------------------------------------------
static bool gs_sortAscending = TRUE;
// function which is called by quick sort
-extern "C" int LINKAGEMODE
+extern "C" int wxC_CALLING_CONV // LINKAGEMODE
wxStringCompareFunction(const void *first, const void *second)
{
wxString *strFirst = (wxString *)first;
END_SORT();
}
-void wxArrayString::Sort(bool reverseOrder)
-{
- START_SORT();
+typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first, const void *second);
- wxASSERT( !gs_compareFunction ); // must have been reset to NULL
- gs_sortAscending = !reverseOrder;
-
- DoSort();
+void wxArrayString::Sort(CompareFunction2 compareFunction)
+{
+ qsort(m_pItems, m_nCount, sizeof(wxChar *), (wxStringCompareFn)compareFunction);
+}
- END_SORT();
+void wxArrayString::Sort(bool reverseOrder)
+{
+ Sort(reverseOrder ? wxStringSortDescending : wxStringSortAscending);
}
void wxArrayString::DoSort()
return TRUE;
}
+#endif // !wxUSE_STL
+
+int wxStringSortAscending(wxString* s1, wxString* s2)
+{
+ return wxStrcmp(s1->c_str(), s2->c_str());
+}
+
+int wxStringSortDescending(wxString* s1, wxString* s2)
+{
+ return -wxStrcmp(s1->c_str(), s2->c_str());
+}