buffer.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*-
  2. * Copyright 2012 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 "allocator.h"
  29. #include "new.h"
  30. #include "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, const T& value, pod_traits<T, false>) {
  52. for (; first < last; ++first)
  53. new(placeholder(), first) T(value);
  54. }
  55. template<typename T>
  56. static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, true>) {
  57. for (; first < last; ++first)
  58. *first = value;
  59. }
  60. template<typename T>
  61. static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
  62. for (T* it = first; it != last; ++it, ++dest)
  63. move_construct(dest, *it);
  64. buffer_destroy_range(first, last);
  65. }
  66. template<typename T>
  67. static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
  68. for (; first != last; ++first, ++dest)
  69. *dest = *first;
  70. }
  71. template<typename T>
  72. static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, false>) {
  73. dest += (last - first);
  74. for (T* it = last; it != first; --it, --dest) {
  75. move_construct(dest - 1, *(it - 1));
  76. buffer_destroy_range(it - 1, it);
  77. }
  78. }
  79. template<typename T>
  80. static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits<T, true>) {
  81. dest += (last - first);
  82. for (T* it = last; it != first; --it, --dest)
  83. *(dest - 1) = *(it - 1);
  84. }
  85. template<typename T>
  86. static inline void buffer_move_urange(T* dest, T* first, T* last) {
  87. buffer_move_urange_traits(dest, first, last, pod_traits<T>());
  88. }
  89. template<typename T>
  90. static inline void buffer_bmove_urange(T* dest, T* first, T* last) {
  91. buffer_bmove_urange_traits(dest, first, last, pod_traits<T>());
  92. }
  93. template<typename T>
  94. static inline void buffer_fill_urange(T* first, T* last, const T& value) {
  95. buffer_fill_urange_traits(first, last, value, pod_traits<T>());
  96. }
  97. template<typename T, typename Alloc>
  98. static inline void buffer_init(buffer<T, Alloc>* b) {
  99. b->first = b->last = b->capacity = 0;
  100. }
  101. template<typename T, typename Alloc>
  102. static inline void buffer_destroy(buffer<T, Alloc>* b) {
  103. buffer_destroy_range(b->first, b->last);
  104. Alloc::static_deallocate(b->first, (size_t)((char*)b->first - (char*)b->last));
  105. }
  106. template<typename T, typename Alloc>
  107. static inline void buffer_reserve(buffer<T, Alloc>* b, size_t capacity) {
  108. if (b->first + capacity <= b->capacity)
  109. return;
  110. typedef T* pointer;
  111. const size_t size = (size_t)(b->last - b->first);
  112. pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity);
  113. buffer_move_urange(newfirst, b->first, b->last);
  114. Alloc::static_deallocate(b->first, sizeof(T) * capacity);
  115. b->first = newfirst;
  116. b->last = newfirst + size;
  117. b->capacity = newfirst + capacity;
  118. }
  119. template<typename T, typename Alloc>
  120. static inline void buffer_resize(buffer<T, Alloc>* b, size_t size, const T& value) {
  121. buffer_reserve(b, size);
  122. buffer_fill_urange(b->last, b->first + size, value);
  123. buffer_destroy_range(b->first + size, b->last);
  124. b->last = b->first + size;
  125. }
  126. template<typename T, typename Alloc>
  127. static inline void buffer_clear(buffer<T, Alloc>* b) {
  128. buffer_destroy_range(b->first, b->last);
  129. b->last = b->first;
  130. }
  131. template<typename T, typename Alloc>
  132. static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const T* first, const T* last) {
  133. const size_t offset = (size_t)(where - b->first);
  134. const size_t newsize = (size_t)((b->last - b->first) + (last - first));
  135. if (b->first + newsize > b->capacity)
  136. buffer_reserve(b, (newsize * 3) / 2);
  137. where = b->first + offset;
  138. const size_t count = (size_t)(last - first);
  139. if (where != b->last)
  140. buffer_bmove_urange(where + count, where, b->last);
  141. for (; first != last; ++first, ++where)
  142. new(placeholder(), where) T(*first);
  143. b->last = b->first + newsize;
  144. }
  145. template<typename T, typename Alloc>
  146. static inline T* buffer_erase(buffer<T, Alloc>* b, T* first, T* last) {
  147. typedef T* pointer;
  148. const size_t range = (last - first);
  149. for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest)
  150. move(*dest, *it);
  151. buffer_destroy_range(b->last - range, b->last);
  152. b->last -= range;
  153. return first;
  154. }
  155. template<typename T, typename Alloc>
  156. static inline T* buffer_erase_unordered(buffer<T, Alloc>* b, T* first, T* last) {
  157. typedef T* pointer;
  158. const size_t range = (last - first);
  159. const size_t tail = (b->last - last);
  160. pointer it = b->last - ((range < tail) ? range : tail);
  161. for (pointer end = b->last, dest = first; it != end; ++it, ++dest)
  162. move(*dest, *it);
  163. buffer_destroy_range(b->last - range, b->last);
  164. b->last -= range;
  165. return first;
  166. }
  167. template<typename T, typename Alloc>
  168. static inline void buffer_swap(buffer<T, Alloc>* b, buffer<T, Alloc>* other) {
  169. typedef T* pointer;
  170. const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity;
  171. b->first = other->first, b->last = other->last, b->capacity = other->capacity;
  172. other->first = tfirst, other->last = tlast, other->capacity = tcapacity;
  173. }
  174. }
  175. #endif