21#ifndef G_NET_LINE_BUFFER_H
22#define G_NET_LINE_BUFFER_H
35 class LineBufferIterator ;
36 class LineBufferState ;
85 G_EXCEPTION( ErrorOverflow ,
tx(
"line buffer overflow") ) ;
86 using SinkArgs = std::tuple<const char*,std::size_t,std::size_t,std::size_t,char,bool> ;
87 using SinkFn = std::function<bool(
const SinkArgs&)> ;
88 using FragmentsFn = std::function<bool()> ;
92 static constexpr std::size_t inf = ~(std::size_t(0)) ;
93 static_assert( (inf+1U) == 0U ,
"" ) ;
94 std::string m_eol {
'\n'} ;
95 std::size_t m_warn {0U} ;
96 std::size_t m_fmin {0U} ;
97 std::size_t m_expect {0U} ;
99 const std::string & eol()
const noexcept ;
100 std::size_t warn()
const noexcept ;
101 std::size_t fmin()
const noexcept ;
102 std::size_t expect()
const noexcept ;
104 Config & set_eol(
const std::string & ) ;
105 Config & set_warn( std::size_t ) noexcept ;
106 Config & set_fmin( std::size_t ) noexcept ;
107 Config & set_expect( std::size_t ) noexcept ;
109 static Config transparent() ;
115 static Config autodetect() ;
124 void add(
const std::string &
data ) ;
132 void expect( std::size_t n ) ;
150 std::string
eol()
const ;
156 template <
typename Tfn>
157 void apply(
const char *
data , std::size_t data_size , Tfn sink_fn ,
bool fragments =
false ) ;
177 template <
typename Tsink,
typename Tmemfun>
178 void apply( Tsink sink_p , Tmemfun sink_memfun ,
const char *
data , std::size_t data_size ,
179 bool fragments =
false ) ;
193 template <
typename Tsink,
typename Tmemfun,
typename Tmemfun2>
194 void apply( Tsink sink_p , Tmemfun sink_memfun ,
const char *
data , std::size_t data_size ,
195 Tmemfun2 fragments_memfun ) ;
210 template <
typename Tfn>
211 void apply(
const std::string & , Tfn sink_fn ,
bool fragments =
false ) ;
215 bool more(
bool fragments =
false ) ;
224 const char *
data()
const ;
230 std::size_t
size()
const ;
286 const char * m_data{
nullptr} ;
287 std::size_t m_size{0U} ;
288 std::size_t m_eolsize{0U} ;
289 std::size_t m_linesize{0U} ;
292 std::size_t set( LineStore & , std::size_t pos , std::size_t
size , std::size_t
eolsize ) ;
296 Extension(
LineBuffer * ,
const char * , std::size_t ) ;
298 Extension(
const Extension & ) = delete ;
299 Extension( Extension && ) = delete ;
300 Extension & operator=(
const Extension & ) = delete ;
301 Extension & operator=( Extension && ) = delete ;
308 ~LineBuffer() = default ;
315 friend class LineBufferState ;
316 void output( std::size_t
size , std::size_t
eolsize ,
bool =
false ) ;
318 bool trivial( std::size_t pos )
const ;
319 bool finite()
const ;
320 std::string head()
const ;
323 friend struct Extension ;
327 std::size_t m_warn_limit ;
329 std::size_t m_expect ;
348 std::string
eol()
const ;
351 std::size_t
size()
const ;
357 std::string
head()
const ;
376GNet::LineBuffer::Extension::Extension(
LineBuffer * line_buffer ,
const char * data , std::size_t size ) :
377 m_line_buffer(line_buffer) ,
378 m_call_frame(line_buffer->m_call_stack)
380 m_line_buffer->extensionStart( data ,
size ) ;
384GNet::LineBuffer::Extension::~Extension()
386 if( m_call_frame.valid() )
387 m_line_buffer->extensionEnd() ;
391bool GNet::LineBuffer::Extension::valid()
const
393 return m_call_frame.valid() ;
401 return m_out.m_size ;
411std::string GNet::LineBuffer::head()
const
413 return m_in.head( 16U ) ;
419 return m_out.m_eolsize ;
425 return m_out.m_linesize ;
434template <
typename Tfn>
437 Extension e(
this , data_in , size_in ) ;
438 while( e.valid() && more(with_fragments) )
440 if( !sink_fn( data() , size() , eolsize() , linesize() , c0() ) )
445template <
typename Tsink,
typename Tmemfun>
446void GNet::LineBuffer::apply( Tsink sink_p , Tmemfun memfun ,
const char * data_in , std::size_t size_in ,
bool with_fragments )
448 Extension e(
this , data_in , size_in ) ;
449 while( e.valid() && more(with_fragments) )
451 if( !(sink_p->*memfun)( data() , size() , eolsize() , linesize() , c0() ) )
456template <
typename Tsink,
typename Tmemfun,
typename Tmemfun2>
457void GNet::LineBuffer::apply( Tsink sink_p , Tmemfun memfun ,
const char * data_in , std::size_t size_in , Tmemfun2 fragments_memfun )
459 Extension e(
this , data_in , size_in ) ;
460 while( e.valid() && more( (sink_p->*fragments_memfun)() ) )
462 if( !(sink_p->*memfun)( data() , size() , eolsize() , linesize() , c0() ) )
470 Extension e(
this , data_in.data() , data_in.size() ) ;
471 while( e.valid() && more( fragments_fn() ) )
473 if( !sink_fn( SinkArgs(data(),size(),eolsize(),linesize(),c0(),peekmore()) ) )
483 return apply( data.data() , data.size() , sink , with_fragments ) ;
488inline const std::string & GNet::LineBuffer::Config::eol() const noexcept {
return m_eol ; }
489inline std::size_t GNet::LineBuffer::Config::warn() const noexcept {
return m_warn ; }
490inline std::size_t GNet::LineBuffer::Config::fmin() const noexcept {
return m_fmin ; }
491inline std::size_t GNet::LineBuffer::Config::expect() const noexcept {
return m_expect ; }
492inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_eol(
const std::string & s ) { m_eol = s ;
return *this ; }
493inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_warn( std::size_t n )
noexcept { m_warn = n ;
return *this ; }
494inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_fmin( std::size_t n )
noexcept { m_fmin = n ;
return *this ; }
495inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_expect( std::size_t n )
noexcept { m_expect = n ;
return *this ; }
498 inline bool operator==(
const LineBuffer::Config & a ,
const LineBuffer::Config & b )
noexcept
500 return a.m_eol == b.m_eol && a.m_warn == b.m_warn && a.m_fmin == b.m_fmin && a.m_expect == b.m_expect ;
508 m_transparent(line_buffer.transparent()) ,
509 m_peekmore(line_buffer.peekmore()) ,
510 m_eol(line_buffer.eol()) ,
511 m_size(line_buffer.buffersize()) ,
512 m_head(line_buffer.head())
525 return m_transparent ;
537 return m_size == 0U ;
Provides information about the state of a line buffer.
bool peekmore() const
Returns true if another complete line is available after the current line or current expect() block.
std::string head() const
Returns the first bytes of buffered data up to a limit of sixteen bytes.
bool empty() const
Returns true iff size() is zero.
bool transparent() const
Returns LineBuffer::transparent().
std::size_t size() const
Returns the number of bytes currently buffered up.
LineBufferState(const LineBuffer &)
Constructor.
std::string eol() const
Returns LineBuffer::eol().
A class that does line buffering, supporting auto-detection of line endings and fixed-size block extr...
void expect(std::size_t n)
Requests that the next 'n' bytes are extracted in one contiguous block, without regard to line ending...
bool transparent() const
Returns true if the current expect() value is infinite.
std::size_t linesize() const
Returns the current size of all the line fragments making up the current line.
void clear()
Clears the internal data.
LineBuffer(const Config &)
Constructor.
void extensionStart(const char *, std::size_t)
A pseudo-private method used by the implementation of the apply() method template.
bool more(bool fragments=false)
Returns true if there is more data() to be had.
std::size_t size() const
Returns the size of the current data(), excluding the line ending.
std::size_t eolsize() const
Returns the size of line-ending associated with the current data().
const char * data() const
Returns a pointer for the current line, expect()ed fixed-size block, or line fragment.
void apply(const char *data, std::size_t data_size, Tfn sink_fn, bool fragments=false)
Adds the data and passes complete lines to the sink function with line-data, line-size,...
std::string eol() const
Returns the end-of-line string as passed in to the constructor, or as auto-detected.
std::size_t buffersize() const
Returns the total number of bytes buffered up.
void extensionEnd()
A pseudo-private method used by the implementation of the apply() method template.
void add(const std::string &data)
Adds a data segment.
void apply(const std::string &, Tfn sink_fn, bool fragments=false)
Overload taking a string as its data input, used in testing.
char c0() const
Returns the first character of the current line.
bool peekmore() const
Returns true if there is a line available after the current line or expect()ation.
LineBufferState state() const
Returns information about the current state of the line-buffer.
An object to represent a nested execution context.
A linked list of CallFrame pointers.
A class like c++17's std::string_view.
constexpr const char * tx(const char *p)
A briefer alternative to G::gettext_noop().
A configuration structure for GNet::LineBuffer.