buffer.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*-
  2. * Copyright 2012-1015 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 "new.h"
  29. #include "traits.h"
  30. namespace tinystl {
  31. template<typename T, typename Alloc = TINYSTL_ALLOCATOR>
  32. struct buffer {
  33. T* first;
  34. T* last;
  35. T* capacity;
  36. };
  37. template<typename T>
  38. static inline void buffer_destroy_range_traits(T* first, T* last, pod_traits<T, false>) {
  39. for (; first < last; ++first)
  40. first->~T();
  41. }
  42. template<typename T>
  43. static inline void buffer_destroy_range_traits(T*, T*, pod_traits<T, true>) {
  44. }
  45. template<typename T>
  46. static inline void buffer_destroy_range(T* first, T* last) {
  47. buffer_destroy_range_traits(first, last, pod_traits<T>());
  48. }
  49. template<typename T>
  50. static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, false>) {
  51. for (; first < last; ++first)
  52. new(placeholder(), first) T();
  53. }
  54. template<typename T>
  55. static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, true>) {
  56. for (; first < last; ++first)
  57. *first = T();
  58. }
  59. template<typename T>
  60. static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, false>) {
  61. for (; first < last; ++first)
  62. new(placeholder(), first) T(value);
  63. }
  64. template<typename T>
  65. static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, true>) {
  66. for (; first < last; ++first)
  67. *first = value;
  68. }
  69. template<typename T>
  70. static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
  71. for (T* it = first; it != last; ++it, ++dest)
  72. move_construct(dest, *it);
  73. buffer_destroy_range(first, last);
  74. }
  75. template<typename T>
  76. static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
  77. for (; first != last; ++first, ++dest)
  78. *dest = *first;
  79. }
  80. template<typename T>
  81. static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
  82. dest += (last - first);
  83. for (T* it = last; it != first; --it, --dest) {
  84. move_construct(dest - 1, *(it - 1));
  85. buffer_destroy_range(it - 1, it);
  86. }
  87. }
  88. template<typename T>
  89. static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
  90. dest += (last - first);
  91. for (T* it = last; it != first; --it, --dest)
  92. *(dest - 1) = *(it - 1);
  93. }
  94. template<typename T>
  95. static inline void buffer_move_urange(T* dest, T* first, T* last) {
  96. buffer_move_urange_traits(dest, first, last, pod_traits<T>());
  97. }
  98. template<typename T>
  99. static inline void buffer_bmove_urange(T* dest, T* first, T* last) {
  100. buffer_bmove_urange_traits(dest, first, last, pod_traits<T>());
  101. }
  102. template<typename T>
  103. static inline void buffer_fill_urange(T* first, T* last) {
  104. buffer_fill_urange_traits(first, last, pod_traits<T>());
  105. }
  106. template<typename T>
  107. static inline void buffer_fill_urange(T* first, T* last, const T& value) {
  108. buffer_fill_urange_traits(first, last, value, pod_traits<T>());
  109. }
  110. template<typename T, typename Alloc>
  111. static inline void buffer_init(buffer<T, Alloc>* b) {
  112. b->first = b->last = b->capacity = 0;
  113. }
  114. template<typename T, typename Alloc>
  115. static inline void buffer_destroy(buffer<T, Alloc>* b) {
  116. buffer_destroy_range(b->first, b->last);
  117. Alloc::static_deallocate(b->first, (size_t)((char*)b->capacity - (char*)b->first));
  118. }
  119. template<typename T, typename Alloc>
  120. static inline void buffer_reserve(buffer<T, Alloc>* b, size_t capacity) {
  121. if (b->first + capacity <= b->capacity)
  122. return;
  123. typedef T* pointer;
  124. const size_t size = (size_t)(b->last - b->first);
  125. pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity);
  126. buffer_move_urange(newfirst, b->first, b->last);
  127. Alloc::static_deallocate(b->first, sizeof(T) * capacity);
  128. b->first = newfirst;
  129. b->last = newfirst + size;
  130. b->capacity = newfirst + capacity;
  131. }
  132. template<typename T, typename Alloc>
  133. static inline void buffer_resize(buffer<T, Alloc>* b, size_t size) {
  134. buffer_reserve(b, size);
  135. buffer_fill_urange(b->last, b->first + size);
  136. buffer_destroy_range(b->first + size, b->last);
  137. b->last = b->first + size;
  138. }
  139. template<typename T, typename Alloc>
  140. static inline void buffer_resize(buffer<T, Alloc>* b, size_t size, const T& value) {
  141. buffer_reserve(b, size);
  142. buffer_fill_urange(b->last, b->first + size, value);
  143. buffer_destroy_range(b->first + size, b->last);
  144. b->last = b->first + size;
  145. }
  146. template<typename T, typename Alloc>
  147. static inline void buffer_shrink_to_fit(buffer<T, Alloc>* b) {
  148. if (b->last == b->first) {
  149. const size_t capacity = (size_t)(b->last - b->first);
  150. Alloc::static_deallocate(b->first, sizeof(T)*capacity);
  151. b->capacity = b->first;
  152. } else if (b->capacity != b->last) {
  153. const size_t capacity = (size_t)(b->capacity - b->first);
  154. const size_t size = (size_t)(b->last - b->first);
  155. T* newfirst = (T*)Alloc::static_allocate(sizeof(T) * size);
  156. buffer_move_urange(newfirst, b->first, b->last);
  157. Alloc::static_deallocate(b->first, sizeof(T) * capacity);
  158. b->first = newfirst;
  159. b->last = newfirst + size;
  160. b->capacity = b->last;
  161. }
  162. }
  163. template<typename T, typename Alloc>
  164. static inline void buffer_clear(buffer<T, Alloc>* b) {
  165. buffer_destroy_range(b->first, b->last);
  166. b->last = b->first;
  167. }
  168. template<typename T, typename Alloc>
  169. static inline T* buffer_insert_common(buffer<T, Alloc>* b, T* where, size_t count) {
  170. const size_t offset = (size_t)(where - b->first);
  171. const size_t newsize = (size_t)((b->last - b->first) + count);
  172. if (b->first + newsize > b->capacity)
  173. buffer_reserve(b, (newsize * 3) / 2);
  174. where = b->first + offset;
  175. if (where != b->last)
  176. buffer_bmove_urange(where + count, where, b->last);
  177. b->last = b->first + newsize;
  178. return where;
  179. }
  180. template<typename T, typename Alloc, typename Param>
  181. static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const Param* first, const Param* last) {
  182. where = buffer_insert_common(b, where, last - first);
  183. for (; first != last; ++first, ++where)
  184. new(placeholder(), where) T(*first);
  185. }
  186. template<typename T, typename Alloc>
  187. static inline void buffer_insert(buffer<T, Alloc>* b, T* where, size_t count) {
  188. where = buffer_insert_common(b, where, count);
  189. for (size_t i = 0; i < count; ++i)
  190. new(placeholder(), where) T();
  191. }
  192. template<typename T, typename Alloc, typename Param>
  193. static inline void buffer_append(buffer<T, Alloc>* b, const Param* param) {
  194. if (b->capacity != b->last) {
  195. new(placeholder(), b->last) T(*param);
  196. ++b->last;
  197. } else {
  198. buffer_insert(b, b->last, param, param + 1);
  199. }
  200. }
  201. template<typename T, typename Alloc>
  202. static inline void buffer_append(buffer<T, Alloc>* b) {
  203. if (b->capacity != b->last) {
  204. new(placeholder(), b->last) T();
  205. ++b->last;
  206. } else {
  207. buffer_insert(b, b->last, 1);
  208. }
  209. }
  210. template<typename T, typename Alloc>
  211. static inline T* buffer_erase(buffer<T, Alloc>* b, T* first, T* last) {
  212. typedef T* pointer;
  213. const size_t range = (last - first);
  214. for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest)
  215. move(*dest, *it);
  216. buffer_destroy_range(b->last - range, b->last);
  217. b->last -= range;
  218. return first;
  219. }
  220. template<typename T, typename Alloc>
  221. static inline T* buffer_erase_unordered(buffer<T, Alloc>* b, T* first, T* last) {
  222. typedef T* pointer;
  223. const size_t range = (last - first);
  224. const size_t tail = (b->last - last);
  225. pointer it = b->last - ((range < tail) ? range : tail);
  226. for (pointer end = b->last, dest = first; it != end; ++it, ++dest)
  227. move(*dest, *it);
  228. buffer_destroy_range(b->last - range, b->last);
  229. b->last -= range;
  230. return first;
  231. }
  232. template<typename T, typename Alloc>
  233. static inline void buffer_swap(buffer<T, Alloc>* b, buffer<T, Alloc>* other) {
  234. typedef T* pointer;
  235. const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity;
  236. b->first = other->first, b->last = other->last, b->capacity = other->capacity;
  237. other->first = tfirst, other->last = tlast, other->capacity = tcapacity;
  238. }
  239. }
  240. #endif