X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9a4232dcb721e93ea4320ea6d87b4337761b8dd7..4b04699b670b4ab4632229fa0264d154acd3bec1:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 902b9a5af7..d8a1d812b2 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -46,17 +46,9 @@ #include #endif -#if wxUSE_WCSRTOMBS - #include // for wcsrtombs(), see comments where it's used -#endif // GNU - -#ifdef WXSTRING_IS_WXOBJECT - IMPLEMENT_DYNAMIC_CLASS(wxString, wxObject) -#endif //WXSTRING_IS_WXOBJECT - #if wxUSE_UNICODE -#undef wxUSE_EXPERIMENTAL_PRINTF -#define wxUSE_EXPERIMENTAL_PRINTF 1 + #undef wxUSE_EXPERIMENTAL_PRINTF + #define wxUSE_EXPERIMENTAL_PRINTF 1 #endif // allocating extra space for each string consumes more memory but speeds up @@ -68,6 +60,12 @@ // static class variables definition // --------------------------------------------------------------------------- +#if defined(__VISAGECPP__) && __IBMCPP__ >= 400 +// must define this static for VA or else you get multiply defined symbols +// everywhere +const unsigned int wxSTRING_MAXLEN = UINT_MAX - 100; +#endif // Visual Age + #ifdef wxSTD_STRING_COMPATIBILITY const size_t wxString::npos = wxSTRING_MAXLEN; #endif // wxSTD_STRING_COMPATIBILITY @@ -85,12 +83,6 @@ static const struct wxChar dummy; } g_strEmpty = { {-1, 0, 0}, wxT('\0') }; -#if defined(__VISAGECPP__) && __IBMCPP__ >= 400 -// must define this static for VA or else you get multiply defined symbols -// everywhere -const unsigned int wxSTRING_MAXLEN = UINT_MAX - 100; -#endif // Visual Age - // empty C style string: points to 'string data' byte of g_strEmpty extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy; @@ -137,7 +129,7 @@ extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy; #endif //compiler #endif // no vsnprintf -#ifdef _AIX +#if defined(_AIX) // AIX has vsnprintf, but there's no prototype in the system headers. extern "C" int vsnprintf(char* str, size_t n, const char* format, va_list ap); #endif @@ -344,10 +336,17 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) #if wxUSE_WCHAR_T // from wide string -wxString::wxString(const wchar_t *pwz, wxMBConv& conv) +wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength) { // first get necessary size - size_t nLen = pwz ? conv.WC2MB((char *) NULL, pwz, 0) : 0; + size_t nLen = 0; + if (pwz) + { + if (nLength == wxSTRING_MAXLEN) + nLen = conv.WC2MB((char *) NULL, pwz, 0); + else + nLen = nLength; + } // empty? if ( (nLen != 0) && (nLen != (size_t)-1) ) { @@ -499,18 +498,21 @@ void wxString::Shrink() { wxStringData *pData = GetStringData(); - // this variable is unused in release build, so avoid the compiler warning - // by just not declaring it -#ifdef __WXDEBUG__ - void *p = -#endif - realloc(pData, sizeof(wxStringData) + (pData->nDataLength + 1)*sizeof(wxChar)); + size_t nLen = pData->nDataLength; + void *p = realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); - // we rely on a reasonable realloc() implementation here - so far I haven't - // seen any which wouldn't behave like this + wxASSERT_MSG( p != NULL, _T("can't free memory?") ); - wxASSERT( p != NULL ); // can't free memory? - wxASSERT( p == pData ); // we're decrementing the size - block shouldn't move! + if ( p != pData ) + { + // contrary to what one might believe, some realloc() implementation do + // move the memory block even when its size is reduced + pData = (wxStringData *)p; + + m_pchData = pData->data(); + } + + pData->nAllocLength = nLen; } // get the pointer to writable buffer of (at least) nLen bytes @@ -589,6 +591,7 @@ wxString& wxString::operator=(wxChar ch) return *this; } + // assigns C string wxString& wxString::operator=(const wxChar *psz) { @@ -1091,26 +1094,28 @@ int wxString::Find(const wxChar *pszSub) const // conversion to numbers // ---------------------------------------------------------------------------- -bool wxString::ToLong(long *val) const +bool wxString::ToLong(long *val, int base) const { wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToLong") ); + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); const wxChar *start = c_str(); wxChar *end; - *val = wxStrtol(start, &end, 10); + *val = wxStrtol(start, &end, base); // return TRUE only if scan was stopped by the terminating NUL and if the // string was not empty to start with return !*end && (end != start); } -bool wxString::ToULong(unsigned long *val) const +bool wxString::ToULong(unsigned long *val, int base) const { wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToULong") ); + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); const wxChar *start = c_str(); wxChar *end; - *val = wxStrtoul(start, &end, 10); + *val = wxStrtoul(start, &end, base); // return TRUE only if scan was stopped by the terminating NUL and if the // string was not empty to start with @@ -1456,6 +1461,53 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) // of them) bool wxString::Matches(const wxChar *pszMask) const { + // I disable this code as it doesn't seem to be faster (in fact, it seems + // to be much slower) than the old, hand-written code below and using it + // here requires always linking with libregex even if the user code doesn't + // use it +#if 0 // wxUSE_REGEX + // first translate the shell-like mask into a regex + wxString pattern; + pattern.reserve(wxStrlen(pszMask)); + + pattern += _T('^'); + while ( *pszMask ) + { + switch ( *pszMask ) + { + case _T('?'): + pattern += _T('.'); + break; + + case _T('*'): + pattern += _T(".*"); + break; + + case _T('^'): + case _T('.'): + case _T('$'): + case _T('('): + case _T(')'): + case _T('|'): + case _T('+'): + case _T('\\'): + // these characters are special in a RE, quote them + // (however note that we don't quote '[' and ']' to allow + // using them for Unix shell like matching) + pattern += _T('\\'); + // fall through + + default: + pattern += *pszMask; + } + + pszMask++; + } + pattern += _T('$'); + + // and now use it + return wxRegEx(pattern, wxRE_NOSUB | wxRE_EXTENDED).Matches(c_str()); +#else // !wxUSE_REGEX // TODO: this is, of course, awfully inefficient... // the char currently being checked @@ -1539,6 +1591,7 @@ match: } return FALSE; +#endif // wxUSE_REGEX/!wxUSE_REGEX } // Count the number of chars @@ -1586,7 +1639,7 @@ void wxString::resize(size_t nSize, wxChar ch) } else if ( nSize > len ) { - *this += wxString(ch, len - nSize); + *this += wxString(ch, nSize - len); } //else: we have exactly the specified length, nothing to do } @@ -1652,7 +1705,7 @@ size_t wxString::find(wxChar ch, size_t nStart) const size_t wxString::rfind(const wxString& str, size_t nStart) const { wxASSERT( str.GetStringData()->IsValid() ); - wxASSERT( nStart <= Len() ); + wxASSERT( nStart == npos || nStart <= Len() ); // TODO could be made much quicker than that const wxChar *p = c_str() + (nStart == npos ? Len() : nStart); @@ -1669,7 +1722,7 @@ size_t wxString::rfind(const wxString& str, size_t nStart) const #if !defined(__VISUALC__) || defined(__WIN32__) size_t wxString::rfind(const wxChar* sz, size_t nStart, size_t n) const { - return rfind(wxString(sz, n == npos ? 0 : n), nStart); + return rfind(wxString(sz, n == npos ? wxSTRING_MAXLEN : n), nStart); } size_t wxString::rfind(wxChar ch, size_t nStart) const @@ -1846,16 +1899,17 @@ wxString& wxString::replace(size_t nStart, size_t nLen, // ArrayString // ============================================================================ -// size increment = max(50% of current size, ARRAY_MAXSIZE_INCREMENT) +// size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) #define ARRAY_MAXSIZE_INCREMENT 4096 + #ifndef ARRAY_DEFAULT_INITIAL_SIZE // also defined in dynarray.h - #define ARRAY_DEFAULT_INITIAL_SIZE (16) +#define ARRAY_DEFAULT_INITIAL_SIZE (16) #endif #define STRING(p) ((wxString *)(&(p))) // ctor -wxArrayString::wxArrayString(bool autoSort) +void wxArrayString::Init(bool autoSort) { m_nSize = m_nCount = 0; @@ -1866,10 +1920,7 @@ wxArrayString::wxArrayString(bool autoSort) // copy ctor wxArrayString::wxArrayString(const wxArrayString& src) { - m_nSize = - m_nCount = 0; - m_pItems = (wxChar **) NULL; - m_autoSort = src.m_autoSort; + Init(src.m_autoSort); *this = src; } @@ -1971,8 +2022,6 @@ wxArrayString::~wxArrayString() // pre-allocates memory (frees the previous data!) void wxArrayString::Alloc(size_t nSize) { - wxASSERT( nSize > 0 ); - // only if old buffer was not big enough if ( nSize > m_nSize ) { Free(); @@ -1999,6 +2048,21 @@ void wxArrayString::Shrink() } } +// 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; +} + // searches the array for an item (forward or backwards) int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const { @@ -2110,6 +2174,16 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex) m_nCount++; } +// expand the array +void wxArrayString::SetCount(size_t count) +{ + Alloc(count); + + wxString s; + while ( m_nCount < count ) + m_pItems[m_nCount++] = (wxChar *)s.c_str(); +} + // removes item from array (by index) void wxArrayString::Remove(size_t nIndex) { @@ -2166,7 +2240,8 @@ static wxArrayString::CompareFunction gs_compareFunction = NULL; static bool gs_sortAscending = TRUE; // function which is called by quick sort -static int LINKAGEMODE wxStringCompareFunction(const void *first, const void *second) +extern "C" int LINKAGEMODE +wxStringCompareFunction(const void *first, const void *second) { wxString *strFirst = (wxString *)first; wxString *strSecond = (wxString *)second;