1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package quotedprintable
11 // A Writer is a quoted-printable writer that implements io.WriteCloser.
13 // Binary mode treats the writer's input as pure binary and processes end of
14 // line bytes as binary data.
23 // NewWriter returns a new Writer that writes to w.
24 func NewWriter(w io
.Writer
) *Writer
{
28 // Write encodes p using quoted-printable encoding and writes it to the
29 // underlying io.Writer. It limits line length to 76 characters. The encoded
30 // bytes are not necessarily flushed until the Writer is closed.
31 func (w
*Writer
) Write(p
[]byte) (n
int, err error
) {
34 // Simple writes are done in batch.
35 case b
>= '!' && b
<= '~' && b
!= '=':
37 case isWhitespace(b
) ||
!w
.Binary
&& (b
== '\n' || b
== '\r'):
42 if err
:= w
.write(p
[n
:i
]); err
!= nil {
48 if err
:= w
.encode(b
); err
!= nil {
58 if err
:= w
.write(p
[n
:]); err
!= nil {
65 // Close closes the Writer, flushing any unwritten data to the underlying
66 // io.Writer, but does not close the underlying io.Writer.
67 func (w
*Writer
) Close() error
{
68 if err
:= w
.checkLastByte(); err
!= nil {
75 // write limits text encoded in quoted-printable to 76 characters per line.
76 func (w
*Writer
) write(p
[]byte) error
{
78 if b
== '\n' || b
== '\r' {
79 // If the previous byte was \r, the CRLF has already been inserted.
80 if w
.cr
&& b
== '\n' {
89 if err
:= w
.checkLastByte(); err
!= nil {
92 if err
:= w
.insertCRLF(); err
!= nil {
98 if w
.i
== lineMaxLen
-1 {
99 if err
:= w
.insertSoftLineBreak(); err
!= nil {
112 func (w
*Writer
) encode(b
byte) error
{
113 if lineMaxLen
-1-w
.i
< 3 {
114 if err
:= w
.insertSoftLineBreak(); err
!= nil {
120 w
.line
[w
.i
+1] = upperhex
[b
>>4]
121 w
.line
[w
.i
+2] = upperhex
[b
&0x0f]
127 const upperhex
= "0123456789ABCDEF"
129 // checkLastByte encodes the last buffered byte if it is a space or a tab.
130 func (w
*Writer
) checkLastByte() error
{
138 if err
:= w
.encode(b
); err
!= nil {
146 func (w
*Writer
) insertSoftLineBreak() error
{
150 return w
.insertCRLF()
153 func (w
*Writer
) insertCRLF() error
{
161 func (w
*Writer
) flush() error
{
162 if _
, err
:= w
.w
.Write(w
.line
[:w
.i
]); err
!= nil {
170 func isWhitespace(b
byte) bool {
171 return b
== ' ' || b
== '\t'