buffer.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*-
  2. * Copyright 2012-2018 Matthew Endsley
  3. * All rights reserved
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted providing that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  18. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  22. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  23. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #ifndef TINYSTL_BUFFER_H
  27. #define TINYSTL_BUFFER_H
  28. #include <tinystl/allocator.h>
  29. #include <tinystl/new.h>
  30. #include <tinystl/traits.h>
  31. namespace tinystl {
  32. template<typename T, typename Alloc = TINYSTL_ALLOCATOR>
  33. struct buffer {
  34. T* first;
  35. T* last;
  36. T* capacity;
  37. };
  38. template<typename T>
  39. static inline void buffer_destroy_range_traits(T* first, T* last, pod_traits<T, false>) {
  40. for (; first < last; ++first)
  41. first->~T();
  42. }
  43. template<typename T>
  44. static inline void buffer_destroy_range_traits(T*, T*, pod_traits<T, true>) {
  45. }
  46. template<typename T>
  47. static inline void buffer_destroy_range(T* first, T* last) {
  48. buffer_destroy_range_traits(first, last, pod_traits<T>());
  49. }
  50. template<typename T>
  51. static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, false>) {
  52. for (; first < last; ++first)
  53. new(placeholder(), first) T();
  54. }
  55. template<typename T>
  56. static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, true>) {
  57. for (; first < last; ++first)
  58. *first = T();
  59. }
  60. template<typename T>
  61. static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, false>) {
  62. for (; first < last; ++first)
  63. new(placeholder(), first) T(value);
  64. }
  65. template<typename T>
  66. static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, true>) {
  67. for (; first < last; ++first)
  68. *first = value;
  69. }
  70. template<typename T>
  71. static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
  72. for (T* it = first; it != last; ++it, ++dest)
  73. move_construct(dest, *it);
  74. buffer_destroy_range(first, last);
  75. }
  76. template<typename T>
  77. static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
  78. for (; first != last; ++first, ++dest)
  79. *dest = *first;
  80. }
  81. template<typename T>
  82. static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
  83. dest += (last - first);
  84. for (T* it = last; it != first; --it, --dest) {
  85. move_construct(dest - 1, *(it - 1));
  86. buffer_destroy_range(it - 1, it);
  87. }
  88. }
  89. template<typename T>
  90. static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
  91. dest += (last - first);
  92. for (T* it = last; it != first; --it, --dest)
  93. *(dest - 1) = *(it - 1);
  94. }
  95. template<typename T>
  96. static inline void buffer_move_urange(T* dest, T* first, T* last) {
  97. buffer_move_urange_traits(dest, first, last, pod_traits<T>());
  98. }
  99. template<typename T>
  100. static inline void buffer_bmove_urange(T* dest, T* first, T* last) {
  101. buffer_bmove_urange_traits(dest, first, last, pod_traits<T>());
  102. }
  103. template<typename T>
  104. static inline void buffer_fill_urange(T* first, T* last) {
  105. buffer_fill_urange_traits(first, last, pod_traits<T>());
  106. }
  107. template<typename T>
  108. static inline void buffer_fill_urange(T* first, T* last, const T& value) {
  109. buffer_fill_urange_traits(first, last, value, pod_traits<T>());
  110. }
  111. template<typename T, typename Alloc>
  112. static inline void buffer_init(buffer<T, Alloc>* b) {
  113. b->first = b->last = b->capacity = 0;
  114. }
  115. template<typename T, typename Alloc>
  116. static inline void buffer_destroy(buffer<T, Alloc>* b) {
  117. buffer_destroy_range(b->first, b->last);
  118. Alloc::static_deallocate(b->first, (size_t)((char*)b->capacity - (char*)b->first));
  119. }
  120. template<typename T, typename Alloc>
  121. static inline void buffer_reserve(buffer<T, Alloc>* b, size_t capacity) {
  122. if (b->first && b->first + capacity <= b->capacity)
  123. return;
  124. typedef T* pointer;
  125. const size_t size = (size_t)(b->last - b->first);
  126. pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity);
  127. buffer_move_urange(newfirst, b->first, b->last);
  128. Alloc::static_deallocate(b->first, sizeof(T) * capacity);
  129. b->first = newfirst;
  130. b->last = newfirst + size;
  131. b->capacity = newfirst + capacity;
  132. }
  133. template<typename T, typename Alloc>
  134. static inline void buffer_resize(buffer<T, Alloc>* b, size_t size) {
  135. buffer_reserve(b, size);
  136. buffer_fill_urange(b->last, b->first + size);
  137. buffer_destroy_range(b->first + size, b->last);
  138. b->last = b->first + size;
  139. }
  140. template<typename T, typename Alloc>
  141. static inline void buffer_resize(buffer<T, Alloc>* b, size_t size, const T& value) {
  142. buffer_reserve(b, size);
  143. buffer_fill_urange(b->last, b->first + size, value);
  144. buffer_destroy_range(b->first + size, b->last);
  145. b->last = b->first + size;
  146. }
  147. template<typename T, typename Alloc>
  148. static inline void buffer_shrink_to_fit(buffer<T, Alloc>* b) {
  149. if (b->capacity != b->last) {
  150. if (b->last == b->first) {
  151. const size_t capacity = (size_t)(b->capacity - b->first);
  152. Alloc::static_deallocate(b->first, sizeof(T)*capacity);
  153. b->capacity = b->first = b->last = nullptr;
  154. } else {
  155. const size_t capacity = (size_t)(b->capacity - b->first);
  156. const size_t size = (size_t)(b->last - b->first);
  157. T* newfirst = (T*)Alloc::static_allocate(sizeof(T) * size);
  158. buffer_move_urange(newfirst, b->first, b->last);
  159. Alloc::static_deallocate(b->first, sizeof(T) * capacity);
  160. b->first = newfirst;
  161. b->last = newfirst + size;
  162. b->capacity = b->last;
  163. }
  164. }
  165. }
  166. template<typename T, typename Alloc>
  167. static inline void buffer_clear(buffer<T, Alloc>* b) {
  168. buffer_destroy_range(b->first, b->last);
  169. b->last = b->first;
  170. }
  171. template<typename T, typename Alloc>
  172. static inline T* buffer_insert_common(buffer<T, Alloc>* b, T* where, size_t count) {
  173. const size_t offset = (size_t)(where - b->first);
  174. const size_t newsize = (size_t)((b->last - b->first) + count);
  175. if (!b->first || b->first + newsize > b->capacity)
  176. buffer_reserve(b, (newsize * 3) / 2);
  177. where = b->first + offset;
  178. if (where != b->last)
  179. buffer_bmove_urange(where + count, where, b->last);
  180. b->last = b->first + newsize;
  181. return where;
  182. }
  183. template<typename T, typename Alloc, typename Param>
  184. static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const Param* first, const Param* last) {
  185. typedef const char* pointer;
  186. const size_t count = last - first;
  187. const bool frombuf = ((pointer)b->first <= (pointer)first && (pointer)b->last >= (pointer)last);
  188. size_t offset;
  189. if (frombuf) {
  190. offset = (pointer)first - (pointer)b->first;
  191. if ((pointer)where <= (pointer)first)
  192. offset += count * sizeof(T);
  193. where = buffer_insert_common(b, where, count);
  194. first = (Param*)((pointer)b->first + offset);
  195. last = first + count;
  196. }
  197. else {
  198. where = buffer_insert_common(b, where, count);
  199. }
  200. for (; first != last; ++first, ++where)
  201. new(placeholder(), where) T(*first);
  202. }
  203. template<typename T, typename Alloc>
  204. static inline void buffer_insert(buffer<T, Alloc>* b, T* where, size_t count) {
  205. where = buffer_insert_common(b, where, count);
  206. for (T* end = where+count; where != end; ++where)
  207. new(placeholder(), where) T();
  208. }
  209. template<typename T, typename Alloc, typename Param>
  210. static inline void buffer_append(buffer<T, Alloc>* b, const Param* param) {
  211. if (b->capacity != b->last) {
  212. new(placeholder(), b->last) T(*param);
  213. ++b->last;
  214. } else {
  215. buffer_insert(b, b->last, param, param + 1);
  216. }
  217. }
  218. template<typename T, typename Alloc>
  219. static inline void buffer_append(buffer<T, Alloc>* b) {
  220. if (b->capacity != b->last) {
  221. new(placeholder(), b->last) T();
  222. ++b->last;
  223. } else {
  224. buffer_insert(b, b->last, 1);
  225. }
  226. }
  227. template<typename T, typename Alloc>
  228. static inline T* buffer_erase(buffer<T, Alloc>* b, T* first, T* last) {
  229. typedef T* pointer;
  230. const size_t count = (last - first);
  231. for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest)
  232. move(*dest, *it);
  233. buffer_destroy_range(b->last - count, b->last);
  234. b->last -= count;
  235. return first;
  236. }
  237. template<typename T, typename Alloc>
  238. static inline T* buffer_erase_unordered(buffer<T, Alloc>* b, T* first, T* last) {
  239. typedef T* pointer;
  240. const size_t count = (last - first);
  241. const size_t tail = (b->last - last);
  242. pointer it = b->last - ((count < tail) ? count : tail);
  243. for (pointer end = b->last, dest = first; it != end; ++it, ++dest)
  244. move(*dest, *it);
  245. buffer_destroy_range(b->last - count, b->last);
  246. b->last -= count;
  247. return first;
  248. }
  249. template<typename T, typename Alloc>
  250. static inline void buffer_swap(buffer<T, Alloc>* b, buffer<T, Alloc>* other) {
  251. typedef T* pointer;
  252. const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity;
  253. b->first = other->first, b->last = other->last, b->capacity = other->capacity;
  254. other->first = tfirst, other->last = tlast, other->capacity = tcapacity;
  255. }
  256. template<typename T, typename Alloc>
  257. static inline void buffer_move(buffer<T, Alloc>* dst, buffer<T, Alloc>* src) {
  258. dst->first = src->first, dst->last = src->last, dst->capacity = src->capacity;
  259. src->first = src->last = src->capacity = nullptr;
  260. }
  261. }
  262. #endif //TINYSTL_BUFFER_H