E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

glinebuffer.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 ///
18 /// \file glinebuffer.h
19 ///
20
21 #ifndef G_NET_LINE_BUFFER__H
22 #define G_NET_LINE_BUFFER__H
23
24 #include "gdef.h"
25 #include "gexception.h"
26 #include <string>
27
28 namespace GNet
29 {
30 class LineBuffer ;
31 class LineBufferConfig ;
32 class LineBufferIterator ;
33 }
34
35 /// \class GNet::LineBuffer
36 /// A class that does line buffering, supporting auto-detection of
37 /// line endings and fixed-size extraction. Raw data is added, and
38 /// newline-delimited lines are extracted, optionally via an iterator.
39 ///
40 /// Usage:
41 /// \code
42 /// {
43 /// GNet::LineBuffer buffer( (GNet::LineBufferConfig()) ) ;
44 /// buffer.add("abc") ;
45 /// buffer.add("def\nABC\nDE") ;
46 /// buffer.add("F\n") ;
47 /// GNet::LineBufferIterator iter( buffer ) ;
48 /// while( iter.more() )
49 /// cout << iter.line() << endl ;
50 /// }
51 /// \endcode
52 ///
53 class GNet::LineBuffer
54 {
55 public:
56 G_EXCEPTION( ErrorOverflow , "line buffer overflow" ) ;
57
58 explicit LineBuffer( LineBufferConfig ) ;
59 ///< Constructor.
60
61 void add( const std::string & data ) ;
62 ///< Adds a data segment.
63
64 void add( const char * data , size_t size ) ;
65 ///< Adds a data segment.
66
67 void expect( size_t n ) ;
68 ///< The next 'n' bytes extracted will be extracted in one
69 ///< contiguous block, without regard to line endings.
70 ///<
71 ///< This method can be used during a data-transfer phase to
72 ///< obtain a chunk of data of known size, as in http with a
73 ///< specific content-length.
74
75 std::string eol() const ;
76 ///< Returns the end-of-line string as passed in to the
77 ///< constructor, or as auto-detected. Returns the empty
78 ///< string if auto-detection by iteration has not yet
79 ///< occurred.
80
81 template <typename Tsink>
82 void apply( const char * data , size_t data_size , Tsink sink ) ;
83 ///< Adds the data and passes complete lines to the sink
84 ///< functor with line-data, line-size and eol-size parameters.
85 ///< Stops if the sink functor returns false. This method
86 ///< is zero-copy if the supplied data contains several
87 ///< complete lines.
88
89 bool more() ;
90 ///< Returns true if there is lineData() to be had.
91
92 const char * lineData() const ;
93 ///< Returns a pointer for the current line, including the
94 ///< line ending.
95 ///< Precondition: more()
96
97 size_t lineSize() const ;
98 ///< Returns the size of the current line, excluding the
99 ///< line ending.
100 ///< Precondition: more()
101
102 size_t eolSize() const ;
103 ///< Returns the size of current line ending. This will
104 ///< be zero if extracting a fixed-size block. (It will
105 ///< never be zero as a result of auto-detection because
106 ///< auto-detection has already happened.)
107 ///< Precondition: more()
108
109 private:
110 LineBuffer( const LineBuffer & ) ;
111 void operator=( const LineBuffer & ) ;
112 void precheck( size_t ) ;
113 void linecheck( size_t ) ;
114 bool detect() ;
115 void addextra( const char * , size_t ) ;
116 void consolidate() ;
117 const char * extraeol() const ;
118
119 private:
120 bool m_auto ;
121 std::string m_eol ;
122 size_t m_warn_limit ;
123 size_t m_fail_limit ;
124 std::string m_store ;
125 const char * m_extra_data ;
126 size_t m_extra_size ;
127 size_t m_expect ;
128 bool m_warned ;
129 size_t m_pos ;
130 const char * m_line_data ;
131 size_t m_line_size ;
132 size_t m_eol_size ;
133 } ;
134
135 /// \class GNet::LineBufferIterator
136 /// Syntactic sugar for calling GNet::LineBuffer iteration methods.
137 ///
138 class GNet::LineBufferIterator
139 {
140 public:
141 explicit LineBufferIterator( LineBuffer & buffer ) ;
142 ///< Constructor.
143
144 bool more() ;
145 ///< See LineBuffer::more().
146
147 const char * lineData() const ;
148 ///< See LineBuffer::lineData().
149
150 size_t lineSize() const ;
151 ///< See LineBuffer::lineSize().
152
153 size_t eolSize() const ;
154 ///< See LineBuffer::eolSize().
155
156 std::string line() const ;
157 ///< Returns the current line.
158
159 std::string eol() const ;
160 ///< Returns the current line ending but returns the empty
161 ///< string if currently inside an expect() block.
162
163 private:
164 LineBufferIterator( const LineBufferIterator & ) ;
165 void operator=( const LineBufferIterator & ) ;
166
167 private:
168 LineBuffer & m_buffer ;
169 } ;
170
171 /// \class GNet::LineBufferConfig
172 /// A configuration structure for GNet::LineBuffer.
173 ///
174 class GNet::LineBufferConfig
175 {
176 public:
177 explicit LineBufferConfig( const std::string & eol = std::string(1U,'\n') ,
178 size_t warn = 0U , size_t fail = 0U ) ;
179 ///< Constructor. An empty end-of-line string detects either
180 ///< LF or CR-LF. The default end-of-line string is newline.
181 ///< A non-zero warn-limit generates a one-shot warning when
182 ///< breached, and the fail-limit causes an exception when
183 ///< breached. The fail-limit defaults to something large if
184 ///< given as zero.
185
186 const std::string & eol() const ;
187 ///< Returns the end-of-line string as passed to the constructor.
188
189 size_t warn() const ;
190 ///< Returns the warn-limit, as passed to the constructor.
191
192 size_t fail() const ;
193 ///< Returns the fail-limit, as passed to the constructor.
194
195 static LineBufferConfig http() ;
196 ///< Convenience factory function.
197
198 static LineBufferConfig smtp() ;
199 ///< Convenience factory function.
200
201 static LineBufferConfig pop() ;
202 ///< Convenience factory function.
203
204 static LineBufferConfig crlf() ;
205 ///< Convenience factory function.
206
207 static LineBufferConfig newline() ;
208 ///< Convenience factory function.
209
210 static LineBufferConfig autodetect() ;
211 ///< Convenience factory function.
212
213 private:
214 std::string m_eol ;
215 size_t m_warn ;
216 size_t m_fail ;
217 } ;
218
219 inline
220 const std::string & GNet::LineBufferConfig::eol() const
221 {
222 return m_eol ;
223 }
224
225 inline
226 size_t GNet::LineBufferConfig::warn() const
227 {
228 return m_warn ;
229 }
230
231 inline
232 size_t GNet::LineBufferConfig::fail() const
233 {
234 return m_fail ;
235 }
236
237 namespace GNet
238 {
239 template <typename T>
240 void LineBuffer::apply( const char * data , size_t size , T sink )
241 {
242 addextra( data , size ) ;
243 while( more() )
244 {
245 if( !sink( lineData() , lineSize() , eolSize() ) )
246 break ;
247 }
248 }
249 }
250
251 inline
252 GNet::LineBufferIterator::LineBufferIterator( LineBuffer & buffer ) :
253 m_buffer(buffer)
254 {
255 }
256
257 inline
258 bool GNet::LineBufferIterator::more()
259 {
260 return m_buffer.more() ;
261 }
262
263 inline
264 std::string GNet::LineBufferIterator::line() const
265 {
266 return std::string( m_buffer.lineData() , m_buffer.lineSize() ) ;
267 }
268
269 inline
270 std::string GNet::LineBufferIterator::eol() const
271 {
272 return m_buffer.eolSize() == 0U ? std::string() : m_buffer.eol() ;
273 }
274
275 inline
276 const char * GNet::LineBufferIterator::lineData() const
277 {
278 return m_buffer.lineData() ;
279 }
280
281 inline
282 size_t GNet::LineBufferIterator::lineSize() const
283 {
284 return m_buffer.lineSize() ;
285 }
286
287 inline
288 size_t GNet::LineBufferIterator::eolSize() const
289 {
290 return m_buffer.eolSize() ;
291 }
292
293 #endif
GNet::LineBufferIterator::eol
std::string eol() const
Returns the current line ending but returns the empty string if currently inside an expect() block...
Definition: glinebuffer.h:270
GNet::LineBufferConfig::newline
static LineBufferConfig newline()
Convenience factory function.
Definition: glinebuffer.cpp:301
GNet::LineBufferConfig::http
static LineBufferConfig http()
Convenience factory function.
Definition: glinebuffer.cpp:326
GNet
Network classes.
Definition: gaddress.h:29
GNet::LineBufferConfig::pop
static LineBufferConfig pop()
Convenience factory function.
Definition: glinebuffer.cpp:321
GNet::LineBuffer::expect
void expect(size_t n)
The next 'n' bytes extracted will be extracted in one contiguous block, without regard to line ending...
Definition: glinebuffer.cpp:257
GNet::LineBufferIterator::lineData
const char * lineData() const
See LineBuffer::lineData().
Definition: glinebuffer.h:276
GNet::LineBufferIterator
Syntactic sugar for calling GNet::LineBuffer iteration methods.
Definition: glinebuffer.h:138
GNet::LineBufferIterator::line
std::string line() const
Returns the current line.
Definition: glinebuffer.h:264
GNet::LineBuffer::more
bool more()
Returns true if there is lineData() to be had.
Definition: glinebuffer.cpp:97
GNet::LineBufferIterator::eolSize
size_t eolSize() const
See LineBuffer::eolSize().
Definition: glinebuffer.h:288
GNet::LineBufferIterator::LineBufferIterator
LineBufferIterator(LineBuffer &buffer)
Constructor.
Definition: glinebuffer.h:252
GNet::LineBufferConfig
A configuration structure for GNet::LineBuffer.
Definition: glinebuffer.h:174
GNet::LineBufferConfig::autodetect
static LineBufferConfig autodetect()
Convenience factory function.
Definition: glinebuffer.cpp:306
GNet::LineBufferConfig::LineBufferConfig
LineBufferConfig(const std::string &eol=std::string(1U,'\n'), size_t warn=0U, size_t fail=0U)
Constructor.
Definition: glinebuffer.cpp:294
GNet::LineBuffer::LineBuffer
LineBuffer(LineBufferConfig)
Constructor.
Definition: glinebuffer.cpp:31
GNet::LineBufferConfig::eol
const std::string & eol() const
Returns the end-of-line string as passed to the constructor.
Definition: glinebuffer.h:220
GNet::LineBufferConfig::smtp
static LineBufferConfig smtp()
Convenience factory function.
Definition: glinebuffer.cpp:316
GNet::LineBufferIterator::lineSize
size_t lineSize() const
See LineBuffer::lineSize().
Definition: glinebuffer.h:282
GNet::LineBufferConfig::crlf
static LineBufferConfig crlf()
Convenience factory function.
Definition: glinebuffer.cpp:311
gexception.h
GNet::LineBuffer::add
void add(const std::string &data)
Adds a data segment.
Definition: glinebuffer.cpp:56
GNet::LineBuffer
A class that does line buffering, supporting auto-detection of line endings and fixed-size extraction...
Definition: glinebuffer.h:53
GNet::LineBuffer::lineSize
size_t lineSize() const
Returns the size of the current line, excluding the line ending.
Definition: glinebuffer.cpp:281
GNet::LineBuffer::eolSize
size_t eolSize() const
Returns the size of current line ending.
Definition: glinebuffer.cpp:276
GNet::LineBuffer::eol
std::string eol() const
Returns the end-of-line string as passed in to the constructor, or as auto-detected.
Definition: glinebuffer.cpp:262
GNet::LineBufferConfig::warn
size_t warn() const
Returns the warn-limit, as passed to the constructor.
Definition: glinebuffer.h:226
GNet::LineBuffer::lineData
const char * lineData() const
Returns a pointer for the current line, including the line ending.
Definition: glinebuffer.cpp:286
GNet::LineBufferConfig::fail
size_t fail() const
Returns the fail-limit, as passed to the constructor.
Definition: glinebuffer.h:232
GNet::LineBuffer::apply
void apply(const char *data, size_t data_size, Tsink sink)
Adds the data and passes complete lines to the sink functor with line-data, line-size and eol-size pa...
GNet::LineBufferIterator::more
bool more()
See LineBuffer::more().
Definition: glinebuffer.h:258