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);
}
Aggregations