]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/string.h
fixed a missing backslash
[wxWidgets.git] / include / wx / string.h
index 2b65099b97ad0bc9eabe59df05564b66e3bb4a4d..e07f95d74d69bb5c7a02564cadf2b54afbf7be79 100644 (file)
@@ -6,14 +6,14 @@
 // 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__
 #define __WXSTRINGH__
 
 #ifdef __GNUG__
-#pragma interface
+#pragma interface "string.h"
 #endif
 
 /* Dependencies (should be included before this header):
 #include <stdio.h>
 #include <stdarg.h>
 #include <limits.h>
+#include <stdlib.h>
+
+#ifndef  WX_PRECOMP
+  #include "wx/defs.h"     // Robert Roebling
+  #ifdef    WXSTRING_IS_WXOBJECT
+    #include "wx/object.h"
+  #endif
+#endif
 
-#include "wx/defs.h"     // Robert Roebling
-#include "wx/object.h"
 #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.
   */
 //@{
@@ -42,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
@@ -62,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()
  */
 // ---------------------------------------------------------------------------
@@ -75,32 +81,69 @@ 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
+// ----------------------------------------------------------------------------
+
+// global pointer to empty string
+extern const char *g_szNul;
+
+// return an empty wxString
+class wxString; // not yet defined
+inline const wxString& wxGetEmptyString() { return *(wxString *)&g_szNul; }
 
 // ---------------------------------------------------------------------------
-// string data prepended with some housekeeping info (used by String class),
+// string data prepended with some housekeeping info (used by wxString class),
 // is never used directly (but had to be put here to allow inlining)
 // ---------------------------------------------------------------------------
 struct WXDLLEXPORT wxStringData
 {
   int     nRefs;        // reference count
-  size_t  nDataLength,  // actual string length
+  uint    nDataLength,  // actual string length
           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;   }
-  bool  IsValid()   const { return nRefs != 0;  }
 
   // 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);  }
 
-extern const char *g_szNul; // global pointer to empty string
+  // 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; }
+};
 
 // ---------------------------------------------------------------------------
 /**
@@ -113,9 +156,9 @@ extern const char *g_szNul; // global pointer to empty string
     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.
@@ -124,7 +167,7 @@ extern const char *g_szNul; // global pointer to empty string
       - 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
@@ -141,15 +184,24 @@ extern const char *g_szNul; // global pointer to empty string
 
 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)
@@ -163,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
@@ -180,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; }
@@ -192,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
@@ -206,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; }
     ///
@@ -226,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 */
     //@{
       ///
@@ -264,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
@@ -284,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
@@ -315,9 +382,9 @@ public:
       /// (returns the whole string if ch not found)
   wxString Right(char ch) const;
     //@}
-    
+
     /** @name case conversion */
-    //@{ 
+    //@{
       ///
   wxString& MakeUpper();
       ///
@@ -333,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)
@@ -347,6 +414,9 @@ public:
       */
   uint Replace(const char *szOld, const char *szNew, bool bReplaceAll = TRUE);
     //@}
+
+    /// check if the string contents matches a mask containing '*' and '?'
+  bool Matches(const char *szMask) const;
   //@}
 
   /** @name formated input/output */
@@ -355,14 +425,25 @@ public:
   int Printf(const char *pszFormat, ...);
     /// as vprintf(), returns the number of characters written or < 0 on error
   int PrintfV(const char* pszFormat, va_list argptr);
-    /// as sscanf()
-  int Scanf(const char *pszFormat, ...) const;
-    /// as vsscanf()
-  int ScanfV(const char *pszFormat, va_list argptr) const;
   //@}
-  
-  // get writable buffer of at least nLen characters
-  char *GetWriteBuf(size_t nLen);
+
+  /** @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.
+        Unget() *must* be called a.s.a.p. to put string back in a reasonable
+        state!
+     */
+  char *GetWriteBuf(uint nLen);
+    /// call this immediately after GetWriteBuf() has been used
+  void UngetWriteBuf();
+  //@}
 
   /** @name wxWindows compatibility functions */
   //@{
@@ -410,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); }
@@ -427,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 */
     //@{
@@ -446,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
@@ -466,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
@@ -525,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);
 
@@ -540,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
@@ -561,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
         */
         //@{
@@ -575,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
         */
@@ -592,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;
           ///
@@ -600,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
         */
@@ -611,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;
           ///
@@ -620,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
       */
       //@{
@@ -644,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
@@ -659,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
@@ -668,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);
@@ -686,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,
@@ -720,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 */
@@ -781,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
  */
 // ---------------------------------------------------------------------------
@@ -822,9 +901,9 @@ inline bool operator>=(const wxString& s1, const char  * s2) { return s1.Cmp(s2)
 ///
 inline bool operator>=(const char  * s1, const wxString& s2) { return s2.Cmp(s1) <= 0; }
 //@}
-    
+
 // ---------------------------------------------------------------------------
-/** @name Global functions complementing standard C string library 
+/** @name Global functions complementing standard C string library
     @memo replacements for strlen() and portable strcasecmp()
  */
 // ---------------------------------------------------------------------------