28 static const unsigned long line_limit = G::limits::net_line_limit ;
34 m_throw_on_overflow(false) ,
43 m_throw_on_overflow(do_throw) ,
46 G_ASSERT( !eol.empty() ) ;
51 if( m_iterator !=
nullptr )
throw Error(
"double lock") ;
52 m_iterator = iterator ;
55 size_t expect = m_expect ;
60 void GNet::LineBuffer::unlock( LineBufferIterator * iterator ,
size_t discard ,
size_t expect )
62 if( m_iterator ==
nullptr || iterator != m_iterator )
throw Error(
"double unlock") ;
63 m_iterator = nullptr ;
66 G_ASSERT( discard <= m_store.size() ) ;
67 if( discard == m_store.size() )
69 else if( discard != 0U )
70 m_store.erase( 0U , discard ) ;
76 m_store.append( p , n ) ;
81 add( s.data() , s.size() ) ;
87 if( m_iterator ==
nullptr )
94 m_iterator->expect( n ) ;
98 void GNet::LineBuffer::detect()
100 std::string::size_type pos = m_auto ? m_store.find(
'\n') : std::string::npos ;
101 if( m_auto && pos != std::string::npos )
103 if( pos > 0U && m_store.at(pos-1U) ==
'\r' )
104 m_eol = std::string(
"\r\n" ) ;
114 bool GNet::LineBuffer::check(
size_t n )
const
116 if( n == 0U )
return false ;
117 if( m_iterator !=
nullptr )
throw Error(
"locked" ) ;
118 bool ok = (m_store.size()+n) <= line_limit ;
121 if( m_throw_on_overflow )
122 throw Error(
"overflow" ) ;
124 G_ERROR(
"GNet::LineBuffer::check: line too long: end-of-line expected: "
125 "have " << m_store.size() <<
" characters, and adding " << n <<
" more" ) ;
136 m_eol_size(buffer.m_eol.size()) ,
137 m_line_begin(buffer.m_store.begin()) ,
138 m_line_end(m_line_begin) ,
141 m_expect = m_buffer.lock(
this ) ;
146 m_buffer.unlock(
this , m_pos , m_expect ) ;
149 void GNet::LineBufferIterator::expect(
size_t n )
156 m_line_valid = false ;
158 const size_t npos = std::string::npos ;
159 std::string & store = m_buffer.m_store ;
160 const std::string & eol = m_buffer.m_eol ;
161 size_t eol_size = eol.size() ;
163 G_ASSERT( m_pos <= store.size() ) ;
164 if( m_pos == store.size() )
173 if( (m_pos+m_expect) <= store.size() )
175 pos = m_pos + m_expect ;
182 pos = store.find( eol , m_pos ) ;
185 if( pos == std::string::npos )
192 G_ASSERT( pos >= m_pos ) ;
193 const std::string & store = m_buffer.m_store ;
194 m_line_begin = store.begin() + m_pos ;
195 m_line_end = store.begin() + pos ;
196 m_pos = pos + eol_size ;
205 m_line.assign( m_line_begin , m_line_end ) ;
206 m_line_valid = true ;
213 return m_line_begin ;
const std::string & eol() const
Returns the line-ending.
void add(const std::string &segment)
Adds a data segment.
void expect(size_t n)
The next 'n' bytes added and/or extracted are treated as a complete line.
std::string::const_iterator end() const
Returns an end iterator for the current line.
An iterator class for GNet::LineBuffer that extracts complete lines.
LineBuffer()
Default constructor for a line buffer that auto-detects either CR or CR-LF line endings based on the ...
LineBufferIterator(LineBuffer &)
Constructor.
~LineBufferIterator()
Destructor.
std::string::const_iterator begin() const
Returns a begin iterator for the current line.
const std::string & line() const
Returns the current line.
A class which does line buffering.
bool more()
Returns true if there is a line() to be had.