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 // ----------------------------------------------------------------------------
30 class WXDLLIMPEXP_BASE wxCharTypeBuffer
35 wxCharTypeBuffer(const CharType
*str
= NULL
)
38 m_data
= new Data(wxStrdup(str
));
43 wxCharTypeBuffer(size_t len
)
45 m_data
= new Data((CharType
*)malloc((len
+ 1)*sizeof(CharType
)));
46 m_data
->m_str
[len
] = (CharType
)0;
49 static const wxCharTypeBuffer
CreateNonOwned(const CharType
*str
)
53 buf
.m_data
= new Data(wx_const_cast(CharType
*, str
), Data::NonOwned
);
62 // NB: this method is only const for backward compatibility. It used to
63 // be needed for auto_ptr-like semantics of the copy ctor, but now
64 // that ref-counting is used, it's not really needed.
65 CharType
*release() const
67 if ( m_data
== &NullData
)
70 wxASSERT_MSG( m_data
->m_owned
, _T("can't release non-owned buffer") );
71 wxASSERT_MSG( m_data
->m_ref
== 1, _T("can't release shared buffer") );
73 CharType
*p
= m_data
->m_str
;
75 wxCharTypeBuffer
*self
= wx_const_cast(wxCharTypeBuffer
*, this);
76 self
->m_data
->m_str
= NULL
;
87 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
93 wxCharTypeBuffer
& operator=(const CharType
*str
)
98 m_data
= new Data(wxStrdup(str
));
102 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
114 bool extend(size_t len
)
116 wxASSERT_MSG( m_data
->m_owned
, _T("cannot extend non-owned buffer") );
117 wxASSERT_MSG( m_data
->m_ref
== 1, _T("can't extend shared buffer") );
120 (CharType
*)realloc(data(), (len
+ 1) * sizeof(CharType
));
124 if ( m_data
== &NullData
)
126 m_data
= new Data(str
);
131 m_data
->m_owned
= true;
137 CharType
*data() { return m_data
->m_str
; }
138 const CharType
*data() const { return m_data
->m_str
; }
139 operator const CharType
*() const { return data(); }
140 CharType
operator[](size_t n
) const { return data()[n
]; }
143 // reference-counted data
152 Data(CharType
*str
, Kind kind
= Owned
)
153 : m_str(str
), m_ref(1), m_owned(kind
== Owned
) {}
163 // "short" to have sizeof(Data)=8 on 32bit archs
164 unsigned short m_ref
;
169 // placeholder for NULL string, to simplify this code
170 // NB: this is defined in string.cpp, not (non-existent) buffer.cpp
172 // MinGW requires explicit WXDLLIMPEXP_DATA_BASE to avoid compilation
174 static WXDLLIMPEXP_DATA_BASE(Data
) NullData
;
176 // but Visual C++ doesn't like it
177 static Data NullData
;
182 if ( m_data
== &NullData
) // exception, not ref-counted
189 if ( m_data
== &NullData
) // exception, not ref-counted
191 if ( --m_data
->m_ref
== 0 )
200 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<char> )
202 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
205 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
207 wxCharBuffer(const wxCharTypeBufferBase
& buf
)
208 : wxCharTypeBufferBase(buf
) {}
210 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
211 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
213 wxCharBuffer(const wxCStrData
& cstr
);
217 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer
<wchar_t> )
219 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
222 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
224 wxWCharBuffer(const wxCharTypeBufferBase
& buf
)
225 : wxCharTypeBufferBase(buf
) {}
227 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
228 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
230 wxWCharBuffer(const wxCStrData
& cstr
);
232 #endif // wxUSE_WCHAR_T
234 // wxCharTypeBuffer<T> implicitly convertible to T*
235 template <typename T
>
236 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
239 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
241 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
242 : wxCharTypeBuffer
<T
>(src
) {}
243 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
244 // always return a buffer
245 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
246 : wxCharTypeBuffer
<T
>(str
) {}
248 operator CharType
*() { return this->data(); }
251 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
252 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
256 #define wxWxCharBuffer wxWCharBuffer
258 #define wxMB2WXbuf wxWCharBuffer
259 #define wxWX2MBbuf wxCharBuffer
260 #if wxUSE_UNICODE_WCHAR
261 #define wxWC2WXbuf wxChar*
262 #define wxWX2WCbuf wxChar*
263 #elif wxUSE_UNICODE_UTF8
264 #define wxWC2WXbuf wxWCharBuffer
265 #define wxWX2WCbuf wxWCharBuffer
268 #define wxWxCharBuffer wxCharBuffer
270 #define wxMB2WXbuf wxChar*
271 #define wxWX2MBbuf wxChar*
272 #define wxWC2WXbuf wxCharBuffer
273 #define wxWX2WCbuf wxWCharBuffer
274 #endif // Unicode/ANSI
276 // type of the value returned by wxString::utf8_str()
277 #if wxUSE_UNICODE_UTF8
278 #define wxUTF8Buf char *
280 #define wxUTF8Buf wxCharBuffer
283 // ----------------------------------------------------------------------------
284 // A class for holding growable data buffers (not necessarily strings)
285 // ----------------------------------------------------------------------------
287 // This class manages the actual data buffer pointer and is ref-counted.
288 class wxMemoryBufferData
291 // the initial size and also the size added by ResizeIfNeeded()
292 enum { DefBufSize
= 1024 };
294 friend class wxMemoryBuffer
;
296 // everyting is private as it can only be used by wxMemoryBuffer
298 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
299 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
302 ~wxMemoryBufferData() { free(m_data
); }
305 void ResizeIfNeeded(size_t newSize
)
307 if (newSize
> m_size
)
309 void *dataOld
= m_data
;
310 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
316 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
320 void IncRef() { m_ref
+= 1; }
324 if (m_ref
== 0) // are there no more references?
329 // the buffer containing the data
332 // the size of the buffer
335 // the amount of data currently in the buffer
338 // the reference count
341 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
345 class WXDLLIMPEXP_BASE wxMemoryBuffer
349 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
351 m_bufdata
= new wxMemoryBufferData(size
);
355 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
358 // copy and assignment
359 wxMemoryBuffer(const wxMemoryBuffer
& src
)
360 : m_bufdata(src
.m_bufdata
)
365 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
370 m_bufdata
= src
.m_bufdata
;
378 void *GetData() const { return m_bufdata
->m_data
; }
379 size_t GetBufSize() const { return m_bufdata
->m_size
; }
380 size_t GetDataLen() const { return m_bufdata
->m_len
; }
382 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
383 void SetDataLen(size_t len
)
385 wxASSERT(len
<= m_bufdata
->m_size
);
386 m_bufdata
->m_len
= len
;
389 // Ensure the buffer is big enough and return a pointer to it
390 void *GetWriteBuf(size_t sizeNeeded
)
392 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
393 return m_bufdata
->m_data
;
396 // Update the length after the write
397 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
399 // Like the above, but appends to the buffer
400 void *GetAppendBuf(size_t sizeNeeded
)
402 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
403 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
406 // Update the length after the append
407 void UngetAppendBuf(size_t sizeUsed
)
409 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
412 // Other ways to append to the buffer
413 void AppendByte(char data
)
415 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
417 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
418 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
419 m_bufdata
->m_len
+= 1;
422 void AppendData(const void *data
, size_t len
)
424 memcpy(GetAppendBuf(len
), data
, len
);
428 operator const char *() const { return (const char*)GetData(); }
431 wxMemoryBufferData
* m_bufdata
;
434 // ----------------------------------------------------------------------------
435 // template class for any kind of data
436 // ----------------------------------------------------------------------------
440 #endif // _WX_BUFFER_H