]> git.saurik.com Git - wxWidgets.git/blob - include/wx/buffer.h
DLLs linking fix wxCharTypeBuffer<T>::NullData
[wxWidgets.git] / include / wx / buffer.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/buffer.h
3 // Purpose: auto buffer classes: buffers which automatically free memory
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 12.04.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_BUFFER_H
13 #define _WX_BUFFER_H
14
15 #include "wx/chartype.h"
16 #include "wx/wxcrtbase.h"
17
18 #ifndef __WXPALMOS5__
19 #include <stdlib.h> // malloc() and free()
20 #endif // ! __WXPALMOS5__
21
22 class WXDLLIMPEXP_FWD_BASE wxCStrData;
23
24 // ----------------------------------------------------------------------------
25 // Special classes for (wide) character strings: they use malloc/free instead
26 // of new/delete
27 // ----------------------------------------------------------------------------
28
29 template <typename T>
30 class WXDLLIMPEXP_BASE wxCharTypeBuffer
31 {
32 public:
33 typedef T CharType;
34
35 wxCharTypeBuffer(const CharType *str = NULL)
36 {
37 if ( str )
38 m_data = new Data(wxStrdup(str));
39 else
40 m_data = &NullData;
41 }
42
43 wxCharTypeBuffer(size_t len)
44 {
45 m_data = new Data((CharType *)malloc((len + 1)*sizeof(CharType)));
46 m_data->m_str[len] = (CharType)0;
47 }
48
49 static const wxCharTypeBuffer CreateNonOwned(const CharType *str)
50 {
51 wxCharTypeBuffer buf;
52 if ( str )
53 buf.m_data = new Data(wx_const_cast(CharType*, str), Data::NonOwned);
54 return buf;
55 }
56
57 ~wxCharTypeBuffer()
58 {
59 DecRef();
60 }
61
62 CharType *release()
63 {
64 if ( m_data == &NullData )
65 return NULL;
66
67 wxASSERT_MSG( m_data->m_owned, _T("can't release non-owned buffer") );
68 wxASSERT_MSG( m_data->m_ref == 1, _T("can't release shared buffer") );
69
70 CharType *p = m_data->m_str;
71 m_data->m_str = NULL;
72 DecRef();
73 return p;
74 }
75
76 void reset()
77 {
78 DecRef();
79 }
80
81 wxCharTypeBuffer(const wxCharTypeBuffer& src)
82 {
83 m_data = src.m_data;
84 IncRef();
85 }
86
87 wxCharTypeBuffer& operator=(const CharType *str)
88 {
89 DecRef();
90
91 if ( str )
92 m_data = new Data(wxStrdup(str));
93 return *this;
94 }
95
96 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
97 {
98 if ( &src == this )
99 return *this;
100
101 DecRef();
102 m_data = src.m_data;
103 IncRef();
104
105 return *this;
106 }
107
108 bool extend(size_t len)
109 {
110 wxASSERT_MSG( m_data->m_owned, _T("cannot extend non-owned buffer") );
111 wxASSERT_MSG( m_data->m_ref == 1, _T("can't extend shared buffer") );
112
113 CharType *str =
114 (CharType *)realloc(data(), (len + 1) * sizeof(CharType));
115 if ( !str )
116 return false;
117
118 if ( m_data == &NullData )
119 {
120 m_data = new Data(str);
121 }
122 else
123 {
124 m_data->m_str = str;
125 m_data->m_owned = true;
126 }
127
128 return true;
129 }
130
131 CharType *data() { return m_data->m_str; }
132 const CharType *data() const { return m_data->m_str; }
133 operator const CharType *() const { return data(); }
134 CharType operator[](size_t n) const { return data()[n]; }
135
136 private:
137 // reference-counted data
138 struct Data
139 {
140 enum Kind
141 {
142 Owned,
143 NonOwned
144 };
145
146 Data(CharType *str, Kind kind = Owned)
147 : m_str(str), m_ref(1), m_owned(kind == Owned) {}
148
149 ~Data()
150 {
151 if ( m_owned )
152 free(m_str);
153 }
154
155 CharType *m_str;
156
157 // "short" to have sizeof(Data)=8 on 32bit archs
158 unsigned short m_ref;
159
160 bool m_owned;
161 };
162
163 // placeholder for NULL string, to simplify this code
164 // NB: this is defined in string.cpp, not (non-existent) buffer.cpp
165 static WXDLLIMPEXP_DATA_BASE(Data) NullData;
166
167 void IncRef()
168 {
169 if ( m_data == &NullData ) // exception, not ref-counted
170 return;
171 m_data->m_ref++;
172 }
173
174 void DecRef()
175 {
176 if ( m_data == &NullData ) // exception, not ref-counted
177 return;
178 if ( --m_data->m_ref == 0 )
179 delete m_data;
180 m_data = &NullData;
181 }
182
183 private:
184 Data *m_data;
185 };
186
187 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
188
189 class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
190 {
191 public:
192 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
193
194 wxCharBuffer(const wxCharTypeBufferBase& buf)
195 : wxCharTypeBufferBase(buf) {}
196
197 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
198 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
199
200 wxCharBuffer(const wxCStrData& cstr);
201 };
202
203 #if wxUSE_WCHAR_T
204 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
205
206 class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
207 {
208 public:
209 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
210
211 wxWCharBuffer(const wxCharTypeBufferBase& buf)
212 : wxCharTypeBufferBase(buf) {}
213
214 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
215 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
216
217 wxWCharBuffer(const wxCStrData& cstr);
218 };
219 #endif // wxUSE_WCHAR_T
220
221 // wxCharTypeBuffer<T> implicitly convertible to T*
222 template <typename T>
223 class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
224 {
225 public:
226 typedef typename wxCharTypeBuffer<T>::CharType CharType;
227
228 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
229 : wxCharTypeBuffer<T>(src) {}
230 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
231 // always return a buffer
232 wxWritableCharTypeBuffer(const CharType *str = NULL)
233 : wxCharTypeBuffer<T>(str) {}
234
235 operator CharType*() { return this->data(); }
236 };
237
238 typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
239 typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
240
241
242 #if wxUSE_UNICODE
243 #define wxWxCharBuffer wxWCharBuffer
244
245 #define wxMB2WXbuf wxWCharBuffer
246 #define wxWX2MBbuf wxCharBuffer
247 #if wxUSE_UNICODE_WCHAR
248 #define wxWC2WXbuf wxChar*
249 #define wxWX2WCbuf wxChar*
250 #elif wxUSE_UNICODE_UTF8
251 #define wxWC2WXbuf wxWCharBuffer
252 #define wxWX2WCbuf wxWCharBuffer
253 #endif
254 #else // ANSI
255 #define wxWxCharBuffer wxCharBuffer
256
257 #define wxMB2WXbuf wxChar*
258 #define wxWX2MBbuf wxChar*
259 #define wxWC2WXbuf wxCharBuffer
260 #define wxWX2WCbuf wxWCharBuffer
261 #endif // Unicode/ANSI
262
263 // type of the value returned by wxString::utf8_str()
264 #if wxUSE_UNICODE_UTF8
265 #define wxUTF8Buf char *
266 #else
267 #define wxUTF8Buf wxCharBuffer
268 #endif
269
270 // ----------------------------------------------------------------------------
271 // A class for holding growable data buffers (not necessarily strings)
272 // ----------------------------------------------------------------------------
273
274 // This class manages the actual data buffer pointer and is ref-counted.
275 class wxMemoryBufferData
276 {
277 public:
278 // the initial size and also the size added by ResizeIfNeeded()
279 enum { DefBufSize = 1024 };
280
281 friend class wxMemoryBuffer;
282
283 // everyting is private as it can only be used by wxMemoryBuffer
284 private:
285 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
286 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
287 {
288 }
289 ~wxMemoryBufferData() { free(m_data); }
290
291
292 void ResizeIfNeeded(size_t newSize)
293 {
294 if (newSize > m_size)
295 {
296 void *dataOld = m_data;
297 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
298 if ( !m_data )
299 {
300 free(dataOld);
301 }
302
303 m_size = newSize + wxMemoryBufferData::DefBufSize;
304 }
305 }
306
307 void IncRef() { m_ref += 1; }
308 void DecRef()
309 {
310 m_ref -= 1;
311 if (m_ref == 0) // are there no more references?
312 delete this;
313 }
314
315
316 // the buffer containing the data
317 void *m_data;
318
319 // the size of the buffer
320 size_t m_size;
321
322 // the amount of data currently in the buffer
323 size_t m_len;
324
325 // the reference count
326 size_t m_ref;
327
328 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
329 };
330
331
332 class WXDLLIMPEXP_BASE wxMemoryBuffer
333 {
334 public:
335 // ctor and dtor
336 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
337 {
338 m_bufdata = new wxMemoryBufferData(size);
339 m_bufdata->IncRef();
340 }
341
342 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
343
344
345 // copy and assignment
346 wxMemoryBuffer(const wxMemoryBuffer& src)
347 : m_bufdata(src.m_bufdata)
348 {
349 m_bufdata->IncRef();
350 }
351
352 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
353 {
354 if (&src != this)
355 {
356 m_bufdata->DecRef();
357 m_bufdata = src.m_bufdata;
358 m_bufdata->IncRef();
359 }
360 return *this;
361 }
362
363
364 // Accessors
365 void *GetData() const { return m_bufdata->m_data; }
366 size_t GetBufSize() const { return m_bufdata->m_size; }
367 size_t GetDataLen() const { return m_bufdata->m_len; }
368
369 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
370 void SetDataLen(size_t len)
371 {
372 wxASSERT(len <= m_bufdata->m_size);
373 m_bufdata->m_len = len;
374 }
375
376 // Ensure the buffer is big enough and return a pointer to it
377 void *GetWriteBuf(size_t sizeNeeded)
378 {
379 m_bufdata->ResizeIfNeeded(sizeNeeded);
380 return m_bufdata->m_data;
381 }
382
383 // Update the length after the write
384 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
385
386 // Like the above, but appends to the buffer
387 void *GetAppendBuf(size_t sizeNeeded)
388 {
389 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
390 return (char*)m_bufdata->m_data + m_bufdata->m_len;
391 }
392
393 // Update the length after the append
394 void UngetAppendBuf(size_t sizeUsed)
395 {
396 SetDataLen(m_bufdata->m_len + sizeUsed);
397 }
398
399 // Other ways to append to the buffer
400 void AppendByte(char data)
401 {
402 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
403
404 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
405 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
406 m_bufdata->m_len += 1;
407 }
408
409 void AppendData(const void *data, size_t len)
410 {
411 memcpy(GetAppendBuf(len), data, len);
412 UngetAppendBuf(len);
413 }
414
415 operator const char *() const { return (const char*)GetData(); }
416
417 private:
418 wxMemoryBufferData* m_bufdata;
419 };
420
421 // ----------------------------------------------------------------------------
422 // template class for any kind of data
423 // ----------------------------------------------------------------------------
424
425 // TODO
426
427 #endif // _WX_BUFFER_H