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
, Kind kind
= Owned
)
42 : m_str(str
), m_ref(1), m_owned(kind
== Owned
) {}
52 // "short" to have sizeof(Data)=8 on 32bit archs
58 // this has to be defined inside the DLL (and not e.g. as a static variable
59 // inside an inline function) as otherwise MSVC gives link errors when the
60 // functions are effectively inlined (i.e. in non-debug build)
62 // NB: this is defined in string.cpp and not the (non-existent) buffer.cpp
63 extern WXDLLIMPEXP_DATA_BASE(UntypedBufferData
* const) untypedNullDataPtr
;
65 } // namespace wxPrivate
68 class wxCharTypeBuffer
73 wxCharTypeBuffer(const CharType
*str
= NULL
)
76 m_data
= new Data(wxStrdup(str
));
78 m_data
= GetNullData();
81 wxCharTypeBuffer(size_t len
)
83 m_data
= new Data((CharType
*)malloc((len
+ 1)*sizeof(CharType
)));
84 m_data
->Get()[len
] = (CharType
)0;
87 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
91 buf
.m_data
= new Data(const_cast<CharType
*>(str
), Data::NonOwned
);
100 // NB: this method is only const for backward compatibility. It used to
101 // be needed for auto_ptr-like semantics of the copy ctor, but now
102 // that ref-counting is used, it's not really needed.
103 CharType
*release() const
105 if ( m_data
== GetNullData() )
108 wxASSERT_MSG( m_data
->m_owned
, _T("can't release non-owned buffer") );
109 wxASSERT_MSG( m_data
->m_ref
== 1, _T("can't release shared buffer") );
111 CharType
* const p
= m_data
->Get();
113 wxCharTypeBuffer
*self
= const_cast<wxCharTypeBuffer
*>(this);
114 self
->m_data
->Set(NULL
);
125 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
131 wxCharTypeBuffer
& operator=(const CharType
*str
)
136 m_data
= new Data(wxStrdup(str
));
140 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
152 bool extend(size_t len
)
154 wxASSERT_MSG( m_data
->m_owned
, _T("cannot extend non-owned buffer") );
155 wxASSERT_MSG( m_data
->m_ref
== 1, _T("can't extend shared buffer") );
158 (CharType
*)realloc(data(), (len
+ 1) * sizeof(CharType
));
162 if ( m_data
== GetNullData() )
164 m_data
= new Data(str
);
169 m_data
->m_owned
= true;
175 CharType
*data() { return m_data
->Get(); }
176 const CharType
*data() const { return m_data
->Get(); }
177 operator const CharType
*() const { return data(); }
178 CharType
operator[](size_t n
) const { return data()[n
]; }
181 // reference-counted data
182 struct Data
: wxPrivate::UntypedBufferData
184 Data(CharType
*str
, Kind kind
= Owned
)
185 : UntypedBufferData(str
, kind
)
189 CharType
*Get() const { return static_cast<CharType
*>(m_str
); }
190 void Set(CharType
*str
) { m_str
= str
; }
193 // placeholder for NULL string, to simplify this code
194 static Data
*GetNullData()
196 return static_cast<Data
*>(wxPrivate::untypedNullDataPtr
);
201 if ( m_data
== GetNullData() ) // exception, not ref-counted
208 if ( m_data
== GetNullData() ) // exception, not ref-counted
210 if ( --m_data
->m_ref
== 0 )
212 m_data
= GetNullData();
219 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
221 class wxCharBuffer
: public wxCharTypeBuffer
<char>
224 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
226 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
227 : wxCharTypeBufferBase(buf
) {}
229 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
230 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
232 wxCharBuffer(const wxCStrData
& cstr
);
236 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
238 class wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
241 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
243 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
244 : wxCharTypeBufferBase(buf
) {}
246 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
247 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
249 wxWCharBuffer(const wxCStrData
& cstr
);
251 #endif // wxUSE_WCHAR_T
253 // wxCharTypeBuffer<T> implicitly convertible to T*
254 template <typename T
>
255 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
258 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
260 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
261 : wxCharTypeBuffer
<T
>(src
) {}
262 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
263 // always return a buffer
264 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
265 : wxCharTypeBuffer
<T
>(str
) {}
267 operator CharType
*() { return this->data(); }
270 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
271 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
275 #define wxWxCharBuffer wxWCharBuffer
277 #define wxMB2WXbuf wxWCharBuffer
278 #define wxWX2MBbuf wxCharBuffer
279 #if wxUSE_UNICODE_WCHAR
280 #define wxWC2WXbuf wxChar*
281 #define wxWX2WCbuf wxChar*
282 #elif wxUSE_UNICODE_UTF8
283 #define wxWC2WXbuf wxWCharBuffer
284 #define wxWX2WCbuf wxWCharBuffer
287 #define wxWxCharBuffer wxCharBuffer
289 #define wxMB2WXbuf wxChar*
290 #define wxWX2MBbuf wxChar*
291 #define wxWC2WXbuf wxCharBuffer
292 #define wxWX2WCbuf wxWCharBuffer
293 #endif // Unicode/ANSI
295 // type of the value returned by wxString::utf8_str()
296 #if wxUSE_UNICODE_UTF8
297 #define wxUTF8Buf char *
299 #define wxUTF8Buf wxCharBuffer
302 // ----------------------------------------------------------------------------
303 // A class for holding growable data buffers (not necessarily strings)
304 // ----------------------------------------------------------------------------
306 // This class manages the actual data buffer pointer and is ref-counted.
307 class wxMemoryBufferData
310 // the initial size and also the size added by ResizeIfNeeded()
311 enum { DefBufSize
= 1024 };
313 friend class wxMemoryBuffer
;
315 // everyting is private as it can only be used by wxMemoryBuffer
317 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
318 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
321 ~wxMemoryBufferData() { free(m_data
); }
324 void ResizeIfNeeded(size_t newSize
)
326 if (newSize
> m_size
)
328 void *dataOld
= m_data
;
329 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
335 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
339 void IncRef() { m_ref
+= 1; }
343 if (m_ref
== 0) // are there no more references?
348 // the buffer containing the data
351 // the size of the buffer
354 // the amount of data currently in the buffer
357 // the reference count
360 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
368 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
370 m_bufdata
= new wxMemoryBufferData(size
);
374 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
377 // copy and assignment
378 wxMemoryBuffer(const wxMemoryBuffer
& src
)
379 : m_bufdata(src
.m_bufdata
)
384 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
389 m_bufdata
= src
.m_bufdata
;
397 void *GetData() const { return m_bufdata
->m_data
; }
398 size_t GetBufSize() const { return m_bufdata
->m_size
; }
399 size_t GetDataLen() const { return m_bufdata
->m_len
; }
401 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
402 void SetDataLen(size_t len
)
404 wxASSERT(len
<= m_bufdata
->m_size
);
405 m_bufdata
->m_len
= len
;
408 // Ensure the buffer is big enough and return a pointer to it
409 void *GetWriteBuf(size_t sizeNeeded
)
411 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
412 return m_bufdata
->m_data
;
415 // Update the length after the write
416 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
418 // Like the above, but appends to the buffer
419 void *GetAppendBuf(size_t sizeNeeded
)
421 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
422 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
425 // Update the length after the append
426 void UngetAppendBuf(size_t sizeUsed
)
428 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
431 // Other ways to append to the buffer
432 void AppendByte(char data
)
434 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
436 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
437 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
438 m_bufdata
->m_len
+= 1;
441 void AppendData(const void *data
, size_t len
)
443 memcpy(GetAppendBuf(len
), data
, len
);
447 operator const char *() const { return (const char*)GetData(); }
450 wxMemoryBufferData
* m_bufdata
;
453 // ----------------------------------------------------------------------------
454 // template class for any kind of data
455 // ----------------------------------------------------------------------------
459 #endif // _WX_BUFFER_H