|
| 1 | +// |
| 2 | +// |
| 3 | +// uti |
| 4 | +// core/container/circular_buffer.hxx |
| 5 | +// |
| 6 | + |
| 7 | +#pragma once |
| 8 | + |
| 9 | +#include <uti/core/util/assert.hxx> |
| 10 | +#include <uti/core/type/traits.hxx> |
| 11 | +#include <uti/core/meta/concepts.hxx> |
| 12 | + |
| 13 | +#include <uti/core/allocator/meta.hxx> |
| 14 | + |
| 15 | +#include <uti/core/iterator/meta.hxx> |
| 16 | +#include <uti/core/iterator/circular_iterator.hxx> |
| 17 | +#include <uti/core/iterator/reverse_iterator.hxx> |
| 18 | + |
| 19 | + |
| 20 | +namespace uti |
| 21 | +{ |
| 22 | + |
| 23 | + |
| 24 | +//////////////////////////////////////////////////////////////////////////////// |
| 25 | + |
| 26 | +template< meta::arithmetic T, ssize_t Capacity > |
| 27 | +class circular_buffer |
| 28 | +{ |
| 29 | + static constexpr ssize_t capacity_ { Capacity } ; |
| 30 | +public: |
| 31 | + using value_type = T ; |
| 32 | + using size_type = size_t ; |
| 33 | + using ssize_type = ssize_t ; |
| 34 | + using difference_type = ssize_t ; |
| 35 | + |
| 36 | + using pointer = value_type * ; |
| 37 | + using const_pointer = value_type const * ; |
| 38 | + using reference = value_type & ; |
| 39 | + using const_reference = value_type const & ; |
| 40 | + |
| 41 | + using iterator = circular_iterator< circular_buffer > ; |
| 42 | + using const_iterator = circular_iterator< circular_buffer const > ; |
| 43 | + using reverse_iterator = ::uti::reverse_iterator< iterator > ; |
| 44 | + using const_reverse_iterator = ::uti::reverse_iterator< const_iterator > ; |
| 45 | + |
| 46 | + using buffer_iterator = iterator_base< value_type , random_access_iterator_tag > ; |
| 47 | + using const_buffer_iterator = iterator_base< value_type const, random_access_iterator_tag > ; |
| 48 | + using reverse_buffer_iterator = ::uti::reverse_iterator< iterator > ; |
| 49 | + using const_reverse_buffer_iterator = ::uti::reverse_iterator< const_iterator > ; |
| 50 | + |
| 51 | + constexpr circular_buffer () noexcept = default ; |
| 52 | + constexpr ~circular_buffer () noexcept = default ; |
| 53 | + |
| 54 | + constexpr circular_buffer ( ssize_type _count_, value_type const & _value_ ) noexcept ; |
| 55 | + |
| 56 | + constexpr void push_back ( value_type const & _value_ ) noexcept ; |
| 57 | + |
| 58 | + UTI_NODISCARD constexpr ssize_type capacity () const noexcept { return capacity_ ; } |
| 59 | + UTI_NODISCARD constexpr ssize_type size () const noexcept { return _size() ; } |
| 60 | + UTI_NODISCARD constexpr bool empty () const noexcept { return begin_ == end_ ; } |
| 61 | + |
| 62 | + UTI_NODISCARD constexpr pointer data () noexcept { return data_ ; } |
| 63 | + UTI_NODISCARD constexpr const_pointer data () const noexcept { return data_ ; } |
| 64 | + |
| 65 | + UTI_NODISCARD constexpr iterator begin () noexcept { return iterator( *this, begin_, 0 ) ; } |
| 66 | + UTI_NODISCARD constexpr const_iterator begin () const noexcept { return const_iterator( *this, begin_, 0 ) ; } |
| 67 | + UTI_NODISCARD constexpr const_iterator cbegin () const noexcept { return begin() ; } |
| 68 | + |
| 69 | + UTI_NODISCARD constexpr iterator end () noexcept { return iterator( *this, end_ + 1, size() ) ; } |
| 70 | + UTI_NODISCARD constexpr const_iterator end () const noexcept { return const_iterator( *this, end_ + 1, size() ) ; } |
| 71 | + UTI_NODISCARD constexpr const_iterator cend () const noexcept { return end() ; } |
| 72 | + |
| 73 | + UTI_NODISCARD constexpr buffer_iterator buffer_begin () noexcept { return buffer_iterator( data_ ) ; } |
| 74 | + UTI_NODISCARD constexpr const_buffer_iterator buffer_begin () const noexcept { return const_buffer_iterator( data_ ) ; } |
| 75 | + UTI_NODISCARD constexpr const_buffer_iterator buffer_cbegin () const noexcept { return const_buffer_iterator( data_ ) ; } |
| 76 | + |
| 77 | + UTI_NODISCARD constexpr buffer_iterator buffer_end () noexcept { return buffer_iterator( data_ + capacity_ ) ; } |
| 78 | + UTI_NODISCARD constexpr const_buffer_iterator buffer_end () const noexcept { return const_buffer_iterator( data_ + capacity_ ) ; } |
| 79 | + UTI_NODISCARD constexpr const_buffer_iterator buffer_cend () const noexcept { return const_buffer_iterator( data_ + capacity_ ) ; } |
| 80 | +private: |
| 81 | + value_type data_ [ capacity_ ] {} ; |
| 82 | + |
| 83 | + pointer begin_ { data_ } ; |
| 84 | + pointer end_ { data_ } ; |
| 85 | + |
| 86 | + bool full_ { false } ; |
| 87 | + |
| 88 | + constexpr ssize_type _size () const noexcept { return full_ ? capacity_ : end_ - begin_ ; } |
| 89 | +} ; |
| 90 | + |
| 91 | +//////////////////////////////////////////////////////////////////////////////// |
| 92 | +//////////////////////////////////////////////////////////////////////////////// |
| 93 | + |
| 94 | +template< meta::arithmetic T, ssize_t Capacity > |
| 95 | +constexpr |
| 96 | +circular_buffer< T, Capacity >::circular_buffer ( ssize_type _count_, value_type const & _value_ ) noexcept |
| 97 | +{ |
| 98 | + if( _count_ > capacity() ) _count_ = capacity() ; |
| 99 | + |
| 100 | + for( ssize_type i = 0; i < _count_; ++i ) |
| 101 | + { |
| 102 | + push_back( _value_ ) ; |
| 103 | + } |
| 104 | +} |
| 105 | + |
| 106 | +//////////////////////////////////////////////////////////////////////////////// |
| 107 | + |
| 108 | +template< meta::arithmetic T, ssize_t Capacity > |
| 109 | +constexpr void |
| 110 | +circular_buffer< T, Capacity >::push_back ( value_type const & _value_ ) noexcept |
| 111 | +{ |
| 112 | + *end_ = _value_ ; |
| 113 | + |
| 114 | + if( full_ ) |
| 115 | + { |
| 116 | + UTI_CEXPR_ASSERT( begin_ == end_, "uti::circular_buffer::push_back : internal error 116" ) ; |
| 117 | + |
| 118 | + if( begin_ >= buffer_end() - 1 ) |
| 119 | + { |
| 120 | + begin_ = buffer_begin() ; |
| 121 | + end_ = buffer_begin() ; |
| 122 | + } |
| 123 | + else |
| 124 | + { |
| 125 | + ++begin_ ; |
| 126 | + ++end_ ; |
| 127 | + } |
| 128 | + } |
| 129 | + else |
| 130 | + { |
| 131 | + UTI_CEXPR_ASSERT( begin_ == buffer_begin(), "uti::circular_buffer::push_back : internal error 131" ) ; |
| 132 | + |
| 133 | + if( end_ >= buffer_end() - 1 ) |
| 134 | + { |
| 135 | + end_ = buffer_begin() ; |
| 136 | + full_ = true ; |
| 137 | + } |
| 138 | + else |
| 139 | + { |
| 140 | + ++end_ ; |
| 141 | + } |
| 142 | + } |
| 143 | +} |
| 144 | + |
| 145 | +//////////////////////////////////////////////////////////////////////////////// |
| 146 | + |
| 147 | + |
| 148 | +} // namespace uti |
0 commit comments