E-MailRelay
Classes | Public Types | Public Member Functions | Friends | List of all members
GNet::LineBuffer Class Reference

A class that does line buffering, supporting auto-detection of line endings and fixed-size block extraction. More...

#include <glinebuffer.h>

Classes

struct  Config
 A configuration structure for GNet::LineBuffer. More...
 

Public Types

using SinkArgs = std::tuple< const char *, std::size_t, std::size_t, std::size_t, char, bool >
 
using SinkFn = std::function< bool(const SinkArgs &)>
 
using FragmentsFn = std::function< bool()>
 

Public Member Functions

 LineBuffer (const Config &)
 Constructor. More...
 
void clear ()
 Clears the internal data. More...
 
void add (const std::string &data)
 Adds a data segment. More...
 
void add (const char *data, std::size_t size)
 Adds a data segment by copying. More...
 
void expect (std::size_t n)
 Requests that the next 'n' bytes are extracted in one contiguous block, without regard to line endings. More...
 
std::string eol () const
 Returns the end-of-line string as passed in to the constructor, or as auto-detected. More...
 
template<typename Tfn >
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, eol-size and c0 parameters. More...
 
template<typename Tsink , typename Tmemfun >
void apply (Tsink sink_p, Tmemfun sink_memfun, const char *data, std::size_t data_size, bool fragments=false)
 Overload that calls out to a member function. More...
 
template<typename Tsink , typename Tmemfun , typename Tmemfun2 >
void apply (Tsink sink_p, Tmemfun sink_memfun, const char *data, std::size_t data_size, Tmemfun2 fragments_memfun)
 Overload where the 'fragments' flag comes from calling a member function on the sink object, allowing the flag to change dynamically as each line is delivered. More...
 
bool apply (SinkFn sink_fn, std::string_view data, FragmentsFn fragments_fn)
 Overload for std::function. More...
 
template<typename Tfn >
void apply (const std::string &, Tfn sink_fn, bool fragments=false)
 Overload taking a string as its data input, used in testing.
 
bool more (bool fragments=false)
 Returns true if there is more data() to be had. More...
 
const char * data () const
 Returns a pointer for the current line, expect()ed fixed-size block, or line fragment. More...
 
std::size_t size () const
 Returns the size of the current data(), excluding the line ending. More...
 
std::size_t eolsize () const
 Returns the size of line-ending associated with the current data(). More...
 
std::size_t linesize () const
 Returns the current size of all the line fragments making up the current line. More...
 
char c0 () const
 Returns the first character of the current line. More...
 
bool transparent () const
 Returns true if the current expect() value is infinite. More...
 
LineBufferState state () const
 Returns information about the current state of the line-buffer. More...
 
std::size_t buffersize () const
 Returns the total number of bytes buffered up. More...
 
bool peekmore () const
 Returns true if there is a line available after the current line or expect()ation. More...
 
void extensionStart (const char *, std::size_t)
 A pseudo-private method used by the implementation of the apply() method template. More...
 
void extensionEnd ()
 A pseudo-private method used by the implementation of the apply() method template. More...
 
 LineBuffer (const LineBuffer &)=delete
 
 LineBuffer (LineBuffer &&)=delete
 
LineBufferoperator= (const LineBuffer &)=delete
 
LineBufferoperator= (LineBuffer &&)=delete
 
template<typename T >
void apply (const std::string &data, T sink, bool with_fragments)
 

Friends

class LineBufferState
 
struct Extension
 

Detailed Description

A class that does line buffering, supporting auto-detection of line endings and fixed-size block extraction.

Raw data is added, and newline-delimited lines are extracted, optionally via an iterator.

Usage:

{
buffer.add("abc") ;
buffer.add("def\nABC\nDE") ;
buffer.add("F\n") ;
while( buffer.more() )
cout << std::string(buffer.data(),buffer.size()) << endl ;
}
A class that does line buffering, supporting auto-detection of line endings and fixed-size block extr...
Definition: glinebuffer.h:84
A configuration structure for GNet::LineBuffer.
Definition: glinebuffer.h:92

A callback mechanism (apply()) can be used that combines adding and extracting. This has the benefit of less data copying, especially if the caller allows incomplete line fragments to be delivered.

{
struct Callback { bool operator()( const char * , std::size_t size , std::size_t eolsize , std::size_t linesize , char c0 ) {...} } callback ;
for( std::string s : std::vector<std::string> { "foo" , "bar\r" , "\n" } )
buffer.apply( s.data() , s.size() , callback , true ) ;
}
std::size_t linesize() const
Returns the current size of all the line fragments making up the current line.
Definition: glinebuffer.h:432
std::size_t size() const
Returns the size of the current data(), excluding the line ending.
Definition: glinebuffer.h:408
std::size_t eolsize() const
Returns the size of line-ending associated with the current data().
Definition: glinebuffer.h:426
char c0() const
Returns the first character of the current line.
Definition: glinebuffer.h:438

The expect() method allows for handling fixed-size blocks that are not line-structured (think http content-length). While the expect() value is in force the line buffer is in a transparent mode, delivering data() with a zero eolsize().

Note that a line buffer that is configured as 'transparent' at run-time is essentially zero cost when using apply() with the 'fragments' option: data passes directly from apply() to the callback.

Definition at line 83 of file glinebuffer.h.

Member Typedef Documentation

◆ FragmentsFn

using GNet::LineBuffer::FragmentsFn = std::function<bool()>

Definition at line 89 of file glinebuffer.h.

◆ SinkArgs

using GNet::LineBuffer::SinkArgs = std::tuple<const char*,std::size_t,std::size_t,std::size_t,char,bool>

Definition at line 87 of file glinebuffer.h.

◆ SinkFn

using GNet::LineBuffer::SinkFn = std::function<bool(const SinkArgs&)>

Definition at line 88 of file glinebuffer.h.

Constructor & Destructor Documentation

◆ LineBuffer()

GNet::LineBuffer::LineBuffer ( const Config config)
explicit

Constructor.

Definition at line 28 of file glinebuffer.cpp.

Member Function Documentation

◆ add() [1/2]

void GNet::LineBuffer::add ( const char *  data,
std::size_t  size 
)

Adds a data segment by copying.

Does nothing if data is null or size is zero. See also apply().

Definition at line 48 of file glinebuffer.cpp.

◆ add() [2/2]

void GNet::LineBuffer::add ( const std::string &  data)

Adds a data segment.

Definition at line 55 of file glinebuffer.cpp.

◆ apply() [1/5]

template<typename Tfn >
void GNet::LineBuffer::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, eol-size and c0 parameters.

Stops if the sink function returns false. The data can be nullptr in order to flush any existing data to the sink function. This method is zero-copy if the supplied data contains complete lines or if allowing line fragments.

< void Foo::onData( const char * data , std::size_t size )
< {
< m_line_buffer.apply( data , size , onLine , false ) ;
< }
< bool onLine( const char * data , std::size_t size , std::size_t , std::size_t , char )
< {
< process( std::string(data,size) ) ;
< }
<
const char * data() const
Returns a pointer for the current line, expect()ed fixed-size block, or line fragment.

Definition at line 444 of file glinebuffer.h.

◆ apply() [2/5]

template<typename T >
void GNet::LineBuffer::apply ( const std::string &  data,
sink,
bool  with_fragments 
)
inline

Definition at line 490 of file glinebuffer.h.

◆ apply() [3/5]

bool GNet::LineBuffer::apply ( SinkFn  sink_fn,
std::string_view  data,
FragmentsFn  fragments_fn 
)
inline

Overload for std::function.

This overload provides extra parameter 'more' to the sink function that is true if there is another complete line buffered-up after the current one (and eolsize is non-zero).

Returns false iff the sink function returned false.

Definition at line 477 of file glinebuffer.h.

◆ apply() [4/5]

template<typename Tsink , typename Tmemfun >
void GNet::LineBuffer::apply ( Tsink  sink_p,
Tmemfun  sink_memfun,
const char *  data,
std::size_t  data_size,
bool  fragments = false 
)

Overload that calls out to a member function.

< void Foo::onData( const char * data , std::size_t size )
< {
< m_line_buffer.apply( this , &Foo::onLine , data , size , false ) ;
< }
< bool Foo::onLine( const char * data , std::size_t size , std::size_t , std::size_t , char )
< {
< process( std::string(data,size) ) ;
< }
<

Definition at line 455 of file glinebuffer.h.

◆ apply() [5/5]

template<typename Tsink , typename Tmemfun , typename Tmemfun2 >
void GNet::LineBuffer::apply ( Tsink  sink_p,
Tmemfun  sink_memfun,
const char *  data,
std::size_t  data_size,
Tmemfun2  fragments_memfun 
)

Overload where the 'fragments' flag comes from calling a member function on the sink object, allowing the flag to change dynamically as each line is delivered.

Definition at line 466 of file glinebuffer.h.

◆ buffersize()

std::size_t GNet::LineBuffer::buffersize ( ) const
inline

Returns the total number of bytes buffered up.

Definition at line 414 of file glinebuffer.h.

◆ c0()

char GNet::LineBuffer::c0 ( ) const
inline

Returns the first character of the current line.

This can be useful in the case of line fragments where treatment of the fragment depends on the first character of the complete line (as in SMTP data transfer). Precondition: linesize() != 0U

Definition at line 438 of file glinebuffer.h.

◆ clear()

void GNet::LineBuffer::clear ( )

Clears the internal data.

Definition at line 37 of file glinebuffer.cpp.

◆ data()

const char * GNet::LineBuffer::data ( ) const

Returns a pointer for the current line, expect()ed fixed-size block, or line fragment.

This includes eolsize() bytes of line-ending. Precondition: more()

Definition at line 203 of file glinebuffer.cpp.

◆ eol()

std::string GNet::LineBuffer::eol ( ) const

Returns the end-of-line string as passed in to the constructor, or as auto-detected.

Returns the empty string if auto-detection by iteration has not yet occurred.

Definition at line 182 of file glinebuffer.cpp.

◆ eolsize()

std::size_t GNet::LineBuffer::eolsize ( ) const
inline

Returns the size of line-ending associated with the current data().

This will be zero for a fixed-size block or non-terminal line fragment. (It will never be zero as a result of auto-detection because the precondition means that auto-detection has already happened.) Precondition: more()

Definition at line 426 of file glinebuffer.h.

◆ expect()

void GNet::LineBuffer::expect ( std::size_t  n)

Requests that the next 'n' bytes are extracted in one contiguous block, without regard to line endings.

Once the expected number of bytes have been extracted the line buffering returns to normal.

This method can be used during a data-transfer phase to obtain a chunk of data of known size, as in http with a known content-length.

A parameter value of zero switches back to normal line buffering immediately.

A parameter value of std::size_t(-1) can be used to represent an infinite expectation that is never fully satisfied. This is only sensible when extracting fragments with apply(), and it results in full transparency.

Definition at line 172 of file glinebuffer.cpp.

◆ extensionEnd()

void GNet::LineBuffer::extensionEnd ( )

A pseudo-private method used by the implementation of the apply() method template.

Definition at line 67 of file glinebuffer.cpp.

◆ extensionStart()

void GNet::LineBuffer::extensionStart ( const char *  data,
std::size_t  size 
)

A pseudo-private method used by the implementation of the apply() method template.

Definition at line 61 of file glinebuffer.cpp.

◆ linesize()

std::size_t GNet::LineBuffer::linesize ( ) const
inline

Returns the current size of all the line fragments making up the current line.

Precondition: more()

Definition at line 432 of file glinebuffer.h.

◆ more()

bool GNet::LineBuffer::more ( bool  fragments = false)

Returns true if there is more data() to be had.

This advances the implied iterator.

If the fragments parameter is true then incomplete lines will be returned (with eolsize zero), but those fragments will explicitly exclude anything that might be part of the line ending.

Definition at line 73 of file glinebuffer.cpp.

◆ peekmore()

bool GNet::LineBuffer::peekmore ( ) const

Returns true if there is a line available after the current line or expect()ation.

Precondition: more()

Definition at line 143 of file glinebuffer.cpp.

◆ size()

std::size_t GNet::LineBuffer::size ( ) const
inline

Returns the size of the current data(), excluding the line ending.

Precondition: more()

Definition at line 408 of file glinebuffer.h.

◆ state()

GNet::LineBufferState GNet::LineBuffer::state ( ) const

Returns information about the current state of the line-buffer.

Definition at line 209 of file glinebuffer.cpp.

◆ transparent()

bool GNet::LineBuffer::transparent ( ) const

Returns true if the current expect() value is infinite.

Definition at line 177 of file glinebuffer.cpp.

Friends And Related Function Documentation

◆ Extension

friend struct Extension
friend

Definition at line 324 of file glinebuffer.h.

◆ LineBufferState

friend class LineBufferState
friend

Definition at line 316 of file glinebuffer.h.


The documentation for this class was generated from the following files: