Buffer.h 6.8 KB

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