package lejos.io; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import lejos.charset.CharsetEncoder; /** * Abstract Single Byte Character Set OutputStream Writer. * @author Sven Köhler */ public class LejosOutputStreamWriter extends Writer { private final static int MIN_BUFFERSIZE = 16; private final CharsetEncoder coder; private final OutputStream os; private final byte[] buffer; private final int limit; //cache for storing a high surrogate private char high; public LejosOutputStreamWriter(OutputStream os, CharsetEncoder coder, int buffersize) { this.os = os; this.coder = coder; if (buffersize < MIN_BUFFERSIZE) buffersize = MIN_BUFFERSIZE; if (coder.getMaxCharLength() > buffersize) throw new IllegalArgumentException("buffer to small for given charset"); this.buffer = new byte[buffersize]; this.limit = buffersize - coder.getMaxCharLength(); } private int writeChar(int len, char c) throws IOException { if (Character.isHighSurrogate(c)) { if (this.high > 0) len = this.coder.encode(-1, buffer, len); this.high = c; return len; } int cp; if (!Character.isLowSurrogate(c)) cp = c; else { if (this.high == 0) return this.coder.encode(-1, buffer, len); cp = Character.toCodePoint(high, c); this.high = 0; } if (len >= limit) { this.bufferFlush(len); len = 0; } return this.coder.encode(cp, this.buffer, len); } private void bufferFlush(int len) throws IOException { this.os.write(this.buffer, 0, len); } @Override public Writer append(char c) throws IOException { this.bufferFlush(this.writeChar(0, c)); return this; } @Override public Writer append(CharSequence str, int start, int end) throws IOException { int bl = 0; for (int i=start; i<end; i++) bl = this.writeChar(bl, str.charAt(i)); this.bufferFlush(bl); return this; } @Override public void write(int c) throws IOException { this.bufferFlush(this.writeChar(0, (char)c)); } @Override public void write(String str, int off, int len) throws IOException { int bl = 0; int end = off + len; for (int i=off; i<end; i++) bl = this.writeChar(bl, str.charAt(i)); this.bufferFlush(bl); } @Override public void write(char[] c, int off, int len) throws IOException { int bl = 0; int end = off + len; for (int i=off; i<end; i++) bl = this.writeChar(bl, c[i]); this.bufferFlush(bl); } @Override public void close() throws IOException { if (this.high > 0) { this.high = 0; this.bufferFlush(this.coder.encode(-1, buffer, 0)); } this.os.close(); } @Override public void flush() throws IOException { this.os.flush(); } }