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:
parent
2ab889ff7b
commit
dd1eaa89dd
@ -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()
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -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--;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user