]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/string.h
add support for wxStrnlen for those platforms where it's available
[wxWidgets.git] / include / wx / string.h
index b66afd79ae384fa28d8111b058d6510ef696d17f..d1c3b6d783e0b880196933b5c3113107822dbaea 100644 (file)
@@ -987,7 +987,7 @@ public:
       iterator(wxString *str, underlying_iterator ptr)
           : m_cur(ptr), m_node(str, &m_cur) {}
 
-      wxString* str() const { return wx_const_cast(wxString*, m_node.m_str); }
+      wxString* str() const { return const_cast<wxString*>(m_node.m_str); }
 
       wxStringIteratorNode m_node;
 
@@ -1526,11 +1526,53 @@ public:
       { return at(n); }
 #endif // size_t != unsigned int
 
-    // explicit conversion to C string (use this with printf()!)
+
+    /*
+        Overview of wxString conversions, implicit and explicit:
+
+        - wxString has a std::[w]string-like c_str() method, however it does
+          not return a C-style string directly but instead returns wxCStrData
+          helper object which is convertible to either "char *" narrow string
+          or "wchar_t *" wide string. Usually the correct conversion will be
+          applied by the compiler automatically but if this doesn't happen you
+          need to explicitly choose one using wxCStrData::AsChar() or AsWChar()
+          methods or another wxString conversion function.
+
+        - One of the places where the conversion does *NOT* happen correctly is
+          when c_str() is passed to a vararg function such as printf() so you
+          must *NOT* use c_str() with them. Either use wxPrintf() (all wx
+          functions do handle c_str() correctly, even if they appear to be
+          vararg (but they're not, really)) or add an explicit AsChar() or, if
+          compatibility with previous wxWidgets versions is important, add a
+          cast to "const char *".
+
+        - In non-STL mode only, wxString is also implicitly convertible to
+          wxCStrData. The same warning as above applies.
+
+        - c_str() is polymorphic as it can be converted to either narrow or
+          wide string. If you explicitly need one or the other, choose to use
+          mb_str() (for narrow) or wc_str() (for wide) instead. Notice that
+          these functions can return either the pointer to string directly (if
+          this is what the string uses internally) or a temporary buffer
+          containing the string and convertible to it. Again, conversion will
+          usually be done automatically by the compiler but beware of the
+          vararg functions: you need an explicit cast when using them.
+
+        - There are also non-const versions of mb_str() and wc_str() called
+          char_str() and wchar_str(). They are only meant to be used with
+          non-const-correct functions and they always return buffers.
+
+        - Finally wx_str() returns whatever string representation is used by
+          wxString internally. It may be either a narrow or wide string
+          depending on wxWidgets build mode but it will always be a raw pointer
+          (and not a buffer).
+     */
+
+    // explicit conversion to wxCStrData
     wxCStrData c_str() const { return wxCStrData(this); }
     wxCStrData data() const { return c_str(); }
 
-    // implicit conversion to C string
+    // implicit conversion to wxCStrData
     operator wxCStrData() const { return c_str(); }
 
     // the first two operators conflict with operators for conversion to
@@ -2075,16 +2117,16 @@ public:
   wxString Left(size_t nCount) const;
       // get last nCount characters
   wxString Right(size_t nCount) const;
-      // get all characters before the first occurance of ch
+      // get all characters before the first occurrence of ch
       // (returns the whole string if ch not found)
   wxString BeforeFirst(wxUniChar ch) const;
-      // get all characters before the last occurence of ch
+      // get all characters before the last occurrence of ch
       // (returns empty string if ch not found)
   wxString BeforeLast(wxUniChar ch) const;
-      // get all characters after the first occurence of ch
+      // get all characters after the first occurrence of ch
       // (returns empty string if ch not found)
   wxString AfterFirst(wxUniChar ch) const;
-      // get all characters after the last occurence of ch
+      // get all characters after the last occurrence of ch
       // (returns the whole string if ch not found)
   wxString AfterLast(wxUniChar ch) const;
 
@@ -2149,7 +2191,7 @@ public:
   int Find(const wxWCharBuffer& sub) const
     { return Find(sub.data()); }
 
-      // replace first (or all of bReplaceAll) occurences of substring with
+      // replace first (or all of bReplaceAll) occurrences of substring with
       // another string, returns the number of replacements made
   size_t Replace(const wxString& strOld,
                  const wxString& strNew,
@@ -2972,7 +3014,7 @@ public:
   size_t find(const wxCStrData& s, size_t nStart = 0, size_t n = npos) const
     { return find(s.AsWChar(), nStart, n); }
 
-    // find the first occurence of character ch after nStart
+    // find the first occurrence of character ch after nStart
   size_t find(wxUniChar ch, size_t nStart = 0) const
   {
 #if wxUSE_UNICODE_UTF8
@@ -3038,7 +3080,7 @@ public:
   size_t rfind(wchar_t ch, size_t nStart = npos) const
     {  return rfind(wxUniChar(ch), nStart); }
 
-  // find first/last occurence of any character (not) in the set:
+  // find first/last occurrence of any character (not) in the set:
 #if wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
   // FIXME-UTF8: this is not entirely correct, because it doesn't work if
   //             sizeof(wchar_t)==2 and surrogates are present in the string;
@@ -3129,7 +3171,7 @@ public:
   size_t find_last_of(wxUniChar c, size_t nStart = npos) const
     { return rfind(c, nStart); }
 
-    // find first/last occurence of any character not in the set
+    // find first/last occurrence of any character not in the set
 
     // as strspn() (starting from nStart), returns npos on failure
   size_t find_first_not_of(const wxString& str, size_t nStart = 0) const
@@ -3563,7 +3605,7 @@ private:
 #endif // !wxUSE_STL_BASED_WXSTRING
 
 template<typename T>
-class WXDLLIMPEXP_BASE wxStringTypeBufferBase
+class wxStringTypeBufferBase
 {
 public:
     typedef T CharType;
@@ -3603,8 +3645,7 @@ protected:
 };
 
 template<typename T>
-class WXDLLIMPEXP_BASE wxStringTypeBufferLengthBase
-    : public wxStringTypeBufferBase<T>
+class wxStringTypeBufferLengthBase : public wxStringTypeBufferBase<T>
 {
 public:
     wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024)
@@ -3708,25 +3749,57 @@ typedef wxStringInternalBufferLength          wxUTF8StringBufferLength;
 
 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<char> )
 
-class WXDLLIMPEXP_BASE wxUTF8StringBuffer : public wxStringTypeBufferBase<char>
+// Note about inlined dtors in the classes below: this is done not for
+// performance reasons but just to avoid linking errors in the MSVC DLL build
+// under Windows: if a class has non-inline methods it must be declared as
+// being DLL-exported but, due to an extremely interesting feature of MSVC 7
+// and later, any template class which is used as a base of a DLL-exported
+// class is implicitly made DLL-exported too, as explained at the bottom of
+// http://msdn.microsoft.com/en-us/library/twa2aw10.aspx (just to confirm: yes,
+// _inheriting_ from a class can change whether it is being exported from DLL)
+//
+// But this results in link errors because the base template class is not DLL-
+// exported, whether it is declared with WXDLLIMPEXP_BASE or not, because it
+// does have only inline functions. So the simplest fix is to just make all the
+// functions of these classes inline too.
+
+class wxUTF8StringBuffer : public wxStringTypeBufferBase<char>
 {
 public:
     wxUTF8StringBuffer(wxString& str, size_t lenWanted = 1024)
         : wxStringTypeBufferBase<char>(str, lenWanted) {}
-    ~wxUTF8StringBuffer();
+    ~wxUTF8StringBuffer()
+    {
+        wxMBConvStrictUTF8 conv;
+        size_t wlen = conv.ToWChar(NULL, 0, m_buf);
+        wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
+
+        wxStringInternalBuffer wbuf(m_str, wlen);
+        conv.ToWChar(wbuf, wlen, m_buf);
+    }
 
     DECLARE_NO_COPY_CLASS(wxUTF8StringBuffer)
 };
 
 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferLengthBase<char> )
 
-class WXDLLIMPEXP_BASE wxUTF8StringBufferLength
-    : public wxStringTypeBufferLengthBase<char>
+class wxUTF8StringBufferLength : public wxStringTypeBufferLengthBase<char>
 {
 public:
     wxUTF8StringBufferLength(wxString& str, size_t lenWanted = 1024)
         : wxStringTypeBufferLengthBase<char>(str, lenWanted) {}
-    ~wxUTF8StringBufferLength();
+    ~wxUTF8StringBufferLength()
+    {
+        wxCHECK_RET(m_lenSet, "length not set");
+
+        wxMBConvStrictUTF8 conv;
+        size_t wlen = conv.ToWChar(NULL, 0, m_buf, m_len);
+        wxCHECK_RET( wlen != wxCONV_FAILED, "invalid UTF-8 data in string buffer?" );
+
+        wxStringInternalBufferLength wbuf(m_str, wlen);
+        conv.ToWChar(wbuf, wlen, m_buf, m_len);
+        wbuf.SetLength(wlen);
+    }
 
     DECLARE_NO_COPY_CLASS(wxUTF8StringBufferLength)
 };
@@ -3882,7 +3955,7 @@ inline wxCStrData::wxCStrData(const wxCStrData& data)
 inline wxCStrData::~wxCStrData()
 {
     if ( m_owned )
-        delete wx_const_cast(wxString*, m_str); // cast to silence warnings
+        delete const_cast<wxString*>(m_str); // cast to silence warnings
 }
 
 // simple cases for AsChar() and AsWChar(), the complicated ones are
@@ -4005,7 +4078,7 @@ void wxStringIteratorNode::DoSet(const wxString *str,
     if ( str )
     {
         m_next = str->m_iterators.ptr;
-        wx_const_cast(wxString*, m_str)->m_iterators.ptr = this;
+        const_cast<wxString*>(m_str)->m_iterators.ptr = this;
         if ( m_next )
             m_next->m_prev = this;
     }
@@ -4022,7 +4095,7 @@ void wxStringIteratorNode::clear()
     if ( m_prev )
         m_prev->m_next = m_next;
     else if ( m_str ) // first in the list
-        wx_const_cast(wxString*, m_str)->m_iterators.ptr = m_next;
+        const_cast<wxString*>(m_str)->m_iterators.ptr = m_next;
 
     m_next = m_prev = NULL;
     m_citer = NULL;