21#ifndef G_NET_LINE_BUFFER_H
22#define G_NET_LINE_BUFFER_H
36 class LineBufferIterator ;
37 class LineBufferState ;
86 G_EXCEPTION( ErrorOverflow ,
tx(
"line buffer overflow") )
87 using SinkArgs = std::tuple<const char*,std::size_t,std::size_t,std::size_t,char,bool> ;
88 using SinkFn = std::function<bool(
const SinkArgs&)> ;
89 using FragmentsFn = std::function<bool()> ;
93 static constexpr std::size_t inf = ~(std::size_t(0)) ;
94 static_assert( (inf+1U) == 0U ,
"" ) ;
95 std::string m_eol {
"\n",1U} ;
96 std::size_t m_warn {0U} ;
97 std::size_t m_fmin {0U} ;
98 std::size_t m_expect {0U} ;
100 const std::string & eol()
const noexcept ;
101 std::size_t warn()
const noexcept ;
102 std::size_t fmin()
const noexcept ;
103 std::size_t expect()
const noexcept ;
105 Config & set_eol(
const std::string & ) ;
106 Config & set_warn( std::size_t ) noexcept ;
107 Config & set_fmin( std::size_t ) noexcept ;
108 Config & set_expect( std::size_t ) noexcept ;
110 static Config transparent() ;
116 static Config autodetect() ;
125 void add(
const std::string &
data ) ;
133 void expect( std::size_t n ) ;
151 std::string
eol()
const ;
157 template <
typename Tfn>
158 void apply(
const char *
data , std::size_t data_size , Tfn sink_fn ,
bool fragments =
false ) ;
178 template <
typename Tsink,
typename Tmemfun>
179 void apply( Tsink sink_p , Tmemfun sink_memfun ,
const char *
data , std::size_t data_size ,
180 bool fragments =
false ) ;
194 template <
typename Tsink,
typename Tmemfun,
typename Tmemfun2>
195 void apply( Tsink sink_p , Tmemfun sink_memfun ,
const char *
data , std::size_t data_size ,
196 Tmemfun2 fragments_memfun ) ;
201 bool apply( SinkFn sink_fn , std::string_view
data , FragmentsFn fragments_fn ) ;
211 template <
typename Tfn>
212 void apply(
const std::string & , Tfn sink_fn ,
bool fragments =
false ) ;
216 bool more(
bool fragments =
false ) ;
225 const char *
data()
const ;
231 std::size_t
size()
const ;
287 const char * m_data{
nullptr} ;
288 std::size_t m_size{0U} ;
289 std::size_t m_eolsize{0U} ;
290 std::size_t m_linesize{0U} ;
293 std::size_t set( LineStore & , std::size_t pos , std::size_t
size , std::size_t
eolsize ) ;
297 Extension(
LineBuffer * ,
const char * , std::size_t ) ;
299 Extension(
const Extension & ) = delete ;
300 Extension( Extension && ) = delete ;
301 Extension & operator=(
const Extension & ) = delete ;
302 Extension & operator=( Extension && ) = delete ;
309 ~LineBuffer() = default ;
316 friend class LineBufferState ;
317 void output( std::size_t
size , std::size_t
eolsize ,
bool =
false ) ;
319 bool trivial( std::size_t pos )
const ;
320 bool finite()
const ;
321 std::string head()
const ;
324 friend struct Extension ;
328 std::size_t m_warn_limit ;
330 std::size_t m_expect ;
331 bool m_warned {
false} ;
334 std::size_t m_pos {0U} ;
349 std::string
eol()
const ;
352 std::size_t
size()
const ;
358 std::string
head()
const ;
377GNet::LineBuffer::Extension::Extension(
LineBuffer * line_buffer ,
const char * data , std::size_t size ) :
378 m_line_buffer(line_buffer) ,
379 m_call_frame(line_buffer->m_call_stack)
381 m_line_buffer->extensionStart( data ,
size ) ;
385GNet::LineBuffer::Extension::~Extension()
387 if( m_call_frame.valid() )
391 m_line_buffer->extensionEnd() ;
400bool GNet::LineBuffer::Extension::valid()
const
402 return m_call_frame.valid() ;
410 return m_out.m_size ;
420std::string GNet::LineBuffer::head()
const
422 return m_in.head( 16U ) ;
428 return m_out.m_eolsize ;
434 return m_out.m_linesize ;
443template <
typename Tfn>
446 Extension e(
this , data_in , size_in ) ;
447 while( e.valid() && more(with_fragments) )
449 if( !sink_fn( data() , size() , eolsize() , linesize() , c0() ) )
454template <
typename Tsink,
typename Tmemfun>
455void GNet::LineBuffer::apply( Tsink sink_p , Tmemfun memfun ,
const char * data_in , std::size_t size_in ,
bool with_fragments )
457 Extension e(
this , data_in , size_in ) ;
458 while( e.valid() && more(with_fragments) )
460 if( !(sink_p->*memfun)( data() , size() , eolsize() , linesize() , c0() ) )
465template <
typename Tsink,
typename Tmemfun,
typename Tmemfun2>
466void GNet::LineBuffer::apply( Tsink sink_p , Tmemfun memfun ,
const char * data_in , std::size_t size_in , Tmemfun2 fragments_memfun )
468 Extension e(
this , data_in , size_in ) ;
469 while( e.valid() && more( (sink_p->*fragments_memfun)() ) )
471 if( !(sink_p->*memfun)( data() , size() , eolsize() , linesize() , c0() ) )
479 Extension e(
this , data_in.data() , data_in.size() ) ;
480 while( e.valid() && more( fragments_fn() ) )
482 if( !sink_fn( SinkArgs(data(),size(),eolsize(),linesize(),c0(),peekmore()) ) )
492 return apply( data.data() , data.size() , sink , with_fragments ) ;
497inline const std::string & GNet::LineBuffer::Config::eol() const noexcept {
return m_eol ; }
498inline std::size_t GNet::LineBuffer::Config::warn() const noexcept {
return m_warn ; }
499inline std::size_t GNet::LineBuffer::Config::fmin() const noexcept {
return m_fmin ; }
500inline std::size_t GNet::LineBuffer::Config::expect() const noexcept {
return m_expect ; }
501inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_eol(
const std::string & s ) { m_eol = s ;
return *this ; }
502inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_warn( std::size_t n )
noexcept { m_warn = n ;
return *this ; }
503inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_fmin( std::size_t n )
noexcept { m_fmin = n ;
return *this ; }
504inline GNet::LineBuffer::Config & GNet::LineBuffer::Config::set_expect( std::size_t n )
noexcept { m_expect = n ;
return *this ; }
507 inline bool operator==(
const LineBuffer::Config & a ,
const LineBuffer::Config & b )
noexcept
509 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 ;
517 m_transparent(line_buffer.transparent()) ,
518 m_peekmore(line_buffer.peekmore()) ,
519 m_eol(line_buffer.eol()) ,
520 m_size(line_buffer.buffersize()) ,
521 m_head(line_buffer.head())
534 return m_transparent ;
546 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.
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
A configuration structure for GNet::LineBuffer.