1 /////////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     auto buffer classes: buffers which automatically free memory 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  15 #include "wx/chartype.h" 
  16 #include "wx/wxcrtbase.h" 
  19 #include <stdlib.h>             // malloc() and free() 
  20 #endif // ! __WXPALMOS5__ 
  22 class WXDLLIMPEXP_FWD_BASE wxCStrData
; 
  24 // ---------------------------------------------------------------------------- 
  25 // Special classes for (wide) character strings: they use malloc/free instead 
  27 // ---------------------------------------------------------------------------- 
  29 // helpers used by wxCharTypeBuffer 
  33 struct UntypedBufferData
 
  41     UntypedBufferData(void *str
, size_t len
, Kind kind 
= Owned
) 
  42         : m_str(str
), m_length(len
), m_ref(1), m_owned(kind 
== Owned
) {} 
  53     // "short" to have sizeof(Data)=12 on 32bit archs 
  59 // NB: this is defined in string.cpp and not the (non-existent) buffer.cpp 
  60 WXDLLIMPEXP_BASE UntypedBufferData 
* GetUntypedNullData(); 
  62 } // namespace wxPrivate 
  65 // Reference-counted character buffer for storing string data. The buffer 
  66 // is only valid for as long as the "parent" object that provided the data 
  67 // is valid; see wxCharTypeBuffer<T> for persistent variant. 
  69 class wxScopedCharTypeBuffer
 
  74     wxScopedCharTypeBuffer() 
  76         m_data 
= GetNullData(); 
  79     // Creates "non-owned" buffer, i.e. 'str' is not owned by the buffer 
  80     // and doesn't get freed by dtor. Used e.g. to point to wxString's internal 
  83     const wxScopedCharTypeBuffer 
CreateNonOwned(const CharType 
*str
, 
  84                                                 size_t len 
= wxNO_LEN
) 
  86         if ( len 
== wxNO_LEN 
) 
  89         wxScopedCharTypeBuffer buf
; 
  91             buf
.m_data 
= new Data(const_cast<CharType
*>(str
), len
, Data::NonOwned
); 
  95     // Creates "owned" buffer, i.e. takes over ownership of 'str' and frees it 
  96     // in dtor (if ref.count reaches 0). 
  98     const wxScopedCharTypeBuffer 
CreateOwned(const CharType 
*str
, 
  99                                              size_t len 
= wxNO_LEN 
) 
 101         if ( len 
== wxNO_LEN 
) 
 104         wxScopedCharTypeBuffer buf
; 
 106             buf
.m_data 
= new Data(StrCopy(str
, len
), len
); 
 110     wxScopedCharTypeBuffer(const wxScopedCharTypeBuffer
& src
) 
 116     wxScopedCharTypeBuffer
& operator=(const wxScopedCharTypeBuffer
& src
) 
 128     ~wxScopedCharTypeBuffer() 
 133     // NB: this method is only const for backward compatibility. It used to 
 134     //     be needed for auto_ptr-like semantics of the copy ctor, but now 
 135     //     that ref-counting is used, it's not really needed. 
 136     CharType 
*release() const 
 138         if ( m_data 
== GetNullData() ) 
 141         wxASSERT_MSG( m_data
->m_owned
, wxT("can't release non-owned buffer") ); 
 142         wxASSERT_MSG( m_data
->m_ref 
== 1, wxT("can't release shared buffer") ); 
 144         CharType 
* const p 
= m_data
->Get(); 
 146         wxScopedCharTypeBuffer 
*self 
= const_cast<wxScopedCharTypeBuffer
*>(this); 
 147         self
->m_data
->Set(NULL
, 0); 
 158     CharType 
*data() { return m_data
->Get(); } 
 159     const CharType 
*data() const { return  m_data
->Get(); } 
 160     operator const CharType 
*() const { return data(); } 
 161     CharType 
operator[](size_t n
) const { return data()[n
]; } 
 163     size_t length() const { return m_data
->m_length
; } 
 166     // reference-counted data 
 167     struct Data 
: public wxPrivate::UntypedBufferData
 
 169         Data(CharType 
*str
, size_t len
, Kind kind 
= Owned
) 
 170             : wxPrivate::UntypedBufferData(str
, len
, kind
) 
 174         CharType 
*Get() const { return static_cast<CharType 
*>(m_str
); } 
 175         void Set(CharType 
*str
, size_t len
) 
 182     // placeholder for NULL string, to simplify this code 
 183     static Data 
*GetNullData() 
 185         return static_cast<Data 
*>(wxPrivate::GetUntypedNullData()); 
 190         if ( m_data 
== GetNullData() ) // exception, not ref-counted 
 197         if ( m_data 
== GetNullData() ) // exception, not ref-counted 
 199         if ( --m_data
->m_ref 
== 0 ) 
 201         m_data 
= GetNullData(); 
 204     // sets this object to a be copy of 'other'; if 'src' is non-owned, 
 205     // a deep copy is made and 'this' will contain new instance of the data 
 206     void MakeOwnedCopyOf(const wxScopedCharTypeBuffer
& src
) 
 210         if ( src
.m_data 
== this->GetNullData() ) 
 212             this->m_data 
= this->GetNullData(); 
 214         else if ( src
.m_data
->m_owned 
) 
 216             this->m_data 
= src
.m_data
; 
 221             // if the scoped buffer had non-owned data, we have to make 
 222             // a copy here, because src.m_data->m_str is valid only for as long 
 224             this->m_data 
= new Data
 
 226                                    StrCopy(src
.data(), src
.length()), 
 232     static CharType 
*StrCopy(const CharType 
*src
, size_t len
) 
 234         CharType 
*dst 
= (CharType
*)malloc(sizeof(CharType
) * (len 
+ 1)); 
 235         memcpy(dst
, src
, sizeof(CharType
) * (len 
+ 1)); 
 243 typedef wxScopedCharTypeBuffer
<char> wxScopedCharBuffer
; 
 244 typedef wxScopedCharTypeBuffer
<wchar_t> wxScopedWCharBuffer
; 
 247 // this buffer class always stores data in "owned" (persistent) manner 
 248 template <typename T
> 
 249 class wxCharTypeBuffer 
: public wxScopedCharTypeBuffer
<T
> 
 252     typedef typename wxScopedCharTypeBuffer
<T
>::Data Data
; 
 257     wxCharTypeBuffer(const CharType 
*str 
= NULL
, size_t len 
= wxNO_LEN
) 
 261             if ( len 
== wxNO_LEN 
) 
 263             this->m_data 
= new Data(StrCopy(str
, len
), len
); 
 267             this->m_data 
= this->GetNullData(); 
 271     wxCharTypeBuffer(size_t len
) 
 274             new Data((CharType 
*)malloc((len 
+ 1)*sizeof(CharType
)), len
); 
 275         this->m_data
->Get()[len
] = (CharType
)0; 
 278     wxCharTypeBuffer(const wxCharTypeBuffer
& src
) 
 279         : wxScopedCharTypeBuffer
<T
>(src
) {} 
 281     wxCharTypeBuffer
& operator=(const CharType 
*str
) 
 286             this->m_data 
= new Data(wxStrdup(str
), wxStrlen(str
)); 
 290     wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
) 
 292         wxScopedCharTypeBuffer
<T
>::operator=(src
); 
 296     wxCharTypeBuffer(const wxScopedCharTypeBuffer
<T
>& src
) 
 298         MakeOwnedCopyOf(src
); 
 301     wxCharTypeBuffer
& operator=(const wxScopedCharTypeBuffer
<T
>& src
) 
 303         MakeOwnedCopyOf(src
); 
 307     bool extend(size_t len
) 
 309         wxASSERT_MSG( this->m_data
->m_owned
, "cannot extend non-owned buffer" ); 
 310         wxASSERT_MSG( this->m_data
->m_ref 
== 1, "can't extend shared buffer" ); 
 313             (CharType 
*)realloc(this->data(), (len 
+ 1) * sizeof(CharType
)); 
 317         if ( this->m_data 
== this->GetNullData() ) 
 319             this->m_data 
= new Data(str
, len
); 
 323             this->m_data
->Set(str
, len
); 
 324             this->m_data
->m_owned 
= true; 
 330     void shrink(size_t len
) 
 332         wxASSERT_MSG( this->m_data
->m_owned
, "cannot shrink non-owned buffer" ); 
 333         wxASSERT_MSG( this->m_data
->m_ref 
== 1, "can't shrink shared buffer" ); 
 335         wxASSERT( len 
<= this->length() ); 
 337         this->m_data
->m_length 
= len
; 
 338         this->data()[len
] = 0; 
 342 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxScopedCharTypeBuffer
<char> ) 
 343 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> ) 
 345 class wxCharBuffer 
: public wxCharTypeBuffer
<char> 
 348     typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
; 
 349     typedef wxScopedCharTypeBuffer
<char> wxScopedCharTypeBufferBase
; 
 351     wxCharBuffer(const wxCharTypeBufferBase
& buf
) 
 352         : wxCharTypeBufferBase(buf
) {} 
 353     wxCharBuffer(const wxScopedCharTypeBufferBase
& buf
) 
 354         : wxCharTypeBufferBase(buf
) {} 
 356     wxCharBuffer(const CharType 
*str 
= NULL
) : wxCharTypeBufferBase(str
) {} 
 357     wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {} 
 359     wxCharBuffer(const wxCStrData
& cstr
); 
 363 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxScopedCharTypeBuffer
<wchar_t> ) 
 364 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> ) 
 366 class wxWCharBuffer 
: public wxCharTypeBuffer
<wchar_t> 
 369     typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
; 
 370     typedef wxScopedCharTypeBuffer
<wchar_t> wxScopedCharTypeBufferBase
; 
 372     wxWCharBuffer(const wxCharTypeBufferBase
& buf
) 
 373         : wxCharTypeBufferBase(buf
) {} 
 374     wxWCharBuffer(const wxScopedCharTypeBufferBase
& buf
) 
 375         : wxCharTypeBufferBase(buf
) {} 
 377     wxWCharBuffer(const CharType 
*str 
= NULL
) : wxCharTypeBufferBase(str
) {} 
 378     wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {} 
 380     wxWCharBuffer(const wxCStrData
& cstr
); 
 382 #endif // wxUSE_WCHAR_T 
 384 // wxCharTypeBuffer<T> implicitly convertible to T* 
 385 template <typename T
> 
 386 class wxWritableCharTypeBuffer 
: public wxCharTypeBuffer
<T
> 
 389     typedef typename wxScopedCharTypeBuffer
<T
>::CharType CharType
; 
 391     wxWritableCharTypeBuffer(const wxScopedCharTypeBuffer
<T
>& src
) 
 392         : wxCharTypeBuffer
<T
>(src
) {} 
 393     // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to 
 394     //             always return a buffer 
 395     //             + we should derive this class from wxScopedCharTypeBuffer 
 397     wxWritableCharTypeBuffer(const CharType 
*str 
= NULL
) 
 398         : wxCharTypeBuffer
<T
>(str
) {} 
 400     operator CharType
*() { return this->data(); } 
 403 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
; 
 404 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
; 
 408     #define wxWxCharBuffer wxWCharBuffer 
 410     #define wxMB2WXbuf wxWCharBuffer 
 411     #define wxWX2MBbuf wxCharBuffer 
 412     #if wxUSE_UNICODE_WCHAR 
 413         #define wxWC2WXbuf wxChar* 
 414         #define wxWX2WCbuf wxChar* 
 415     #elif wxUSE_UNICODE_UTF8 
 416         #define wxWC2WXbuf wxWCharBuffer 
 417         #define wxWX2WCbuf wxWCharBuffer 
 420     #define wxWxCharBuffer wxCharBuffer 
 422     #define wxMB2WXbuf wxChar* 
 423     #define wxWX2MBbuf wxChar* 
 424     #define wxWC2WXbuf wxCharBuffer 
 425     #define wxWX2WCbuf wxWCharBuffer 
 426 #endif // Unicode/ANSI 
 428 // ---------------------------------------------------------------------------- 
 429 // A class for holding growable data buffers (not necessarily strings) 
 430 // ---------------------------------------------------------------------------- 
 432 // This class manages the actual data buffer pointer and is ref-counted. 
 433 class wxMemoryBufferData
 
 436     // the initial size and also the size added by ResizeIfNeeded() 
 437     enum { DefBufSize 
= 1024 }; 
 439     friend class wxMemoryBuffer
; 
 441     // everyting is private as it can only be used by wxMemoryBuffer 
 443     wxMemoryBufferData(size_t size 
= wxMemoryBufferData::DefBufSize
) 
 444         : m_data(size 
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0) 
 447     ~wxMemoryBufferData() { free(m_data
); } 
 450     void ResizeIfNeeded(size_t newSize
) 
 452         if (newSize 
> m_size
) 
 454             void *dataOld 
= m_data
; 
 455             m_data 
= realloc(m_data
, newSize 
+ wxMemoryBufferData::DefBufSize
); 
 461             m_size 
= newSize 
+ wxMemoryBufferData::DefBufSize
; 
 465     void IncRef() { m_ref 
+= 1; } 
 469         if (m_ref 
== 0)  // are there no more references? 
 474     // the buffer containing the data 
 477     // the size of the buffer 
 480     // the amount of data currently in the buffer 
 483     // the reference count 
 486     wxDECLARE_NO_COPY_CLASS(wxMemoryBufferData
); 
 494     wxMemoryBuffer(size_t size 
= wxMemoryBufferData::DefBufSize
) 
 496         m_bufdata 
= new wxMemoryBufferData(size
); 
 500     ~wxMemoryBuffer() { m_bufdata
->DecRef(); } 
 503     // copy and assignment 
 504     wxMemoryBuffer(const wxMemoryBuffer
& src
) 
 505         : m_bufdata(src
.m_bufdata
) 
 510     wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
) 
 515             m_bufdata 
= src
.m_bufdata
; 
 523     void  *GetData() const    { return m_bufdata
->m_data
; } 
 524     size_t GetBufSize() const { return m_bufdata
->m_size
; } 
 525     size_t GetDataLen() const { return m_bufdata
->m_len
; } 
 527     void   SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); } 
 528     void   SetDataLen(size_t len
) 
 530         wxASSERT(len 
<= m_bufdata
->m_size
); 
 531         m_bufdata
->m_len 
= len
; 
 534     // Ensure the buffer is big enough and return a pointer to it 
 535     void *GetWriteBuf(size_t sizeNeeded
) 
 537         m_bufdata
->ResizeIfNeeded(sizeNeeded
); 
 538         return m_bufdata
->m_data
; 
 541     // Update the length after the write 
 542     void  UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); } 
 544     // Like the above, but appends to the buffer 
 545     void *GetAppendBuf(size_t sizeNeeded
) 
 547         m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len 
+ sizeNeeded
); 
 548         return (char*)m_bufdata
->m_data 
+ m_bufdata
->m_len
; 
 551     // Update the length after the append 
 552     void  UngetAppendBuf(size_t sizeUsed
) 
 554         SetDataLen(m_bufdata
->m_len 
+ sizeUsed
); 
 557     // Other ways to append to the buffer 
 558     void  AppendByte(char data
) 
 560         wxCHECK_RET( m_bufdata
->m_data
, wxT("invalid wxMemoryBuffer") ); 
 562         m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len 
+ 1); 
 563         *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
; 
 564         m_bufdata
->m_len 
+= 1; 
 567     void  AppendData(const void *data
, size_t len
) 
 569         memcpy(GetAppendBuf(len
), data
, len
); 
 573     operator const char *() const { return (const char*)GetData(); } 
 576     wxMemoryBufferData
*  m_bufdata
; 
 579 // ---------------------------------------------------------------------------- 
 580 // template class for any kind of data 
 581 // ---------------------------------------------------------------------------- 
 585 #endif // _WX_BUFFER_H