196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* ====================================================================
296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (c) 2006 J.T. Beetstra
396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining
596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * a copy of this software and associated documentation files (the
696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * "Software"), to deal in the Software without restriction, including
796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * without limitation the rights to use, copy, modify, merge, publish,
896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distribute, sublicense, and/or sell copies of the Software, and to
996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * permit persons to whom the Software is furnished to do so, subject to
1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * the following conditions:
1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * The above copyright notice and this permission notice shall be
1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * included in all copies or substantial portions of the Software.
1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * ====================================================================
2396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
2496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
2596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.beetstra.jutf7;
2696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
2796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.nio.ByteBuffer;
2896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.nio.CharBuffer;
2996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.nio.charset.CharsetEncoder;
3096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.nio.charset.CoderResult;
3196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/**
3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * <p>
3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * The CharsetEncoder used to encode both variants of the UTF-7 charset and the
3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * modified-UTF-7 charset.
3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * </p>
3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * <p>
3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * <strong>Please note this class does not behave strictly according to the
3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * specification in Sun Java VMs before 1.6.</strong> This is done to get around
4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * a bug in the implementation of
4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * {@link java.nio.charset.CharsetEncoder#encode(CharBuffer)}. Unfortunately,
4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * that method cannot be overridden.
4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * </p>
4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *
4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6221056">JDK
4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project *      bug 6221056< /a>
4796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @author Jaap Beetstra
4896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
4996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectclass UTF7StyleCharsetEncoder extends CharsetEncoder {
5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static final float AVG_BYTES_PER_CHAR = 1.5f;
5196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private static final float MAX_BYTES_PER_CHAR = 5.0f;
5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private final UTF7StyleCharset cs;
5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private final Base64Util base64;
5496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private final byte shift;
5596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private final byte unshift;
5696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private final boolean strict;
5796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private boolean base64mode;
5896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private int bitsToOutput;
5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private int sextet;
6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    static boolean useUglyHackToForceCallToFlushInJava5;
6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    static {
6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String version = System.getProperty("java.specification.version");
6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        String vendor = System.getProperty("java.vm.vendor");
6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        useUglyHackToForceCallToFlushInJava5 = "1.4".equals(version) || "1.5".equals(version);
6596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        useUglyHackToForceCallToFlushInJava5 &= "Sun Microsystems Inc.".equals(vendor);
6696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
6796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    UTF7StyleCharsetEncoder(UTF7StyleCharset cs, Base64Util base64, boolean strict) {
6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        super(cs, AVG_BYTES_PER_CHAR, MAX_BYTES_PER_CHAR);
7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        this.cs = cs;
7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        this.base64 = base64;
7296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        this.strict = strict;
7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        this.shift = cs.shift();
7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        this.unshift = cs.unshift();
7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /*
7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * (non-Javadoc)
7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @see java.nio.charset.CharsetEncoder#implReset()
8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    protected void implReset() {
8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        base64mode = false;
8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        sextet = 0;
8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        bitsToOutput = 0;
8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * {@inheritDoc}
8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <p>
9096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Note that this method might return <code>CoderResult.OVERFLOW</code> (as
9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * is required by the specification) if insufficient space is available in
9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * the output buffer. However, calling it again on JDKs before Java 6
9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * triggers a bug in
9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * {@link java.nio.charset.CharsetEncoder#flush(ByteBuffer)} causing it to
9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * throw an IllegalStateException (the buggy method is <code>final</code>,
9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * thus cannot be overridden).
9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * </p>
9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @see <a
10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *      href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6227608">
10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *      JDK bug 6227608< /a>
10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param out The output byte buffer
10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return A coder-result object describing the reason for termination
10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
10596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    protected CoderResult implFlush(ByteBuffer out) {
10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (base64mode) {
10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (out.remaining() < 2)
10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                return CoderResult.OVERFLOW;
10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (bitsToOutput != 0)
11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                out.put(base64.getChar(sextet));
11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            out.put(unshift);
11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return CoderResult.UNDERFLOW;
11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * {@inheritDoc}
11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <p>
11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Note that this method might return <code>CoderResult.OVERFLOW</code>,
12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * even though there is sufficient space available in the output buffer.
12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * This is done to force the broken implementation of
12296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * {@link java.nio.charset.CharsetEncoder#encode(CharBuffer)} to call flush
12396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * (the buggy method is <code>final</code>, thus cannot be overridden).
12496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * </p>
12596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <p>
12696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * However, String.getBytes() fails if CoderResult.OVERFLOW is returned,
12796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * since this assumes it always allocates sufficient bytes (maxBytesPerChar
12896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * * nr_of_chars). Thus, as an extra check, the size of the input buffer is
12996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * compared against the size of the output buffer. A static variable is used
13096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * to indicate if a broken java version is used.
13196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * </p>
13296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <p>
13396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * It is not possible to directly write the last few bytes, since more bytes
13496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * might be waiting to be encoded then those available in the input buffer.
13596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * </p>
13696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
13796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @see <a
13896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *      href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6221056">
13996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *      JDK bug 6221056< /a>
14096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param in The input character buffer
14196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param out The output byte buffer
14296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @return A coder-result object describing the reason for termination
14396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
14496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
14596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        while (in.hasRemaining()) {
14696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (out.remaining() < 4)
14796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                return CoderResult.OVERFLOW;
14896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            char ch = in.get();
14996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            if (cs.canEncodeDirectly(ch)) {
15096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                unshift(out, ch);
15196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                out.put((byte)ch);
15296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            } else if (!base64mode && ch == shift) {
15396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                out.put(shift);
15496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                out.put(unshift);
15596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            } else
15696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                encodeBase64(ch, out);
15796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
15896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        /*
15996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         * <HACK type="ugly"> These lines are required to trick JDK 1.5 and
16096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         * earlier into flushing when using Charset.encode(String),
16196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         * Charset.encode(CharBuffer) or CharsetEncoder.encode(CharBuffer)
16296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         * Without them, the last few bytes may be missing.
16396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project         */
16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (base64mode && useUglyHackToForceCallToFlushInJava5
16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                && out.limit() != MAX_BYTES_PER_CHAR * in.limit())
16696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return CoderResult.OVERFLOW;
16796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        /* </HACK> */
16896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return CoderResult.UNDERFLOW;
16996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
17096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
17196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
17296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <p>
17396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Writes the bytes necessary to leave <i>base 64 mode</i>. This might
17496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * include an unshift character.
17596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * </p>
17696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
17796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param out
17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param ch
17996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
18096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void unshift(ByteBuffer out, char ch) {
18196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (!base64mode)
18296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            return;
18396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (bitsToOutput != 0)
18496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            out.put(base64.getChar(sextet));
18596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (base64.contains(ch) || ch == unshift || strict)
18696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            out.put(unshift);
18796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        base64mode = false;
18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        sextet = 0;
18996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        bitsToOutput = 0;
19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <p>
19496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Writes the bytes necessary to encode a character in <i>base 64 mode</i>.
19596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * All bytes which are fully determined will be written. The fields
19696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * <code>bitsToOutput</code> and <code>sextet</code> are used to remember
19796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * the bytes not yet fully determined.
19896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * </p>
19996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     *
20096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param out
20196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param ch
20296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
20396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void encodeBase64(char ch, ByteBuffer out) {
20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (!base64mode)
20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            out.put(shift);
20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        base64mode = true;
20796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        bitsToOutput += 16;
20896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        while (bitsToOutput >= 6) {
20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            bitsToOutput -= 6;
21096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            sextet += (ch >> bitsToOutput);
21196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            sextet &= 0x3F;
21296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            out.put(base64.getChar(sextet));
21396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            sextet = 0;
21496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        sextet = (ch << (6 - bitsToOutput)) & 0x3F;
21696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}
218