X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5c69ef61f3ad09c0aef39915d4361a534f598520..86ac84b8ce086e6bbda58f422d41f84268606e35:/include/wx/buffer.h diff --git a/include/wx/buffer.h b/include/wx/buffer.h index e8de10a3c7..558874d5df 100644 --- a/include/wx/buffer.h +++ b/include/wx/buffer.h @@ -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; @@ -64,35 +65,71 @@ extern WXDLLIMPEXP_DATA_BASE(UntypedBufferData * const) untypedNullDataPtr; } // namespace wxPrivate + +// Reference-counted character buffer for storing string data. The buffer +// is only valid for as long as the "parent" object that provided the data +// is valid; see wxCharTypeBuffer for persistent variant. template -class wxCharTypeBuffer +class wxScopedCharTypeBuffer { public: typedef T CharType; - wxCharTypeBuffer(const CharType *str = NULL) + wxScopedCharTypeBuffer() { - if ( str ) - m_data = new Data(wxStrdup(str)); - else - m_data = GetNullData(); + m_data = GetNullData(); } - wxCharTypeBuffer(size_t len) + // 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, + size_t len = wxNO_LEN) { - m_data = new Data((CharType *)malloc((len + 1)*sizeof(CharType))); - m_data->Get()[len] = (CharType)0; + if ( len == wxNO_LEN ) + len = wxStrlen(str); + + wxScopedCharTypeBuffer buf; + if ( str ) + buf.m_data = new Data(const_cast(str), len, Data::NonOwned); + return buf; } - static const wxCharTypeBuffer CreateNonOwned(const CharType *str) + // 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, + size_t len = wxNO_LEN ) { - wxCharTypeBuffer buf; + if ( len == wxNO_LEN ) + len = wxStrlen(str); + + wxScopedCharTypeBuffer buf; if ( str ) - buf.m_data = new Data(const_cast(str), Data::NonOwned); + buf.m_data = new Data(StrCopy(str, len), len); return buf; } - ~wxCharTypeBuffer() + wxScopedCharTypeBuffer(const wxScopedCharTypeBuffer& src) + { + m_data = src.m_data; + IncRef(); + } + + wxScopedCharTypeBuffer& operator=(const wxScopedCharTypeBuffer& src) + { + if ( &src == this ) + return *this; + + DecRef(); + m_data = src.m_data; + IncRef(); + + return *this; + } + + ~wxScopedCharTypeBuffer() { DecRef(); } @@ -110,8 +147,8 @@ public: CharType * const p = m_data->Get(); - wxCharTypeBuffer *self = const_cast(this); - self->m_data->Set(NULL); + wxScopedCharTypeBuffer *self = const_cast(this); + self->m_data->Set(NULL, 0); self->DecRef(); return p; @@ -122,72 +159,28 @@ public: DecRef(); } - wxCharTypeBuffer(const wxCharTypeBuffer& src) - { - m_data = src.m_data; - IncRef(); - } - - wxCharTypeBuffer& operator=(const CharType *str) - { - DecRef(); - - if ( str ) - m_data = new Data(wxStrdup(str)); - return *this; - } - - wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src) - { - if ( &src == this ) - return *this; - - DecRef(); - m_data = src.m_data; - IncRef(); - - return *this; - } - - bool extend(size_t len) - { - wxASSERT_MSG( m_data->m_owned, _T("cannot extend non-owned buffer") ); - wxASSERT_MSG( m_data->m_ref == 1, _T("can't extend shared buffer") ); - - CharType *str = - (CharType *)realloc(data(), (len + 1) * sizeof(CharType)); - if ( !str ) - return false; - - if ( m_data == GetNullData() ) - { - m_data = new Data(str); - } - else - { - m_data->Set(str); - m_data->m_owned = true; - } - - return true; - } - CharType *data() { return m_data->Get(); } const CharType *data() const { return m_data->Get(); } operator const CharType *() const { return data(); } CharType operator[](size_t n) const { return data()[n]; } -private: + size_t length() const { return m_data->m_length; } + +protected: // reference-counted data struct Data : public wxPrivate::UntypedBufferData { - Data(CharType *str, Kind kind = Owned) - : UntypedBufferData(str, kind) + Data(CharType *str, size_t len, Kind kind = Owned) + : wxPrivate::UntypedBufferData(str, len, kind) { } CharType *Get() const { return static_cast(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 @@ -212,19 +205,157 @@ private: m_data = GetNullData(); } -private: + // sets this object to a be copy of 'other'; if 'src' is non-owned, + // a deep copy is made and 'this' will contain new instance of the data + void MakeOwnedCopyOf(const wxScopedCharTypeBuffer& src) + { + this->DecRef(); + + if ( src.m_data == this->GetNullData() ) + { + this->m_data = this->GetNullData(); + } + else if ( src.m_data->m_owned ) + { + this->m_data = src.m_data; + this->IncRef(); + } + else + { + // 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 + ( + 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; }; +typedef wxScopedCharTypeBuffer wxScopedCharBuffer; +typedef wxScopedCharTypeBuffer wxScopedWCharBuffer; + + +// this buffer class always stores data in "owned" (persistent) manner +template +class wxCharTypeBuffer : public wxScopedCharTypeBuffer +{ +protected: + typedef typename wxScopedCharTypeBuffer::Data Data; + +public: + typedef T CharType; + + wxCharTypeBuffer(const CharType *str = NULL, size_t len = wxNO_LEN) + { + if ( 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)), len); + this->m_data->Get()[len] = (CharType)0; + } + + wxCharTypeBuffer(const wxCharTypeBuffer& src) + : wxScopedCharTypeBuffer(src) {} + + wxCharTypeBuffer& operator=(const CharType *str) + { + this->DecRef(); + + if ( str ) + this->m_data = new Data(wxStrdup(str), wxStrlen(str)); + return *this; + } + + wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src) + { + wxScopedCharTypeBuffer::operator=(src); + return *this; + } + + wxCharTypeBuffer(const wxScopedCharTypeBuffer& src) + { + MakeOwnedCopyOf(src); + } + + wxCharTypeBuffer& operator=(const wxScopedCharTypeBuffer& src) + { + MakeOwnedCopyOf(src); + return *this; + } + + bool extend(size_t len) + { + wxASSERT_MSG( this->m_data->m_owned, "cannot extend non-owned buffer" ); + wxASSERT_MSG( this->m_data->m_ref == 1, "can't extend shared buffer" ); + + CharType *str = + (CharType *)realloc(this->data(), (len + 1) * sizeof(CharType)); + if ( !str ) + return false; + + if ( this->m_data == this->GetNullData() ) + { + this->m_data = new Data(str, len); + } + else + { + this->m_data->Set(str, len); + this->m_data->m_owned = true; + } + + return true; + } + + void shrink(size_t len) + { + wxASSERT_MSG( this->m_data->m_owned, "cannot shrink non-owned buffer" ); + wxASSERT_MSG( this->m_data->m_ref == 1, "can't shrink shared buffer" ); + + wxASSERT( len <= this->length() ); + + this->m_data->m_length = len; + this->data()[len] = 0; + } +}; + +WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxScopedCharTypeBuffer ) WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer ) class wxCharBuffer : public wxCharTypeBuffer { public: typedef wxCharTypeBuffer wxCharTypeBufferBase; + typedef wxScopedCharTypeBuffer wxScopedCharTypeBufferBase; wxCharBuffer(const wxCharTypeBufferBase& buf) : wxCharTypeBufferBase(buf) {} + wxCharBuffer(const wxScopedCharTypeBufferBase& buf) + : wxCharTypeBufferBase(buf) {} wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {} wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {} @@ -233,15 +364,19 @@ public: }; #if wxUSE_WCHAR_T +WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxScopedCharTypeBuffer ) WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer ) class wxWCharBuffer : public wxCharTypeBuffer { public: typedef wxCharTypeBuffer wxCharTypeBufferBase; + typedef wxScopedCharTypeBuffer wxScopedCharTypeBufferBase; wxWCharBuffer(const wxCharTypeBufferBase& buf) : wxCharTypeBufferBase(buf) {} + wxWCharBuffer(const wxScopedCharTypeBufferBase& buf) + : wxCharTypeBufferBase(buf) {} wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {} wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {} @@ -255,12 +390,14 @@ template class wxWritableCharTypeBuffer : public wxCharTypeBuffer { public: - typedef typename wxCharTypeBuffer::CharType CharType; + typedef typename wxScopedCharTypeBuffer::CharType CharType; - wxWritableCharTypeBuffer(const wxCharTypeBuffer& src) + wxWritableCharTypeBuffer(const wxScopedCharTypeBuffer& src) : wxCharTypeBuffer(src) {} // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to // always return a buffer + // + we should derive this class from wxScopedCharTypeBuffer + // then wxWritableCharTypeBuffer(const CharType *str = NULL) : wxCharTypeBuffer(str) {} @@ -292,13 +429,6 @@ typedef wxWritableCharTypeBuffer wxWritableWCharBuffer; #define wxWX2WCbuf wxWCharBuffer #endif // Unicode/ANSI -// type of the value returned by wxString::utf8_str() -#if wxUSE_UNICODE_UTF8 - #define wxUTF8Buf char * -#else - #define wxUTF8Buf wxCharBuffer -#endif - // ---------------------------------------------------------------------------- // A class for holding growable data buffers (not necessarily strings) // ---------------------------------------------------------------------------- @@ -357,7 +487,7 @@ private: // the reference count size_t m_ref; - DECLARE_NO_COPY_CLASS(wxMemoryBufferData) + wxDECLARE_NO_COPY_CLASS(wxMemoryBufferData); };