]> git.saurik.com Git - wxWidgets.git/blob - include/wx/buffer.h
general docview.cpp code cleanup; use wxVector<> instead of manually-allocated arrays...
[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 : m_str(str ? wxStrdup(str) : NULL),
37 m_owned(true)
38 {
39 }
40
41 wxCharTypeBuffer(size_t len)
42 : m_str((CharType *)malloc((len + 1)*sizeof(CharType))),
43 m_owned(true)
44 {
45 m_str[len] = (CharType)0;
46 }
47
48 static const wxCharTypeBuffer CreateNonOwned(const CharType *str)
49 {
50 wxCharTypeBuffer buf;
51 buf.m_str = wx_const_cast(CharType*, str);
52 buf.m_owned = false;
53 return buf;
54 }
55
56 /* no need to check for NULL, free() does it */
57 ~wxCharTypeBuffer()
58 {
59 if ( m_owned)
60 free(m_str);
61 }
62
63 /*
64 WARNING:
65
66 the copy ctor and assignment operators change the passed in object
67 even although it is declared as "const", so:
68
69 a) it shouldn't be really const
70 b) you shouldn't use it afterwards (or know that it was reset)
71
72 This is very ugly but is unfortunately needed to make the normal use
73 of wxCharTypeBuffer buffer objects possible and is very similar to what
74 std::auto_ptr<> does (as if it were an excuse...)
75 */
76
77 /*
78 because of the remark above, release() is declared const even if it
79 isn't really const
80 */
81 CharType *release() const
82 {
83 wxASSERT_MSG( m_owned, _T("can't release non-owned buffer") );
84 return DoRelease();
85 }
86
87 void reset()
88 {
89 if ( m_owned )
90 free(m_str);
91 m_str = NULL;
92 }
93
94 wxCharTypeBuffer(const wxCharTypeBuffer& src)
95 {
96 CopyFrom(src);
97 }
98
99 wxCharTypeBuffer& operator=(const CharType *str)
100 {
101 if ( m_owned )
102 free(m_str);
103 m_str = str ? wxStrdup(str) : NULL;
104 m_owned = true;
105 return *this;
106 }
107
108 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
109 {
110 if (&src != this)
111 {
112 if ( m_owned )
113 free(m_str);
114 CopyFrom(src);
115 }
116 return *this;
117 }
118
119 bool extend(size_t len)
120 {
121 wxASSERT_MSG( m_owned, _T("cannot extend non-owned buffer") );
122
123 CharType *
124 str = (CharType *)realloc(m_str, (len + 1)*sizeof(CharType));
125 if ( !str )
126 return false;
127
128 m_str = str;
129
130 return true;
131 }
132
133 CharType *data() { return m_str; }
134 const CharType *data() const { return m_str; }
135 operator const CharType *() const { return m_str; }
136 CharType operator[](size_t n) const { return m_str[n]; }
137
138
139 private:
140 CharType *DoRelease() const
141 {
142 CharType *p = m_str;
143 ((wxCharTypeBuffer *)this)->m_str = NULL;
144 return p;
145 }
146
147 void CopyFrom(const wxCharTypeBuffer& src)
148 {
149 m_owned = src.m_owned;
150 m_str = src.DoRelease();
151 }
152
153 private:
154 CharType *m_str;
155 bool m_owned;
156 };
157
158 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
159
160 class WXDLLIMPEXP_BASE wxCharBuffer : public wxCharTypeBuffer<char>
161 {
162 public:
163 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
164
165 wxCharBuffer(const wxCharTypeBufferBase& buf)
166 : wxCharTypeBufferBase(buf) {}
167
168 wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
169 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
170
171 wxCharBuffer(const wxCStrData& cstr);
172 };
173
174 #if wxUSE_WCHAR_T
175 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
176
177 class WXDLLIMPEXP_BASE wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
178 {
179 public:
180 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
181
182 wxWCharBuffer(const wxCharTypeBufferBase& buf)
183 : wxCharTypeBufferBase(buf) {}
184
185 wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
186 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
187
188 wxWCharBuffer(const wxCStrData& cstr);
189 };
190 #endif // wxUSE_WCHAR_T
191
192 // wxCharTypeBuffer<T> implicitly convertible to T*
193 template <typename T>
194 class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
195 {
196 public:
197 typedef typename wxCharTypeBuffer<T>::CharType CharType;
198
199 wxWritableCharTypeBuffer(const wxCharTypeBuffer<T>& src)
200 : wxCharTypeBuffer<T>(src) {}
201 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
202 // always return a buffer
203 wxWritableCharTypeBuffer(const CharType *str = NULL)
204 : wxCharTypeBuffer<T>(str) {}
205
206 operator CharType*() { return this->data(); }
207 };
208
209 typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
210 typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
211
212
213 #if wxUSE_UNICODE
214 #define wxWxCharBuffer wxWCharBuffer
215
216 #define wxMB2WXbuf wxWCharBuffer
217 #define wxWX2MBbuf wxCharBuffer
218 #if wxUSE_UNICODE_WCHAR
219 #define wxWC2WXbuf wxChar*
220 #define wxWX2WCbuf wxChar*
221 #elif wxUSE_UNICODE_UTF8
222 #define wxWC2WXbuf wxWCharBuffer
223 #define wxWX2WCbuf wxWCharBuffer
224 #endif
225 #else // ANSI
226 #define wxWxCharBuffer wxCharBuffer
227
228 #define wxMB2WXbuf wxChar*
229 #define wxWX2MBbuf wxChar*
230 #define wxWC2WXbuf wxCharBuffer
231 #define wxWX2WCbuf wxWCharBuffer
232 #endif // Unicode/ANSI
233
234 // type of the value returned by wxString::utf8_str()
235 #if wxUSE_UNICODE_UTF8
236 #define wxUTF8Buf char *
237 #else
238 #define wxUTF8Buf wxCharBuffer
239 #endif
240
241 // ----------------------------------------------------------------------------
242 // A class for holding growable data buffers (not necessarily strings)
243 // ----------------------------------------------------------------------------
244
245 // This class manages the actual data buffer pointer and is ref-counted.
246 class wxMemoryBufferData
247 {
248 public:
249 // the initial size and also the size added by ResizeIfNeeded()
250 enum { DefBufSize = 1024 };
251
252 friend class wxMemoryBuffer;
253
254 // everyting is private as it can only be used by wxMemoryBuffer
255 private:
256 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
257 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
258 {
259 }
260 ~wxMemoryBufferData() { free(m_data); }
261
262
263 void ResizeIfNeeded(size_t newSize)
264 {
265 if (newSize > m_size)
266 {
267 void *dataOld = m_data;
268 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
269 if ( !m_data )
270 {
271 free(dataOld);
272 }
273
274 m_size = newSize + wxMemoryBufferData::DefBufSize;
275 }
276 }
277
278 void IncRef() { m_ref += 1; }
279 void DecRef()
280 {
281 m_ref -= 1;
282 if (m_ref == 0) // are there no more references?
283 delete this;
284 }
285
286
287 // the buffer containing the data
288 void *m_data;
289
290 // the size of the buffer
291 size_t m_size;
292
293 // the amount of data currently in the buffer
294 size_t m_len;
295
296 // the reference count
297 size_t m_ref;
298
299 DECLARE_NO_COPY_CLASS(wxMemoryBufferData)
300 };
301
302
303 class WXDLLIMPEXP_BASE wxMemoryBuffer
304 {
305 public:
306 // ctor and dtor
307 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
308 {
309 m_bufdata = new wxMemoryBufferData(size);
310 m_bufdata->IncRef();
311 }
312
313 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
314
315
316 // copy and assignment
317 wxMemoryBuffer(const wxMemoryBuffer& src)
318 : m_bufdata(src.m_bufdata)
319 {
320 m_bufdata->IncRef();
321 }
322
323 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
324 {
325 if (&src != this)
326 {
327 m_bufdata->DecRef();
328 m_bufdata = src.m_bufdata;
329 m_bufdata->IncRef();
330 }
331 return *this;
332 }
333
334
335 // Accessors
336 void *GetData() const { return m_bufdata->m_data; }
337 size_t GetBufSize() const { return m_bufdata->m_size; }
338 size_t GetDataLen() const { return m_bufdata->m_len; }
339
340 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
341 void SetDataLen(size_t len)
342 {
343 wxASSERT(len <= m_bufdata->m_size);
344 m_bufdata->m_len = len;
345 }
346
347 // Ensure the buffer is big enough and return a pointer to it
348 void *GetWriteBuf(size_t sizeNeeded)
349 {
350 m_bufdata->ResizeIfNeeded(sizeNeeded);
351 return m_bufdata->m_data;
352 }
353
354 // Update the length after the write
355 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
356
357 // Like the above, but appends to the buffer
358 void *GetAppendBuf(size_t sizeNeeded)
359 {
360 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
361 return (char*)m_bufdata->m_data + m_bufdata->m_len;
362 }
363
364 // Update the length after the append
365 void UngetAppendBuf(size_t sizeUsed)
366 {
367 SetDataLen(m_bufdata->m_len + sizeUsed);
368 }
369
370 // Other ways to append to the buffer
371 void AppendByte(char data)
372 {
373 wxCHECK_RET( m_bufdata->m_data, _T("invalid wxMemoryBuffer") );
374
375 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
376 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
377 m_bufdata->m_len += 1;
378 }
379
380 void AppendData(const void *data, size_t len)
381 {
382 memcpy(GetAppendBuf(len), data, len);
383 UngetAppendBuf(len);
384 }
385
386 operator const char *() const { return (const char*)GetData(); }
387
388 private:
389 wxMemoryBufferData* m_bufdata;
390 };
391
392 // ----------------------------------------------------------------------------
393 // template class for any kind of data
394 // ----------------------------------------------------------------------------
395
396 // TODO
397
398 #endif // _WX_BUFFER_H