64 static_assert(
sizeof(T) == 1 ,
"sizeof t is one" ) ;
65 using value_type = T ;
66 using iterator = T * ;
67 using const_iterator =
const T * ;
68 Buffer()
noexcept = default ;
69 explicit Buffer( std::size_t n ) : m_n(n) , m_c(n)
71 m_p =
static_cast<T*
>( std::malloc(n) ) ;
78 void reserve( std::size_t n )
82 T * new_p =
static_cast<T*
>( std::realloc(m_p,n) ) ;
83 m_p = checkalloc( new_p ) ;
87 void resize( std::size_t n ) { reserve( n ) ; m_n = n ; }
88 const T & operator[]( std::size_t i )
const noexcept {
return *(m_p+i) ; }
89 T & operator[]( std::size_t i )
noexcept {
return *(m_p+i) ; }
90 const T & at( std::size_t i )
const { checkindex( i ) ;
return *(m_p+i) ; }
91 T & at( std::size_t i ) { checkindex( i ) ;
return *(m_p+i) ; }
92 std::size_t size()
const noexcept {
return m_n ; }
93 std::size_t capacity()
const noexcept {
return m_c ; }
94 bool empty()
const noexcept {
return m_n == 0U ; }
95 void clear()
noexcept { m_n = 0 ; }
96 void shrink_to_fit()
noexcept {
if( empty() && m_p ) { std::free( m_p ) ; m_p = nullptr ; m_c = 0U ; } }
97 iterator begin()
noexcept {
return m_p ? m_p : &m_c0 ; }
98 iterator end()
noexcept {
return m_p ? (m_p+m_n) : &m_c0 ; }
99 const value_type * data()
const noexcept {
return m_p ? m_p : &m_c0 ; }
100 value_type * data()
noexcept {
return m_p ? m_p : &m_c0 ; }
101 const_iterator begin()
const noexcept {
return m_p ? m_p : &m_c0 ; }
102 const_iterator end()
const noexcept {
return m_p ? (m_p+m_n) : &m_c0 ; }
103 const_iterator cbegin()
const noexcept {
return m_p ? m_p : &m_c0 ; }
104 const_iterator cend()
const noexcept {
return m_p ? (m_p+m_n) : &m_c0 ; }
105 iterator erase( iterator range_begin , iterator range_end )
noexcept
107 if( range_end == end() )
109 m_n = std::distance( begin() , range_begin ) ;
111 else if( range_begin != range_end )
113 std::size_t range = std::distance( range_begin , range_end ) ;
114 std::size_t end_offset = std::distance( begin() , range_end ) ;
115 std::memmove( range_begin , range_end , m_n-end_offset ) ;
120 template <
typename U>
void insert( iterator p , U range_begin , U range_end )
122 std::size_t range = std::distance( range_begin , range_end ) ;
125 p = makespace( p , range ) ;
126 std::copy( range_begin , range_end , p ) ;
129 template <
typename U>
void insert( iterator p , U * range_begin , U * range_end )
131 std::size_t range = std::distance( range_begin , range_end ) ;
134 p = makespace( p , range ) ;
135 std::memcpy( p , range_begin , range ) ;
140 std::swap( m_n , other.m_n ) ;
141 std::swap( m_p , other.m_p ) ;
142 std::swap( m_c , other.m_c ) ;
148 resize( other.m_n ) ;
149 std::memcpy( m_p , other.m_p , m_n ) ;
163 Buffer<T>(std::move(other)).swap(*
this) ;
166 template <
typename U> T * aligned()
168 if( m_n == 0U || m_p ==
nullptr )
return nullptr ;
170 std::size_t space = m_n ;
171 void * result = std::align(
alignof(U) ,
sizeof(U) , vp , space ) ;
172 return static_cast<T*
>(result) ;
175 iterator makespace( iterator p , std::size_t range )
177 G_ASSERT( p >= begin() && p <= end() ) ;
178 G_ASSERT( range != 0U ) ;
179 std::size_t head = std::distance( begin() , p ) ;
180 std::size_t tail = std::distance( p , end() ) ;
181 resize( m_n + range ) ;
183 std::memmove( p+range , p , tail ) ;
186 void checkalloc() { checkalloc(m_p) ; }
187 T * checkalloc( T * p ) {
if( p ==
nullptr )
throw std::bad_alloc() ;
return p ; }
188 void checkindex( std::size_t i )
const {
if( i >= m_n )
throw std::out_of_range(
"G::Buffer") ; }
189 char * m_p {
nullptr} ;
190 std::size_t m_n {0U} ;
191 std::size_t m_c {0U} ;
192 value_type m_c0 {
'\0'} ;
195 template <
typename Uptr,
typename T =
char>
198 using U =
typename std::remove_pointer<Uptr>::type ;
199 T * p = buffer.template aligned<U>() ;
200 G_ASSERT( p ==
nullptr || p == buffer.data() ) ;
201 if( p != buffer.data() )
202 throw std::bad_cast() ;
206 template <
typename Uptr,
typename T =
char>
207 Uptr buffer_cast( Buffer<T> & buffer , std::nothrow_t )
209 using U =
typename std::remove_pointer<Uptr>::type ;
210 T * p = buffer.template aligned<U>() ;
211 G_ASSERT( p ==
nullptr || p == buffer.data() ) ;
212 if( p != buffer.data() )
217 template <
typename Uptr,
typename T =
char>
218 Uptr buffer_cast(
const Buffer<T> & buffer )
220 using U =
typename std::remove_pointer<Uptr>::type ;
221 return const_cast<Uptr
>( buffer_cast<U*>(
const_cast<Buffer<T>&
>(buffer) ) ) ;
224 template <
typename T>
void swap( Buffer<T> & a , Buffer<T> & b )
noexcept
A substitute for std::vector<char> that has more useful alignment guarantees and explicitly avoids de...