Buffer.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. //
  2. // Buffer.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/Buffer.h#2 $
  5. //
  6. // Library: Foundation
  7. // Package: Core
  8. // Module: Buffer
  9. //
  10. // Definition of the Buffer class.
  11. //
  12. // Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_Buffer_INCLUDED
  18. #define Foundation_Buffer_INCLUDED
  19. #include "Poco/Foundation.h"
  20. #include "Poco/Exception.h"
  21. #include <cstring>
  22. #include <cstddef>
  23. namespace Poco {
  24. template <class T>
  25. class Buffer
  26. /// A buffer class that allocates a buffer of a given type and size
  27. /// in the constructor and deallocates the buffer in the destructor.
  28. ///
  29. /// This class is useful everywhere where a temporary buffer
  30. /// is needed.
  31. {
  32. public:
  33. Buffer(std::size_t capacity):
  34. _capacity(capacity),
  35. _used(capacity),
  36. _ptr(0),
  37. _ownMem(true)
  38. /// Creates and allocates the Buffer.
  39. {
  40. if (capacity > 0)
  41. {
  42. _ptr = new T[capacity];
  43. }
  44. }
  45. Buffer(T* pMem, std::size_t length):
  46. _capacity(length),
  47. _used(length),
  48. _ptr(pMem),
  49. _ownMem(false)
  50. /// Creates the Buffer. Length argument specifies the length
  51. /// of the supplied memory pointed to by pMem in the number
  52. /// of elements of type T. Supplied pointer is considered
  53. /// blank and not owned by Buffer, so in this case Buffer
  54. /// only acts as a wrapper around externally supplied
  55. /// (and lifetime-managed) memory.
  56. {
  57. }
  58. Buffer(const T* pMem, std::size_t length):
  59. _capacity(length),
  60. _used(length),
  61. _ptr(0),
  62. _ownMem(true)
  63. /// Creates and allocates the Buffer; copies the contents of
  64. /// the supplied memory into the buffer. Length argument specifies
  65. /// the length of the supplied memory pointed to by pMem in the
  66. /// number of elements of type T.
  67. {
  68. if (_capacity > 0)
  69. {
  70. _ptr = new T[_capacity];
  71. std::memcpy(_ptr, pMem, _used * sizeof(T));
  72. }
  73. }
  74. Buffer(const Buffer& other):
  75. /// Copy constructor.
  76. _capacity(other._used),
  77. _used(other._used),
  78. _ptr(0),
  79. _ownMem(true)
  80. {
  81. if (_used)
  82. {
  83. _ptr = new T[_used];
  84. std::memcpy(_ptr, other._ptr, _used * sizeof(T));
  85. }
  86. }
  87. Buffer& operator = (const Buffer& other)
  88. /// Assignment operator.
  89. {
  90. if (this != &other)
  91. {
  92. Buffer tmp(other);
  93. swap(tmp);
  94. }
  95. return *this;
  96. }
  97. ~Buffer()
  98. /// Destroys the Buffer.
  99. {
  100. if (_ownMem) delete [] _ptr;
  101. }
  102. void resize(std::size_t newCapacity, bool preserveContent = true)
  103. /// Resizes the buffer capacity and size. If preserveContent is true,
  104. /// the content of the old buffer is copied over to the
  105. /// new buffer. The new capacity can be larger or smaller than
  106. /// the current one; if it is smaller, capacity will remain intact.
  107. /// Size will always be set to the new capacity.
  108. ///
  109. /// Buffers only wrapping externally owned storage can not be
  110. /// resized. If resize is attempted on those, IllegalAccessException
  111. /// is thrown.
  112. {
  113. if (!_ownMem) throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage.");
  114. if (newCapacity > _capacity)
  115. {
  116. T* ptr = new T[newCapacity];
  117. if (preserveContent)
  118. {
  119. std::memcpy(ptr, _ptr, _used * sizeof(T));
  120. }
  121. delete [] _ptr;
  122. _ptr = ptr;
  123. _capacity = newCapacity;
  124. }
  125. _used = newCapacity;
  126. }
  127. void setCapacity(std::size_t newCapacity, bool preserveContent = true)
  128. /// Sets the buffer capacity. If preserveContent is true,
  129. /// the content of the old buffer is copied over to the
  130. /// new buffer. The new capacity can be larger or smaller than
  131. /// the current one; size will be set to the new capacity only if
  132. /// new capacity is smaller than the current size, otherwise it will
  133. /// remain intact.
  134. ///
  135. /// Buffers only wrapping externally owned storage can not be
  136. /// resized. If resize is attempted on those, IllegalAccessException
  137. /// is thrown.
  138. {
  139. if (!_ownMem) throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage.");
  140. if (newCapacity != _capacity)
  141. {
  142. T* ptr = 0;
  143. if (newCapacity > 0)
  144. {
  145. ptr = new T[newCapacity];
  146. if (preserveContent)
  147. {
  148. std::size_t newSz = _used < newCapacity ? _used : newCapacity;
  149. std::memcpy(ptr, _ptr, newSz * sizeof(T));
  150. }
  151. }
  152. delete [] _ptr;
  153. _ptr = ptr;
  154. _capacity = newCapacity;
  155. if (newCapacity < _used) _used = newCapacity;
  156. }
  157. }
  158. void assign(const T* buf, std::size_t sz)
  159. /// Assigns the argument buffer to this buffer.
  160. /// If necessary, resizes the buffer.
  161. {
  162. if (0 == sz) return;
  163. if (sz > _capacity) resize(sz, false);
  164. std::memcpy(_ptr, buf, sz * sizeof(T));
  165. _used = sz;
  166. }
  167. void append(const T* buf, std::size_t sz)
  168. /// Resizes this buffer and appends the argument buffer.
  169. {
  170. if (0 == sz) return;
  171. resize(_used + sz, true);
  172. std::memcpy(_ptr + _used - sz, buf, sz * sizeof(T));
  173. }
  174. void append(T val)
  175. /// Resizes this buffer by one element and appends the argument value.
  176. {
  177. resize(_used + 1, true);
  178. _ptr[_used - 1] = val;
  179. }
  180. void append(const Buffer& buf)
  181. /// Resizes this buffer and appends the argument buffer.
  182. {
  183. append(buf.begin(), buf.size());
  184. }
  185. std::size_t capacity() const
  186. /// Returns the allocated memory size in elements.
  187. {
  188. return _capacity;
  189. }
  190. std::size_t capacityBytes() const
  191. /// Returns the allocated memory size in bytes.
  192. {
  193. return _capacity * sizeof(T);
  194. }
  195. void swap(Buffer& other)
  196. /// Swaps the buffer with another one.
  197. {
  198. using std::swap;
  199. swap(_ptr, other._ptr);
  200. swap(_capacity, other._capacity);
  201. swap(_used, other._used);
  202. }
  203. bool operator == (const Buffer& other) const
  204. /// Compare operator.
  205. {
  206. if (this != &other)
  207. {
  208. if (_used == other._used)
  209. {
  210. if (std::memcmp(_ptr, other._ptr, _used * sizeof(T)) == 0)
  211. {
  212. return true;
  213. }
  214. }
  215. return false;
  216. }
  217. return true;
  218. }
  219. bool operator != (const Buffer& other) const
  220. /// Compare operator.
  221. {
  222. return !(*this == other);
  223. }
  224. void clear()
  225. /// Sets the contents of the buffer to zero.
  226. {
  227. std::memset(_ptr, 0, _used * sizeof(T));
  228. }
  229. std::size_t size() const
  230. /// Returns the used size of the buffer in elements.
  231. {
  232. return _used;
  233. }
  234. std::size_t sizeBytes() const
  235. /// Returns the used size of the buffer in bytes.
  236. {
  237. return _used * sizeof(T);
  238. }
  239. T* begin()
  240. /// Returns a pointer to the beginning of the buffer.
  241. {
  242. return _ptr;
  243. }
  244. const T* begin() const
  245. /// Returns a pointer to the beginning of the buffer.
  246. {
  247. return _ptr;
  248. }
  249. T* end()
  250. /// Returns a pointer to end of the buffer.
  251. {
  252. return _ptr + _used;
  253. }
  254. const T* end() const
  255. /// Returns a pointer to the end of the buffer.
  256. {
  257. return _ptr + _used;
  258. }
  259. bool empty() const
  260. /// Return true if buffer is empty.
  261. {
  262. return 0 == _used;
  263. }
  264. T& operator [] (std::size_t index)
  265. {
  266. poco_assert (index < _used);
  267. return _ptr[index];
  268. }
  269. const T& operator [] (std::size_t index) const
  270. {
  271. poco_assert (index < _used);
  272. return _ptr[index];
  273. }
  274. private:
  275. Buffer();
  276. std::size_t _capacity;
  277. std::size_t _used;
  278. T* _ptr;
  279. bool _ownMem;
  280. };
  281. } // namespace Poco
  282. #endif // Foundation_Buffer_INCLUDED