31 class LineStoreIterator ;
40 G_EXCEPTION( Error ,
tx(
"line buffer internal error") )
41 using iterator_category = std::bidirectional_iterator_tag ;
42 using value_type = char ;
43 using difference_type = std::ptrdiff_t ;
44 using pointer =
char* ;
45 using reference = char ;
50 m_pos(end?line_store.
size():0U)
69 return m_pos == other.m_pos ;
73 return m_pos != other.m_pos ;
77 return m_pos < other.m_pos ;
81 return m_pos <= other.m_pos ;
85 return m_pos > other.m_pos ;
89 return m_pos >= other.m_pos ;
91 char operator*()
const
93 G_ASSERT( m_p !=
nullptr ) ;
94 return m_p ? m_p->
at( m_pos ) :
'\0' ;
96 char operator[]( std::size_t n )
const
98 G_ASSERT( m_p !=
nullptr ) ;
99 return m_p ? m_p->
at( m_pos + n ) :
'\0' ;
101 void operator+=( std::ptrdiff_t n )
104 m_pos -=
static_cast<std::size_t
>(-n) ;
106 m_pos +=
static_cast<std::size_t
>(n) ;
108 void operator-=( std::ptrdiff_t n )
111 m_pos +=
static_cast<std::size_t
>(-n) ;
113 m_pos -=
static_cast<std::size_t
>(n) ;
117 if( other.m_pos >= m_pos )
118 return static_cast<std::ptrdiff_t
>(other.m_pos-m_pos) ;
120 return -
static_cast<std::ptrdiff_t
>(m_pos-other.m_pos) ;
122 std::size_t pos()
const
124 return ( m_p ==
nullptr || m_pos >= m_p->
size() ) ? std::string::npos : m_pos ;
129 std::size_t m_pos {0U} ;
140 inline LineStoreIterator operator-(
const LineStoreIterator & in , std::ptrdiff_t n )
142 LineStoreIterator result( in ) ;
146 inline LineStoreIterator operator+( std::ptrdiff_t n ,
const LineStoreIterator & in )
148 LineStoreIterator result( in ) ;
152 inline std::ptrdiff_t operator-(
const LineStoreIterator & a ,
const LineStoreIterator & b )
154 return a.distanceTo( b ) ;
160 namespace LineStoreImp
162 template <
typename T1,
typename T2>
bool std_equal( T1 p1 , T1 end1 , T2 p2 , T2 end2 )
165 for( ; p1 != end1 && p2 != end2 ; ++p1 , ++p2 )
170 return p1 == end1 && p2 == end2 ;
183 m_store.append( s ) ;
189 m_store.append( data , size ) ;
195 m_extra_data = data ;
196 m_extra_size = size ;
208 m_store.append( m_extra_data , m_extra_size ) ;
218 m_store.append( m_extra_data , m_extra_size ) ;
222 else if( n < m_store.size() )
224 m_store.erase( 0U , n ) ;
227 m_store.append( m_extra_data , m_extra_size ) ;
231 else if( n == m_store.size() )
236 m_store.assign( m_extra_data , m_extra_size ) ;
240 else if( n < size() )
242 std::size_t offset = n - m_store.size() ;
246 G_ASSERT( m_extra_size >= offset ) ;
247 m_store.assign( m_extra_data+offset , m_extra_size-offset ) ;
259 G_ASSERT( startpos <= size() ) ;
260 std::size_t result = std::string::npos ;
261 const std::size_t store_size = m_store.size() ;
262 if( startpos < store_size )
264 result = m_store.find( c , startpos ) ;
266 if( result == std::string::npos && m_extra_size != 0U )
268 const std::size_t offset = startpos > store_size ? (startpos-store_size) : 0U ;
269 const char *
const begin = m_extra_data + offset ;
270 const char *
const end = m_extra_data + m_extra_size ;
271 G_ASSERT( begin >= m_extra_data && begin <= end ) ;
272 const char * p = std::find( begin , end , c ) ;
274 result = store_size + std::distance(m_extra_data,p) ;
282 const std::size_t npos = std::string::npos ;
283 std::size_t result = npos ;
286 const char c0 = s[0] ;
287 const char c1 = s[1] ;
288 const std::size_t end = size() ;
289 for( std::size_t pos = startpos ; pos != npos ; ++pos )
291 pos = find( c0 , pos ) ;
292 if( pos == npos ) break ;
293 if( (pos+1U) != end && at(pos+1U) == c1 )
299 G_ASSERT( result == search(s.begin(),s.end(),startpos) ) ;
301 else if( s.size() == 1U )
303 result = find( s[0] , startpos ) ;
304 G_ASSERT( result == search(s.begin(),s.end(),startpos) ) ;
308 result = search( s.begin() , s.end() , startpos ) ;
313std::size_t GNet::LineStore::search( std::string::const_iterator begin , std::string::const_iterator end ,
314 std::size_t startpos )
const
321 namespace imp = LineStoreImp ;
328 std::size_t result = std::string::npos ;
329 std::size_t s_size = s.size() ;
330 std::string::const_iterator s_start = s.begin() ;
331 std::string::const_iterator s_end = s.end() ;
333 for( --s_size , --s_end ; s_start != s_end ; --s_size , --s_end )
335 if( (size()-startpos) >= s_size )
340 if( imp::std_equal(s_start,s_end,p,end) )
353 return (
const_cast<LineStore*
>(
this))->dataimp( pos , n ) ;
356const char * GNet::LineStore::dataimp( std::size_t pos , std::size_t n )
358 G_ASSERT( (n==0U && size()==0U) || (pos+n) <= size() ) ;
359 if( n == 0U && size() == 0U )
363 else if( n == 0U && pos == size() )
367 else if( (pos+n) <= m_store.size() )
369 return m_store.data() + pos ;
371 else if( pos >= m_store.size() )
373 std::size_t offset = pos - m_store.size() ;
374 return m_extra_data + offset ;
378 std::size_t nmove = pos + n - m_store.size() ;
379 m_store.append( m_extra_data , nmove ) ;
380 m_extra_data += nmove ;
381 m_extra_size -= nmove ;
382 return m_store.data() + pos ;
389 std::string result( m_store ) ;
391 result.append( m_extra_data , m_extra_size ) ;
399 if( result.size() < n && m_extra_size )
400 result.append( m_extra_data , std::min(n-result.size(),m_extra_size) ) ;
An iterator class for GNet::LineStore.
A pair of character buffers, one kept by value and the other being an ephemeral extension.
void discard(std::size_t n)
Discards the first 'n' bytes and consolidates the residue.
void append(const std::string &)
Appends to the store (by copying).
const char * data(std::size_t pos, std::size_t size) const
Returns a pointer for the data at the given position that is contiguous for the given size.
std::string head(std::size_t n) const
Returns the leading sub-string of str() of up to 'n' characters.
void clear()
Clears all data.
LineStore()
Default constructor.
std::string str() const
Returns the complete string.
std::size_t find(char c, std::size_t startpos=0U) const
Finds the given character.
std::size_t size() const
Returns the overall size.
void consolidate()
Consolidates the extension into the store.
void extend(const char *, std::size_t)
Sets the extension.
std::size_t findSubStringAtEnd(const std::string &s, std::size_t startpos=0U) const
Tries to find some leading sub-string of 's' that appears right at the end of the data,...
char at(std::size_t n) const
Returns the n'th character.
static std::string head(std::string_view in, std::size_t pos, std::string_view default_={})
Returns the first part of the string up to just before the given position.
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().