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: buffer.h 61872 2009-09-09 22:37:05Z VZ $ 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/wxchar.h" 16 17#include <stdlib.h> // malloc() and free() 18 19// ---------------------------------------------------------------------------- 20// Special classes for (wide) character strings: they use malloc/free instead 21// of new/delete 22// ---------------------------------------------------------------------------- 23 24#define DEFINE_BUFFER(classname, chartype, strdupfunc) \ 25class WXDLLIMPEXP_BASE classname \ 26{ \ 27public: \ 28 classname(const chartype *str = NULL) \ 29 : m_str(str ? strdupfunc(str) : NULL) \ 30 { \ 31 } \ 32 \ 33 classname(size_t len) \ 34 : m_str((chartype *)malloc((len + 1)*sizeof(chartype))) \ 35 { \ 36 m_str[len] = (chartype)0; \ 37 } \ 38 \ 39 /* no need to check for NULL, free() does it */ \ 40 ~classname() { free(m_str); } \ 41 \ 42 /* \ 43 WARNING: \ 44 \ 45 the copy ctor and assignment operators change the passed in object \ 46 even although it is declared as "const", so: \ 47 \ 48 a) it shouldn't be really const \ 49 b) you shouldn't use it afterwards (or know that it was reset) \ 50 \ 51 This is very ugly but is unfortunately needed to make the normal use\ 52 of classname buffer objects possible and is very similar to what \ 53 std::auto_ptr<> does (as if it were an excuse...) \ 54 */ \ 55 \ 56 /* \ 57 because of the remark above, release() is declared const even if it \ 58 isn't really const \ 59 */ \ 60 chartype *release() const \ 61 { \ 62 chartype *p = m_str; \ 63 ((classname *)this)->m_str = NULL; \ 64 return p; \ 65 } \ 66 \ 67 void reset() \ 68 { \ 69 free(m_str); \ 70 m_str = NULL; \ 71 } \ 72 \ 73 classname(const classname& src) \ 74 : m_str(src.release()) \ 75 { \ 76 } \ 77 \ 78 classname& operator=(const chartype *str) \ 79 { \ 80 free(m_str); \ 81 m_str = str ? strdupfunc(str) : NULL; \ 82 return *this; \ 83 } \ 84 \ 85 classname& operator=(const classname& src) \ 86 { \ 87 free(m_str); \ 88 m_str = src.release(); \ 89 \ 90 return *this; \ 91 } \ 92 \ 93 bool extend(size_t len) \ 94 { \ 95 chartype * \ 96 str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype)); \ 97 if ( !str ) \ 98 return false; \ 99 \ 100 m_str = str; \ 101 \ 102 return true; \ 103 } \ 104 \ 105 chartype *data() { return m_str; } \ 106 const chartype *data() const { return m_str; } \ 107 operator const chartype *() const { return m_str; } \ 108 chartype operator[](size_t n) const { return m_str[n]; } \ 109 \ 110private: \ 111 chartype *m_str; \ 112} 113 114#if wxABI_VERSION >= 20804 115// needed for wxString::char_str() and wchar_str() 116#define DEFINE_WRITABLE_BUFFER(classname, baseclass, chartype) \ 117class WXDLLIMPEXP_BASE classname : public baseclass \ 118{ \ 119public: \ 120 classname(const baseclass& src) : baseclass(src) {} \ 121 classname(const chartype *str = NULL) : baseclass(str) {} \ 122 \ 123 operator chartype*() { return this->data(); } \ 124} 125#endif // wxABI_VERSION >= 20804 126 127DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA); 128#if wxABI_VERSION >= 20804 129DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char); 130#endif 131 132#if wxUSE_WCHAR_T 133 134DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW); 135#if wxABI_VERSION >= 20804 136DEFINE_WRITABLE_BUFFER(wxWritableWCharBuffer, wxWCharBuffer, wchar_t); 137#endif 138 139#endif // wxUSE_WCHAR_T 140 141#undef DEFINE_BUFFER 142#undef DEFINE_WRITABLE_BUFFER 143 144#if wxUSE_UNICODE 145 typedef wxWCharBuffer wxWxCharBuffer; 146 147 #define wxMB2WXbuf wxWCharBuffer 148 #define wxWX2MBbuf wxCharBuffer 149 #define wxWC2WXbuf wxChar* 150 #define wxWX2WCbuf wxChar* 151#else // ANSI 152 typedef wxCharBuffer wxWxCharBuffer; 153 154 #define wxMB2WXbuf wxChar* 155 #define wxWX2MBbuf wxChar* 156 #define wxWC2WXbuf wxCharBuffer 157 #define wxWX2WCbuf wxWCharBuffer 158#endif // Unicode/ANSI 159 160// ---------------------------------------------------------------------------- 161// A class for holding growable data buffers (not necessarily strings) 162// ---------------------------------------------------------------------------- 163 164// This class manages the actual data buffer pointer and is ref-counted. 165class wxMemoryBufferData 166{ 167public: 168 // the initial size and also the size added by ResizeIfNeeded() 169 enum { DefBufSize = 1024 }; 170 171 friend class wxMemoryBuffer; 172 173 // everyting is private as it can only be used by wxMemoryBuffer 174private: 175 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize) 176 : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0) 177 { 178 } 179 ~wxMemoryBufferData() { free(m_data); } 180 181 182 void ResizeIfNeeded(size_t newSize) 183 { 184 if (newSize > m_size) 185 { 186 void *dataOld = m_data; 187 m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize); 188 if ( !m_data ) 189 { 190 free(dataOld); 191 } 192 193 m_size = newSize + wxMemoryBufferData::DefBufSize; 194 } 195 } 196 197 void IncRef() { m_ref += 1; } 198 void DecRef() 199 { 200 m_ref -= 1; 201 if (m_ref == 0) // are there no more references? 202 delete this; 203 } 204 205 206 // the buffer containing the data 207 void *m_data; 208 209 // the size of the buffer 210 size_t m_size; 211 212 // the amount of data currently in the buffer 213 size_t m_len; 214 215 // the reference count 216 size_t m_ref; 217 218 DECLARE_NO_COPY_CLASS(wxMemoryBufferData) 219}; 220 221 222class wxMemoryBuffer 223{ 224public: 225 // ctor and dtor 226 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize) 227 { 228 m_bufdata = new wxMemoryBufferData(size); 229 m_bufdata->IncRef(); 230 } 231 232 ~wxMemoryBuffer() { m_bufdata->DecRef(); } 233 234 235 // copy and assignment 236 wxMemoryBuffer(const wxMemoryBuffer& src) 237 : m_bufdata(src.m_bufdata) 238 { 239 m_bufdata->IncRef(); 240 } 241 242 wxMemoryBuffer& operator=(const wxMemoryBuffer& src) 243 { 244 m_bufdata->DecRef(); 245 m_bufdata = src.m_bufdata; 246 m_bufdata->IncRef(); 247 return *this; 248 } 249 250 251 // Accessors 252 void *GetData() const { return m_bufdata->m_data; } 253 size_t GetBufSize() const { return m_bufdata->m_size; } 254 size_t GetDataLen() const { return m_bufdata->m_len; } 255 256 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); } 257 void SetDataLen(size_t len) 258 { 259 wxASSERT(len <= m_bufdata->m_size); 260 m_bufdata->m_len = len; 261 } 262 263 // Ensure the buffer is big enough and return a pointer to it 264 void *GetWriteBuf(size_t sizeNeeded) 265 { 266 m_bufdata->ResizeIfNeeded(sizeNeeded); 267 return m_bufdata->m_data; 268 } 269 270 // Update the length after the write 271 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); } 272 273 // Like the above, but appends to the buffer 274 void *GetAppendBuf(size_t sizeNeeded) 275 { 276 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded); 277 return (char*)m_bufdata->m_data + m_bufdata->m_len; 278 } 279 280 // Update the length after the append 281 void UngetAppendBuf(size_t sizeUsed) 282 { 283 SetDataLen(m_bufdata->m_len + sizeUsed); 284 } 285 286 // Other ways to append to the buffer 287 void AppendByte(char data) 288 { 289 wxCHECK_RET( m_bufdata->m_data, wxT("invalid wxMemoryBuffer") ); 290 291 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1); 292 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data; 293 m_bufdata->m_len += 1; 294 } 295 296 void AppendData(const void *data, size_t len) 297 { 298 memcpy(GetAppendBuf(len), data, len); 299 UngetAppendBuf(len); 300 } 301 302 operator const char *() const { return (const char*)GetData(); } 303 304private: 305 wxMemoryBufferData* m_bufdata; 306}; 307 308// ---------------------------------------------------------------------------- 309// template class for any kind of data 310// ---------------------------------------------------------------------------- 311 312// TODO 313 314#endif // _WX_BUFFER_H 315