1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* Licensed to the Apache Software Foundation (ASF) under one or more 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.nio.charset; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.BufferOverflowException; 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.BufferUnderflowException; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.CharBuffer; 238454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughesimport java.util.Arrays; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 2657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * Transforms a sequence of 16-bit Java characters to a byte sequence in some encoding. 2757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 2857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>The input character sequence is a {@link java.nio.CharBuffer CharBuffer} and the 2957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * output byte sequence is a {@link java.nio.ByteBuffer ByteBuffer}. 3057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 3157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>Use {@link #encode(CharBuffer)} to encode an entire {@code CharBuffer} to a 3257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * new {@code ByteBuffer}, or {@link #encode(CharBuffer, ByteBuffer, boolean)} for more 3357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * control. When using the latter method, the entire operation proceeds as follows: 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ol> 3557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #reset()} to reset the encoder if this instance has been used before.</li> 3657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #encode(CharBuffer, ByteBuffer, boolean) encode} with the {@code endOfInput} 3757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * parameter set to false until additional input is not needed (as signaled by the return value). 3857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * The input buffer must be filled and the output buffer must be flushed between invocations. 3957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>The {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method will 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * convert as many characters as possible, and the process won't stop until the 4157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * input buffer has been exhausted, the output buffer has been filled, or an 4257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * error has occurred. A {@link CoderResult CoderResult} instance will be 4357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * returned to indicate the current state. The caller should fill the input buffer, flush 4457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * the output buffer, or recovering from an error and try again, accordingly. 4557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * </li> 4657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #encode(CharBuffer, ByteBuffer, boolean) encode} for the last time with 4757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@code endOfInput} set to true.</li> 4857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #flush(ByteBuffer)} to flush remaining output.</li> 4957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * </ol> 5057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 5157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>There are two classes of encoding error: <i>malformed input</i> 5257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * signifies that the input character sequence is not legal, while <i>unmappable character</i> 5357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * signifies that the input is legal but cannot be mapped to a byte sequence (because the charset 5457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * cannot represent the character, for example). 5557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 5657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>Errors can be handled in three ways. The default is to 57b10f4611e8c74fd4e996c8ed999a16d81f0df986Elliott Hughes * {@link CodingErrorAction#REPORT report} the error to the caller. The alternatives are to 58b10f4611e8c74fd4e996c8ed999a16d81f0df986Elliott Hughes * {@link CodingErrorAction#IGNORE ignore} the error or {@link CodingErrorAction#REPLACE replace} 5957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * the problematic input with the byte sequence returned by {@link #replacement}. The disposition 6057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * for each of the two kinds of error can be set independently using the {@link #onMalformedInput} 6157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * and {@link #onUnmappableCharacter} methods. 6257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 6357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>The default replacement bytes depend on the charset but can be overridden using the 6457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@link #replaceWith} method. 6557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 6657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>This class is abstract and encapsulates many common operations of the 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding process for all charsets. Encoders for a specific charset should 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * extend this class and need only to implement the 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method for basic 7057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * encoding. If a subclass maintains internal state, it should also override the 7157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@link #implFlush(ByteBuffer) implFlush} and {@link #implReset() implReset} methods. 7257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 7357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>This class is not thread-safe. 74eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.nio.charset.Charset 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.nio.charset.CharsetDecoder 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class CharsetEncoder { 7930a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes private static final int READY = 0; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int ONGOING = 1; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int END = 2; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FLUSH = 3; 8330a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes private static final int INIT = 4; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private final Charset cs; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private final float averageBytesPerChar; 8837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private final float maxBytesPerChar; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private byte[] replacementBytes; 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int status; 9330a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes // internal status indicates encode(CharBuffer) operation is finished 9430a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes private boolean finished; 9530a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes 9637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private CodingErrorAction malformedInputAction; 9737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private CodingErrorAction unmappableCharacterAction; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes // decoder instance for this encoder's charset, used for replacement value checking 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private CharsetDecoder decoder; 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 103c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * Constructs a new {@code CharsetEncoder} using the given parameters and 104c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * the replacement byte array {@code { (byte) '?' }}. 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 106cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar) { 107cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes this(cs, averageBytesPerChar, maxBytesPerChar, new byte[] { (byte) '?' }); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new <code>CharsetEncoder</code> using the given 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>Charset</code>, replacement byte array, average number and 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * maximum number of bytes created by this encoder for one input character. 114f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param cs 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the <code>Charset</code> to be used by this encoder. 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param averageBytesPerChar 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * average number of bytes created by this encoder for one single 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character, must be positive. 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param maxBytesPerChar 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * maximum number of bytes which can be created by this encoder 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for one single input character, must be positive. 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param replacement 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement byte array, cannot be null or empty, its 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length cannot be larger than <code>maxBytesPerChar</code>, 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and must be a legal replacement, which can be justified by 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #isLegalReplacement(byte[]) isLegalReplacement}. 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if any parameters are invalid. 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1313664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement) { 1323664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes this(cs, averageBytesPerChar, maxBytesPerChar, replacement, false); 1333664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes } 1343664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes 1353664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement, boolean trusted) { 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (averageBytesPerChar <= 0 || maxBytesPerChar <= 0) { 1378454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("averageBytesPerChar and maxBytesPerChar must both be positive"); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (averageBytesPerChar > maxBytesPerChar) { 1408454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("averageBytesPerChar is greater than maxBytesPerChar"); 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.cs = cs; 14337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes this.averageBytesPerChar = averageBytesPerChar; 14437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes this.maxBytesPerChar = maxBytesPerChar; 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = INIT; 14637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes malformedInputAction = CodingErrorAction.REPORT; 14737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes unmappableCharacterAction = CodingErrorAction.REPORT; 1483664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes if (trusted) { 1493664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes // The RI enforces unnecessary restrictions on the replacement bytes. We trust ICU to 1503664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes // know what it's doing. Doing so lets us support ICU's EUC-JP, SCSU, and Shift_JIS. 1513664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes this.replacementBytes = replacement; 1523664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes } else { 1533664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes replaceWith(replacement); 1543664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 15837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the average number of bytes created by this encoder for a single 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character. 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final float averageBytesPerChar() { 16237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return averageBytesPerChar; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks if the given character can be encoded by this encoder. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that this method can change the internal status of this encoder, so 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it should not be called when another encoding process is ongoing, 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise it will throw an <code>IllegalStateException</code>. 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method can be overridden for performance improvement. 173eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param c 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given encoder. 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if given character can be encoded by this encoder. 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if another encode process is ongoing so that the current 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * internal status is neither RESET or FLUSH. 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode(char c) { 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return implCanEncode(CharBuffer.wrap(new char[] { c })); 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // implementation of canEncode 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean implCanEncode(CharBuffer cb) { 18730a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes if (status == FLUSH || status == INIT) { 18830a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes status = READY; 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 19030a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes if (status != READY) { 1918454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalStateException("encoding already in progress"); 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 19337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes CodingErrorAction malformBak = malformedInputAction; 19437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes CodingErrorAction unmapBak = unmappableCharacterAction; 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onMalformedInput(CodingErrorAction.REPORT); 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onUnmappableCharacter(CodingErrorAction.REPORT); 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean result = true; 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.encode(cb); 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CharacterCodingException e) { 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = false; 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onMalformedInput(malformBak); 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onUnmappableCharacter(unmapBak); 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reset(); 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks if a given <code>CharSequence</code> can be encoded by this 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoder. 212f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that this method can change the internal status of this encoder, so 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it should not be called when another encode process is ongoing, otherwise 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it will throw an <code>IllegalStateException</code>. 216f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method can be overridden for performance improvement. 218f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param sequence 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given <code>CharSequence</code>. 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the given <code>CharSequence</code> can be encoded by 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this encoder. 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if current internal status is neither RESET or FLUSH. 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode(CharSequence sequence) { 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CharBuffer cb; 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (sequence instanceof CharBuffer) { 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cb = ((CharBuffer) sequence).duplicate(); 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cb = CharBuffer.wrap(sequence); 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return implCanEncode(cb); 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 23737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the {@link Charset} which this encoder uses. 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Charset charset() { 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return cs; 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This is a facade method for the encoding operation. 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method encodes the remaining character sequence of the given 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character buffer into a new byte buffer. This method performs a complete 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding operation, resets at first, then encodes, and flushes at last. 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method should not be invoked if another encode operation is ongoing. 251eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new <code>ByteBuffer</code> containing the bytes produced by 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this encoding operation. The buffer's limit will be the position 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the last byte in the buffer, and the position will be zero. 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if another encoding operation is ongoing. 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws MalformedInputException 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an illegal input character sequence for this charset is 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encountered, and the action for malformed error is 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT} 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnmappableCharacterException 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a legal but unmappable input character sequence for this 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * charset is encountered, and the action for unmappable 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character error is 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unmappable means the Unicode character sequence at the input 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer's current position cannot be mapped to a equivalent 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * byte sequence. 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws CharacterCodingException 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if other exception happened during the encode operation. 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 27457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException { 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in.remaining() == 0) { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ByteBuffer.allocate(0); 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reset(); 27937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes int length = (int) (in.remaining() * averageBytesPerChar); 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteBuffer output = ByteBuffer.allocate(length); 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = null; 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encode(in, output, false); 284eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result==CoderResult.UNDERFLOW) { 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 286eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result==CoderResult.OVERFLOW) { 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project output = allocateMore(output); 288eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson continue; 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson checkCoderResult(result); 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encode(in, output, true); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkCoderResult(result); 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = flush(output); 297eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result==CoderResult.UNDERFLOW) { 298eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson output.flip(); 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 300eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result==CoderResult.OVERFLOW) { 301eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson output = allocateMore(output); 302eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson continue; 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 304eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson checkCoderResult(result); 305eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson output.flip(); 306eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result.isMalformed()) { 307eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson throw new MalformedInputException(result.length()); 308eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result.isUnmappable()) { 309eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson throw new UnmappableCharacterException(result.length()); 310eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 311eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson break; 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 31330a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes status = READY; 31430a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes finished = true; 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return output; 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * checks the result whether it needs to throw CharacterCodingException. 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 32157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes private void checkCoderResult(CoderResult result) throws CharacterCodingException { 32237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed() ) { 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new MalformedInputException(result.length()); 32437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes } else if (unmappableCharacterAction == CodingErrorAction.REPORT && result.isUnmappable()) { 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnmappableCharacterException(result.length()); 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // allocate more spaces to the given ByteBuffer 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ByteBuffer allocateMore(ByteBuffer output) { 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (output.capacity() == 0) { 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ByteBuffer.allocate(1); 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteBuffer result = ByteBuffer.allocate(output.capacity() * 2); 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project output.flip(); 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result.put(output); 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Encodes characters starting at the current position of the given input 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer, and writes the equivalent byte sequence into the given output 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer from its current position. 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffers' position will be changed with the reading and writing 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * operation, but their limits and marks will be kept intact. 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A <code>CoderResult</code> instance will be returned according to 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * following rules: 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul> 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A {@link CoderResult#malformedForLength(int) malformed input} result 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * indicates that some malformed input error was encountered, and the 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * erroneous characters start at the input buffer's position and their 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * number can be got by result's {@link CoderResult#length() length}. This 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * kind of result can be returned only if the malformed action is 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li> 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as many characters as possible in the input buffer have been encoded. If 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * there is no further input and no characters left in the input buffer then 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this task is complete. If this is not the case then the client should 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * call this method again supplying some more input characters.</li> 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that the 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * output buffer has been filled, while there are still some characters 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * remaining in the input buffer. This method should be invoked again with a 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * non-full output buffer.</li> 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A {@link CoderResult#unmappableForLength(int) unmappable character} 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * result indicates that some unmappable character error was encountered, 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and the erroneous characters start at the input buffer's position and 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * their number can be got by result's {@link CoderResult#length() length}. 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This kind of result can be returned only on 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li> 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul> 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The <code>endOfInput</code> parameter indicates if the invoker can 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provider further input. This parameter is true if and only if the 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * characters in the current input buffer are all inputs for this encoding 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * operation. Note that it is common and won't cause an error if the invoker 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sets false and then has no more input available, while it may cause an 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * error if the invoker always sets true in several consecutive invocations. 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This would make the remaining input to be treated as malformed input. 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input. 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method invokes the 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implement the basic encode logic for a specific charset. 386eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param endOfInput 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * true if all the input characters have been provided. 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>CoderResult</code> instance indicating the result. 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the encoding operation has already started or no more 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input is needed in this encoding process. 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws CoderMalfunctionError 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method threw an <code>BufferUnderflowException</code> or 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>BufferUnderflowException</code>. 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 402cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) { 40330a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes // If the previous step is encode(CharBuffer), then no more input is needed 40430a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes // thus endOfInput should not be false 40530a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes if (status == READY && finished && !endOfInput) { 40630a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes throw new IllegalStateException(); 40730a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes } 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((status == FLUSH) || (!endOfInput && status == END)) { 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(); 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result; 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encodeLoop(in, out); 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (BufferOverflowException e) { 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new CoderMalfunctionError(e); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (BufferUnderflowException e) { 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new CoderMalfunctionError(e); 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 421eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result==CoderResult.UNDERFLOW) { 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = endOfInput ? END : ONGOING; 423eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (endOfInput) { 424eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int remaining = in.remaining(); 425eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (remaining > 0) { 426eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson result = CoderResult.malformedForLength(remaining); 427eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else { 428eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return result; 429eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 433eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result==CoderResult.OVERFLOW) { 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = endOfInput ? END : ONGOING; 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 43737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes CodingErrorAction action = malformedInputAction; 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result.isUnmappable()) { 43937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes action = unmappableCharacterAction; 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If the action is IGNORE or REPLACE, we should continue 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // encoding. 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (action == CodingErrorAction.REPLACE) { 44437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (out.remaining() < replacementBytes.length) { 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CoderResult.OVERFLOW; 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 44737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes out.put(replacementBytes); 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (action != CodingErrorAction.IGNORE) { 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.position(in.position() + result.length()); 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Encodes characters into bytes. This method is called by 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will implement the essential encoding operation, and it won't 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * stop encoding until either all the input characters are read, the output 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer is filled, or some exception is encountered. Then it will 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * return a <code>CoderResult</code> object indicating the result of the 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * current encoding operation. The rule to construct the 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult</code> is the same as for 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. When an 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exception is encountered in the encoding operation, most implementations 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of this method will return a relevant result object to the 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * performance optimized implementation may handle the exception and 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implement the error action itself. 473eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p> 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffers are scanned from their current positions, and their positions 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be modified accordingly, while their marks and limits will be 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * intact. At most {@link CharBuffer#remaining() in.remaining()} characters 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be read, and {@link ByteBuffer#remaining() out.remaining()} bytes 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be written. 479eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p> 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that some implementations may pre-scan the input buffer and return 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input. 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>CoderResult</code> instance indicating the result. 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected abstract CoderResult encodeLoop(CharBuffer in, ByteBuffer out); 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this encoder. 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call {@link #implFlush(ByteBuffer) implFlush}. Some 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoders may need to write some bytes to the output buffer when they have 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read all input characters, subclasses can overridden 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implFlush(ByteBuffer) implFlush} to perform writing action. 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The maximum number of written bytes won't larger than 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link ByteBuffer#remaining() out.remaining()}. If some encoder wants to 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write more bytes than the output buffer's available remaining space, then 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code> will be returned, and this method 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be called again with a byte buffer that has free space. Otherwise 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this method will return <code>CoderResult.UNDERFLOW</code>, which 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * means one encoding process has been completed successfully. 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * During the flush, the output buffer's position will be changed 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * accordingly, while its mark and limit will be intact. 509f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given output buffer. 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return <code>CoderResult.UNDERFLOW</code> or 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code>. 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this encoder hasn't read all input characters during one 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding process, which means neither after calling 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer) encode(CharBuffer)} nor after 518f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * calling {@link #encode(CharBuffer, ByteBuffer, boolean) 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encode(CharBuffer, ByteBuffer, boolean)} with {@code true} 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the last boolean parameter. 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CoderResult flush(ByteBuffer out) { 52330a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes if (status != END && status != READY) { 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(); 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = implFlush(out); 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == CoderResult.UNDERFLOW) { 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FLUSH; 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this encoder. The default implementation does nothing and always 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * returns <code>CoderResult.UNDERFLOW</code>; this method can be 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * overridden if needed. 537f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return <code>CoderResult.UNDERFLOW</code> or 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code>. 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected CoderResult implFlush(ByteBuffer out) { 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CoderResult.UNDERFLOW; 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's <code>CodingErrorAction</code> specified 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for malformed input error has been changed. The default implementation 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * does nothing; this method can be overridden if needed. 551f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action. 554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implOnMalformedInput(CodingErrorAction newAction) { 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's <code>CodingErrorAction</code> specified 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for unmappable character error has been changed. The default 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implementation does nothing; this method can be overridden if needed. 563f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action. 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implOnUnmappableCharacter(CodingErrorAction newAction) { 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's replacement has been changed. The default 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implementation does nothing; this method can be overridden if needed. 574f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newReplacement 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new replacement string. 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implReplaceWith(byte[] newReplacement) { 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Resets this encoder's charset related state. The default implementation 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * does nothing; this method can be overridden if needed. 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implReset() { 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks if the given argument is legal as this encoder's replacement byte 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * array. 593f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The given byte array is legal if and only if it can be decode into 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sixteen bits Unicode characters. 596f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method can be overridden for performance improvement. 598f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 59957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * @param replacement 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given byte array to be checked. 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the the given argument is legal as this encoder's 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * replacement byte array. 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 60457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes public boolean isLegalReplacement(byte[] replacement) { 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (decoder == null) { 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder = cs.newDecoder(); 60757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes decoder.onMalformedInput(CodingErrorAction.REPORT); 60857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes decoder.onUnmappableCharacter(CodingErrorAction.REPORT); 609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 61057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes ByteBuffer in = ByteBuffer.wrap(replacement); 61157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes CharBuffer out = CharBuffer.allocate((int) (replacement.length * decoder.maxCharsPerByte())); 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = decoder.decode(in, out, true); 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return !result.isError(); 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 61737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns this encoder's <code>CodingErrorAction</code> when a malformed 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input error occurred during the encoding process. 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CodingErrorAction malformedInputAction() { 62137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return malformedInputAction; 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 62537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the maximum number of bytes which can be created by this encoder for 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * one input character, must be positive. 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final float maxBytesPerChar() { 62937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return maxBytesPerChar; 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets this encoder's action on malformed input error. 634f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call the 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implOnMalformedInput(CodingErrorAction) implOnMalformedInput} 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method with the given new action as argument. 638f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action on malformed input error. 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given newAction is null. 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) { 6468454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (newAction == null) { 6478454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("newAction == null"); 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 64937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes malformedInputAction = newAction; 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implOnMalformedInput(newAction); 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets this encoder's action on unmappable character error. 656f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call the 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implOnUnmappableCharacter(CodingErrorAction) implOnUnmappableCharacter} 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method with the given new action as argument. 660f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action on unmappable character error. 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given newAction is null. 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6678454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes public final CharsetEncoder onUnmappableCharacter(CodingErrorAction newAction) { 6688454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (newAction == null) { 6698454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("newAction == null"); 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 67137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes unmappableCharacterAction = newAction; 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implOnUnmappableCharacter(newAction); 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 67737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the replacement byte array, which is never null or empty. 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final byte[] replacement() { 68037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return replacementBytes; 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the new replacement value. 685f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method first checks the given replacement's validity, then changes 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement value and finally calls the 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implReplaceWith(byte[]) implReplaceWith} method with the given 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * new replacement as argument. 690f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param replacement 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement byte array, cannot be null or empty, its 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length cannot be larger than <code>maxBytesPerChar</code>, 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and it must be legal replacement, which can be justified by 6958454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes * calling <code>isLegalReplacement(byte[] replacement)</code>. 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given replacement cannot satisfy the requirement 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * mentioned above. 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder replaceWith(byte[] replacement) { 70257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (replacement == null) { 70357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes throw new IllegalArgumentException("replacement == null"); 70457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 70537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (replacement.length == 0) { 70637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes throw new IllegalArgumentException("replacement.length == 0"); 70737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes } 70837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (replacement.length > maxBytesPerChar()) { 709126ab1b546c71137a97cef68cc89267e7f7be634Elliott Hughes throw new IllegalArgumentException("replacement.length > maxBytesPerChar: " + 71037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes replacement.length + " > " + maxBytesPerChar()); 71157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 71257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (!isLegalReplacement(replacement)) { 713126ab1b546c71137a97cef68cc89267e7f7be634Elliott Hughes throw new IllegalArgumentException("Bad replacement: " + Arrays.toString(replacement)); 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 715c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // It seems like a bug, but the RI doesn't clone, and we have tests that check we don't. 71637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes this.replacementBytes = replacement; 71737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes implReplaceWith(replacementBytes); 71837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return this; 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Resets this encoder. This method will reset the internal status and then 72337871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * calls <code>implReset()</code> to reset any status related to the 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specific charset. 725f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder reset() { 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = INIT; 730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implReset(); 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 73537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns this encoder's <code>CodingErrorAction</code> when unmappable 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character occurred during encoding process. 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CodingErrorAction unmappableCharacterAction() { 73937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return unmappableCharacterAction; 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 742