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

Commit c694aa75 authored by Doug Zongker's avatar Doug Zongker Committed by Android (Google) Code Review
Browse files

Merge "tweak the Base64 implementation"

parents bd275440 9df2ffd4
Loading
Loading
Loading
Loading
+401 −366

File changed.

Preview size limit exceeded, changes collapsed.

+16 −33
Original line number Diff line number Diff line
@@ -25,16 +25,13 @@ import java.io.InputStream;
 * it.
 */
public class Base64InputStream extends FilterInputStream {
    private final boolean encode;
    private final Base64.EncoderState estate;
    private final Base64.DecoderState dstate;
    private final Base64.Coder coder;

    private static byte[] EMPTY = new byte[0];

    private static final int BUFFER_SIZE = 2048;
    private boolean eof;
    private byte[] inputBuffer;
    private byte[] outputBuffer;
    private int outputStart;
    private int outputEnd;

@@ -63,22 +60,14 @@ public class Base64InputStream extends FilterInputStream {
     */
    public Base64InputStream(InputStream in, int flags, boolean encode) {
        super(in);
        this.encode = encode;
        eof = false;
        inputBuffer = new byte[BUFFER_SIZE];
        if (encode) {
            // len*8/5+10 is an overestimate of the most bytes the
            // encoder can produce for len bytes of input.
            outputBuffer = new byte[BUFFER_SIZE * 8/5 + 10];
            estate = new Base64.EncoderState(flags, outputBuffer);
            dstate = null;
            coder = new Base64.Encoder(flags, null);
        } else {
            // len*3/4+10 is an overestimate of the most bytes the
            // decoder can produce for len bytes of input.
            outputBuffer = new byte[BUFFER_SIZE * 3/4 + 10];
            estate = null;
            dstate = new Base64.DecoderState(flags, outputBuffer);
            coder = new Base64.Decoder(flags, null);
        }
        coder.output = new byte[coder.maxOutputSize(BUFFER_SIZE)];
        outputStart = 0;
        outputEnd = 0;
    }
@@ -123,7 +112,7 @@ public class Base64InputStream extends FilterInputStream {
        if (outputStart >= outputEnd) {
            return -1;
        } else {
            return outputBuffer[outputStart++];
            return coder.output[outputStart++];
        }
    }

@@ -135,36 +124,30 @@ public class Base64InputStream extends FilterInputStream {
            return -1;
        }
        int bytes = Math.min(len, outputEnd-outputStart);
        System.arraycopy(outputBuffer, outputStart, b, off, bytes);
        System.arraycopy(coder.output, outputStart, b, off, bytes);
        outputStart += bytes;
        return bytes;
    }

    /**
     * Read data from the input stream into inputBuffer, then
     * decode/encode it into the empty outputBuffer, and reset the
     * decode/encode it into the empty coder.output, and reset the
     * outputStart and outputEnd pointers.
     */
    private void refill() throws IOException {
        if (eof) return;
        int bytesRead = in.read(inputBuffer);
        if (encode) {
            if (bytesRead == -1) {
                eof = true;
                Base64.encodeInternal(EMPTY, 0, 0, estate, true);
            } else {
                Base64.encodeInternal(inputBuffer, 0, bytesRead, estate, false);
            }
            outputEnd = estate.op;
        } else {
        boolean success;
        if (bytesRead == -1) {
            eof = true;
                Base64.decodeInternal(EMPTY, 0, 0, dstate, true);
            success = coder.process(EMPTY, 0, 0, true);
        } else {
                Base64.decodeInternal(inputBuffer, 0, bytesRead, dstate, false);
            success = coder.process(inputBuffer, 0, bytesRead, false);
        }
            outputEnd = dstate.op;
        if (!success) {
            throw new IOException("bad base-64");
        }
        outputEnd = coder.op;
        outputStart = 0;
    }
}
+29 −28
Original line number Diff line number Diff line
@@ -25,9 +25,7 @@ import java.io.OutputStream;
 * it, writing the resulting data to another OutputStream.
 */
public class Base64OutputStream extends FilterOutputStream {
    private final boolean encode;
    private final Base64.EncoderState estate;
    private final Base64.DecoderState dstate;
    private final Base64.Coder coder;
    private final int flags;

    private byte[] buffer = null;
@@ -62,13 +60,10 @@ public class Base64OutputStream extends FilterOutputStream {
    public Base64OutputStream(OutputStream out, int flags, boolean encode) {
        super(out);
        this.flags = flags;
        this.encode = encode;
        if (encode) {
            estate = new Base64.EncoderState(flags, null);
            dstate = null;
            coder = new Base64.Encoder(flags, null);
        } else {
            estate = null;
            dstate = new Base64.DecoderState(flags, null);
            coder = new Base64.Decoder(flags, null);
        }
    }

@@ -107,13 +102,29 @@ public class Base64OutputStream extends FilterOutputStream {
    }

    public void close() throws IOException {
        IOException thrown = null;
        try {
            flushBuffer();
            internalWrite(EMPTY, 0, 0, true);
        } catch (IOException e) {
            thrown = e;
        }

        try {
            if ((flags & Base64.NO_CLOSE) == 0) {
                out.close();
            } else {
                out.flush();
            }
        } catch (IOException e) {
            if (thrown != null) {
                thrown = e;
            }
        }

        if (thrown != null) {
            throw thrown;
        }
    }

    /**
@@ -123,21 +134,11 @@ public class Base64OutputStream extends FilterOutputStream {
     *        encoder/decoder state to be finalized.
     */
    private void internalWrite(byte[] b, int off, int len, boolean finish) throws IOException {
        if (encode) {
            // len*8/5+10 is an overestimate of the most bytes the
            // encoder can produce for len bytes of input.
            estate.output = embiggen(estate.output, len*8/5+10);
            Base64.encodeInternal(b, off, len, estate, finish);
            out.write(estate.output, 0, estate.op);
        } else {
            // len*3/4+10 is an overestimate of the most bytes the
            // decoder can produce for len bytes of input.
            dstate.output = embiggen(dstate.output, len*3/4+10);
            if (!Base64.decodeInternal(b, off, len, dstate, finish)) {
        coder.output = embiggen(coder.output, coder.maxOutputSize(len));
        if (!coder.process(b, off, len, finish)) {
            throw new IOException("bad base-64");
        }
            out.write(dstate.output, 0, dstate.op);
        }
        out.write(coder.output, 0, coder.op);
    }

    /**
+51 −51
Original line number Diff line number Diff line
@@ -134,25 +134,25 @@ public class Base64Test extends TestCase {
    }

    public void testWebSafe() throws Exception {
        assertEquals(BYTES, 0, Base64.decode("", Base64.WEB_SAFE));
        assertEquals(BYTES, 1, Base64.decode("_w==", Base64.WEB_SAFE));
        assertEquals(BYTES, 2, Base64.decode("_-4=", Base64.WEB_SAFE));
        assertEquals(BYTES, 3, Base64.decode("_-7d", Base64.WEB_SAFE));
        assertEquals(BYTES, 4, Base64.decode("_-7dzA==", Base64.WEB_SAFE));
        assertEquals(BYTES, 5, Base64.decode("_-7dzLs=", Base64.WEB_SAFE));
        assertEquals(BYTES, 6, Base64.decode("_-7dzLuq", Base64.WEB_SAFE));
        assertEquals(BYTES, 7, Base64.decode("_-7dzLuqmQ==", Base64.WEB_SAFE));
        assertEquals(BYTES, 8, Base64.decode("_-7dzLuqmYg=", Base64.WEB_SAFE));

        assertEquals("", Base64.encodeToString(BYTES, 0, 0, Base64.WEB_SAFE));
        assertEquals("_w==\n", Base64.encodeToString(BYTES, 0, 1, Base64.WEB_SAFE));
        assertEquals("_-4=\n", Base64.encodeToString(BYTES, 0, 2, Base64.WEB_SAFE));
        assertEquals("_-7d\n", Base64.encodeToString(BYTES, 0, 3, Base64.WEB_SAFE));
        assertEquals("_-7dzA==\n", Base64.encodeToString(BYTES, 0, 4, Base64.WEB_SAFE));
        assertEquals("_-7dzLs=\n", Base64.encodeToString(BYTES, 0, 5, Base64.WEB_SAFE));
        assertEquals("_-7dzLuq\n", Base64.encodeToString(BYTES, 0, 6, Base64.WEB_SAFE));
        assertEquals("_-7dzLuqmQ==\n", Base64.encodeToString(BYTES, 0, 7, Base64.WEB_SAFE));
        assertEquals("_-7dzLuqmYg=\n", Base64.encodeToString(BYTES, 0, 8, Base64.WEB_SAFE));
        assertEquals(BYTES, 0, Base64.decode("", Base64.URL_SAFE));
        assertEquals(BYTES, 1, Base64.decode("_w==", Base64.URL_SAFE));
        assertEquals(BYTES, 2, Base64.decode("_-4=", Base64.URL_SAFE));
        assertEquals(BYTES, 3, Base64.decode("_-7d", Base64.URL_SAFE));
        assertEquals(BYTES, 4, Base64.decode("_-7dzA==", Base64.URL_SAFE));
        assertEquals(BYTES, 5, Base64.decode("_-7dzLs=", Base64.URL_SAFE));
        assertEquals(BYTES, 6, Base64.decode("_-7dzLuq", Base64.URL_SAFE));
        assertEquals(BYTES, 7, Base64.decode("_-7dzLuqmQ==", Base64.URL_SAFE));
        assertEquals(BYTES, 8, Base64.decode("_-7dzLuqmYg=", Base64.URL_SAFE));

        assertEquals("", Base64.encodeToString(BYTES, 0, 0, Base64.URL_SAFE));
        assertEquals("_w==\n", Base64.encodeToString(BYTES, 0, 1, Base64.URL_SAFE));
        assertEquals("_-4=\n", Base64.encodeToString(BYTES, 0, 2, Base64.URL_SAFE));
        assertEquals("_-7d\n", Base64.encodeToString(BYTES, 0, 3, Base64.URL_SAFE));
        assertEquals("_-7dzA==\n", Base64.encodeToString(BYTES, 0, 4, Base64.URL_SAFE));
        assertEquals("_-7dzLs=\n", Base64.encodeToString(BYTES, 0, 5, Base64.URL_SAFE));
        assertEquals("_-7dzLuq\n", Base64.encodeToString(BYTES, 0, 6, Base64.URL_SAFE));
        assertEquals("_-7dzLuqmQ==\n", Base64.encodeToString(BYTES, 0, 7, Base64.URL_SAFE));
        assertEquals("_-7dzLuqmYg=\n", Base64.encodeToString(BYTES, 0, 8, Base64.URL_SAFE));
    }

    public void testFlags() throws Exception {
@@ -227,55 +227,55 @@ public class Base64Test extends TestCase {
    }

    /**
     * Tests that Base64.encodeInternal does correct handling of the
     * Tests that Base64.Encoder.encode() does correct handling of the
     * tail for each call.
     *
     * This test is disabled because while it passes if you can get it
     * to run, android's test infrastructure currently doesn't allow
     * us to get at package-private members (Base64.EncoderState in
     * us to get at package-private members (Base64.Encoder in
     * this case).
     */
    public void XXXtestEncodeInternal() throws Exception {
        byte[] input = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
        byte[] output = new byte[100];

        Base64.EncoderState state = new Base64.EncoderState(Base64.NO_PADDING | Base64.NO_WRAP,
        Base64.Encoder encoder = new Base64.Encoder(Base64.NO_PADDING | Base64.NO_WRAP,
                                                    output);

        Base64.encodeInternal(input, 0, 3, state, false);
        assertEquals("YWJj".getBytes(), 4, state.output, state.op);
        assertEquals(0, state.tailLen);
        encoder.process(input, 0, 3, false);
        assertEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
        assertEquals(0, encoder.tailLen);

        Base64.encodeInternal(input, 0, 3, state, false);
        assertEquals("YWJj".getBytes(), 4, state.output, state.op);
        assertEquals(0, state.tailLen);
        encoder.process(input, 0, 3, false);
        assertEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
        assertEquals(0, encoder.tailLen);

        Base64.encodeInternal(input, 0, 1, state, false);
        assertEquals(0, state.op);
        assertEquals(1, state.tailLen);
        encoder.process(input, 0, 1, false);
        assertEquals(0, encoder.op);
        assertEquals(1, encoder.tailLen);

        Base64.encodeInternal(input, 0, 1, state, false);
        assertEquals(0, state.op);
        assertEquals(2, state.tailLen);
        encoder.process(input, 0, 1, false);
        assertEquals(0, encoder.op);
        assertEquals(2, encoder.tailLen);

        Base64.encodeInternal(input, 0, 1, state, false);
        assertEquals("YWFh".getBytes(), 4, state.output, state.op);
        assertEquals(0, state.tailLen);
        encoder.process(input, 0, 1, false);
        assertEquals("YWFh".getBytes(), 4, encoder.output, encoder.op);
        assertEquals(0, encoder.tailLen);

        Base64.encodeInternal(input, 0, 2, state, false);
        assertEquals(0, state.op);
        assertEquals(2, state.tailLen);
        encoder.process(input, 0, 2, false);
        assertEquals(0, encoder.op);
        assertEquals(2, encoder.tailLen);

        Base64.encodeInternal(input, 0, 2, state, false);
        assertEquals("YWJh".getBytes(), 4, state.output, state.op);
        assertEquals(1, state.tailLen);
        encoder.process(input, 0, 2, false);
        assertEquals("YWJh".getBytes(), 4, encoder.output, encoder.op);
        assertEquals(1, encoder.tailLen);

        Base64.encodeInternal(input, 0, 2, state, false);
        assertEquals("YmFi".getBytes(), 4, state.output, state.op);
        assertEquals(0, state.tailLen);
        encoder.process(input, 0, 2, false);
        assertEquals("YmFi".getBytes(), 4, encoder.output, encoder.op);
        assertEquals(0, encoder.tailLen);

        Base64.encodeInternal(input, 0, 1, state, true);
        assertEquals("YQ".getBytes(), 2, state.output, state.op);
        encoder.process(input, 0, 1, true);
        assertEquals("YQ".getBytes(), 2, encoder.output, encoder.op);
    }

    private static final String lipsum =
@@ -307,7 +307,7 @@ public class Base64Test extends TestCase {
                          Base64.NO_WRAP,
                          Base64.NO_PADDING | Base64.NO_WRAP,
                          Base64.CRLF,
                          Base64.WEB_SAFE };
                          Base64.URL_SAFE };
        int[] writeLengths = { -10, -5, -1, 0, 1, 1, 2, 2, 3, 10, 100 };
        Random rng = new Random(32176L);

@@ -414,7 +414,7 @@ public class Base64Test extends TestCase {
                          Base64.NO_WRAP,
                          Base64.NO_PADDING | Base64.NO_WRAP,
                          Base64.CRLF,
                          Base64.WEB_SAFE };
                          Base64.URL_SAFE };
        int[] writeLengths = { -10, -5, -1, 0, 1, 1, 2, 2, 3, 10, 100 };
        Random rng = new Random(32176L);