]> git.saurik.com Git - wxWidgets.git/commitdiff
added length to wx(Scoped)CharBuffer to improve handling of embedded NULs
authorVáclav Slavík <vslavik@fastmail.fm>
Sun, 29 Mar 2009 20:58:39 +0000 (20:58 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Sun, 29 Mar 2009 20:58:39 +0000 (20:58 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59927 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/buffer.h
include/wx/defs.h
include/wx/strconv.h
include/wx/string.h
interface/wx/buffer.h
src/common/fileconf.cpp
src/common/string.cpp

index 3be01fee36b5821c0fcab3347dfe843ec4564176..66450e77f701c5b50ff6e655d643e6794187c494 100644 (file)
@@ -38,8 +38,8 @@ struct UntypedBufferData
         NonOwned
     };
 
-    UntypedBufferData(void *str, Kind kind = Owned)
-        : m_str(str), m_ref(1), m_owned(kind == Owned) {}
+    UntypedBufferData(void *str, size_t len, Kind kind = Owned)
+        : m_str(str), m_length(len), m_ref(1), m_owned(kind == Owned) {}
 
     ~UntypedBufferData()
     {
@@ -48,8 +48,9 @@ struct UntypedBufferData
     }
 
     void *m_str;
+    size_t m_length;
 
-    // "short" to have sizeof(Data)=8 on 32bit archs
+    // "short" to have sizeof(Data)=12 on 32bit archs
     unsigned short m_ref;
 
     bool m_owned;
@@ -82,21 +83,31 @@ public:
     // Creates "non-owned" buffer, i.e. 'str' is not owned by the buffer
     // and doesn't get freed by dtor. Used e.g. to point to wxString's internal
     // storage.
-    static const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str)
+    static
+    const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str,
+                                                size_t len = wxNO_LEN)
     {
+        if ( len == wxNO_LEN )
+            len = wxStrlen(str);
+
         wxScopedCharTypeBuffer buf;
         if ( str )
-            buf.m_data = new Data(const_cast<CharType*>(str), Data::NonOwned);
+            buf.m_data = new Data(const_cast<CharType*>(str), len, Data::NonOwned);
         return buf;
     }
 
     // Creates "owned" buffer, i.e. takes over ownership of 'str' and frees it
     // in dtor (if ref.count reaches 0).
-    static const wxScopedCharTypeBuffer CreateOwned(const CharType *str)
+    static
+    const wxScopedCharTypeBuffer CreateOwned(const CharType *str,
+                                             size_t len = wxNO_LEN )
     {
+        if ( len == wxNO_LEN )
+            len = wxStrlen(str);
+
         wxScopedCharTypeBuffer buf;
         if ( str )
-            buf.m_data = new Data(wxStrdup(str));
+            buf.m_data = new Data(StrCopy(str, len), len);
         return buf;
     }
 
@@ -137,7 +148,7 @@ public:
         CharType * const p = m_data->Get();
 
         wxScopedCharTypeBuffer *self = const_cast<wxScopedCharTypeBuffer*>(this);
-        self->m_data->Set(NULL);
+        self->m_data->Set(NULL, 0);
         self->DecRef();
 
         return p;
@@ -153,17 +164,23 @@ public:
     operator const CharType *() const { return data(); }
     CharType operator[](size_t n) const { return data()[n]; }
 
+    size_t length() const { return m_data->m_length; }
+
 protected:
     // reference-counted data
     struct Data : public wxPrivate::UntypedBufferData
     {
-        Data(CharType *str, Kind kind = Owned)
-            : wxPrivate::UntypedBufferData(str, kind)
+        Data(CharType *str, size_t len, Kind kind = Owned)
+            : wxPrivate::UntypedBufferData(str, len, kind)
         {
         }
 
         CharType *Get() const { return static_cast<CharType *>(m_str); }
-        void Set(CharType *str) { m_str = str; }
+        void Set(CharType *str, size_t len)
+        {
+            m_str = str;
+            m_length = len;
+        }
     };
 
     // placeholder for NULL string, to simplify this code
@@ -208,10 +225,21 @@ protected:
             // if the scoped buffer had non-owned data, we have to make
             // a copy here, because src.m_data->m_str is valid only for as long
             // as 'src' exists
-            this->m_data = new Data(wxStrdup(src.m_data->Get()));
+            this->m_data = new Data
+                               (
+                                   StrCopy(src.data(), src.length()),
+                                   src.length()
+                               );
         }
     }
 
+    static CharType *StrCopy(const CharType *src, size_t len)
+    {
+        CharType *dst = (CharType*)malloc(sizeof(CharType) * (len + 1));
+        memcpy(dst, src, sizeof(CharType) * (len + 1));
+        return dst;
+    }
+
 protected:
     Data *m_data;
 };
@@ -230,17 +258,24 @@ protected:
 public:
     typedef T CharType;
 
-    wxCharTypeBuffer(const CharType *str = NULL)
+    wxCharTypeBuffer(const CharType *str = NULL, size_t len = wxNO_LEN)
     {
         if ( str )
-            this->m_data = new Data(wxStrdup(str));
+        {
+            if ( len == wxNO_LEN )
+                len = wxStrlen(str);
+            this->m_data = new Data(StrCopy(str, len), len);
+        }
         else
+        {
             this->m_data = this->GetNullData();
+        }
     }
 
     wxCharTypeBuffer(size_t len)
     {
-        this->m_data = new Data((CharType *)malloc((len + 1)*sizeof(CharType)));
+        this->m_data =
+            new Data((CharType *)malloc((len + 1)*sizeof(CharType)), len);
         this->m_data->Get()[len] = (CharType)0;
     }
 
@@ -252,7 +287,7 @@ public:
         this->DecRef();
 
         if ( str )
-            this->m_data = new Data(wxStrdup(str));
+            this->m_data = new Data(wxStrdup(str), wxStrlen(str));
         return *this;
     }
 
@@ -285,11 +320,11 @@ public:
 
         if ( this->m_data == this->GetNullData() )
         {
-            this->m_data = new Data(str);
+            this->m_data = new Data(str, len);
         }
         else
         {
-            this->m_data->Set(str);
+            this->m_data->Set(str, len);
             this->m_data->m_owned = true;
         }
 
index 69212fd8b06b839f5b6132fcf76264088d607e68..f4c9bea0c7563c6eb9c4e80b756d77922669527c 100644 (file)
@@ -596,6 +596,10 @@ typedef short int WXTYPE;
 /*  integer on success as failure indicator */
 #define wxNOT_FOUND       (-1)
 
+/* the default value for some length parameters meaning that the string is */
+/* NUL-terminated */
+#define wxNO_LEN ((size_t)-1)
+
 /*  ---------------------------------------------------------------------------- */
 /*  macros dealing with comparison operators */
 /*  ---------------------------------------------------------------------------- */
index cf538d1491ee437533c452d0f77966fa3ec30589..0061aa770c524c6a0a70689ba21d3d0686bd0eed 100644 (file)
@@ -36,10 +36,6 @@ class WXDLLIMPEXP_FWD_BASE wxString;
 // the error value returned by wxMBConv methods
 #define wxCONV_FAILED ((size_t)-1)
 
-// the default value for some length parameters meaning that the string is
-// NUL-terminated
-#define wxNO_LEN ((size_t)-1)
-
 // ----------------------------------------------------------------------------
 // wxMBConv (abstract base class for conversions)
 // ----------------------------------------------------------------------------
index ebd2f0f774e71561ccf5be68c27edc82c9538aa0..414cfd087f93b10fa2f9758e1a69c1a4b0301fe7 100644 (file)
@@ -1637,7 +1637,7 @@ public:
         if ( len )
             *len = length();
 
-        return wxCharTypeBuffer<T>::CreateNonOwned(wx_str());
+        return wxCharTypeBuffer<T>::CreateNonOwned(wx_str(), length());
 #endif // Unicode build kind
     }
 
@@ -3540,9 +3540,10 @@ struct wxStringAsBufHelper<wchar_t>
 {
     static wxScopedWCharBuffer Get(const wxString& s, size_t *len)
     {
+        const size_t length = s.length();
         if ( len )
-            *len = s.length();
-        return wxScopedWCharBuffer::CreateNonOwned(s.wx_str());
+            *len = length;
+        return wxScopedWCharBuffer::CreateNonOwned(s.wx_str(), length);
     }
 };
 
@@ -3553,9 +3554,10 @@ struct wxStringAsBufHelper<char>
 {
     static wxScopedCharBuffer Get(const wxString& s, size_t *len)
     {
+        const size_t length = s.utf8_length();
         if ( len )
-            *len = s.utf8_length();
-        return wxScopedCharBuffer::CreateNonOwned(s.wx_str());
+            *len = length;
+        return wxScopedCharBuffer::CreateNonOwned(s.wx_str(), length);
     }
 };
 
index bb14bb1ab26dcfeb3ee1d20fd8222d962caf7317..3d5287b6c7270730e13ade1ffe04a03162ec5ca3 100644 (file)
@@ -57,16 +57,24 @@ public:
 
         The buffer's destructor will not destroy @a str. The returned buffer's
         data is valid only as long as @a str is valid.
+
+        @param str String data.
+        @param len If specified, length of the string, otherwise the string
+                   is considered to be NUL-terminated.
      */
-    static const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str);
+    static const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str, size_t len = wxNO_LEN);
 
     /**
         Creates owned buffer from @a str and takes ownership of it.
 
         The buffer's destructor will free @a str when its reference count
         reaches zero (initial count is 1).
+
+        @param str String data.
+        @param len If specified, length of the string, otherwise the string
+                   is considered to be NUL-terminated.
      */
-    static const wxScopedCharTypeBuffer CreateOwned(const CharType *str);
+    static const wxScopedCharTypeBuffer CreateOwned(const CharType *str, size_t len = wxNO_LEN);
 
     /**
         Copy constructor.
@@ -94,6 +102,9 @@ public:
     /// Returns const pointer to the stored data.
     const CharType *data() const;
 
+    /// Returns length of the string stored.
+    size_t length() const;
+
     /// Implicit conversion to C string.
     operator const CharType *() const;
 
@@ -133,9 +144,13 @@ public:
     /**
         Creates (owned) buffer from @a str and takes ownership of it.
 
+        @param str String data.
+        @param len If specified, length of the string, otherwise the string
+                   is considered to be NUL-terminated.
+
         @see wxScopedCharTypeBuffer<T>::CreateOwned()
      */
-    wxCharTypeBuffer(const CharType *str = NULL);
+    wxCharTypeBuffer(const CharType *str = NULL, size_t len = wxNO_LEN);
 
 
     /**
index 69df300ba2639319b675c1637f91a6edc3d05bba..e3b61cf806258d78fdef0c163f0b6a6e77a711b1 100644 (file)
@@ -471,7 +471,7 @@ wxFileConfig::wxFileConfig(wxInputStream &inStream, const wxMBConv& conv)
     }
 #else // !wxUSE_UNICODE
     // no need for conversion
-    cbuf = wxCharBuffer::CreateNonOwned((char *)buf.GetData());
+    cbuf = wxCharBuffer::CreateNonOwned((char *)buf.GetData(), buf.GetDataLen());
 #endif // wxUSE_UNICODE/!wxUSE_UNICODE
 
 
index 960b6d2d35f2ea044e75c6c4dfe9eab0b88788cd..b66d5bbeb0a29537fe554cb35a635c8113430685 100644 (file)
@@ -59,7 +59,7 @@
 namespace wxPrivate
 {
 
-static UntypedBufferData s_untypedNullData(NULL);
+static UntypedBufferData s_untypedNullData(NULL, 0);
 
 UntypedBufferData * const untypedNullDataPtr = &s_untypedNullData;
 
@@ -499,7 +499,8 @@ wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
             // we must pass the real string length to SubstrBufFromMB ctor
             if ( nLength == npos )
                 nLength = psz ? strlen(psz) : 0;
-            return SubstrBufFromMB(wxCharBuffer::CreateNonOwned(psz), nLength);
+            return SubstrBufFromMB(wxCharBuffer::CreateNonOwned(psz, nLength),
+                                   nLength);
         }
         // else: do the roundtrip through wchar_t*
     }
@@ -567,7 +568,7 @@ const wxScopedWCharBuffer wxString::wc_str() const
 const wxScopedCharBuffer wxString::mb_str(const wxMBConv& conv) const
 {
     if ( conv.IsUTF8() )
-        return wxScopedCharBuffer::CreateNonOwned(m_impl.c_str());
+        return wxScopedCharBuffer::CreateNonOwned(m_impl.c_str(), m_impl.length());
 
     // FIXME-UTF8: use wc_str() here once we have buffers with length