X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/097c080b74811b9217e7e5ddf1e5d825c1fa713f..e99c30481090eb4ceaec74c0c1b5fac89b235e7f:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 3e5e41f2d6..bb02779aee 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -6,7 +6,7 @@ // Created: 29/01/98 // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ @@ -61,8 +61,6 @@ static int g_strEmpty[] = { -1, // ref count (locked) 0, // current length 0, // allocated memory 0 }; // string data -// empty string shares memory with g_strEmpty -static wxStringData *g_strNul = (wxStringData*)&g_strEmpty; // empty C style string: points to 'string data' byte of g_strEmpty extern const char *g_szNul = (const char *)(&g_strEmpty[3]); @@ -101,7 +99,7 @@ NAMESPACE istream& operator>>(NAMESPACE istream& is, wxString& WXUNUSED(str)) sb->sungetc(); break; } - + str += ch; if ( --w == 1 ) break; @@ -176,7 +174,7 @@ void wxString::InitWith(const char *psz, size_t nPos, size_t nLength) memcpy(m_pchData, psz + nPos, nLength*sizeof(char)); } } - + // take first nLength characters of C string psz // (default value of STRING_MAXLEN means take all the string) wxString::wxString(const char *psz, size_t nLength) @@ -188,8 +186,8 @@ wxString::wxString(const char *psz, size_t nLength) wxString::wxString(const unsigned char* psz, size_t nLength) { InitWith((const char *)psz, 0, nLength); -} - +} + #ifdef STD_STRING_COMPATIBILITY // ctor from a substring @@ -203,7 +201,7 @@ wxString::wxString(const wxString& str, size_t nPos, size_t nLen) // poor man's iterators are "void *" pointers wxString::wxString(const void *pStart, const void *pEnd) { - InitWith((const char *)pStart, 0, + InitWith((const char *)pStart, 0, (const char *)pEnd - (const char *)pStart); } @@ -238,8 +236,8 @@ void wxString::AllocBuffer(size_t nLen) // allocate memory: // 1) one extra character for '\0' termination // 2) sizeof(wxStringData) for housekeeping info - wxStringData* pData = (wxStringData*)new char[sizeof(wxStringData) + - (nLen + 1)*sizeof(char)]; + wxStringData* pData = (wxStringData*)malloc(sizeof(wxStringData) + + (nLen + 1)*sizeof(char)); pData->nRefs = 1; pData->data()[nLen] = '\0'; pData->nDataLength = nLen; @@ -247,23 +245,6 @@ void wxString::AllocBuffer(size_t nLen) m_pchData = pData->data(); // data starts after wxStringData } -// releases the string memory and reinits it -void wxString::Reinit() -{ - GetStringData()->Unlock(); - Init(); -} - -// wrapper around wxString::Reinit -void wxString::Empty() -{ - if ( GetStringData()->nDataLength != 0 ) - Reinit(); - - wxASSERT( GetStringData()->nDataLength == 0 ); - wxASSERT( GetStringData()->nAllocLength == 0 ); -} - // must be called before changing this string void wxString::CopyBeforeWrite() { @@ -294,8 +275,44 @@ void wxString::AllocBeforeWrite(size_t nLen) wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner } +// allocate enough memory for nLen characters +void wxString::Alloc(uint nLen) +{ + wxStringData *pData = GetStringData(); + if ( pData->nAllocLength <= nLen ) { + if ( pData->IsEmpty() ) + AllocBuffer(nLen); + else { + wxStringData *p = (wxStringData *) + realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(char)); + if ( p != NULL && p != pData ) { + // the call succeeded but the pointer changed + pData->Unlock(); + free(pData); + + p->nRefs = 1; + p->nAllocLength = nLen; + m_pchData = p->data(); + } + //else: do nothing: either the call failed or the pointer is unchanged + } + } + //else: we've already got enough +} + +// shrink to minimal size (releasing extra memory) +void wxString::Shrink() +{ + wxStringData *pData = GetStringData(); + void *p = realloc(pData, sizeof(wxStringData) + + (pData->nDataLength + 1)*sizeof(char)); + if ( p == NULL ) // huh? can't unallocate memory? unlikely but possible. + return; + wxASSERT( p == pData ); // we're decrementing the size - block shouldn't move! +} + // get the pointer to writable buffer of (at least) nLen bytes -char *wxString::GetWriteBuf(int nLen) +char *wxString::GetWriteBuf(uint nLen) { AllocBeforeWrite(nLen); @@ -328,7 +345,7 @@ wxString::~wxString() // assignment operators // --------------------------------------------------------------------------- -// helper function: does real copy +// helper function: does real copy void wxString::AssignCopy(size_t nSrcLen, const char *pszSrcData) { if ( nSrcLen == 0 ) { @@ -398,7 +415,7 @@ wxString& wxString::operator=(const wchar_t *pwz) // concatenate two sources // NB: assume that 'this' is a new wxString object void wxString::ConcatCopy(int nSrc1Len, const char *pszSrc1Data, - int nSrc2Len, const char *pszSrc2Data) + int nSrc2Len, const char *pszSrc2Data) { int nNewLen = nSrc1Len + nSrc2Len; if ( nNewLen != 0 ) @@ -417,7 +434,7 @@ void wxString::ConcatSelf(int nSrcLen, const char *pszSrcData) register wxStringData *pData = GetStringData(); // alloc new buffer if current is too small - if ( pData->IsShared() || + if ( pData->IsShared() || pData->nDataLength + nSrcLen > pData->nAllocLength ) { // we have to grow the buffer, use the ConcatCopy routine // (which will allocate memory) @@ -439,51 +456,6 @@ void wxString::ConcatSelf(int nSrcLen, const char *pszSrcData) } /* - * string may be concatenated with other string, C string or a character - */ - -void wxString::operator+=(const wxString& string) -{ - wxASSERT( string.GetStringData()->IsValid() ); - - ConcatSelf(string.Len(), string); -} - -void wxString::operator+=(const char *psz) -{ - ConcatSelf(Strlen(psz), psz); -} - -void wxString::operator+=(char ch) -{ - ConcatSelf(1, &ch); -} - -/* - * Same as above but return the result - */ - -wxString& wxString::operator<<(const wxString& string) -{ - wxASSERT( string.GetStringData()->IsValid() ); - - ConcatSelf(string.Len(), string); - return *this; -} - -wxString& wxString::operator<<(const char *psz) -{ - ConcatSelf(Strlen(psz), psz); - return *this; -} - -wxString& wxString::operator<<(char ch) -{ - ConcatSelf(1, &ch); - return *this; -} - -/* * concatenation functions come in 5 flavours: * string + string * char + string and string + char @@ -659,7 +631,7 @@ uint wxString::Replace(const char *szOld, const char *szNew, bool bReplaceAll) wxString strTemp; const char *pCurrent = m_pchData; - const char *pSubstr; + const char *pSubstr; while ( *pCurrent != '\0' ) { pSubstr = strstr(pCurrent, szOld); if ( pSubstr == NULL ) { @@ -701,7 +673,7 @@ bool wxString::IsAscii() const } return(TRUE); } - + bool wxString::IsWord() const { const char *s = (const char*) *this; @@ -711,7 +683,7 @@ bool wxString::IsWord() const } return(TRUE); } - + bool wxString::IsNumber() const { const char *s = (const char*) *this; @@ -722,10 +694,6 @@ bool wxString::IsNumber() const return(TRUE); } -// kludge: we don't have declaraton of wxStringData here, so we add offsets -// manually to get to the "length" field of wxStringData structure -bool wxString::IsEmpty() const { return Len() == 0; } - wxString wxString::Strip(stripType w) const { wxString s = *this; @@ -734,33 +702,6 @@ wxString wxString::Strip(stripType w) const return s; } -/// case-insensitive strcmp() (platform independent) -int Stricmp(const char *psz1, const char *psz2) -{ -#if defined(_MSC_VER) - return _stricmp(psz1, psz2); -#elif defined(__BORLANDC__) - return stricmp(psz1, psz2); -#elif defined(__UNIX__) || defined(__GNUWIN32__) - return strcasecmp(psz1, psz2); -#else - // almost all compilers/libraries provide this function (unfortunately under - // different names), that's why we don't implement our own which will surely - // be more efficient than this code (uncomment to use): - /* - register char c1, c2; - do { - c1 = tolower(*psz1++); - c2 = tolower(*psz2++); - } while ( c1 && (c1 == c2) ); - - return c1 - c2; - */ - - #error "Please define string case-insensitive compare for your OS/compiler" -#endif // OS/compiler -} - // --------------------------------------------------------------------------- // case conversion // --------------------------------------------------------------------------- @@ -778,7 +719,7 @@ wxString& wxString::MakeUpper() wxString& wxString::MakeLower() { CopyBeforeWrite(); - + for ( char *p = m_pchData; *p; p++ ) *p = (char)tolower(*p); @@ -907,7 +848,7 @@ int wxString::Scanf(const char *pszFormat, ...) const int wxString::ScanfV(const char *pszFormat, va_list argptr) const { -#ifdef __WINDOWS__ +#ifdef __WXMSW__ wxMessageBox("ScanfV not implemented"); return 0; #else @@ -993,9 +934,10 @@ wxString& wxString::insert(size_t nPos, const wxString& str) strncpy(pc, c_str(), nPos); strcpy(pc + nPos, str); strcpy(pc + nPos + str.Len(), c_str() + nPos); + strTmp.UngetWriteBuf(); *this = strTmp; - - return *this; + + return *this; } size_t wxString::find(const wxString& str, size_t nStart) const @@ -1004,7 +946,7 @@ size_t wxString::find(const wxString& str, size_t nStart) const wxASSERT( nStart <= Len() ); const char *p = strstr(c_str() + nStart, str); - + return p == NULL ? npos : p - c_str(); } @@ -1015,13 +957,13 @@ size_t wxString::find(const char* sz, size_t nStart, size_t n) const return find(wxString(sz, n == npos ? 0 : n), nStart); } #endif - + size_t wxString::find(char ch, size_t nStart) const { wxASSERT( nStart <= Len() ); const char *p = strchr(c_str() + nStart, ch); - + return p == NULL ? npos : p - c_str(); } @@ -1037,10 +979,10 @@ size_t wxString::rfind(const wxString& str, size_t nStart) const return p - str.Len() - c_str(); p--; } - + return npos; } - + // VC++ 1.5 can't cope with the default argument in the header. #if ! (defined(_MSC_VER) && !defined(__WIN32__)) size_t wxString::rfind(const char* sz, size_t nStart, size_t n) const @@ -1053,7 +995,7 @@ size_t wxString::rfind(char ch, size_t nStart) const wxASSERT( nStart <= Len() ); const char *p = strrchr(c_str() + nStart, ch); - + return p == NULL ? npos : p - c_str(); } #endif @@ -1091,7 +1033,7 @@ wxString& wxString::replace(size_t nStart, size_t nLen, const char *sz) strTmp.append(c_str(), nStart); strTmp += sz; strTmp.append(c_str() + nStart + nLen); - + *this = strTmp; return *this; } @@ -1101,13 +1043,13 @@ wxString& wxString::replace(size_t nStart, size_t nLen, size_t nCount, char ch) return replace(nStart, nLen, wxString(ch, nCount)); } -wxString& wxString::replace(size_t nStart, size_t nLen, +wxString& wxString::replace(size_t nStart, size_t nLen, const wxString& str, size_t nStart2, size_t nLen2) { return replace(nStart, nLen, str.substr(nStart2, nLen2)); } -wxString& wxString::replace(size_t nStart, size_t nLen, +wxString& wxString::replace(size_t nStart, size_t nLen, const char* sz, size_t nCount) { return replace(nStart, nLen, wxString(sz, nCount)); @@ -1159,7 +1101,7 @@ wxArrayString& wxArrayString::operator=(const wxArrayString& src) m_nCount = src.m_nCount; if ( m_nSize != 0 ) - m_pItems = new char *[m_nSize]; + m_pItems = new char *[m_nCount]; else m_pItems = NULL; @@ -1218,7 +1160,7 @@ void wxArrayString::Clear() { Free(); - m_nSize = + m_nSize = m_nCount = 0; DELETEA(m_pItems); @@ -1296,7 +1238,7 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex) Grow(); - memmove(&m_pItems[nIndex + 1], &m_pItems[nIndex], + memmove(&m_pItems[nIndex + 1], &m_pItems[nIndex], (m_nCount - nIndex)*sizeof(char *)); str.GetStringData()->Lock(); @@ -1313,7 +1255,7 @@ void wxArrayString::Remove(size_t nIndex) // release our lock Item(nIndex).GetStringData()->Unlock(); - memmove(&m_pItems[nIndex], &m_pItems[nIndex + 1], + memmove(&m_pItems[nIndex], &m_pItems[nIndex + 1], (m_nCount - nIndex - 1)*sizeof(char *)); m_nCount--; }