BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlde_quotedprintableencoder.h
Go to the documentation of this file.
1/// @file bdlde_quotedprintableencoder.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlde_quotedprintableencoder.h -*-C++-*-
8#ifndef INCLUDED_BDLDE_QUOTEDPRINTABLEENCODER
9#define INCLUDED_BDLDE_QUOTEDPRINTABLEENCODER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlde_quotedprintableencoder bdlde_quotedprintableencoder
15/// @brief Provide automata converting to and from Quoted-Printable encodings.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlde
19/// @{
20/// @addtogroup bdlde_quotedprintableencoder
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlde_quotedprintableencoder-purpose"> Purpose</a>
25/// * <a href="#bdlde_quotedprintableencoder-classes"> Classes </a>
26/// * <a href="#bdlde_quotedprintableencoder-description"> Description </a>
27/// * <a href="#bdlde_quotedprintableencoder-quoted-printable-encoding"> Quoted-Printable Encoding </a>
28/// * <a href="#bdlde_quotedprintableencoder-general-8-bit-representation"> General 8-Bit Representation </a>
29/// * <a href="#bdlde_quotedprintableencoder-literal-representation"> Literal Representation </a>
30/// * <a href="#bdlde_quotedprintableencoder-whitespace"> Whitespace </a>
31/// * <a href="#bdlde_quotedprintableencoder-line-breaks"> Line Breaks </a>
32/// * <a href="#bdlde_quotedprintableencoder-soft-line-breaks"> Soft Line Breaks </a>
33/// * <a href="#bdlde_quotedprintableencoder-example-1"> Example 1 </a>
34/// * <a href="#bdlde_quotedprintableencoder-example-2"> Example 2 </a>
35/// * <a href="#bdlde_quotedprintableencoder-quoted-printable-decoding"> Quoted-Printable Decoding </a>
36/// * <a href="#bdlde_quotedprintableencoder-usage"> Usage </a>
37/// * <a href="#bdlde_quotedprintableencoder-example-1-encoding"> Example 1: Encoding </a>
38///
39/// # Purpose {#bdlde_quotedprintableencoder-purpose}
40/// Provide automata converting to and from Quoted-Printable encodings.
41///
42/// # Classes {#bdlde_quotedprintableencoder-classes}
43///
44/// - bdlde::QuotedPrintableEncoder: automaton for Quoted-Printable encoding
45///
46/// @see bdlde_quotedprintabledecoder
47///
48/// # Description {#bdlde_quotedprintableencoder-description}
49/// This component provides a class that can be used to encode byte
50/// sequences of arbitrary length into the Quoted Printable representation
51/// described in Section 6.7 "Quoted-Printable Content Transfer Encoding" of RFC
52/// 2045, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of
53/// Internet Message Bodies."
54///
55/// Each instance of the encoder retains the state of the conversion from one
56/// supplied input to the next, enabling the processing of segmented input --
57/// i.e., processing resumes where it left off with the next invocation on new
58/// input. Instance methods are provided for the encoder to (1) assert the end
59/// of input, (2) determine whether the input so far is currently acceptable,
60/// and (3) indicate whether a non-recoverable error has occurred.
61///
62/// ## Quoted-Printable Encoding {#bdlde_quotedprintableencoder-quoted-printable-encoding}
63///
64///
65/// This encoding scheme is suitable for encoding arbitrary data consisting
66/// primarily of printable text characters. Additionally, this scheme seeks to
67/// preserve the integrity of the byte stream during transfer by making it
68/// difficult for any intermediate interpreting software in the path of the
69/// transfer to disruptively change its content (e.g., because of trailing
70/// whitespace and line breaks). For binary data, Base64 encoding may be a more
71/// appropriate scheme (see @ref bdlde_base64 ).
72///
73/// The data stream is processed one byte at a time from left to right as
74/// follows:
75///
76/// ### General 8-Bit Representation {#bdlde_quotedprintableencoder-general-8-bit-representation}
77///
78///
79/// Any 8-bit input character, except a CR or LF, *may* be represented by an "="
80/// followed by a 2-digit hexadecimal representation of its ASCII value. Only
81/// uppercase hexadecimal digits are allowed. For example, the letter `n` can
82/// be encoded into `=6E`.
83///
84/// ### Literal Representation {#bdlde_quotedprintableencoder-literal-representation}
85///
86///
87/// Characters with decimal values in the range [33..126], with the exception of
88/// 61 (`=`), *may* be represented literally as they appear before encoding.
89/// Hence, in addition to [0-9][a-z][A-Z], the following characters may
90/// propagate to the encoded stream unchanged.
91/// @code
92/// [!"#$%&'()*+,-./:;<>?@[\]^_`{|}~]
93/// @endcode
94///
95/// ### Whitespace {#bdlde_quotedprintableencoder-whitespace}
96///
97///
98/// Space and tab *may* be represented literally, unless they appear at the end
99/// of an encoded line, in which case they must be followed by a `=` character
100/// serving as a soft line break (see rule #5), or they must be encoded
101/// according to rule #1. It follows that any trailing whitespace encountered
102/// in a Quoted-Printable body must necessarily be added by intermediate
103/// transport agents and must be deleted during decoding.
104///
105/// ### Line Breaks {#bdlde_quotedprintableencoder-line-breaks}
106///
107///
108/// A line break must be represented in the Quoted-Printable encoding as in rule
109/// number 1, i.e., LF -> =0A; CR -> =0D.
110///
111/// ### Soft Line Breaks {#bdlde_quotedprintableencoder-soft-line-breaks}
112///
113///
114/// Encoded lines are required to be no longer than 76 characters in this
115/// encoding scheme. Soft line breaks in the form of an `=` sign placed at the
116/// end of an encoded line are used to break up longer lines, either necessarily
117/// when the number of encoded characters, including any `=` characters but not
118/// counting the trailing CRLF, reaches the limit of 76, or at the user's
119/// discretion -- e.g., during manual encoding. Soft line breaks are to be
120/// removed during decoding as they are not part of the original content.
121///
122/// The Quoted-Printable encoding scheme allows one or two forms of encoding
123/// depending on the value of the character to be encoded as well as its
124/// location with respect to the end of line. When both forms are permissible,
125/// the choice is discretionary. For example, the word `From` is often used as
126/// a message separator in the standard UNIX mail folder format. To reduce the
127/// chance of a message getting broken, a sentence such as "From point A ..." is
128/// often best encoded as "=46rom point A ...", although "From point A ..." is
129/// also a valid encoding.
130///
131/// This implementation by default prefers literal encoding to Quoted-Printable
132/// encoding. In the case of a space or tab character happening at the end of
133/// an encoded line, if there is more input to follow, a soft line break is
134/// inserted; otherwise, the last line of encoding should be terminated with the
135/// Quoted Printable encoding of space or tab (a line break is both redundant
136/// and contrived).
137///
138/// In situations where it is desirable to specify certain characters to be
139/// encoded to their numeric form, the encoder in this implementation also
140/// offers a means to specify these characters through the first parameter to
141/// the following constructor
142/// @code
143/// bdlde::QuotedPrintableEncoder(
144/// const char *extraCharsToEncode,
145/// bdlde::QuotedPrintableEncoder::LineBreakMode lineBreakMode
146/// = bdlde::QuotedPrintableEncoder::e_CRLF_MODE,
147/// int maxLineLength =
148/// bdlde::QuotedPrintableEncoder::k_DEFAULT_MAX_LINELEN);
149/// @endcode
150///
151/// The following examples demonstrate the above rules per the design choices
152/// made for this implementation. Note that there is a hard line break at the
153/// 77th character position, immediately after "dozing".
154///
155/// ### Example 1 {#bdlde_quotedprintableencoder-example-1}
156///
157///
158/// Data:
159/// @code
160/// From point A to point B, the distance is 1245.56 miles. Driving at a dozing
161/// speed of 15mph, it will take 2 hours to complete the trip.
162/// @endcode
163///
164/// Encoding:
165/// @code
166/// =46rom point A to point B, the distance is 1245.56 miles. Driving at a doz=
167/// ing=0D=0A speed of 15mph, =
168/// it will take 2 hours=
169/// to complete the trip.
170/// @endcode
171///
172/// ### Example 2 {#bdlde_quotedprintableencoder-example-2}
173///
174///
175/// Data:
176/// @code
177/// Hello, world.
178/// @endcode
179/// (The last line of input ends with a whitespace.)
180///
181/// Encoding:
182/// @code
183/// Hello, world.=20
184/// @endcode
185/// (In this case, a Quoted Printable is preferred to soft line break as there
186/// should only be one encoded line.)
187///
188/// The above encoding is acceptable, although it is by no means unique.
189///
190/// ## Quoted-Printable Decoding {#bdlde_quotedprintableencoder-quoted-printable-decoding}
191///
192///
193/// (In the following, all rules mentioned refer to those listed in the encoder
194/// section above.)
195///
196/// The decoding process for this encoding scheme involves:
197///
198/// 1. transforming any encoded character triplets back into their original
199/// representation (rule #1 and rule #4).
200/// 2. literally writing out characters that have not been changed (rule #2).
201/// 3. deleting any trailing whitespace at the end of an encoded line (rule #3).
202/// 4. removing the soft line breaks including the `=` prefix (i.e.,
203/// concatenating broken sentences) (rule #5).
204///
205/// The standard imposes a maximum of 76 characters exclusive of CRLF; however,
206/// the decoder implemented in this component will handle lines of arbitrary
207/// length.
208///
209/// The decoder also provides support for two error-reporting modes,
210/// configurable at construction: the strict mode and the relaxed mode. A
211/// strict-mode decoder stops decoding at the first offending character
212/// encountered, while a relaxed-mode decoder continues decoding to the end of
213/// the input, allowing straight pass-through of character sets that cannot be
214/// interpreted.
215///
216/// ## Usage {#bdlde_quotedprintableencoder-usage}
217///
218///
219/// This section illustrates intended use of this component.
220///
221/// ### Example 1: Encoding {#bdlde_quotedprintableencoder-example-1-encoding}
222///
223///
224/// The following example shows how to use a `bdlde::QuotedPrintableEncoder`
225/// object to implement a function, `streamconverter`, that reads text from a
226/// `bsl::istream`, encodes that text in Quoted-Printable representation, and
227/// write928s the encoded text to a `bsl::ostream`. `streamconverter` returns 0
228/// on success, and a negative value if the input data could not be successfully
229/// encoded or if there is an I/O error.
230/// @code
231/// streamconverter.h -*-C++-*-
232///
233/// /// Read the entire contents of the specified input stream `is`, convert
234/// /// the input plain text to quoted-printable encoding, and write the
235/// /// encoded text to the specified output stream `os`. Return 0 on
236/// /// success, and a negative value otherwise.
237/// int streamconverter(bsl::ostream& os, bsl::istream& is);
238/// @endcode
239/// We will use fixed-sized input and output buffers in the implementation, but,
240/// because of the flexibility of `bsl::istream` and the output-buffer
241/// monitoring functionality of `QuotedPrintableEncoder`, the fixed buffer sizes
242/// do *not* limit the quantity of data that can be read, encoded, or written to
243/// the output stream. The implementation file is as follows.
244/// @code
245/// streamconverter.cpp -*-C++-*-
246///
247/// #include <streamconverter.h>
248///
249/// #include <bdlde_quotedprintableencoder.h>
250///
251/// namespace BloombergLP {
252///
253/// int streamconverter(bsl::ostream& os, bsl::istream& is)
254/// {
255/// enum {
256/// SUCCESS = 0,
257/// ENCODE_ERROR = -1,
258/// IO_ERROR = -2
259/// };
260/// @endcode
261/// We declare a `bdlde::QuotedPrintableEncoder` object `converter`, which will
262/// encode the input data. Note that various internal buffers and cursors are
263/// used as needed without further comment. We read as much data as is
264/// available from the user-supplied input stream `is` *or* as much as will fit
265/// in `inputBuffer` before beginning conversion.
266/// @code
267/// bdlde::QuotedPrintableEncoder converter;
268///
269/// const int INBUFFER_SIZE = 1 << 10;
270/// const int OUTBUFFER_SIZE = 1 << 10;
271///
272/// char inputBuffer[INBUFFER_SIZE];
273/// char outputBuffer[OUTBUFFER_SIZE];
274///
275/// char *output = outputBuffer;
276/// char *outputEnd = outputBuffer + sizeof outputBuffer;
277///
278/// while (is.good()) { // input stream not exhausted
279///
280/// is.read(inputBuffer, sizeof inputBuffer);
281/// @endcode
282/// With `inputBuffer` now populated, we'll use `converter` in an inner `while`
283/// loop to encode the input and write the encoded data to `outputBuffer` (via
284/// the `output` cursor'). Note that if the call to `converter.convert` fails,
285/// our function terminates with a negative status.
286/// @code
287/// const char *input = inputBuffer;
288/// const char *inputEnd = input + is.gcount();
289///
290/// while (input < inputEnd) { // input encoding not complete
291///
292/// int numOut;
293/// int numIn;
294///
295/// int status = converter.convert(output, &numOut, &numIn,
296/// input, inputEnd,
297/// outputEnd - output);
298/// if (status < 0) {
299/// return ENCODE_ERROR; // RETURN
300/// }
301/// @endcode
302/// If the call to `converter.convert` returns successfully, we'll see if the
303/// output buffer is full, and if so, write its contents to the user-supplied
304/// output stream `os`. Note how we use the values of `numOut` and `numIn`
305/// generated by `convert` to update the relevant cursors.
306/// @code
307/// output += numOut;
308/// input += numIn;
309///
310/// if (output == outputEnd) { // output buffer full; write data
311/// os.write (outputBuffer, sizeof outputBuffer);
312/// if (os.fail()) {
313/// return IO_ERROR; // RETURN
314/// }
315/// output = outputBuffer;
316/// }
317/// }
318/// }
319/// @endcode
320/// We have now exited both the input and the "encode" loops. `converter` may
321/// still hold encoded output characters, and so we call `converter.endConvert`
322/// to emit any retained output. To guarantee correct behavior, we call this
323/// method in an infinite loop, because it is possible that the retained output
324/// can fill the output buffer. In that case, we solve the problem by writing
325/// the contents of the output buffer to `os` within the loop. The most likely
326/// case, however, is that `endConvert` will return 0, in which case we exit the
327/// loop and write any data remaining in `outputBuffer` to `os`. As above, if
328/// `endConvert` fails, we exit the function with a negative return status.
329/// @code
330/// for (;;) {
331///
332/// int more =
333/// converter.endConvert(output, &numOut, outputEnd - output);
334/// if (more < 0) {
335/// return ENCODE_ERROR; // RETURN
336/// }
337///
338/// output += numOut;
339///
340/// if (!more) { // no more output
341/// break;
342/// }
343///
344/// assert (output == outputEnd); // output buffer is full
345///
346/// os.write (outputBuffer, sizeof outputBuffer); // write buffer
347/// if (os.fail()) {
348/// return IO_ERROR; // RETURN
349/// }
350/// output = outputBuffer;
351/// }
352///
353/// if (output > outputBuffer) { // still data in output buffer; write it
354/// // all
355/// os.write(outputBuffer, output - outputBuffer);
356/// }
357///
358/// return is.eof() && os.good() ? SUCCESS : IO_ERROR;
359/// }
360///
361/// } // Close namespace BloombergLP
362/// @endcode
363/// For ease of reading, we repeat the full content of the `streamconverter.cpp`
364/// file without interruption.
365/// @code
366/// streamconverter.cpp -*-C++-*-
367///
368/// #include <streamconverter.h>
369///
370/// #include <bdlde_quotedprintableencoder.h>
371///
372/// namespace BloombergLP {
373///
374/// int streamconverter(bsl::ostream& os, bsl::istream& is)
375/// {
376/// enum {
377/// SUCCESS = 0,
378/// ENCODE_ERROR = -1,
379/// IO_ERROR = -2
380/// };
381///
382/// bdlde::QuotedPrintableEncoder converter;
383///
384/// const int INBUFFER_SIZE = 1 << 10;
385/// const int OUTBUFFER_SIZE = 1 << 10;
386///
387/// char inputBuffer[INBUFFER_SIZE];
388/// char outputBuffer[OUTBUFFER_SIZE];
389///
390/// char *output = outputBuffer;
391/// char *outputEnd = outputBuffer + sizeof outputBuffer;
392///
393/// while (is.good()) { // input stream not exhausted
394///
395/// is.read(inputBuffer, sizeof inputBuffer);
396///
397/// const char *input = inputBuffer;
398/// const char *inputEnd = input + is.gcount();
399///
400/// while (input < inputEnd) { // input encoding not complete
401///
402/// int numOut;
403/// int numIn;
404///
405/// int status = converter.convert(output, &numOut, &numIn,
406/// input, inputEnd,
407/// outputEnd - output);
408/// if (status < 0) {
409/// return ENCODE_ERROR; // RETURN
410/// }
411///
412/// output += numOut;
413/// input += numIn;
414///
415/// if (output == outputEnd) { // output buffer full; write data
416/// os.write(outputBuffer, sizeof outputBuffer);
417/// if (os.fail()) {
418/// return IO_ERROR; // RETURN
419/// }
420/// output = outputBuffer;
421/// }
422/// }
423/// }
424///
425/// for (;;) {
426///
427/// int more =
428/// converter.endConvert(output, &numOut, outputEnd - output);
429/// if (more < 0) {
430/// return ENCODE_ERROR; // RETURN
431/// }
432///
433/// output += numOut;
434///
435/// if (!more) { // no more output
436/// break;
437/// }
438///
439/// assert (output == outputEnd); // output buffer is full
440///
441/// os.write (outputBuffer, sizeof outputBuffer); // write buffer
442/// if (os.fail()) {
443/// return IO_ERROR; // RETURN
444/// }
445/// output = outputBuffer;
446/// }
447///
448/// if (output > outputBuffer) {
449/// os.write (outputBuffer, output - outputBuffer);
450/// }
451///
452/// return is.eof() && os.good() ? SUCCESS : IO_ERROR;
453/// }
454///
455/// } // Close namespace BloombergLP
456/// @endcode
457/// @}
458/** @} */
459/** @} */
460
461/** @addtogroup bdl
462 * @{
463 */
464/** @addtogroup bdlde
465 * @{
466 */
467/** @addtogroup bdlde_quotedprintableencoder
468 * @{
469 */
470
471#include <bdlscm_version.h>
472
473#include <bslma_allocator.h>
475
476#include <bsl_climits.h> // INT_MAX
477
478#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
480#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
481
482
483namespace bdlde {
484
485 // ============================
486 // class QuotedPrintableEncoder
487 // ============================
488
489/// This class implements a mechanism capable of converting data of
490/// arbitrary length to its corresponding Quoted-Printable representation.
491///
492/// See @ref bdlde_quotedprintableencoder
494
495 // PRIVATE TYPES
496
497 /// Symbolic state values for the encoder
498 enum States {
499 e_ERROR_STATE = -1, // input is irreparably invalid
500 e_INITIAL_STATE = 0, // require no more input
501 e_INPUT_STATE = 1, // general input state
502 e_DONE_STATE = 2 // accepting; any additional input is error
503 };
504
505 enum {
506 k_DEFAULT_MAX_LINELEN = 76 // maximum allowed by RFC 2045
507 };
508
509 public:
510 // PUBLIC TYPES
511
512 /// The input equivalence classes
514 e_PC = 0, // printable character - copy straight to output
515 e_CR, // carriage return - wait for more input
516 e_LF, // line feed - complete linebreak
517 e_WS, // whitespace - buffer; wait for more input
518 e_CC // control character - encode to Quoted Printable
519 };
520
522 // Configuration governing how various forms of line breaks are to be
523 // interpreted
524
525 e_CRLF_MODE = 0, // allow "\r\n" as linebreaks
526
527 e_LF_MODE, // allow '\n' as linebreaks (without the '\r' prefix)
528
529 e_MIXED_MODE, // allow "\r\n" and '\n' as linebreaks
530 e_BINARY_MODE // allow no linebreaks
531 };
532
533 private:
534 // CLASS DATA
535 static const char *s_defaultEquivClass_p; // default map of
536 // `unsigned char` to
537 // equivalent class
538
539 static const char *s_lineBreakModeName[]; // names of line break mode
540
541 // INSTANCE DATA
542 LineBreakMode d_lineBreakMode; // linebreak mode
543
544 int d_maxLineLength; // maximum length of output line
545
546 int d_outputLength; // total number of output characters
547
548 int d_lineLength; // number of characters on the current
549 //line
550
551 char *d_equivClass_p; // map of `unsigned char` to input
552 // equivalence class; dynamically
553 // allocated if the default map is to
554 // be modified; otherwise it is
555 // assigned; compare with static
556 // address to know whether to delete
557
558 char d_lastInputChar; // stores an input space or tab if it
559 // happens at the end of input
560
561 int d_state; // stores current state of this object
562
563 char d_buffer[5]; // stack of characters to output
564
565 int d_bufferLength; // size of the stack
566
567 int d_lineStart; // index of output character that
568 // starts the current line
569
570 char d_deffered; // stores 0 or the deffered input
571 // character
572
573 bool d_lastWasWS; // stores whether last printed
574 // character was a whitespace character
575
576 bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
577
578 private:
579 // PRIVATE MANIPULATORS
580
581 /// Append to the buffer addressed by the specified `out` the first
582 /// character of the soft line-break character sequence and push onto
583 /// the buffered output stack the characters representing the residual
584 /// of the soft line-break character sequence.
585 void appendSoftLineBreak(char *out);
586
587 /// Append to the buffer addressed by the specified `out` the first
588 /// character of the hard line-break character sequence and push onto
589 /// the buffered output stack the characters representing the residual
590 /// of the hard line-break character sequence.
591 void appendHardLineBreak(char *out);
592
593 /// Append to the buffer addressed by the specified `out` or, through
594 /// the buffered output stack, schedule to append the characters
595 /// representing, if needed, a soft line-break and the specified
596 /// character `ch`.
597 void appendPrintable(char *out, char ch);
598
599 /// Append to the buffer addressed by the specified `out` or, through
600 /// the buffered output stack, schedule to append the characters
601 /// representing, if needed, a soft line-break, with consideration for
602 /// whether or not this is the final chanracters in the encoding as per
603 /// the specified `isFinal`, and the specified character `ch`
604 /// represented as a hexadecimal encoding.
605 void appendAsHex(char *out, char ch, bool isFinal = false);
606
607 // NOT IMPLEMENTED
610
611 public:
612 // CLASS METHODS
613
614 /// Return the string representation exactly matching the enumerator
615 /// name corresponding to the specified enumerator `mode`.
616 static const char* lineBreakModeToAscii(
618
619 // CREATORS
620
621 /// Create a Quoted-Printable encoder in the initial state, configured
622 /// to accept hard line breaks based on the optionally specified
623 /// `lineBreakMode`, and to insert soft line breaks when the line length
624 /// exceeds the optionally specified `maxLineLength` (default is the RFC
625 /// 2045 maximum 76). Optionally specify a `basicAllocator` used to
626 /// supply memory. If `basicAllocator` is 0, the currently installed
627 /// default allocator is used. The behavior is undefined unless
628 /// `4 <= maxLineLength <= 76`. Note that e_CRLF_MODE passes "\r\n"
629 /// straight to output and converts '\n'; e_LF_MODE passes '\n' and
630 /// converts '\r'; e_MIXED_MODE passes both "\r\n" and '\n'.
631 explicit
634 int maxLineLength = k_DEFAULT_MAX_LINELEN,
635 bslma::Allocator *basicAllocator = 0);
636
637 /// Create a Quoted-Printable encoder in the initial state, configured
638 /// to convert to the form "=XX" any input character matching a
639 /// printable or whitespace character in the specified
640 /// `extraCharsToEncode` array (as opposed to the default setting of
641 /// passing the input character straight to output), to accept hard
642 /// linebreaks based on the optionally specified `lineBreakMode`, and to
643 /// insert soft linebreaks when the line length exceeds the optionally
644 /// specified `maxLineLength` (default is the RFC 2045 maximum 76).
645 /// Optionally specify a `basicAllocator` used to supply memory. If
646 /// `basicAllocator` is 0, the currently installed default allocator is
647 /// used. The behavior is undefined unless `4 <= `maxLineLength <= 76'.
648 /// Note that e_CRLF_MODE passes "\r\n" straight to output and converts
649 /// '\n'; e_LF_MODE passes '\n' and converts '\r'; e_MIXED_MODE passes
650 /// both "\r\n" and '\n'.
651 explicit
653 const char *extraCharsToEncode,
655 int maxLineLength = k_DEFAULT_MAX_LINELEN,
656 bslma::Allocator *basicAllocator = 0);
657
658 /// Destroy this object.
660
661 // MANIPULATORS
662
663 /// Append to the buffer addressed by the specified `out` all pending
664 /// output (if there is any) up to the optionally specified `maxNumOut`
665 /// limit (default is negative, meaning no limit) and, when there is no
666 /// pending output and `maxNumOut` is still not reached, begin to
667 /// consume and encode a sequence of input characters starting at the
668 /// specified `begin` position, up to but not including the specified
669 /// `end` position, writing any resulting output in the specified `out`
670 /// buffer up to the (cumulative) `maxNumOut` limit. If `maxNumOut`
671 /// limit is reached, no further input will be consumed. Load into the
672 /// specified `numOut` and `numIn` the number of output bytes produced
673 /// and input bytes consumed, respectively. Return a non-negative value
674 /// on success and a negative value otherwise. A successful return
675 /// status indicates the number of characters that would be output if
676 /// `endConvert` were called subsequently with no output limit. These
677 /// bytes *may* be available for output if this method is called with a
678 /// sufficiently large `maxNumOut`. Note that calling this method after
679 /// `endConvert` has been invoked without an intervening `reset` call
680 /// will place this instance in an error state, and return an error
681 /// status. Note also that it is recommended that after all calls to
682 /// `convert` are finished, the `endConvert` method be called to
683 /// complete the encoding of any unprocessed input characters.
684 int convert(char *out,
685 int *numOut,
686 int *numIn,
687 const char *begin,
688 const char *end,
689 int maxNumOut = -1);
690
691 /// Terminate encoding for this encoder; write any retained output
692 /// (e.g., from a previous call to `convert` with a non-zero `maxNumOut`
693 /// argument) to the specified `out` buffer. Optionally specify the
694 /// `maxNumOut` limit on the number of bytes to output; if `maxNumOut`
695 /// is negative, no limit is imposed. Load into the specified `numOut`
696 /// the number of output bytes produced. Return a non-negative value on
697 /// success and a negative value otherwise. A successful return status
698 /// indicates the number of characters that would be output if
699 /// `endConvert` were called subsequently with no output limit. Any
700 /// retained bytes are available on a subsequent call to `endConvert`.
701 /// Once this method is called, no additional input may be supplied
702 /// without an intervening call to `reset`; once this method returns a
703 /// zero status, a subsequent call will place this encoder in the error
704 /// state, and return an error status.
705 int endConvert(char *out, int *numOut, int maxNumOut = -1);
706
707 /// Reset this encoder to its initial state (i.e., as if no input had
708 /// been consumed).
709 void reset();
710
711 // ACCESSORS
712
713 /// Return `true` if the input read so far by this encoder is considered
714 /// syntactically complete, and `false` otherwise.
715 bool isAccepting() const;
716
717 /// Return `true` if this encoder is in the done state (i.e.,
718 /// `endConvert` has been called and any additional input will result in
719 /// an error), and if there is no pending output, and `false` otherwise.
720 bool isDone() const;
721
722 /// Return `true` if there is no possibility of achieving an
723 /// "acceptable" result, and `false` otherwise. Note that for an
724 /// encoder, no input can cause an error; the possible errors result
725 /// either from a call to the `convert` method after the `endConvert`
726 /// method is called the first time, or from a call to either the
727 /// `convert` or the `endConvert` methods after the `endConvert` method
728 /// has returned successfully.
729 bool isError() const;
730
731 /// Return `true` if this encoder is in the initial state (i.e., as if
732 /// no input had been consumed), and `false` otherwise.
733 bool isInitialState() const;
734
735 /// Return the line break mode configured at the construction of this
736 /// encoder.
738
739 /// Return the value for the maximum line length configured at the
740 /// construction of this encoder.
741 int maxLineLength() const;
742
743 /// Return the number of characters that would be output if `endConvert`
744 /// were called with no output limit.
745 int numOutputPending() const;
746
747 /// Return the total length of the output emitted by this encoder
748 /// (possibly after one or more calls to the `convert` or the `input`
749 /// methods) since its initial construction or the latest `reset`. Note
750 /// that soft line breaks are included in the counts if added.
751 int outputLength() const;
752};
753
754// ============================================================================
755// INLINE DEFINITIONS
756// ============================================================================
757
758// CLASS METHODS
759inline
761{
762 return s_lineBreakModeName[mode];
763}
764
765// MANIPULATORS
766inline
768{
769 d_state = e_INITIAL_STATE;
770 d_outputLength = 0;
771 d_lineLength = 0;
772 d_bufferLength = 0;
773 d_deffered = 0;
774}
775
776// ACCESSORS
777inline
779{
780 return e_ERROR_STATE != d_state;
781}
782
783inline
785{
786 return e_DONE_STATE == d_state && 0 == d_deffered && 0 == d_bufferLength;
787}
788
789inline
791{
792 return e_ERROR_STATE == d_state;
793}
794
795inline
797{
798 return e_INITIAL_STATE == d_state;
799}
800
801inline
804{
805 return d_lineBreakMode;
806}
807
808inline
810{
811 return d_maxLineLength;
812}
813
814inline
816{
817 return d_deffered ? 3 : d_bufferLength;
818}
819
820inline
822{
823 return d_outputLength;
824}
825
826} // close package namespace
827
828
829// TRAITS
830
831
832namespace bslma {
833
834template <>
835struct UsesBslmaAllocator<bdlde::QuotedPrintableEncoder> : bsl::true_type {};
836
837} // close namespace bslma
838
839
840#endif
841
842// ----------------------------------------------------------------------------
843// Copyright 2016 Bloomberg Finance L.P.
844//
845// Licensed under the Apache License, Version 2.0 (the "License");
846// you may not use this file except in compliance with the License.
847// You may obtain a copy of the License at
848//
849// http://www.apache.org/licenses/LICENSE-2.0
850//
851// Unless required by applicable law or agreed to in writing, software
852// distributed under the License is distributed on an "AS IS" BASIS,
853// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
854// See the License for the specific language governing permissions and
855// limitations under the License.
856// ----------------------------- END-OF-FILE ----------------------------------
857
858/** @} */
859/** @} */
860/** @} */
Definition bdlde_quotedprintableencoder.h:493
QuotedPrintableEncoder(const char *extraCharsToEncode, LineBreakMode lineBreakMode=e_CRLF_MODE, int maxLineLength=k_DEFAULT_MAX_LINELEN, bslma::Allocator *basicAllocator=0)
int numOutputPending() const
Definition bdlde_quotedprintableencoder.h:815
bool isInitialState() const
Definition bdlde_quotedprintableencoder.h:796
int endConvert(char *out, int *numOut, int maxNumOut=-1)
void reset()
Definition bdlde_quotedprintableencoder.h:767
int outputLength() const
Definition bdlde_quotedprintableencoder.h:821
bool isDone() const
Definition bdlde_quotedprintableencoder.h:784
~QuotedPrintableEncoder()
Destroy this object.
int maxLineLength() const
Definition bdlde_quotedprintableencoder.h:809
QuotedPrintableEncoder(LineBreakMode lineBreakMode=e_CRLF_MODE, int maxLineLength=k_DEFAULT_MAX_LINELEN, bslma::Allocator *basicAllocator=0)
LineBreakMode
Definition bdlde_quotedprintableencoder.h:521
@ e_LF_MODE
Definition bdlde_quotedprintableencoder.h:527
@ e_MIXED_MODE
Definition bdlde_quotedprintableencoder.h:529
@ e_BINARY_MODE
Definition bdlde_quotedprintableencoder.h:530
@ e_CRLF_MODE
Definition bdlde_quotedprintableencoder.h:525
LineBreakMode lineBreakMode() const
Definition bdlde_quotedprintableencoder.h:803
int convert(char *out, int *numOut, int *numIn, const char *begin, const char *end, int maxNumOut=-1)
EquivalenceClass
The input equivalence classes.
Definition bdlde_quotedprintableencoder.h:513
@ e_PC
Definition bdlde_quotedprintableencoder.h:514
@ e_WS
Definition bdlde_quotedprintableencoder.h:517
@ e_CR
Definition bdlde_quotedprintableencoder.h:515
@ e_CC
Definition bdlde_quotedprintableencoder.h:518
@ e_LF
Definition bdlde_quotedprintableencoder.h:516
bool isAccepting() const
Definition bdlde_quotedprintableencoder.h:778
bool isError() const
Definition bdlde_quotedprintableencoder.h:790
static const char * lineBreakModeToAscii(QuotedPrintableEncoder::LineBreakMode mode)
Definition bdlde_quotedprintableencoder.h:760
Definition bslma_allocator.h:457
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlde_base64alphabet.h:118
Definition balxml_encoderoptions.h:68
Definition bslma_usesbslmaallocator.h:343