optimizations: more functions made inline, added Alloc()/Shrink() function for

more precise control over string's memory


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@275 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 1998-07-15 17:10:23 +00:00
parent 2ab889ff7b
commit dd1eaa89dd
2 changed files with 218 additions and 220 deletions

View File

@ -6,7 +6,7 @@
// Created: 29/01/98
// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows license
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#ifndef __WXSTRINGH__
@ -26,17 +26,20 @@
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
#include <stdlib.h>
#ifndef WX_PRECOMP
#include "wx/defs.h" // Robert Roebling
#include "wx/object.h"
#ifdef WXSTRING_IS_WXOBJECT
#include "wx/object.h"
#endif
#endif
#include "wx/debug.h"
/** @name wxString library
@memo Efficient wxString class [more or less] compatible with MFC CString,
wxWindows wxString and std::string and some handy functions
wxWindows wxString and std::string and some handy functions
missing from string.h.
*/
//@{
@ -45,7 +48,7 @@
// macros
// ---------------------------------------------------------------------------
/** @name Macros
/** @name Macros
@memo You can switch off wxString/std::string compatibility if desired
*/
/// compile the std::string compatibility functions
@ -65,7 +68,7 @@
#define ASSERT_VALID_INDEX(i) wxASSERT( (unsigned)(i) < Len() )
// ---------------------------------------------------------------------------
/** @name Global functions complementing standard C string library
/** @name Global functions complementing standard C string library
@memo replacements for strlen() and portable strcasecmp()
*/
// ---------------------------------------------------------------------------
@ -78,7 +81,31 @@ inline size_t WXDLLEXPORT Strlen(const char *psz)
{ return psz ? strlen(psz) : 0; }
/// portable strcasecmp/_stricmp
int WXDLLEXPORT Stricmp(const char *, const char *);
inline int WXDLLEXPORT 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
}
// ----------------------------------------------------------------------------
// global data
@ -102,17 +129,17 @@ struct WXDLLEXPORT wxStringData
nAllocLength; // allocated memory size
// mimics declaration 'char data[nAllocLength]'
char* data() const { return (char*)(this + 1); }
char* data() const { return (char*)(this + 1); }
// empty string has a special ref count so it's never deleted
bool IsEmpty() const { return nRefs == -1; }
bool IsShared() const { return nRefs > 1; }
// lock/unlock
void Lock() { if ( !IsEmpty() ) nRefs++; }
void Unlock() { if ( !IsEmpty() && --nRefs == 0) delete (char *)this; }
void Lock() { if ( !IsEmpty() ) nRefs++; }
void Unlock() { if ( !IsEmpty() && --nRefs == 0) free(this); }
// if we had taken control over string memory (GetWriteBuf), it's
// if we had taken control over string memory (GetWriteBuf), it's
// intentionally put in invalid state
void Validate(bool b) { nRefs = b ? 1 : 0; }
bool IsValid() const { return nRefs != 0; }
@ -129,9 +156,9 @@ struct WXDLLEXPORT wxStringData
This class aims to be as compatible as possible with the new standard
std::string class, but adds some additional functions and should be
at least as efficient than the standard implementation.
Performance note: it's more efficient to write functions which take
"const String&" arguments than "const char *" if you assign the argument
Performance note: it's more efficient to write functions which take
"const String&" arguments than "const char *" if you assign the argument
to another string.
It was compiled and tested under Win32, Linux (libc 5 & 6), Solaris 5.5.
@ -140,7 +167,7 @@ struct WXDLLEXPORT wxStringData
- ressource support (string tables in ressources)
- more wide character (UNICODE) support
- regular expressions support
@memo A non-template portable wxString class implementing copy-on-write.
@author VZ
@version 1.3
@ -157,15 +184,24 @@ struct WXDLLEXPORT wxStringData
friend class wxArrayString;
// NB: this data must be here (before all other functions) to be sure that all
// inline functions are really inlined by all compilers
private:
// points to data preceded by wxStringData structure with ref count info
char *m_pchData;
// accessor to string data
wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; }
public:
/** @name constructors & dtor */
//@{
/// ctor for an empty string
wxString();
/// copy ctor
wxString(const wxString& stringSrc);
wxString(const wxString& stringSrc);
/// string containing nRepeat copies of ch
wxString(char ch, size_t nRepeat = 1);
wxString(char ch, size_t nRepeat = 1);
/// ctor takes first nLength characters from C string
wxString(const char *psz, size_t nLength = STRING_MAXLEN);
/// from C string (for compilers using unsigned char)
@ -179,11 +215,19 @@ public:
/** @name generic attributes & operations */
//@{
/// as standard strlen()
size_t Len() const { return GetStringData()->nDataLength; }
uint Len() const { return GetStringData()->nDataLength; }
/// string contains any characters?
bool IsEmpty() const;
bool IsEmpty() const { return Len() == 0; }
/// reinitialize string (and free data!)
void Empty();
void Empty()
{
if ( GetStringData()->nDataLength != 0 )
Reinit();
wxASSERT( GetStringData()->nDataLength == 0 );
wxASSERT( GetStringData()->nAllocLength == 0 );
}
/// Is an ascii value
bool IsAscii() const;
/// Is a number
@ -196,10 +240,10 @@ public:
//@{
/// read access
char GetChar(size_t n) const
{ ASSERT_VALID_INDEX( n ); return m_pchData[n]; }
{ ASSERT_VALID_INDEX( n ); return m_pchData[n]; }
/// read/write access
char& GetWritableChar(size_t n)
{ ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
{ ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
/// write access
void SetChar(size_t n, char ch)
{ ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); m_pchData[n] = ch; }
@ -208,7 +252,7 @@ public:
char Last() const
{ wxASSERT( !IsEmpty() ); return m_pchData[Len() - 1]; }
/// get writable last character
char& Last()
char& Last()
{ wxASSERT( !IsEmpty() ); CopyBeforeWrite(); return m_pchData[Len()-1]; }
/// operator version of GetChar
@ -222,7 +266,7 @@ public:
{ ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
/// implicit conversion to C string
operator const char*() const { return m_pchData; }
operator const char*() const { return m_pchData; }
/// explicit conversion to C string (use this with printf()!)
const char* c_str() const { return m_pchData; }
///
@ -242,30 +286,37 @@ public:
///
wxString& operator=(const wchar_t *pwz);
//@}
/** @name string concatenation */
//@{
/** @name in place concatenation */
//@{
/// string += string
void operator+=(const wxString& string);
void operator+=(const wxString& s) { (void)operator<<(s); }
/// string += C string
void operator+=(const char *psz);
void operator+=(const char *psz) { (void)operator<<(psz); }
/// string += char
void operator+=(char ch);
void operator+=(char ch) { (void)operator<<(ch); }
//@}
/** @name concatenate and return the result
left to right associativity of << allows to write
left to right associativity of << allows to write
things like "str << str1 << str2 << ..." */
//@{
/// as +=
wxString& operator<<(const wxString& string);
wxString& operator<<(const wxString& s)
{
wxASSERT( s.GetStringData()->IsValid() );
ConcatSelf(s.Len(), s);
return *this;
}
/// as +=
wxString& operator<<(char ch);
wxString& operator<<(const char *psz)
{ ConcatSelf(Strlen(psz), psz); return *this; }
/// as +=
wxString& operator<<(const char *psz);
wxString& operator<<(char ch) { ConcatSelf(1, &ch); return *this; }
//@}
/** @name return resulting string */
//@{
///
@ -280,10 +331,10 @@ public:
friend wxString operator+(const char *psz, const wxString& string);
//@}
//@}
/** @name string comparison */
//@{
/**
/**
case-sensitive comparaison
@return 0 if equal, +1 if greater or -1 if less
@see CmpNoCase, IsSameAs
@ -300,20 +351,20 @@ public:
@return TRUE if strings are equal, FALSE otherwise
@see Cmp, CmpNoCase
*/
bool IsSameAs(const char *psz, bool bCase = TRUE) const
bool IsSameAs(const char *psz, bool bCase = TRUE) const
{ return !(bCase ? Cmp(psz) : CmpNoCase(psz)); }
//@}
/** @name other standard string operations */
//@{
/** @name simple sub-string extraction
*/
//@{
/**
return substring starting at nFirst of length
/**
return substring starting at nFirst of length
nCount (or till the end if nCount = default value)
*/
wxString Mid(size_t nFirst, size_t nCount = STRING_MAXLEN) const;
wxString Mid(size_t nFirst, size_t nCount = STRING_MAXLEN) const;
/// get first nCount characters
wxString Left(size_t nCount) const;
/// get all characters before the first occurence of ch
@ -331,9 +382,9 @@ public:
/// (returns the whole string if ch not found)
wxString Right(char ch) const;
//@}
/** @name case conversion */
//@{
//@{
///
wxString& MakeUpper();
///
@ -349,7 +400,7 @@ public:
/// truncate string to given length
wxString& Truncate(size_t uiLen);
//@}
/** @name searching and replacing */
//@{
/// searching (return starting index, or -1 if not found)
@ -375,15 +426,21 @@ public:
/// as vprintf(), returns the number of characters written or < 0 on error
int PrintfV(const char* pszFormat, va_list argptr);
//@}
/** @name raw access to string memory */
//@{
/**
get writable buffer of at least nLen bytes.
/// ensure that string has space for at least nLen characters
// only works if the data of this string is not shared
void Alloc(uint nLen);
/// minimize the string's memory
// only works if the data of this string is not shared
void Shrink();
/**
get writable buffer of at least nLen bytes.
Unget() *must* be called a.s.a.p. to put string back in a reasonable
state!
*/
char *GetWriteBuf(int nLen);
char *GetWriteBuf(uint nLen);
/// call this immediately after GetWriteBuf() has been used
void UngetWriteBuf();
//@}
@ -434,9 +491,9 @@ public:
wxString& RemoveLast() { return Truncate(Len() - 1); }
// Robert Roebling
wxString& Remove(size_t nStart, size_t nLen) { return erase( nStart, nLen ); }
size_t First( const char ch ) const { return find(ch); }
size_t First( const char* psz ) const { return find(psz); }
size_t First( const wxString &str ) const { return find(str); }
@ -451,10 +508,10 @@ public:
#ifdef STD_STRING_COMPATIBILITY
/** @name std::string compatibility functions */
/// an 'invalid' value for string index
static const size_t npos;
//@{
/** @name constructors */
//@{
@ -470,7 +527,7 @@ public:
/// return the length of the string
size_t length() const { return Len(); }
/// return the maximum size of the string
size_t max_size() const { return STRING_MAXLEN; }
size_t max_size() const { return STRING_MAXLEN; }
/// resize the string, filling the space with c if c != 0
void resize(size_t nSize, char ch = '\0');
/// delete the contents of the string
@ -490,58 +547,58 @@ public:
/** @name append something to the end of this one */
//@{
/// append a string
wxString& append(const wxString& str)
wxString& append(const wxString& str)
{ *this += str; return *this; }
/// append elements str[pos], ..., str[pos+n]
wxString& append(const wxString& str, size_t pos, size_t n)
wxString& append(const wxString& str, size_t pos, size_t n)
{ ConcatSelf(n, str.c_str() + pos); return *this; }
/// append first n (or all if n == npos) characters of sz
wxString& append(const char *sz, size_t n = npos)
wxString& append(const char *sz, size_t n = npos)
{ ConcatSelf(n == npos ? Strlen(sz) : n, sz); return *this; }
/// append n copies of ch
wxString& append(size_t n, char ch) { return Pad(n, ch); }
//@}
/** @name replaces the contents of this string with another one */
//@{
/// same as `this_string = str'
wxString& assign(const wxString& str) { return (*this) = str; }
/// same as ` = str[pos..pos + n]
wxString& assign(const wxString& str, size_t pos, size_t n)
wxString& assign(const wxString& str, size_t pos, size_t n)
{ return *this = wxString((const char *)str + pos, n); }
/// same as `= first n (or all if n == npos) characters of sz'
wxString& assign(const char *sz, size_t n = npos)
wxString& assign(const char *sz, size_t n = npos)
{ return *this = wxString(sz, n); }
/// same as `= n copies of ch'
wxString& assign(size_t n, char ch)
wxString& assign(size_t n, char ch)
{ return *this = wxString(ch, n); }
//@}
/** @name inserts something at position nPos into this one */
/** @name inserts something at position nPos into this one */
//@{
/// insert another string
wxString& insert(size_t nPos, const wxString& str);
/// insert n chars of str starting at nStart (in str)
wxString& insert(size_t nPos, const wxString& str, size_t nStart, size_t n)
{ return insert(nPos, wxString((const char *)str + nStart, n)); }
{ return insert(nPos, wxString((const char *)str + nStart, n)); }
/// insert first n (or all if n == npos) characters of sz
wxString& insert(size_t nPos, const char *sz, size_t n = npos)
{ return insert(nPos, wxString(sz, n)); }
/// insert n copies of ch
wxString& insert(size_t nPos, size_t n, char ch)
wxString& insert(size_t nPos, size_t n, char ch)
{ return insert(nPos, wxString(ch, n)); }
//@}
/** @name deletes a part of the string */
//@{
/// delete characters from nStart to nStart + nLen
wxString& erase(size_t nStart = 0, size_t nLen = npos);
//@}
/** @name replaces a substring of this string with another one */
//@{
/// replaces the substring of length nLen starting at nStart
@ -549,14 +606,14 @@ public:
/// replaces the substring with nCount copies of ch
wxString& replace(size_t nStart, size_t nLen, size_t nCount, char ch);
/// replaces a substring with another substring
wxString& replace(size_t nStart, size_t nLen,
wxString& replace(size_t nStart, size_t nLen,
const wxString& str, size_t nStart2, size_t nLen2);
/// replaces the substring with first nCount chars of sz
wxString& replace(size_t nStart, size_t nLen,
wxString& replace(size_t nStart, size_t nLen,
const char* sz, size_t nCount);
//@}
//@}
/// swap two strings
void swap(wxString& str);
@ -564,14 +621,14 @@ public:
//@{
/** All find() functions take the nStart argument which specifies
the position to start the search on, the default value is 0.
All functions return npos if there were no match.
@name string search
@name string search
*/
//@{
/**
@name find a match for the string/character in this string
@name find a match for the string/character in this string
*/
//@{
/// find a substring
@ -585,12 +642,12 @@ public:
/// find the first occurence of character ch after nStart
size_t find(char ch, size_t nStart = 0) const;
// wxWin compatibility
inline bool Contains(const wxString& str) { return (Find(str) != -1); }
// wxWin compatibility
inline bool Contains(const wxString& str) { return Find(str) != -1; }
//@}
/**
/**
@name rfind() family is exactly like find() but works right to left
*/
//@{
@ -599,13 +656,13 @@ public:
/// as find, but from the end
// VC++ 1.5 can't cope with this syntax.
#if ! (defined(_MSC_VER) && !defined(__WIN32__))
size_t rfind(const char* sz, size_t nStart = npos,
size_t rfind(const char* sz, size_t nStart = npos,
size_t n = npos) const;
/// as find, but from the end
size_t rfind(char ch, size_t nStart = npos) const;
#endif
//@}
/**
@name find first/last occurence of any character in the set
*/
@ -616,7 +673,7 @@ public:
size_t find_first_of(const char* sz, size_t nStart = 0) const;
/// same as find(char, size_t)
size_t find_first_of(char c, size_t nStart = 0) const;
///
size_t find_last_of (const wxString& str, size_t nStart = npos) const;
///
@ -624,7 +681,7 @@ public:
/// same as rfind(char, size_t)
size_t find_last_of (char c, size_t nStart = npos) const;
//@}
/**
@name find first/last occurence of any character not in the set
*/
@ -635,7 +692,7 @@ public:
size_t find_first_not_of(const char* s, size_t nStart = 0) const;
///
size_t find_first_not_of(char ch, size_t nStart = 0) const;
///
size_t find_last_not_of(const wxString& str, size_t nStart=npos) const;
///
@ -644,11 +701,11 @@ public:
size_t find_last_not_of(char ch, size_t nStart = npos) const;
//@}
//@}
/**
All compare functions return -1, 0 or 1 if the [sub]string
/**
All compare functions return -1, 0 or 1 if the [sub]string
is less, equal or greater than the compare() argument.
@name comparison
*/
//@{
@ -668,13 +725,9 @@ public:
wxString substr(size_t nStart = 0, size_t nLen = npos) const;
//@}
#endif
protected:
// points to data preceded by wxStringData structure with ref count info
char *m_pchData;
// accessor to string data
wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; }
private:
// string (re)initialization functions
// initializes the string to the empty value (must be called only from
@ -683,7 +736,7 @@ protected:
// initializaes the string with (a part of) C-string
void InitWith(const char *psz, size_t nPos = 0, size_t nLen = STRING_MAXLEN);
// as Init, but also frees old data
inline void Reinit();
void Reinit() { GetStringData()->Unlock(); Init(); }
// memory allocation
// allocates memory for string of lenght nLen
@ -692,12 +745,12 @@ protected:
void AllocCopy(wxString&, int, int) const;
// effectively copies data to string
void AssignCopy(size_t, const char *);
// append a (sub)string
void ConcatCopy(int nLen1, const char *src1, int nLen2, const char *src2);
void ConcatSelf(int nLen, const char *src);
// functions called before writing to the string: they copy it if there
// functions called before writing to the string: they copy it if there
// other references (should be the only owner when writing)
void CopyBeforeWrite();
void AllocBeforeWrite(size_t);
@ -710,7 +763,7 @@ protected:
sizeof(char *)) we store these pointers instead. The cast to "String *"
is really all we need to turn such pointer into a string!
Of course, it can be called a dirty hack, but we use twice less memory
Of course, it can be called a dirty hack, but we use twice less memory
and this approach is also more speed efficient, so it's probably worth it.
Usage notes: when a string is added/inserted, a new copy of it is created,
@ -744,6 +797,8 @@ public:
void Clear();
/// preallocates memory for given number of items
void Alloc(size_t nCount);
/// minimzes the memory usage (by freeing all extra memory)
void Shrink();
//@}
/** @name simple accessors */
@ -805,7 +860,7 @@ private:
// Put back into class, since BC++ can't create precompiled header otherwise
// ---------------------------------------------------------------------------
/** @name wxString comparaison functions
/** @name wxString comparaison functions
@memo Comparaisons are case sensitive
*/
// ---------------------------------------------------------------------------
@ -848,7 +903,7 @@ inline bool operator>=(const char * s1, const wxString& s2) { return s2.Cmp(s1)
//@}
// ---------------------------------------------------------------------------
/** @name Global functions complementing standard C string library
/** @name Global functions complementing standard C string library
@memo replacements for strlen() and portable strcasecmp()
*/
// ---------------------------------------------------------------------------

View File

@ -6,7 +6,7 @@
// Created: 29/01/98
// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows license
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
@ -99,7 +99,7 @@ NAMESPACE istream& operator>>(NAMESPACE istream& is, wxString& WXUNUSED(str))
sb->sungetc();
break;
}
str += ch;
if ( --w == 1 )
break;
@ -174,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)
@ -186,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
@ -201,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);
}
@ -236,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;
@ -245,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()
{
@ -292,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);
@ -326,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 ) {
@ -396,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 )
@ -415,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)
@ -437,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
@ -657,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 ) {
@ -699,7 +673,7 @@ bool wxString::IsAscii() const
}
return(TRUE);
}
bool wxString::IsWord() const
{
const char *s = (const char*) *this;
@ -709,7 +683,7 @@ bool wxString::IsWord() const
}
return(TRUE);
}
bool wxString::IsNumber() const
{
const char *s = (const char*) *this;
@ -720,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;
@ -732,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
// ---------------------------------------------------------------------------
@ -776,7 +719,7 @@ wxString& wxString::MakeUpper()
wxString& wxString::MakeLower()
{
CopyBeforeWrite();
for ( char *p = m_pchData; *p; p++ )
*p = (char)tolower(*p);
@ -993,8 +936,8 @@ wxString& wxString::insert(size_t nPos, const wxString& 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
@ -1003,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();
}
@ -1014,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();
}
@ -1036,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
@ -1052,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
@ -1090,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;
}
@ -1100,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));
@ -1158,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;
@ -1217,7 +1160,7 @@ void wxArrayString::Clear()
{
Free();
m_nSize =
m_nSize =
m_nCount = 0;
DELETEA(m_pItems);
@ -1295,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();
@ -1312,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--;
}