Advertisement
Guest User

Untitled

a guest
Jan 18th, 2017
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.65 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iterator>
  3. #include <memory>
  4.  
  5. namespace sg14 {
  6.  
  7. template<typename T>
  8. class buffer : public std::iterator_traits<T*> {
  9. public:
  10. using size_type = typename buffer<T>::difference_type;
  11.  
  12. buffer() noexcept = default;
  13.  
  14. buffer(buffer const& rhs)
  15. :buffer(rhs.size())
  16. {
  17. std::copy(std::begin(rhs), std::end(rhs), std::begin(*this));
  18. }
  19.  
  20. buffer(int size)
  21. :first(new T[size]), last(data() + size) { }
  22.  
  23. buffer& operator=(buffer const& rhs)
  24. {
  25. using std::swap;
  26.  
  27. auto copy = rhs;
  28. swap(*this, copy);
  29.  
  30. return *this;
  31. }
  32.  
  33. bool empty() const noexcept
  34. {
  35. return cbegin() == cend();
  36. }
  37.  
  38. size_type size() const noexcept
  39. {
  40. return std::distance(cbegin(), cend());
  41. }
  42.  
  43. T* begin() noexcept
  44. {
  45. return data();
  46. }
  47.  
  48. T const* begin() const noexcept
  49. {
  50. return data();
  51. }
  52.  
  53. T const* cbegin() const noexcept
  54. {
  55. return data();
  56. }
  57.  
  58. T* end() noexcept
  59. {
  60. return last;
  61. }
  62.  
  63. T const* end() const noexcept
  64. {
  65. return last;
  66. }
  67.  
  68. T const* cend() const noexcept
  69. {
  70. return last;
  71. }
  72.  
  73. T* data() noexcept
  74. {
  75. return first.get();
  76. }
  77.  
  78. T const* data() const noexcept
  79. {
  80. return first.get();
  81. }
  82.  
  83. friend void swap(buffer& lhs, buffer& rhs) noexcept
  84. {
  85. using std::swap;
  86. swap(lhs.first, rhs.first);
  87. swap(lhs.last, rhs.last);
  88. }
  89.  
  90. private:
  91. std::unique_ptr<T[]> first;
  92. T* last = nullptr;
  93. };
  94.  
  95. template<typename LT, typename RT>
  96. bool
  97. operator==(buffer<LT> const& lhs, buffer<RT> const& rhs) noexcept(noexcept(std::equal(std::begin(lhs), std::end(lhs),
  98. std::begin(rhs))))
  99. {
  100. return (lhs.size() == rhs.size()) && std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
  101. }
  102.  
  103. template<typename LT, typename RT>
  104. bool operator!=(buffer<LT> const& lhs, buffer<RT> const& rhs) noexcept(noexcept(lhs == rhs))
  105. {
  106. return !(lhs == rhs);
  107. }
  108.  
  109. }
  110.  
  111. #include <cassert>
  112. #include <iostream>
  113. #include <string>
  114. #include <type_traits>
  115.  
  116. namespace {
  117. using byte = std::uint8_t;
  118. constexpr auto uninitialized = byte{0x1a};
  119.  
  120. template<typename T>
  121. void test(T const& some_value)
  122. {
  123. using buffer = sg14::buffer<T>;
  124. static_assert(sizeof(buffer) == 2 * sizeof(T*), "");
  125. static_assert(std::is_same<typename buffer::iterator_category, std::random_access_iterator_tag>::value, "");
  126. static_assert(std::is_same<typename buffer::value_type, T>::value, "");
  127. static_assert(std::is_same<typename buffer::difference_type, std::ptrdiff_t>::value, "");
  128. static_assert(std::is_same<typename buffer::pointer, T*>::value, "");
  129. static_assert(std::is_same<typename buffer::reference, T&>::value, "");
  130. static_assert(std::is_same<typename buffer::size_type, std::ptrdiff_t>::value, "");
  131.  
  132. buffer sequence(10);
  133. std::fill(std::begin(sequence), std::end(sequence), some_value);
  134.  
  135. auto empty_sequence = buffer();
  136. assert(empty_sequence.size() == 0);
  137.  
  138. {
  139. auto copied_sequence(sequence);
  140. assert(sequence == copied_sequence);
  141. assert(empty_sequence != copied_sequence);
  142.  
  143. copied_sequence = empty_sequence;
  144. assert(sequence != copied_sequence);
  145. assert(empty_sequence == copied_sequence);
  146. }
  147.  
  148. assert(sequence != empty_sequence);
  149.  
  150. for (auto n : sequence) {
  151. assert(n == some_value);
  152. }
  153. }
  154.  
  155. template<typename T>
  156. void test_pod(sg14::buffer<T> const& default_sequence, T const& some_value)
  157. {
  158. // for every byte in the buffer.
  159. auto data_begin = reinterpret_cast<std::uint8_t const*>(default_sequence.data());
  160. auto data_end = reinterpret_cast<std::uint8_t const*>(default_sequence.data() + default_sequence.size());
  161.  
  162. std::for_each(data_begin, data_end, [](T b) {
  163. assert(b == uninitialized);
  164. });
  165.  
  166. test(some_value);
  167. }
  168.  
  169. template<typename T>
  170. void test_non_pod(sg14::buffer<T> const& default_sequence, T const& some_value)
  171. {
  172. std::for_each(std::begin(default_sequence), std::end(default_sequence), [](T e) {
  173. assert(e == T());
  174. });
  175.  
  176. test(some_value);
  177. }
  178.  
  179. void trash_heap()
  180. {
  181. constexpr auto bytes_of_heap_to_trash = 10000;
  182.  
  183. auto buffer = (std::uint8_t*) (malloc(bytes_of_heap_to_trash));
  184. std::fill(buffer, buffer + bytes_of_heap_to_trash, uninitialized);
  185. delete buffer;
  186. }
  187. }
  188.  
  189. int main()
  190. {
  191. trash_heap();
  192.  
  193. auto char_buffer = sg14::buffer<char>(10);
  194. auto int_buffer = sg14::buffer<int>(10);
  195. auto double_buffer = sg14::buffer<double>(10);
  196. auto string_buffer = sg14::buffer<std::string>(10);
  197.  
  198. test_pod(char_buffer, char{0x7f});
  199. test_pod(int_buffer, 0x12345678);
  200. test_pod(double_buffer, 98765.4321);
  201. test_non_pod(string_buffer, std::string{"abc XYZ 987"});
  202. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement