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

Commit 3af16b22 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Improve FastPrintWriter."

parents 8b44040a e5a9c923
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");
                        }
                    }
                }
            }