]> git.saurik.com Git - wxWidgets.git/commitdiff
optimizations: more functions made inline, added Alloc()/Shrink() function for
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 15 Jul 1998 17:10:23 +0000 (17:10 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 15 Jul 1998 17:10:23 +0000 (17:10 +0000)
more precise control over string's memory

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@275 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/string.h
src/common/string.cpp

index 1145fffbf453b0644dcc621a367ee3a73cd30c1d..e07f95d74d69bb5c7a02564cadf2b54afbf7be79 100644 (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__
 #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()
  */
 // ---------------------------------------------------------------------------
index 3031ae6dafe7ccde81f696a18e5b88d89a8285dc..bb02779aee932d74d9adbe243a52801147348506 100644 (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--;
 }