buffer.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  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. // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  8. // Licence: wxWindows licence
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #ifndef _WX_BUFFER_H
  11. #define _WX_BUFFER_H
  12. #include "wx/chartype.h"
  13. #include "wx/wxcrtbase.h"
  14. #include <stdlib.h> // malloc() and free()
  15. class WXDLLIMPEXP_FWD_BASE wxCStrData;
  16. // ----------------------------------------------------------------------------
  17. // Special classes for (wide) character strings: they use malloc/free instead
  18. // of new/delete
  19. // ----------------------------------------------------------------------------
  20. // helpers used by wxCharTypeBuffer
  21. namespace wxPrivate
  22. {
  23. struct UntypedBufferData
  24. {
  25. enum Kind
  26. {
  27. Owned,
  28. NonOwned
  29. };
  30. UntypedBufferData(void *str, size_t len, Kind kind = Owned)
  31. : m_str(str), m_length(len), m_ref(1), m_owned(kind == Owned) {}
  32. ~UntypedBufferData()
  33. {
  34. if ( m_owned )
  35. free(m_str);
  36. }
  37. void *m_str;
  38. size_t m_length;
  39. // "short" to have sizeof(Data)=12 on 32bit archs
  40. unsigned short m_ref;
  41. bool m_owned;
  42. };
  43. // NB: this is defined in string.cpp and not the (non-existent) buffer.cpp
  44. WXDLLIMPEXP_BASE UntypedBufferData * GetUntypedNullData();
  45. } // namespace wxPrivate
  46. // Reference-counted character buffer for storing string data. The buffer
  47. // is only valid for as long as the "parent" object that provided the data
  48. // is valid; see wxCharTypeBuffer<T> for persistent variant.
  49. template <typename T>
  50. class wxScopedCharTypeBuffer
  51. {
  52. public:
  53. typedef T CharType;
  54. wxScopedCharTypeBuffer()
  55. {
  56. m_data = GetNullData();
  57. }
  58. // Creates "non-owned" buffer, i.e. 'str' is not owned by the buffer
  59. // and doesn't get freed by dtor. Used e.g. to point to wxString's internal
  60. // storage.
  61. static
  62. const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str,
  63. size_t len = wxNO_LEN)
  64. {
  65. if ( len == wxNO_LEN )
  66. len = wxStrlen(str);
  67. wxScopedCharTypeBuffer buf;
  68. if ( str )
  69. buf.m_data = new Data(const_cast<CharType*>(str), len, Data::NonOwned);
  70. return buf;
  71. }
  72. // Creates "owned" buffer, i.e. takes over ownership of 'str' and frees it
  73. // in dtor (if ref.count reaches 0).
  74. static
  75. const wxScopedCharTypeBuffer CreateOwned(CharType *str,
  76. size_t len = wxNO_LEN )
  77. {
  78. if ( len == wxNO_LEN )
  79. len = wxStrlen(str);
  80. wxScopedCharTypeBuffer buf;
  81. if ( str )
  82. buf.m_data = new Data(str, len);
  83. return buf;
  84. }
  85. wxScopedCharTypeBuffer(const wxScopedCharTypeBuffer& src)
  86. {
  87. m_data = src.m_data;
  88. IncRef();
  89. }
  90. wxScopedCharTypeBuffer& operator=(const wxScopedCharTypeBuffer& src)
  91. {
  92. if ( &src == this )
  93. return *this;
  94. DecRef();
  95. m_data = src.m_data;
  96. IncRef();
  97. return *this;
  98. }
  99. ~wxScopedCharTypeBuffer()
  100. {
  101. DecRef();
  102. }
  103. // NB: this method is only const for backward compatibility. It used to
  104. // be needed for auto_ptr-like semantics of the copy ctor, but now
  105. // that ref-counting is used, it's not really needed.
  106. CharType *release() const
  107. {
  108. if ( m_data == GetNullData() )
  109. return NULL;
  110. wxASSERT_MSG( m_data->m_owned, wxT("can't release non-owned buffer") );
  111. wxASSERT_MSG( m_data->m_ref == 1, wxT("can't release shared buffer") );
  112. CharType * const p = m_data->Get();
  113. wxScopedCharTypeBuffer *self = const_cast<wxScopedCharTypeBuffer*>(this);
  114. self->m_data->Set(NULL, 0);
  115. self->DecRef();
  116. return p;
  117. }
  118. void reset()
  119. {
  120. DecRef();
  121. }
  122. CharType *data() { return m_data->Get(); }
  123. const CharType *data() const { return m_data->Get(); }
  124. operator const CharType *() const { return data(); }
  125. CharType operator[](size_t n) const { return data()[n]; }
  126. size_t length() const { return m_data->m_length; }
  127. protected:
  128. // reference-counted data
  129. struct Data : public wxPrivate::UntypedBufferData
  130. {
  131. Data(CharType *str, size_t len, Kind kind = Owned)
  132. : wxPrivate::UntypedBufferData(str, len, kind)
  133. {
  134. }
  135. CharType *Get() const { return static_cast<CharType *>(m_str); }
  136. void Set(CharType *str, size_t len)
  137. {
  138. m_str = str;
  139. m_length = len;
  140. }
  141. };
  142. // placeholder for NULL string, to simplify this code
  143. static Data *GetNullData()
  144. {
  145. return static_cast<Data *>(wxPrivate::GetUntypedNullData());
  146. }
  147. void IncRef()
  148. {
  149. if ( m_data == GetNullData() ) // exception, not ref-counted
  150. return;
  151. m_data->m_ref++;
  152. }
  153. void DecRef()
  154. {
  155. if ( m_data == GetNullData() ) // exception, not ref-counted
  156. return;
  157. if ( --m_data->m_ref == 0 )
  158. delete m_data;
  159. m_data = GetNullData();
  160. }
  161. // sets this object to a be copy of 'other'; if 'src' is non-owned,
  162. // a deep copy is made and 'this' will contain new instance of the data
  163. void MakeOwnedCopyOf(const wxScopedCharTypeBuffer& src)
  164. {
  165. this->DecRef();
  166. if ( src.m_data == this->GetNullData() )
  167. {
  168. this->m_data = this->GetNullData();
  169. }
  170. else if ( src.m_data->m_owned )
  171. {
  172. this->m_data = src.m_data;
  173. this->IncRef();
  174. }
  175. else
  176. {
  177. // if the scoped buffer had non-owned data, we have to make
  178. // a copy here, because src.m_data->m_str is valid only for as long
  179. // as 'src' exists
  180. this->m_data = new Data
  181. (
  182. StrCopy(src.data(), src.length()),
  183. src.length()
  184. );
  185. }
  186. }
  187. static CharType *StrCopy(const CharType *src, size_t len)
  188. {
  189. CharType *dst = (CharType*)malloc(sizeof(CharType) * (len + 1));
  190. if ( dst )
  191. memcpy(dst, src, sizeof(CharType) * (len + 1));
  192. return dst;
  193. }
  194. protected:
  195. Data *m_data;
  196. };
  197. typedef wxScopedCharTypeBuffer<char> wxScopedCharBuffer;
  198. typedef wxScopedCharTypeBuffer<wchar_t> wxScopedWCharBuffer;
  199. // this buffer class always stores data in "owned" (persistent) manner
  200. template <typename T>
  201. class wxCharTypeBuffer : public wxScopedCharTypeBuffer<T>
  202. {
  203. protected:
  204. typedef typename wxScopedCharTypeBuffer<T>::Data Data;
  205. public:
  206. typedef T CharType;
  207. wxCharTypeBuffer(const CharType *str = NULL, size_t len = wxNO_LEN)
  208. {
  209. if ( str )
  210. {
  211. if ( len == wxNO_LEN )
  212. len = wxStrlen(str);
  213. this->m_data = new Data(this->StrCopy(str, len), len);
  214. }
  215. else
  216. {
  217. this->m_data = this->GetNullData();
  218. }
  219. }
  220. wxCharTypeBuffer(size_t len)
  221. {
  222. CharType* const str = (CharType *)malloc((len + 1)*sizeof(CharType));
  223. if ( str )
  224. {
  225. str[len] = (CharType)0;
  226. // There is a potential memory leak here if new throws because it
  227. // fails to allocate Data, we ought to use new(nothrow) here, but
  228. // this might fail to compile under some platforms so until this
  229. // can be fully tested, just live with this (rather unlikely, as
  230. // Data is a small object) potential leak.
  231. this->m_data = new Data(str, len);
  232. }
  233. else
  234. {
  235. this->m_data = this->GetNullData();
  236. }
  237. }
  238. wxCharTypeBuffer(const wxCharTypeBuffer& src)
  239. : wxScopedCharTypeBuffer<T>(src) {}
  240. wxCharTypeBuffer& operator=(const CharType *str)
  241. {
  242. this->DecRef();
  243. if ( str )
  244. this->m_data = new Data(wxStrdup(str), wxStrlen(str));
  245. return *this;
  246. }
  247. wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
  248. {
  249. wxScopedCharTypeBuffer<T>::operator=(src);
  250. return *this;
  251. }
  252. wxCharTypeBuffer(const wxScopedCharTypeBuffer<T>& src)
  253. {
  254. this->MakeOwnedCopyOf(src);
  255. }
  256. wxCharTypeBuffer& operator=(const wxScopedCharTypeBuffer<T>& src)
  257. {
  258. MakeOwnedCopyOf(src);
  259. return *this;
  260. }
  261. bool extend(size_t len)
  262. {
  263. wxASSERT_MSG( this->m_data->m_owned, "cannot extend non-owned buffer" );
  264. wxASSERT_MSG( this->m_data->m_ref == 1, "can't extend shared buffer" );
  265. CharType *str =
  266. (CharType *)realloc(this->data(), (len + 1) * sizeof(CharType));
  267. if ( !str )
  268. return false;
  269. // For consistency with the ctor taking just the length, NUL-terminate
  270. // the buffer.
  271. str[len] = (CharType)0;
  272. if ( this->m_data == this->GetNullData() )
  273. {
  274. this->m_data = new Data(str, len);
  275. }
  276. else
  277. {
  278. this->m_data->Set(str, len);
  279. this->m_data->m_owned = true;
  280. }
  281. return true;
  282. }
  283. void shrink(size_t len)
  284. {
  285. wxASSERT_MSG( this->m_data->m_owned, "cannot shrink non-owned buffer" );
  286. wxASSERT_MSG( this->m_data->m_ref == 1, "can't shrink shared buffer" );
  287. wxASSERT( len <= this->length() );
  288. this->m_data->m_length = len;
  289. this->data()[len] = 0;
  290. }
  291. };
  292. WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxScopedCharTypeBuffer<char> )
  293. WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<char> )
  294. class wxCharBuffer : public wxCharTypeBuffer<char>
  295. {
  296. public:
  297. typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
  298. typedef wxScopedCharTypeBuffer<char> wxScopedCharTypeBufferBase;
  299. wxCharBuffer(const wxCharTypeBufferBase& buf)
  300. : wxCharTypeBufferBase(buf) {}
  301. wxCharBuffer(const wxScopedCharTypeBufferBase& buf)
  302. : wxCharTypeBufferBase(buf) {}
  303. wxCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
  304. wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
  305. wxCharBuffer(const wxCStrData& cstr);
  306. };
  307. WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxScopedCharTypeBuffer<wchar_t> )
  308. WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxCharTypeBuffer<wchar_t> )
  309. class wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
  310. {
  311. public:
  312. typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
  313. typedef wxScopedCharTypeBuffer<wchar_t> wxScopedCharTypeBufferBase;
  314. wxWCharBuffer(const wxCharTypeBufferBase& buf)
  315. : wxCharTypeBufferBase(buf) {}
  316. wxWCharBuffer(const wxScopedCharTypeBufferBase& buf)
  317. : wxCharTypeBufferBase(buf) {}
  318. wxWCharBuffer(const CharType *str = NULL) : wxCharTypeBufferBase(str) {}
  319. wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
  320. wxWCharBuffer(const wxCStrData& cstr);
  321. };
  322. // wxCharTypeBuffer<T> implicitly convertible to T*
  323. template <typename T>
  324. class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
  325. {
  326. public:
  327. typedef typename wxScopedCharTypeBuffer<T>::CharType CharType;
  328. wxWritableCharTypeBuffer(const wxScopedCharTypeBuffer<T>& src)
  329. : wxCharTypeBuffer<T>(src) {}
  330. // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
  331. // always return a buffer
  332. // + we should derive this class from wxScopedCharTypeBuffer
  333. // then
  334. wxWritableCharTypeBuffer(const CharType *str = NULL)
  335. : wxCharTypeBuffer<T>(str) {}
  336. operator CharType*() { return this->data(); }
  337. };
  338. typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
  339. typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
  340. #if wxUSE_UNICODE
  341. #define wxWxCharBuffer wxWCharBuffer
  342. #define wxMB2WXbuf wxWCharBuffer
  343. #define wxWX2MBbuf wxCharBuffer
  344. #if wxUSE_UNICODE_WCHAR
  345. #define wxWC2WXbuf wxChar*
  346. #define wxWX2WCbuf wxChar*
  347. #elif wxUSE_UNICODE_UTF8
  348. #define wxWC2WXbuf wxWCharBuffer
  349. #define wxWX2WCbuf wxWCharBuffer
  350. #endif
  351. #else // ANSI
  352. #define wxWxCharBuffer wxCharBuffer
  353. #define wxMB2WXbuf wxChar*
  354. #define wxWX2MBbuf wxChar*
  355. #define wxWC2WXbuf wxCharBuffer
  356. #define wxWX2WCbuf wxWCharBuffer
  357. #endif // Unicode/ANSI
  358. // ----------------------------------------------------------------------------
  359. // A class for holding growable data buffers (not necessarily strings)
  360. // ----------------------------------------------------------------------------
  361. // This class manages the actual data buffer pointer and is ref-counted.
  362. class wxMemoryBufferData
  363. {
  364. public:
  365. // the initial size and also the size added by ResizeIfNeeded()
  366. enum { DefBufSize = 1024 };
  367. friend class wxMemoryBuffer;
  368. // everything is private as it can only be used by wxMemoryBuffer
  369. private:
  370. wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
  371. : m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
  372. {
  373. }
  374. ~wxMemoryBufferData() { free(m_data); }
  375. void ResizeIfNeeded(size_t newSize)
  376. {
  377. if (newSize > m_size)
  378. {
  379. void *dataOld = m_data;
  380. m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
  381. if ( !m_data )
  382. {
  383. free(dataOld);
  384. }
  385. m_size = newSize + wxMemoryBufferData::DefBufSize;
  386. }
  387. }
  388. void IncRef() { m_ref += 1; }
  389. void DecRef()
  390. {
  391. m_ref -= 1;
  392. if (m_ref == 0) // are there no more references?
  393. delete this;
  394. }
  395. void *release()
  396. {
  397. if ( m_data == NULL )
  398. return NULL;
  399. wxASSERT_MSG( m_ref == 1, "can't release shared buffer" );
  400. void *p = m_data;
  401. m_data = NULL;
  402. m_len =
  403. m_size = 0;
  404. return p;
  405. }
  406. // the buffer containing the data
  407. void *m_data;
  408. // the size of the buffer
  409. size_t m_size;
  410. // the amount of data currently in the buffer
  411. size_t m_len;
  412. // the reference count
  413. size_t m_ref;
  414. wxDECLARE_NO_COPY_CLASS(wxMemoryBufferData);
  415. };
  416. class wxMemoryBuffer
  417. {
  418. public:
  419. // ctor and dtor
  420. wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
  421. {
  422. m_bufdata = new wxMemoryBufferData(size);
  423. m_bufdata->IncRef();
  424. }
  425. ~wxMemoryBuffer() { m_bufdata->DecRef(); }
  426. // copy and assignment
  427. wxMemoryBuffer(const wxMemoryBuffer& src)
  428. : m_bufdata(src.m_bufdata)
  429. {
  430. m_bufdata->IncRef();
  431. }
  432. wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
  433. {
  434. if (&src != this)
  435. {
  436. m_bufdata->DecRef();
  437. m_bufdata = src.m_bufdata;
  438. m_bufdata->IncRef();
  439. }
  440. return *this;
  441. }
  442. // Accessors
  443. void *GetData() const { return m_bufdata->m_data; }
  444. size_t GetBufSize() const { return m_bufdata->m_size; }
  445. size_t GetDataLen() const { return m_bufdata->m_len; }
  446. bool IsEmpty() const { return GetDataLen() == 0; }
  447. void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
  448. void SetDataLen(size_t len)
  449. {
  450. wxASSERT(len <= m_bufdata->m_size);
  451. m_bufdata->m_len = len;
  452. }
  453. void Clear() { SetDataLen(0); }
  454. // Ensure the buffer is big enough and return a pointer to it
  455. void *GetWriteBuf(size_t sizeNeeded)
  456. {
  457. m_bufdata->ResizeIfNeeded(sizeNeeded);
  458. return m_bufdata->m_data;
  459. }
  460. // Update the length after the write
  461. void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
  462. // Like the above, but appends to the buffer
  463. void *GetAppendBuf(size_t sizeNeeded)
  464. {
  465. m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
  466. return (char*)m_bufdata->m_data + m_bufdata->m_len;
  467. }
  468. // Update the length after the append
  469. void UngetAppendBuf(size_t sizeUsed)
  470. {
  471. SetDataLen(m_bufdata->m_len + sizeUsed);
  472. }
  473. // Other ways to append to the buffer
  474. void AppendByte(char data)
  475. {
  476. wxCHECK_RET( m_bufdata->m_data, wxT("invalid wxMemoryBuffer") );
  477. m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
  478. *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
  479. m_bufdata->m_len += 1;
  480. }
  481. void AppendData(const void *data, size_t len)
  482. {
  483. memcpy(GetAppendBuf(len), data, len);
  484. UngetAppendBuf(len);
  485. }
  486. operator const char *() const { return (const char*)GetData(); }
  487. // gives up ownership of data, returns the pointer; after this call,
  488. // data isn't freed by the buffer and its content is resent to empty
  489. void *release()
  490. {
  491. return m_bufdata->release();
  492. }
  493. private:
  494. wxMemoryBufferData* m_bufdata;
  495. };
  496. // ----------------------------------------------------------------------------
  497. // template class for any kind of data
  498. // ----------------------------------------------------------------------------
  499. // TODO
  500. #endif // _WX_BUFFER_H