Search in sources :

Example 1 with EncoderException

use of com.github.mangstadt.vinnie.codec.EncoderException in project vinnie by mangstadt.

the class FoldedLineWriter method write.

/**
 * Writes a portion of an array of characters.
 * @param cbuf the array of characters
 * @param off the offset from which to start writing characters
 * @param len the number of characters to write
 * @param quotedPrintable true to encode the string in quoted-printable
 * encoding, false not to
 * @param charset the character set to use when encoding the string into
 * quoted-printable
 * @throws IOException if there's a problem writing to the output stream
 */
public void write(char[] cbuf, int off, int len, boolean quotedPrintable, Charset charset) throws IOException {
    if (quotedPrintable) {
        String str = new String(cbuf, off, len);
        QuotedPrintableCodec codec = new QuotedPrintableCodec(charset.name());
        String encoded;
        try {
            encoded = codec.encode(str);
        } catch (EncoderException e) {
            /*
				 * Thrown if an unsupported charset is passed into the codec.
				 * This should never happen because we already know the charset
				 * is valid (a Charset object is passed into the method).
				 */
            throw new IOException(e);
        }
        cbuf = encoded.toCharArray();
        off = 0;
        len = cbuf.length;
    }
    if (lineLength == null) {
        /*
			 * If line folding is disabled, then write directly to the Writer.
			 */
        writer.write(cbuf, off, len);
        return;
    }
    int effectiveLineLength = lineLength;
    if (quotedPrintable) {
        /*
			 * Account for the "=" character that must be appended onto each
			 * line.
			 */
        effectiveLineLength -= 1;
    }
    int encodedCharPos = -1;
    int start = off;
    int end = off + len;
    for (int i = start; i < end; i++) {
        char c = cbuf[i];
        /*
			 * Keep track of the quoted-printable characters to prevent them
			 * from being cut in two at a folding boundary.
			 */
        if (encodedCharPos >= 0) {
            encodedCharPos++;
            if (encodedCharPos == 3) {
                encodedCharPos = -1;
            }
        }
        if (c == '\n') {
            writer.write(cbuf, start, i - start + 1);
            curLineLength = 0;
            start = i + 1;
            continue;
        }
        if (c == '\r') {
            if (i == end - 1 || cbuf[i + 1] != '\n') {
                writer.write(cbuf, start, i - start + 1);
                curLineLength = 0;
                start = i + 1;
            } else {
                curLineLength++;
            }
            continue;
        }
        if (c == '=' && quotedPrintable) {
            encodedCharPos = 0;
        }
        if (curLineLength >= effectiveLineLength) {
            /*
				 * If the last characters on the line are whitespace, then
				 * exceed the max line length in order to include the whitespace
				 * on the same line.
				 * 
				 * This is to prevent the whitespace from merging with the
				 * folding whitespace of the following folded line and
				 * potentially being lost.
				 * 
				 * Old syntax style allows multiple whitespace characters to be
				 * used for folding, so it could get lost here. New syntax style
				 * only allows one character to be used.
				 */
            if (Character.isWhitespace(c)) {
                while (Character.isWhitespace(c) && i < end - 1) {
                    i++;
                    c = cbuf[i];
                }
                if (i >= end - 1) {
                    /*
						 * The rest of the char array is whitespace, so leave
						 * the loop.
						 */
                    break;
                }
            }
            /*
				 * If we are in the middle of a quoted-printable encoded
				 * character, then exceed the max line length so the sequence
				 * doesn't get split up across multiple lines.
				 */
            if (encodedCharPos > 0) {
                i += 3 - encodedCharPos;
                if (i >= end - 1) {
                    /*
						 * The rest of the char array was a quoted-printable
						 * encoded char, so leave the loop.
						 */
                    break;
                }
            }
            /*
				 * If the last char is the low (second) char in a surrogate
				 * pair, don't split the pair across two lines.
				 */
            if (Character.isLowSurrogate(c)) {
                i++;
                if (i >= end - 1) {
                    /*
						 * Surrogate pair finishes the char array, so leave the
						 * loop.
						 */
                    break;
                }
            }
            writer.write(cbuf, start, i - start);
            if (quotedPrintable) {
                writer.write('=');
            }
            writer.write(CRLF);
            /*
				 * Do not include indentation whitespace if the value is
				 * quoted-printable.
				 */
            curLineLength = 1;
            if (!quotedPrintable) {
                writer.write(indent);
                curLineLength += indent.length();
            }
            start = i;
            continue;
        }
        curLineLength++;
    }
    writer.write(cbuf, start, end - start);
}
Also used : EncoderException(com.github.mangstadt.vinnie.codec.EncoderException) QuotedPrintableCodec(com.github.mangstadt.vinnie.codec.QuotedPrintableCodec) IOException(java.io.IOException)

Aggregations

EncoderException (com.github.mangstadt.vinnie.codec.EncoderException)1 QuotedPrintableCodec (com.github.mangstadt.vinnie.codec.QuotedPrintableCodec)1 IOException (java.io.IOException)1