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/wxchar.h"
17 #include <stdlib.h> // malloc() and free()
19 inline char *wxStrDup(const char *s
) { return wxStrdupA(s
); }
21 inline wchar_t *wxStrDup(const wchar_t *ws
) { return wxStrdupW(ws
); }
24 // ----------------------------------------------------------------------------
25 // Special classes for (wide) character strings: they use malloc/free instead
27 // ----------------------------------------------------------------------------
30 class wxCharTypeBuffer
35 wxCharTypeBuffer(const CharType
*str
= NULL
)
36 : m_str(str
? wxStrDup(str
) : NULL
)
40 wxCharTypeBuffer(size_t len
)
41 : m_str((CharType
*)malloc((len
+ 1)*sizeof(CharType
)))
43 m_str
[len
] = (CharType
)0;
46 /* no need to check for NULL, free() does it */
47 ~wxCharTypeBuffer() { free(m_str
); }
52 the copy ctor and assignment operators change the passed in object
53 even although it is declared as "const", so:
55 a) it shouldn't be really const
56 b) you shouldn't use it afterwards (or know that it was reset)
58 This is very ugly but is unfortunately needed to make the normal use\
59 of wxCharTypeBuffer buffer objects possible and is very similar to what
60 std::auto_ptr<> does (as if it were an excuse...)
64 because of the remark above, release() is declared const even if it
67 CharType
*release() const
70 ((wxCharTypeBuffer
*)this)->m_str
= NULL
;
80 wxCharTypeBuffer(const wxCharTypeBuffer
& src
)
81 : m_str(src
.release())
85 wxCharTypeBuffer
& operator=(const CharType
*str
)
88 m_str
= str
? wxStrDup(str
) : NULL
;
92 wxCharTypeBuffer
& operator=(const wxCharTypeBuffer
& src
)
95 m_str
= src
.release();
100 bool extend(size_t len
)
103 str
= (CharType
*)realloc(m_str
, (len
+ 1)*sizeof(CharType
));
112 CharType
*data() { return m_str
; }
113 const CharType
*data() const { return m_str
; }
114 operator const CharType
*() const { return m_str
; }
115 CharType
operator[](size_t n
) const { return m_str
[n
]; }
121 class WXDLLIMPEXP_BASE wxCharBuffer
: public wxCharTypeBuffer
<char>
124 typedef wxCharTypeBuffer
<char> wxCharTypeBufferBase
;
126 wxCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
127 wxCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
129 wxCharBuffer(const wxCStrData
& cstr
);
133 class WXDLLIMPEXP_BASE wxWCharBuffer
: public wxCharTypeBuffer
<wchar_t>
136 typedef wxCharTypeBuffer
<wchar_t> wxCharTypeBufferBase
;
138 wxWCharBuffer(const CharType
*str
= NULL
) : wxCharTypeBufferBase(str
) {}
139 wxWCharBuffer(size_t len
) : wxCharTypeBufferBase(len
) {}
141 wxWCharBuffer(const wxCStrData
& cstr
);
143 #endif // wxUSE_WCHAR_T
145 // wxCharTypeBuffer<T> implicitly convertible to T*
146 template <typename T
>
147 class wxWritableCharTypeBuffer
: public wxCharTypeBuffer
<T
>
150 typedef typename wxCharTypeBuffer
<T
>::CharType CharType
;
152 wxWritableCharTypeBuffer(const wxCharTypeBuffer
<T
>& src
)
153 : wxCharTypeBuffer
<T
>(src
) {}
154 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
155 // always return a buffer
156 wxWritableCharTypeBuffer(const CharType
*str
= NULL
)
157 : wxCharTypeBuffer
<T
>(str
) {}
159 operator CharType
*() { return this->data(); }
162 typedef wxWritableCharTypeBuffer
<char> wxWritableCharBuffer
;
163 typedef wxWritableCharTypeBuffer
<wchar_t> wxWritableWCharBuffer
;
167 #define wxWxCharBuffer wxWCharBuffer
169 #define wxMB2WXbuf wxWCharBuffer
170 #define wxWX2MBbuf wxCharBuffer
171 #if wxUSE_UNICODE_WCHAR
172 #define wxWC2WXbuf wxChar*
173 #define wxWX2WCbuf wxChar*
174 #elif wxUSE_UNICODE_UTF8
175 #define wxWC2WXbuf wxWCharBuffer
176 #define wxWX2WCbuf wxWCharBuffer
179 #define wxWxCharBuffer wxCharBuffer
181 #define wxMB2WXbuf wxChar*
182 #define wxWX2MBbuf wxChar*
183 #define wxWC2WXbuf wxCharBuffer
184 #define wxWX2WCbuf wxWCharBuffer
185 #endif // Unicode/ANSI
187 // ----------------------------------------------------------------------------
188 // A class for holding growable data buffers (not necessarily strings)
189 // ----------------------------------------------------------------------------
191 // This class manages the actual data buffer pointer and is ref-counted.
192 class wxMemoryBufferData
195 // the initial size and also the size added by ResizeIfNeeded()
196 enum { DefBufSize
= 1024 };
198 friend class wxMemoryBuffer
;
200 // everyting is private as it can only be used by wxMemoryBuffer
202 wxMemoryBufferData(size_t size
= wxMemoryBufferData::DefBufSize
)
203 : m_data(size
? malloc(size
) : NULL
), m_size(size
), m_len(0), m_ref(0)
206 ~wxMemoryBufferData() { free(m_data
); }
209 void ResizeIfNeeded(size_t newSize
)
211 if (newSize
> m_size
)
213 void *dataOld
= m_data
;
214 m_data
= realloc(m_data
, newSize
+ wxMemoryBufferData::DefBufSize
);
220 m_size
= newSize
+ wxMemoryBufferData::DefBufSize
;
224 void IncRef() { m_ref
+= 1; }
228 if (m_ref
== 0) // are there no more references?
233 // the buffer containing the data
236 // the size of the buffer
239 // the amount of data currently in the buffer
242 // the reference count
245 DECLARE_NO_COPY_CLASS(wxMemoryBufferData
)
253 wxMemoryBuffer(size_t size
= wxMemoryBufferData::DefBufSize
)
255 m_bufdata
= new wxMemoryBufferData(size
);
259 ~wxMemoryBuffer() { m_bufdata
->DecRef(); }
262 // copy and assignment
263 wxMemoryBuffer(const wxMemoryBuffer
& src
)
264 : m_bufdata(src
.m_bufdata
)
269 wxMemoryBuffer
& operator=(const wxMemoryBuffer
& src
)
272 m_bufdata
= src
.m_bufdata
;
279 void *GetData() const { return m_bufdata
->m_data
; }
280 size_t GetBufSize() const { return m_bufdata
->m_size
; }
281 size_t GetDataLen() const { return m_bufdata
->m_len
; }
283 void SetBufSize(size_t size
) { m_bufdata
->ResizeIfNeeded(size
); }
284 void SetDataLen(size_t len
)
286 wxASSERT(len
<= m_bufdata
->m_size
);
287 m_bufdata
->m_len
= len
;
290 // Ensure the buffer is big enough and return a pointer to it
291 void *GetWriteBuf(size_t sizeNeeded
)
293 m_bufdata
->ResizeIfNeeded(sizeNeeded
);
294 return m_bufdata
->m_data
;
297 // Update the length after the write
298 void UngetWriteBuf(size_t sizeUsed
) { SetDataLen(sizeUsed
); }
300 // Like the above, but appends to the buffer
301 void *GetAppendBuf(size_t sizeNeeded
)
303 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ sizeNeeded
);
304 return (char*)m_bufdata
->m_data
+ m_bufdata
->m_len
;
307 // Update the length after the append
308 void UngetAppendBuf(size_t sizeUsed
)
310 SetDataLen(m_bufdata
->m_len
+ sizeUsed
);
313 // Other ways to append to the buffer
314 void AppendByte(char data
)
316 wxCHECK_RET( m_bufdata
->m_data
, _T("invalid wxMemoryBuffer") );
318 m_bufdata
->ResizeIfNeeded(m_bufdata
->m_len
+ 1);
319 *(((char*)m_bufdata
->m_data
) + m_bufdata
->m_len
) = data
;
320 m_bufdata
->m_len
+= 1;
323 void AppendData(const void *data
, size_t len
)
325 memcpy(GetAppendBuf(len
), data
, len
);
329 operator const char *() const { return (const char*)GetData(); }
332 wxMemoryBufferData
* m_bufdata
;
335 // ----------------------------------------------------------------------------
336 // template class for any kind of data
337 // ----------------------------------------------------------------------------
341 #endif // _WX_BUFFER_H