Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5a9c923 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Improve FastPrintWriter.

Change-Id: I23acb8d4c3db1f2f8e2f8003296f8c253e2ae7d2
parent 142dd915
Loading
Loading
Loading
Loading
+198 −128
Original line number Diff line number Diff line
package com.android.internal.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
@@ -17,12 +15,35 @@ import java.nio.charset.CodingErrorAction;
public class FastPrintWriter extends PrintWriter {
    private static final int BUFFER_LEN = 8192;

    private static Writer sDummyWriter = new Writer() {
        @Override
        public void close() throws IOException {
            UnsupportedOperationException ex
                    = new UnsupportedOperationException("Shouldn't be here");
            throw ex;
        }

        @Override
        public void flush() throws IOException {
            close();
        }

        @Override
        public void write(char[] buf, int offset, int count) throws IOException {
            close();
        }
    };

    private final char[] mText = new char[BUFFER_LEN];
    private int mPos;

    final private OutputStream mOutputStream;
    final private Writer mWriter;
    final private boolean mAutoFlush;
    final private String mSeparator;
    private CharsetEncoder mCharset;
    final private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
    private boolean mIoError;

    /**
     * Constructs a new {@code PrintWriter} with {@code out} as its target
@@ -35,8 +56,11 @@ public class FastPrintWriter extends PrintWriter {
     *             if {@code out} is {@code null}.
     */
    public FastPrintWriter(OutputStream out) {
        super(out);
        super(sDummyWriter);
        mOutputStream = out;
        mWriter = null;
        mAutoFlush = false;
        mSeparator = System.lineSeparator();
        initDefaultEncoder();
    }

@@ -55,8 +79,11 @@ public class FastPrintWriter extends PrintWriter {
     *             if {@code out} is {@code null}.
     */
    public FastPrintWriter(OutputStream out, boolean autoFlush) {
        super(out, autoFlush);
        super(sDummyWriter, autoFlush);
        mOutputStream = out;
        mWriter = null;
        mAutoFlush = autoFlush;
        mSeparator = System.lineSeparator();
        initDefaultEncoder();
    }

@@ -71,8 +98,11 @@ public class FastPrintWriter extends PrintWriter {
     *             if {@code wr} is {@code null}.
     */
    public FastPrintWriter(Writer wr) {
        super(wr);
        super(sDummyWriter);
        mOutputStream = null;
        mWriter = wr;
        mAutoFlush = false;
        mSeparator = System.lineSeparator();
        initDefaultEncoder();
    }

@@ -91,107 +121,56 @@ public class FastPrintWriter extends PrintWriter {
     *             if {@code out} is {@code null}.
     */
    public FastPrintWriter(Writer wr, boolean autoFlush) {
        super(wr, autoFlush);
        super(sDummyWriter, autoFlush);
        mOutputStream = null;
        mWriter = wr;
        mAutoFlush = autoFlush;
        mSeparator = System.lineSeparator();
        initDefaultEncoder();
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
     * VM's default character set is used for character encoding.
     * The print writer does not automatically flush its contents to the target
     * file when a newline is encountered. The output to the file is buffered.
     *
     * @param file
     *            the target file. If the file already exists, its contents are
     *            removed, otherwise a new file is created.
     * @throws java.io.FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     */
    public FastPrintWriter(File file) throws FileNotFoundException {
        super(file);
        mOutputStream = null;
        initDefaultEncoder();
    private final void initEncoder(String csn) throws UnsupportedEncodingException {
        try {
            mCharset = Charset.forName(csn).newEncoder();
        } catch (Exception e) {
            throw new UnsupportedEncodingException(csn);
        }
        mCharset.onMalformedInput(CodingErrorAction.REPLACE);
        mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
    }

    /**
     * Constructs a new {@code PrintWriter} with {@code file} as its target. The
     * character set named {@code csn} is used for character encoding.
     * The print writer does not automatically flush its contents to the target
     * file when a newline is encountered. The output to the file is buffered.
     * Flushes this writer and returns the value of the error flag.
     *
     * @param file
     *            the target file. If the file already exists, its contents are
     *            removed, otherwise a new file is created.
     * @param csn
     *            the name of the character set used for character encoding.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * @throws NullPointerException
     *             if {@code csn} is {@code null}.
     * @throws java.io.UnsupportedEncodingException
     *             if the encoding specified by {@code csn} is not supported.
     * @return {@code true} if either an {@code IOException} has been thrown
     *         previously or if {@code setError()} has been called;
     *         {@code false} otherwise.
     * @see #setError()
     */
    public FastPrintWriter(File file, String csn) throws FileNotFoundException,
            UnsupportedEncodingException {
        super(file, csn);
        mOutputStream = null;
        initEncoder(csn);
    public boolean checkError() {
        flush();
        synchronized (lock) {
            return mIoError;
        }
    }

    /**
     * Constructs a new {@code PrintWriter} with the file identified by {@code
     * fileName} as its target. The VM's default character set is
     * used for character encoding. The print writer does not automatically
     * flush its contents to the target file when a newline is encountered. The
     * output to the file is buffered.
     *
     * @param fileName
     *            the target file's name. If the file already exists, its
     *            contents are removed, otherwise a new file is created.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * Sets the error state of the stream to false.
     * @since 1.6
     */
    public FastPrintWriter(String fileName) throws FileNotFoundException {
        super(fileName);
        mOutputStream = null;
        initDefaultEncoder();
    protected void clearError() {
        synchronized (lock) {
            mIoError = false;
        }
    }

    /**
     * Constructs a new {@code PrintWriter} with the file identified by {@code
     * fileName} as its target. The character set named {@code csn} is used for
     * character encoding. The print writer does not automatically flush its
     * contents to the target file when a newline is encountered. The output to
     * the file is buffered.
     *
     * @param fileName
     *            the target file's name. If the file already exists, its
     *            contents are removed, otherwise a new file is created.
     * @param csn
     *            the name of the character set used for character encoding.
     * @throws FileNotFoundException
     *             if an error occurs while opening or creating the target file.
     * @throws NullPointerException
     *             if {@code csn} is {@code null}.
     * @throws UnsupportedEncodingException
     *             if the encoding specified by {@code csn} is not supported.
     * Sets the error flag of this writer to true.
     */
    public FastPrintWriter(String fileName, String csn)
            throws FileNotFoundException, UnsupportedEncodingException {
        super(fileName, csn);
        mOutputStream = null;
        initEncoder(csn);
    }

    private final void initEncoder(String csn) throws UnsupportedEncodingException {
        try {
            mCharset = Charset.forName(csn).newEncoder();
        } catch (Exception e) {
            throw new UnsupportedEncodingException(csn);
    protected void setError() {
        synchronized (lock) {
            mIoError = true;
        }
        mCharset.onMalformedInput(CodingErrorAction.REPLACE);
        mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
    }

    private final void initDefaultEncoder() {
@@ -200,55 +179,55 @@ public class FastPrintWriter extends PrintWriter {
        mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
    }

    private void appendInner(char c) throws IOException {
    private void appendLocked(char c) throws IOException {
        int pos = mPos;
        if (pos >= (BUFFER_LEN-1)) {
            flush();
            flushLocked();
            pos = mPos;
        }
        mText[pos] = c;
        mPos = pos+1;
    }

    private void appendInner(String str, int i, final int length) throws IOException {
    private void appendLocked(String str, int i, final int length) throws IOException {
        if (length > BUFFER_LEN) {
            final int end = i + length;
            while (i < end) {
                int next = i + BUFFER_LEN;
                appendInner(str, i, next<end ? BUFFER_LEN : (end-i));
                appendLocked(str, i, next < end ? BUFFER_LEN : (end - i));
                i = next;
            }
            return;
        }
        int pos = mPos;
        if ((pos+length) > BUFFER_LEN) {
            flush();
            flushLocked();
            pos = mPos;
        }
        str.getChars(i, i + length, mText, pos);
        mPos = pos + length;
    }

    private void appendInner(char[] buf, int i, final int length) throws IOException {
    private void appendLocked(char[] buf, int i, final int length) throws IOException {
        if (length > BUFFER_LEN) {
            final int end = i + length;
            while (i < end) {
                int next = i + BUFFER_LEN;
                appendInner(buf, i, next < end ? BUFFER_LEN : (end - i));
                appendLocked(buf, i, next < end ? BUFFER_LEN : (end - i));
                i = next;
            }
            return;
        }
        int pos = mPos;
        if ((pos+length) > BUFFER_LEN) {
            flush();
            flushLocked();
            pos = mPos;
        }
        System.arraycopy(buf, i, mText, pos, length);
        mPos = pos + length;
    }

    private void flushBytesInner() throws IOException {
    private void flushBytesLocked() throws IOException {
        int position;
        if ((position = mBytes.position()) > 0) {
            mBytes.flip();
@@ -257,7 +236,7 @@ public class FastPrintWriter extends PrintWriter {
        }
    }

    private void flushInner() throws IOException {
    private void flushLocked() throws IOException {
        //Log.i("PackageManager", "flush mPos=" + mPos);
        if (mPos > 0) {
            if (mOutputStream != null) {
@@ -267,17 +246,17 @@ public class FastPrintWriter extends PrintWriter {
                    if (result.isError()) {
                        throw new IOException(result.toString());
                    } else if (result.isOverflow()) {
                        flushBytesInner();
                        flushBytesLocked();
                        result = mCharset.encode(charBuffer, mBytes, true);
                        continue;
                    }
                    break;
                }
                flushBytesInner();
                flushBytesLocked();
                mOutputStream.flush();
            } else {
                out.write(mText, 0, mPos);
                out.flush();
                mWriter.write(mText, 0, mPos);
                mWriter.flush();
            }
            mPos = 0;
        }
@@ -290,11 +269,34 @@ public class FastPrintWriter extends PrintWriter {
     */
    @Override
    public void flush() {
        synchronized (lock) {
            try {
            flushInner();
                flushLocked();
                if (mOutputStream != null) {
                    mOutputStream.flush();
                } else {
                    mWriter.flush();
                }
            } catch (IOException e) {
                setError();
            }
        }
    }

    @Override
    public void close() {
        synchronized (lock) {
            try {
                flushLocked();
                if (mOutputStream != null) {
                    mOutputStream.close();
                } else {
                    mWriter.close();
                }
            } catch (IOException e) {
                setError();
            }
        }
        super.flush();
    }

    /**
@@ -306,11 +308,13 @@ public class FastPrintWriter extends PrintWriter {
     * @see #print(String)
     */
    public void print(char[] charArray) {
        synchronized (lock) {
            try {
            appendInner(charArray, 0, charArray.length);
                appendLocked(charArray, 0, charArray.length);
            } catch (IOException e) {
            }
        }
    }

    /**
     * Prints the string representation of the specified character to the
@@ -321,11 +325,13 @@ public class FastPrintWriter extends PrintWriter {
     * @see #print(String)
     */
    public void print(char ch) {
        synchronized (lock) {
            try {
            appendInner(ch);
                appendLocked(ch);
            } catch (IOException e) {
            }
        }
    }

    /**
     * Prints a string to the target. The string is converted to an array of
@@ -342,9 +348,65 @@ public class FastPrintWriter extends PrintWriter {
        if (str == null) {
            str = String.valueOf((Object) null);
        }
        synchronized (lock) {
            try {
                appendLocked(str, 0, str.length());
            } catch (IOException e) {
                setError();
            }
        }
    }


    @Override
    public void print(int inum) {
        if (inum == 0) {
            print("0");
        } else {
            super.print(inum);
        }
    }

    @Override
    public void print(long lnum) {
        if (lnum == 0) {
            print("0");
        } else {
            super.print(lnum);
        }
    }

    /**
     * Prints a newline. Flushes this writer if the autoFlush flag is set to {@code true}.
     */
    public void println() {
        synchronized (lock) {
            try {
            appendInner(str, 0, str.length());
                appendLocked(mSeparator, 0, mSeparator.length());
                if (mAutoFlush) {
                    flushLocked();
                }
            } catch (IOException e) {
                setError();
            }
        }
    }

    @Override
    public void println(int inum) {
        if (inum == 0) {
            println("0");
        } else {
            super.println(inum);
        }
    }

    @Override
    public void println(long lnum) {
        if (lnum == 0) {
            println("0");
        } else {
            super.print(lnum);
        }
    }

@@ -385,11 +447,13 @@ public class FastPrintWriter extends PrintWriter {
     */
    @Override
    public void write(char[] buf, int offset, int count) {
        synchronized (lock) {
            try {
            appendInner(buf, offset, count);
                appendLocked(buf, offset, count);
            } catch (IOException e) {
            }
        }
    }

    /**
     * Writes one character to the target. Only the two least significant bytes
@@ -403,11 +467,13 @@ public class FastPrintWriter extends PrintWriter {
     */
    @Override
    public void write(int oneChar) {
        synchronized (lock) {
            try {
            appendInner((char) oneChar);
                appendLocked((char) oneChar);
            } catch (IOException e) {
            }
        }
    }

    /**
     * Writes the characters from the specified string to the target.
@@ -417,11 +483,13 @@ public class FastPrintWriter extends PrintWriter {
     */
    @Override
    public void write(String str) {
        synchronized (lock) {
            try {
            appendInner(str, 0, str.length());
                appendLocked(str, 0, str.length());
            } catch (IOException e) {
            }
        }
    }

    /**
     * Writes {@code count} characters from {@code str} starting at {@code
@@ -439,11 +507,13 @@ public class FastPrintWriter extends PrintWriter {
     */
    @Override
    public void write(String str, int offset, int count) {
        synchronized (lock) {
            try {
            appendInner(str, offset, count);
                appendLocked(str, offset, count);
            } catch (IOException e) {
            }
        }
    }

    /**
     * Appends a subsequence of the character sequence {@code csq} to the
+3 −15
Original line number Diff line number Diff line
@@ -480,11 +480,7 @@ public final class ProcessTracker {
                    time += now - curStartTime;
                }
                pw.print(sep);
                if (time != 0) {
                pw.print(time);
                } else {
                    pw.print("0");
                }
            }
        }
    }
@@ -681,11 +677,7 @@ public final class ProcessTracker {
                        }
                    }
                    pw.print(CSV_SEP);
                    if (totalTime != 0) {
                    pw.print(totalTime);
                    } else {
                        pw.print("0");
                    }
                }
            }
        }
@@ -783,11 +775,7 @@ public final class ProcessTracker {
                        }
                    } else {
                        pw.print(",");
                        if (time != 0) {
                        pw.print(time);
                        } else {
                            pw.print("0");
                        }
                    }
                }
            }