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:
@@ -26,11 +26,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/defs.h" // Robert Roebling
|
#include "wx/defs.h" // Robert Roebling
|
||||||
|
#ifdef WXSTRING_IS_WXOBJECT
|
||||||
#include "wx/object.h"
|
#include "wx/object.h"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "wx/debug.h"
|
#include "wx/debug.h"
|
||||||
|
|
||||||
@@ -78,7 +81,31 @@ inline size_t WXDLLEXPORT Strlen(const char *psz)
|
|||||||
{ return psz ? strlen(psz) : 0; }
|
{ return psz ? strlen(psz) : 0; }
|
||||||
|
|
||||||
/// portable strcasecmp/_stricmp
|
/// 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
|
// global data
|
||||||
@@ -110,7 +137,7 @@ struct WXDLLEXPORT wxStringData
|
|||||||
|
|
||||||
// lock/unlock
|
// lock/unlock
|
||||||
void Lock() { if ( !IsEmpty() ) nRefs++; }
|
void Lock() { if ( !IsEmpty() ) nRefs++; }
|
||||||
void Unlock() { if ( !IsEmpty() && --nRefs == 0) delete (char *)this; }
|
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
|
// intentionally put in invalid state
|
||||||
@@ -157,6 +184,15 @@ struct WXDLLEXPORT wxStringData
|
|||||||
|
|
||||||
friend class wxArrayString;
|
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:
|
public:
|
||||||
/** @name constructors & dtor */
|
/** @name constructors & dtor */
|
||||||
//@{
|
//@{
|
||||||
@@ -179,11 +215,19 @@ public:
|
|||||||
/** @name generic attributes & operations */
|
/** @name generic attributes & operations */
|
||||||
//@{
|
//@{
|
||||||
/// as standard strlen()
|
/// as standard strlen()
|
||||||
size_t Len() const { return GetStringData()->nDataLength; }
|
uint Len() const { return GetStringData()->nDataLength; }
|
||||||
/// string contains any characters?
|
/// string contains any characters?
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const { return Len() == 0; }
|
||||||
/// reinitialize string (and free data!)
|
/// 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
|
/// Is an ascii value
|
||||||
bool IsAscii() const;
|
bool IsAscii() const;
|
||||||
/// Is a number
|
/// Is a number
|
||||||
@@ -248,22 +292,29 @@ public:
|
|||||||
/** @name in place concatenation */
|
/** @name in place concatenation */
|
||||||
//@{
|
//@{
|
||||||
/// string += string
|
/// string += string
|
||||||
void operator+=(const wxString& string);
|
void operator+=(const wxString& s) { (void)operator<<(s); }
|
||||||
/// string += C string
|
/// string += C string
|
||||||
void operator+=(const char *psz);
|
void operator+=(const char *psz) { (void)operator<<(psz); }
|
||||||
/// string += char
|
/// string += char
|
||||||
void operator+=(char ch);
|
void operator+=(char ch) { (void)operator<<(ch); }
|
||||||
//@}
|
//@}
|
||||||
/** @name concatenate and return the result
|
/** @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 << ..." */
|
things like "str << str1 << str2 << ..." */
|
||||||
//@{
|
//@{
|
||||||
/// as +=
|
/// as +=
|
||||||
wxString& operator<<(const wxString& string);
|
wxString& operator<<(const wxString& s)
|
||||||
|
{
|
||||||
|
wxASSERT( s.GetStringData()->IsValid() );
|
||||||
|
|
||||||
|
ConcatSelf(s.Len(), s);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
/// as +=
|
/// as +=
|
||||||
wxString& operator<<(char ch);
|
wxString& operator<<(const char *psz)
|
||||||
|
{ ConcatSelf(Strlen(psz), psz); return *this; }
|
||||||
/// as +=
|
/// as +=
|
||||||
wxString& operator<<(const char *psz);
|
wxString& operator<<(char ch) { ConcatSelf(1, &ch); return *this; }
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/** @name return resulting string */
|
/** @name return resulting string */
|
||||||
@@ -378,12 +429,18 @@ public:
|
|||||||
|
|
||||||
/** @name raw access to string memory */
|
/** @name raw access to string memory */
|
||||||
//@{
|
//@{
|
||||||
|
/// 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.
|
get writable buffer of at least nLen bytes.
|
||||||
Unget() *must* be called a.s.a.p. to put string back in a reasonable
|
Unget() *must* be called a.s.a.p. to put string back in a reasonable
|
||||||
state!
|
state!
|
||||||
*/
|
*/
|
||||||
char *GetWriteBuf(int nLen);
|
char *GetWriteBuf(uint nLen);
|
||||||
/// call this immediately after GetWriteBuf() has been used
|
/// call this immediately after GetWriteBuf() has been used
|
||||||
void UngetWriteBuf();
|
void UngetWriteBuf();
|
||||||
//@}
|
//@}
|
||||||
@@ -586,7 +643,7 @@ public:
|
|||||||
size_t find(char ch, size_t nStart = 0) const;
|
size_t find(char ch, size_t nStart = 0) const;
|
||||||
|
|
||||||
// wxWin compatibility
|
// wxWin compatibility
|
||||||
inline bool Contains(const wxString& str) { return (Find(str) != -1); }
|
inline bool Contains(const wxString& str) { return Find(str) != -1; }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
@@ -669,12 +726,8 @@ public:
|
|||||||
//@}
|
//@}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
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; }
|
|
||||||
|
|
||||||
// string (re)initialization functions
|
// string (re)initialization functions
|
||||||
// initializes the string to the empty value (must be called only from
|
// 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
|
// initializaes the string with (a part of) C-string
|
||||||
void InitWith(const char *psz, size_t nPos = 0, size_t nLen = STRING_MAXLEN);
|
void InitWith(const char *psz, size_t nPos = 0, size_t nLen = STRING_MAXLEN);
|
||||||
// as Init, but also frees old data
|
// as Init, but also frees old data
|
||||||
inline void Reinit();
|
void Reinit() { GetStringData()->Unlock(); Init(); }
|
||||||
|
|
||||||
// memory allocation
|
// memory allocation
|
||||||
// allocates memory for string of lenght nLen
|
// allocates memory for string of lenght nLen
|
||||||
@@ -744,6 +797,8 @@ public:
|
|||||||
void Clear();
|
void Clear();
|
||||||
/// preallocates memory for given number of items
|
/// preallocates memory for given number of items
|
||||||
void Alloc(size_t nCount);
|
void Alloc(size_t nCount);
|
||||||
|
/// minimzes the memory usage (by freeing all extra memory)
|
||||||
|
void Shrink();
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/** @name simple accessors */
|
/** @name simple accessors */
|
||||||
|
@@ -236,8 +236,8 @@ void wxString::AllocBuffer(size_t nLen)
|
|||||||
// allocate memory:
|
// allocate memory:
|
||||||
// 1) one extra character for '\0' termination
|
// 1) one extra character for '\0' termination
|
||||||
// 2) sizeof(wxStringData) for housekeeping info
|
// 2) sizeof(wxStringData) for housekeeping info
|
||||||
wxStringData* pData = (wxStringData*)new char[sizeof(wxStringData) +
|
wxStringData* pData = (wxStringData*)malloc(sizeof(wxStringData) +
|
||||||
(nLen + 1)*sizeof(char)];
|
(nLen + 1)*sizeof(char));
|
||||||
pData->nRefs = 1;
|
pData->nRefs = 1;
|
||||||
pData->data()[nLen] = '\0';
|
pData->data()[nLen] = '\0';
|
||||||
pData->nDataLength = nLen;
|
pData->nDataLength = nLen;
|
||||||
@@ -245,23 +245,6 @@ void wxString::AllocBuffer(size_t nLen)
|
|||||||
m_pchData = pData->data(); // data starts after wxStringData
|
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
|
// must be called before changing this string
|
||||||
void wxString::CopyBeforeWrite()
|
void wxString::CopyBeforeWrite()
|
||||||
{
|
{
|
||||||
@@ -292,8 +275,44 @@ void wxString::AllocBeforeWrite(size_t nLen)
|
|||||||
wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner
|
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
|
// get the pointer to writable buffer of (at least) nLen bytes
|
||||||
char *wxString::GetWriteBuf(int nLen)
|
char *wxString::GetWriteBuf(uint nLen)
|
||||||
{
|
{
|
||||||
AllocBeforeWrite(nLen);
|
AllocBeforeWrite(nLen);
|
||||||
|
|
||||||
@@ -436,51 +455,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:
|
* concatenation functions come in 5 flavours:
|
||||||
* string + string
|
* string + string
|
||||||
@@ -720,10 +694,6 @@ bool wxString::IsNumber() const
|
|||||||
return(TRUE);
|
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 wxString::Strip(stripType w) const
|
||||||
{
|
{
|
||||||
wxString s = *this;
|
wxString s = *this;
|
||||||
@@ -732,33 +702,6 @@ wxString wxString::Strip(stripType w) const
|
|||||||
return s;
|
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
|
// case conversion
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -1158,7 +1101,7 @@ wxArrayString& wxArrayString::operator=(const wxArrayString& src)
|
|||||||
m_nCount = src.m_nCount;
|
m_nCount = src.m_nCount;
|
||||||
|
|
||||||
if ( m_nSize != 0 )
|
if ( m_nSize != 0 )
|
||||||
m_pItems = new char *[m_nSize];
|
m_pItems = new char *[m_nCount];
|
||||||
else
|
else
|
||||||
m_pItems = NULL;
|
m_pItems = NULL;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user