FastPrintWriter.java revision e5a9c92377e035b24f50f9f66f4cdfd9cf79c2dd
172961230a5890071bcca436eb5630172ce84ec41Andreas Huberpackage com.android.internal.util;
272961230a5890071bcca436eb5630172ce84ec41Andreas Huber
372961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.io.IOException;
472961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.io.OutputStream;
572961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.io.PrintWriter;
672961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.io.UnsupportedEncodingException;
772961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.io.Writer;
872961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.nio.ByteBuffer;
972961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.nio.CharBuffer;
1072961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.nio.charset.Charset;
1172961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.nio.charset.CharsetEncoder;
1272961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.nio.charset.CoderResult;
1372961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.nio.charset.CodingErrorAction;
1472961230a5890071bcca436eb5630172ce84ec41Andreas Huber
1572961230a5890071bcca436eb5630172ce84ec41Andreas Huberpublic class FastPrintWriter extends PrintWriter {
1672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private static final int BUFFER_LEN = 8192;
1772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
1872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private static Writer sDummyWriter = new Writer() {
1972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        @Override
2072961230a5890071bcca436eb5630172ce84ec41Andreas Huber        public void close() throws IOException {
2172961230a5890071bcca436eb5630172ce84ec41Andreas Huber            UnsupportedOperationException ex
2272961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    = new UnsupportedOperationException("Shouldn't be here");
23bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar            throw ex;
2472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
2572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
2672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        @Override
2772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        public void flush() throws IOException {
2872961230a5890071bcca436eb5630172ce84ec41Andreas Huber            close();
2972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
3072961230a5890071bcca436eb5630172ce84ec41Andreas Huber
3172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        @Override
3272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        public void write(char[] buf, int offset, int count) throws IOException {
3372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            close();
3472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
3572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    };
3672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
3772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private final char[] mText = new char[BUFFER_LEN];
3872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private int mPos;
3972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
4072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    final private OutputStream mOutputStream;
4172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    final private Writer mWriter;
4272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    final private boolean mAutoFlush;
4372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    final private String mSeparator;
4472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private CharsetEncoder mCharset;
4572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    final private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
4672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private boolean mIoError;
4772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
4872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
4972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Constructs a new {@code PrintWriter} with {@code out} as its target
5072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * stream. By default, the new print writer does not automatically flush its
5172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * contents to the target stream when a newline is encountered.
52bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar     *
53bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar     * @param out
54bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar     *            the target output stream.
55bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar     * @throws NullPointerException
56bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar     *             if {@code out} is {@code null}.
57bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar     */
58bcf08569453dcb42730cda3230d5d375a697005bLajos Molnar    public FastPrintWriter(OutputStream out) {
5972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        super(sDummyWriter);
6072961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mOutputStream = out;
6172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mWriter = null;
6272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mAutoFlush = false;
6372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mSeparator = System.lineSeparator();
6472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        initDefaultEncoder();
6572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
6672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
6772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
6872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Constructs a new {@code PrintWriter} with {@code out} as its target
6972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * stream. The parameter {@code autoFlush} determines if the print writer
7072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * automatically flushes its contents to the target stream when a newline is
7172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * encountered.
7272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *
7372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param out
7472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            the target output stream.
7572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param autoFlush
7672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            indicates whether contents are flushed upon encountering a
7772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            newline sequence.
7872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @throws NullPointerException
7972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *             if {@code out} is {@code null}.
8072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
8172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public FastPrintWriter(OutputStream out, boolean autoFlush) {
8272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        super(sDummyWriter, autoFlush);
8372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mOutputStream = out;
8472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mWriter = null;
8572961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mAutoFlush = autoFlush;
8672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mSeparator = System.lineSeparator();
8772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        initDefaultEncoder();
8872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
8972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
9072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
9172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Constructs a new {@code PrintWriter} with {@code wr} as its target
9272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * writer. By default, the new print writer does not automatically flush its
9372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * contents to the target writer when a newline is encountered.
9472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *
9572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param wr
9672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            the target writer.
9772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @throws NullPointerException
9872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *             if {@code wr} is {@code null}.
9972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
10072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public FastPrintWriter(Writer wr) {
10172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        super(sDummyWriter);
10272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mOutputStream = null;
10372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mWriter = wr;
10472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mAutoFlush = false;
10572961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mSeparator = System.lineSeparator();
10672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        initDefaultEncoder();
10772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
10872961230a5890071bcca436eb5630172ce84ec41Andreas Huber
10972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
11072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Constructs a new {@code PrintWriter} with {@code out} as its target
11172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * writer. The parameter {@code autoFlush} determines if the print writer
11272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * automatically flushes its contents to the target writer when a newline is
11372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * encountered.
11472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *
11572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param wr
11672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            the target writer.
11772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param autoFlush
11872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            indicates whether to flush contents upon encountering a
11972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            newline sequence.
12072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @throws NullPointerException
12172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *             if {@code out} is {@code null}.
12272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
12372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public FastPrintWriter(Writer wr, boolean autoFlush) {
12472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        super(sDummyWriter, autoFlush);
12572961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mOutputStream = null;
12672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mWriter = wr;
12772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mAutoFlush = autoFlush;
12872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mSeparator = System.lineSeparator();
12972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        initDefaultEncoder();
13072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
13172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
13272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private final void initEncoder(String csn) throws UnsupportedEncodingException {
13372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        try {
13472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mCharset = Charset.forName(csn).newEncoder();
13572961230a5890071bcca436eb5630172ce84ec41Andreas Huber        } catch (Exception e) {
13672961230a5890071bcca436eb5630172ce84ec41Andreas Huber            throw new UnsupportedEncodingException(csn);
13772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
13872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mCharset.onMalformedInput(CodingErrorAction.REPLACE);
13972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
14072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
14172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
14272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
14372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Flushes this writer and returns the value of the error flag.
14472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *
14572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @return {@code true} if either an {@code IOException} has been thrown
14672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *         previously or if {@code setError()} has been called;
14772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *         {@code false} otherwise.
14872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @see #setError()
14972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
15072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public boolean checkError() {
15172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        flush();
15272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        synchronized (lock) {
15372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            return mIoError;
15472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
15572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
15672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
15772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
15872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Sets the error state of the stream to false.
15972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @since 1.6
16072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
16172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    protected void clearError() {
16272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        synchronized (lock) {
16372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mIoError = false;
16472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
16572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
16672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
16772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
16872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Sets the error flag of this writer to true.
16972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
17072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    protected void setError() {
17172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        synchronized (lock) {
17272961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mIoError = true;
17372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
17472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
17572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
17672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private final void initDefaultEncoder() {
17772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mCharset = Charset.defaultCharset().newEncoder();
17872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mCharset.onMalformedInput(CodingErrorAction.REPLACE);
17972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
18072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
18172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
18272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private void appendLocked(char c) throws IOException {
18372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        int pos = mPos;
18472961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if (pos >= (BUFFER_LEN-1)) {
18572961230a5890071bcca436eb5630172ce84ec41Andreas Huber            flushLocked();
18672961230a5890071bcca436eb5630172ce84ec41Andreas Huber            pos = mPos;
18772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
18872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mText[pos] = c;
18972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mPos = pos+1;
19072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
19172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
19272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private void appendLocked(String str, int i, final int length) throws IOException {
19372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if (length > BUFFER_LEN) {
19472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            final int end = i + length;
19572961230a5890071bcca436eb5630172ce84ec41Andreas Huber            while (i < end) {
19672961230a5890071bcca436eb5630172ce84ec41Andreas Huber                int next = i + BUFFER_LEN;
19772961230a5890071bcca436eb5630172ce84ec41Andreas Huber                appendLocked(str, i, next < end ? BUFFER_LEN : (end - i));
19872961230a5890071bcca436eb5630172ce84ec41Andreas Huber                i = next;
19972961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
20072961230a5890071bcca436eb5630172ce84ec41Andreas Huber            return;
20172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
20272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        int pos = mPos;
20372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if ((pos+length) > BUFFER_LEN) {
20472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            flushLocked();
20572961230a5890071bcca436eb5630172ce84ec41Andreas Huber            pos = mPos;
20672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
20772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        str.getChars(i, i + length, mText, pos);
20872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mPos = pos + length;
20972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
21072961230a5890071bcca436eb5630172ce84ec41Andreas Huber
21172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private void appendLocked(char[] buf, int i, final int length) throws IOException {
21272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if (length > BUFFER_LEN) {
21372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            final int end = i + length;
21472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            while (i < end) {
21572961230a5890071bcca436eb5630172ce84ec41Andreas Huber                int next = i + BUFFER_LEN;
21672961230a5890071bcca436eb5630172ce84ec41Andreas Huber                appendLocked(buf, i, next < end ? BUFFER_LEN : (end - i));
21772961230a5890071bcca436eb5630172ce84ec41Andreas Huber                i = next;
21872961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
21972961230a5890071bcca436eb5630172ce84ec41Andreas Huber            return;
22072961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
22172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        int pos = mPos;
22272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if ((pos+length) > BUFFER_LEN) {
22372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            flushLocked();
22472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            pos = mPos;
22572961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
22672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        System.arraycopy(buf, i, mText, pos, length);
22772961230a5890071bcca436eb5630172ce84ec41Andreas Huber        mPos = pos + length;
22872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
22972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
23072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private void flushBytesLocked() throws IOException {
23172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        int position;
23272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if ((position = mBytes.position()) > 0) {
23372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mBytes.flip();
23472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mOutputStream.write(mBytes.array(), 0, position);
23572961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mBytes.clear();
23672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
23772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
23872961230a5890071bcca436eb5630172ce84ec41Andreas Huber
23972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private void flushLocked() throws IOException {
24072961230a5890071bcca436eb5630172ce84ec41Andreas Huber        //Log.i("PackageManager", "flush mPos=" + mPos);
24172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if (mPos > 0) {
24272961230a5890071bcca436eb5630172ce84ec41Andreas Huber            if (mOutputStream != null) {
24372961230a5890071bcca436eb5630172ce84ec41Andreas Huber                CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos);
24472961230a5890071bcca436eb5630172ce84ec41Andreas Huber                CoderResult result = mCharset.encode(charBuffer, mBytes, true);
24572961230a5890071bcca436eb5630172ce84ec41Andreas Huber                while (true) {
24672961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    if (result.isError()) {
24772961230a5890071bcca436eb5630172ce84ec41Andreas Huber                        throw new IOException(result.toString());
24872961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    } else if (result.isOverflow()) {
24972961230a5890071bcca436eb5630172ce84ec41Andreas Huber                        flushBytesLocked();
25072961230a5890071bcca436eb5630172ce84ec41Andreas Huber                        result = mCharset.encode(charBuffer, mBytes, true);
25172961230a5890071bcca436eb5630172ce84ec41Andreas Huber                        continue;
25272961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    }
25372961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    break;
25472961230a5890071bcca436eb5630172ce84ec41Andreas Huber                }
25572961230a5890071bcca436eb5630172ce84ec41Andreas Huber                flushBytesLocked();
25672961230a5890071bcca436eb5630172ce84ec41Andreas Huber                mOutputStream.flush();
25772961230a5890071bcca436eb5630172ce84ec41Andreas Huber            } else {
25872961230a5890071bcca436eb5630172ce84ec41Andreas Huber                mWriter.write(mText, 0, mPos);
25972961230a5890071bcca436eb5630172ce84ec41Andreas Huber                mWriter.flush();
26072961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
26172961230a5890071bcca436eb5630172ce84ec41Andreas Huber            mPos = 0;
26272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
26372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
26472961230a5890071bcca436eb5630172ce84ec41Andreas Huber
26572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
26672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Ensures that all pending data is sent out to the target. It also
26772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * flushes the target. If an I/O error occurs, this writer's error
26872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * state is set to {@code true}.
26972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
27072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    @Override
27172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public void flush() {
27272961230a5890071bcca436eb5630172ce84ec41Andreas Huber        synchronized (lock) {
27372961230a5890071bcca436eb5630172ce84ec41Andreas Huber            try {
27472961230a5890071bcca436eb5630172ce84ec41Andreas Huber                flushLocked();
27572961230a5890071bcca436eb5630172ce84ec41Andreas Huber                if (mOutputStream != null) {
27672961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    mOutputStream.flush();
27772961230a5890071bcca436eb5630172ce84ec41Andreas Huber                } else {
27872961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    mWriter.flush();
27972961230a5890071bcca436eb5630172ce84ec41Andreas Huber                }
28072961230a5890071bcca436eb5630172ce84ec41Andreas Huber            } catch (IOException e) {
28172961230a5890071bcca436eb5630172ce84ec41Andreas Huber                setError();
28272961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
28372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
28472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
28572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
28672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    @Override
28772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public void close() {
28872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        synchronized (lock) {
28972961230a5890071bcca436eb5630172ce84ec41Andreas Huber            try {
29072961230a5890071bcca436eb5630172ce84ec41Andreas Huber                flushLocked();
29172961230a5890071bcca436eb5630172ce84ec41Andreas Huber                if (mOutputStream != null) {
29272961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    mOutputStream.close();
29372961230a5890071bcca436eb5630172ce84ec41Andreas Huber                } else {
29472961230a5890071bcca436eb5630172ce84ec41Andreas Huber                    mWriter.close();
29572961230a5890071bcca436eb5630172ce84ec41Andreas Huber                }
29672961230a5890071bcca436eb5630172ce84ec41Andreas Huber            } catch (IOException e) {
29772961230a5890071bcca436eb5630172ce84ec41Andreas Huber                setError();
29872961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
29972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
30072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
30172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
30272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
30372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Prints the string representation of the specified character array
30472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * to the target.
30572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *
30672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param charArray
30772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            the character array to print to the target.
30872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @see #print(String)
30972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
31072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public void print(char[] charArray) {
31172961230a5890071bcca436eb5630172ce84ec41Andreas Huber        synchronized (lock) {
31272961230a5890071bcca436eb5630172ce84ec41Andreas Huber            try {
31372961230a5890071bcca436eb5630172ce84ec41Andreas Huber                appendLocked(charArray, 0, charArray.length);
31472961230a5890071bcca436eb5630172ce84ec41Andreas Huber            } catch (IOException e) {
31572961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
31672961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
31772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
31872961230a5890071bcca436eb5630172ce84ec41Andreas Huber
31972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
32072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Prints the string representation of the specified character to the
321ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber     * target.
322ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber     *
323ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber     * @param ch
324ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber     *            the character to print to the target.
325ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber     * @see #print(String)
326ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber     */
327ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    public void print(char ch) {
328ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        synchronized (lock) {
329ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            try {
330ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber                appendLocked(ch);
33172961230a5890071bcca436eb5630172ce84ec41Andreas Huber            } catch (IOException e) {
33272961230a5890071bcca436eb5630172ce84ec41Andreas Huber            }
33372961230a5890071bcca436eb5630172ce84ec41Andreas Huber        }
33472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
33572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
33672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
33772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Prints a string to the target. The string is converted to an array of
33872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * bytes using the encoding chosen during the construction of this writer.
33972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * The bytes are then written to the target with {@code write(int)}.
34072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * <p>
34172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * If an I/O error occurs, this writer's error flag is set to {@code true}.
34272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *
34372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @param str
34472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     *            the string to print to the target.
34572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @see #write(int)
34672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
34772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public void print(String str) {
34872961230a5890071bcca436eb5630172ce84ec41Andreas Huber        if (str == null) {
34972961230a5890071bcca436eb5630172ce84ec41Andreas Huber            str = String.valueOf((Object) null);
350        }
351        synchronized (lock) {
352            try {
353                appendLocked(str, 0, str.length());
354            } catch (IOException e) {
355                setError();
356            }
357        }
358    }
359
360
361    @Override
362    public void print(int inum) {
363        if (inum == 0) {
364            print("0");
365        } else {
366            super.print(inum);
367        }
368    }
369
370    @Override
371    public void print(long lnum) {
372        if (lnum == 0) {
373            print("0");
374        } else {
375            super.print(lnum);
376        }
377    }
378
379    /**
380     * Prints a newline. Flushes this writer if the autoFlush flag is set to {@code true}.
381     */
382    public void println() {
383        synchronized (lock) {
384            try {
385                appendLocked(mSeparator, 0, mSeparator.length());
386                if (mAutoFlush) {
387                    flushLocked();
388                }
389            } catch (IOException e) {
390                setError();
391            }
392        }
393    }
394
395    @Override
396    public void println(int inum) {
397        if (inum == 0) {
398            println("0");
399        } else {
400            super.println(inum);
401        }
402    }
403
404    @Override
405    public void println(long lnum) {
406        if (lnum == 0) {
407            println("0");
408        } else {
409            super.print(lnum);
410        }
411    }
412
413    /**
414     * Prints the string representation of the character array {@code chars} followed by a newline.
415     * Flushes this writer if the autoFlush flag is set to {@code true}.
416     */
417    public void println(char[] chars) {
418        print(chars);
419        println();
420    }
421
422    /**
423     * Prints the string representation of the char {@code c} followed by a newline.
424     * Flushes this writer if the autoFlush flag is set to {@code true}.
425     */
426    public void println(char c) {
427        print(c);
428        println();
429    }
430
431    /**
432     * Writes {@code count} characters from {@code buffer} starting at {@code
433     * offset} to the target.
434     * <p>
435     * This writer's error flag is set to {@code true} if this writer is closed
436     * or an I/O error occurs.
437     *
438     * @param buf
439     *            the buffer to write to the target.
440     * @param offset
441     *            the index of the first character in {@code buffer} to write.
442     * @param count
443     *            the number of characters in {@code buffer} to write.
444     * @throws IndexOutOfBoundsException
445     *             if {@code offset < 0} or {@code count < 0}, or if {@code
446     *             offset + count} is greater than the length of {@code buf}.
447     */
448    @Override
449    public void write(char[] buf, int offset, int count) {
450        synchronized (lock) {
451            try {
452                appendLocked(buf, offset, count);
453            } catch (IOException e) {
454            }
455        }
456    }
457
458    /**
459     * Writes one character to the target. Only the two least significant bytes
460     * of the integer {@code oneChar} are written.
461     * <p>
462     * This writer's error flag is set to {@code true} if this writer is closed
463     * or an I/O error occurs.
464     *
465     * @param oneChar
466     *            the character to write to the target.
467     */
468    @Override
469    public void write(int oneChar) {
470        synchronized (lock) {
471            try {
472                appendLocked((char) oneChar);
473            } catch (IOException e) {
474            }
475        }
476    }
477
478    /**
479     * Writes the characters from the specified string to the target.
480     *
481     * @param str
482     *            the non-null string containing the characters to write.
483     */
484    @Override
485    public void write(String str) {
486        synchronized (lock) {
487            try {
488                appendLocked(str, 0, str.length());
489            } catch (IOException e) {
490            }
491        }
492    }
493
494    /**
495     * Writes {@code count} characters from {@code str} starting at {@code
496     * offset} to the target.
497     *
498     * @param str
499     *            the non-null string containing the characters to write.
500     * @param offset
501     *            the index of the first character in {@code str} to write.
502     * @param count
503     *            the number of characters from {@code str} to write.
504     * @throws IndexOutOfBoundsException
505     *             if {@code offset < 0} or {@code count < 0}, or if {@code
506     *             offset + count} is greater than the length of {@code str}.
507     */
508    @Override
509    public void write(String str, int offset, int count) {
510        synchronized (lock) {
511            try {
512                appendLocked(str, offset, count);
513            } catch (IOException e) {
514            }
515        }
516    }
517
518    /**
519     * Appends a subsequence of the character sequence {@code csq} to the
520     * target. This method works the same way as {@code
521     * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code
522     * csq} is {@code null}, then the specified subsequence of the string "null"
523     * will be written to the target.
524     *
525     * @param csq
526     *            the character sequence appended to the target.
527     * @param start
528     *            the index of the first char in the character sequence appended
529     *            to the target.
530     * @param end
531     *            the index of the character following the last character of the
532     *            subsequence appended to the target.
533     * @return this writer.
534     * @throws StringIndexOutOfBoundsException
535     *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
536     *             either {@code start} or {@code end} are greater or equal than
537     *             the length of {@code csq}.
538     */
539    @Override
540    public PrintWriter append(CharSequence csq, int start, int end) {
541        if (csq == null) {
542            csq = "null";
543        }
544        String output = csq.subSequence(start, end).toString();
545        write(output, 0, output.length());
546        return this;
547    }
548}
549