CharsetEncoder.java revision 57a151cc43ef3dfc1040fad5581836c66c8e53f3
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 1957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughesimport com.ibm.icu4jni.charset.CharsetEncoderICU; 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.BufferOverflowException; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.BufferUnderflowException; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.CharBuffer; 248454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughesimport java.util.Arrays; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 2757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * Transforms a sequence of 16-bit Java characters to a byte sequence in some encoding. 2857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 2957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>The input character sequence is a {@link java.nio.CharBuffer CharBuffer} and the 3057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * output byte sequence is a {@link java.nio.ByteBuffer ByteBuffer}. 3157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 3257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>Use {@link #encode(CharBuffer)} to encode an entire {@code CharBuffer} to a 3357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * new {@code ByteBuffer}, or {@link #encode(CharBuffer, ByteBuffer, boolean)} for more 3457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * control. When using the latter method, the entire operation proceeds as follows: 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ol> 3657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #reset()} to reset the encoder if this instance has been used before.</li> 3757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #encode(CharBuffer, ByteBuffer, boolean) encode} with the {@code endOfInput} 3857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * parameter set to false until additional input is not needed (as signaled by the return value). 3957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * The input buffer must be filled and the output buffer must be flushed between invocations. 4057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>The {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method will 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * convert as many characters as possible, and the process won't stop until the 4257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * input buffer has been exhausted, the output buffer has been filled, or an 4357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * error has occurred. A {@link CoderResult CoderResult} instance will be 4457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * returned to indicate the current state. The caller should fill the input buffer, flush 4557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * the output buffer, or recovering from an error and try again, accordingly. 4657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * </li> 4757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #encode(CharBuffer, ByteBuffer, boolean) encode} for the last time with 4857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@code endOfInput} set to true.</li> 4957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <li>Invoke {@link #flush(ByteBuffer)} to flush remaining output.</li> 5057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * </ol> 5157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 5257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>There are two classes of encoding error: <i>malformed input</i> 5357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * signifies that the input character sequence is not legal, while <i>unmappable character</i> 5457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * signifies that the input is legal but cannot be mapped to a byte sequence (because the charset 5557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * cannot represent the character, for example). 5657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 5757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>Errors can be handled in three ways. The default is to 5857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@link CodingErrorAction.REPORT report} the error to the caller. The alternatives are to 5957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@link CodingErrorAction.IGNORE ignore} the error or {@link CodingErrorAction.IGNORE replace} 6057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * the problematic input with the byte sequence returned by {@link #replacement}. The disposition 6157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * for each of the two kinds of error can be set independently using the {@link #onMalformedInput} 6257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * and {@link #onUnmappableCharacter} methods. 6357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 6457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>The default replacement bytes depend on the charset but can be overridden using the 6557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@link #replaceWith} method. 6657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 6757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>This class is abstract and encapsulates many common operations of the 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding process for all charsets. Encoders for a specific charset should 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * extend this class and need only to implement the 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method for basic 7157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * encoding. If a subclass maintains internal state, it should also override the 7257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * {@link #implFlush(ByteBuffer) implFlush} and {@link #implReset() implReset} methods. 7357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * 7457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * <p>This class is not thread-safe. 75eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.nio.charset.Charset 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.nio.charset.CharsetDecoder 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class CharsetEncoder { 80eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * internal status consts 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int INIT = 0; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int ONGOING = 1; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int END = 2; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int FLUSH = 3; 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the Charset which creates this encoder 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Charset cs; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // average bytes per character created by this encoder 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private float averBytes; 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // maximum bytes per character can be created by this encoder 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private float maxBytes; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // replacement byte array 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private byte[] replace; 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // internal status 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int status; 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // action for malformed input 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private CodingErrorAction malformAction; 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // action for unmapped char input 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private CodingErrorAction unmapAction; 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // decoder instance for this encoder's charset, used for replacement value 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // checking 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private CharsetDecoder decoder; 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 118c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * Constructs a new {@code CharsetEncoder} using the given parameters and 119c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * the replacement byte array {@code { (byte) '?' }}. 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 121cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar) { 122cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes this(cs, averageBytesPerChar, maxBytesPerChar, new byte[] { (byte) '?' }); 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new <code>CharsetEncoder</code> using the given 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>Charset</code>, replacement byte array, average number and 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * maximum number of bytes created by this encoder for one input character. 129f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param cs 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the <code>Charset</code> to be used by this encoder. 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param averageBytesPerChar 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * average number of bytes created by this encoder for one single 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character, must be positive. 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param maxBytesPerChar 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * maximum number of bytes which can be created by this encoder 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for one single input character, must be positive. 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param replacement 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement byte array, cannot be null or empty, its 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length cannot be larger than <code>maxBytesPerChar</code>, 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and must be a legal replacement, which can be justified by 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #isLegalReplacement(byte[]) isLegalReplacement}. 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if any parameters are invalid. 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected CharsetEncoder(Charset cs, float averageBytesPerChar, 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project float maxBytesPerChar, byte[] replacement) { 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (averageBytesPerChar <= 0 || maxBytesPerChar <= 0) { 1498454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("averageBytesPerChar and maxBytesPerChar must both be positive"); 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (averageBytesPerChar > maxBytesPerChar) { 1528454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("averageBytesPerChar is greater than maxBytesPerChar"); 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.cs = cs; 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project averBytes = averageBytesPerChar; 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project maxBytes = maxBytesPerChar; 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = INIT; 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project malformAction = CodingErrorAction.REPORT; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unmapAction = CodingErrorAction.REPORT; 16057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (this instanceof CharsetEncoderICU) { 16157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes // The RI enforces unnecessary restrictions on the replacement bytes. We trust ICU to 16257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes // know what it's doing. This lets us support EUC-JP, SCSU, and Shift_JIS. 16357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes uncheckedReplaceWith(replacement); 16457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } else { 16557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes replaceWith(replacement); 16657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the average number of bytes created by this encoder for a single 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character. 172f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the average number of bytes created by this encoder for a single 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character. 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final float averageBytesPerChar() { 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return averBytes; 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks if the given character can be encoded by this encoder. 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that this method can change the internal status of this encoder, so 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it should not be called when another encoding process is ongoing, 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise it will throw an <code>IllegalStateException</code>. 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method can be overridden for performance improvement. 188eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param c 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given encoder. 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if given character can be encoded by this encoder. 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if another encode process is ongoing so that the current 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * internal status is neither RESET or FLUSH. 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode(char c) { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return implCanEncode(CharBuffer.wrap(new char[] { c })); 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // implementation of canEncode 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean implCanEncode(CharBuffer cb) { 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (status == FLUSH) { 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = INIT; 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (status != INIT) { 2068454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalStateException("encoding already in progress"); 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction malformBak = malformAction; 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction unmapBak = unmapAction; 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onMalformedInput(CodingErrorAction.REPORT); 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onUnmappableCharacter(CodingErrorAction.REPORT); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean result = true; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.encode(cb); 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CharacterCodingException e) { 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = false; 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onMalformedInput(malformBak); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project onUnmappableCharacter(unmapBak); 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reset(); 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks if a given <code>CharSequence</code> can be encoded by this 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoder. 227f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that this method can change the internal status of this encoder, so 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it should not be called when another encode process is ongoing, otherwise 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it will throw an <code>IllegalStateException</code>. 231f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method can be overridden for performance improvement. 233f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param sequence 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given <code>CharSequence</code>. 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the given <code>CharSequence</code> can be encoded by 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this encoder. 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if current internal status is neither RESET or FLUSH. 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode(CharSequence sequence) { 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CharBuffer cb; 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (sequence instanceof CharBuffer) { 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cb = ((CharBuffer) sequence).duplicate(); 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cb = CharBuffer.wrap(sequence); 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return implCanEncode(cb); 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the <code>Charset</code> which this encoder uses. 253f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the <code>Charset</code> which this encoder uses. 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Charset charset() { 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return cs; 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This is a facade method for the encoding operation. 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method encodes the remaining character sequence of the given 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character buffer into a new byte buffer. This method performs a complete 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding operation, resets at first, then encodes, and flushes at last. 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method should not be invoked if another encode operation is ongoing. 268eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new <code>ByteBuffer</code> containing the bytes produced by 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this encoding operation. The buffer's limit will be the position 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the last byte in the buffer, and the position will be zero. 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if another encoding operation is ongoing. 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws MalformedInputException 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an illegal input character sequence for this charset is 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encountered, and the action for malformed error is 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT} 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnmappableCharacterException 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a legal but unmappable input character sequence for this 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * charset is encountered, and the action for unmappable 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character error is 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unmappable means the Unicode character sequence at the input 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer's current position cannot be mapped to a equivalent 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * byte sequence. 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws CharacterCodingException 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if other exception happened during the encode operation. 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 29157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException { 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in.remaining() == 0) { 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ByteBuffer.allocate(0); 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reset(); 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = (int) (in.remaining() * averBytes); 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteBuffer output = ByteBuffer.allocate(length); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = null; 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encode(in, output, false); 301eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result==CoderResult.UNDERFLOW) { 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 303eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result==CoderResult.OVERFLOW) { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project output = allocateMore(output); 305eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson continue; 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 307eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson checkCoderResult(result); 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encode(in, output, true); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkCoderResult(result); 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = flush(output); 314eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result==CoderResult.UNDERFLOW) { 315eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson output.flip(); 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 317eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result==CoderResult.OVERFLOW) { 318eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson output = allocateMore(output); 319eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson continue; 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 321eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson checkCoderResult(result); 322eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson output.flip(); 323eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result.isMalformed()) { 324eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson throw new MalformedInputException(result.length()); 325eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result.isUnmappable()) { 326eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson throw new UnmappableCharacterException(result.length()); 327eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 328eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson break; 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FLUSH; 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return output; 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * checks the result whether it needs to throw CharacterCodingException. 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 33757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes private void checkCoderResult(CoderResult result) throws CharacterCodingException { 338eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (malformAction == CodingErrorAction.REPORT && result.isMalformed() ) { 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new MalformedInputException(result.length()); 340eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (unmapAction == CodingErrorAction.REPORT && result.isUnmappable()) { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnmappableCharacterException(result.length()); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // allocate more spaces to the given ByteBuffer 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ByteBuffer allocateMore(ByteBuffer output) { 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (output.capacity() == 0) { 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ByteBuffer.allocate(1); 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteBuffer result = ByteBuffer.allocate(output.capacity() * 2); 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project output.flip(); 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result.put(output); 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Encodes characters starting at the current position of the given input 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer, and writes the equivalent byte sequence into the given output 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer from its current position. 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffers' position will be changed with the reading and writing 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * operation, but their limits and marks will be kept intact. 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A <code>CoderResult</code> instance will be returned according to 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * following rules: 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul> 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A {@link CoderResult#malformedForLength(int) malformed input} result 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * indicates that some malformed input error was encountered, and the 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * erroneous characters start at the input buffer's position and their 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * number can be got by result's {@link CoderResult#length() length}. This 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * kind of result can be returned only if the malformed action is 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li> 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as many characters as possible in the input buffer have been encoded. If 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * there is no further input and no characters left in the input buffer then 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this task is complete. If this is not the case then the client should 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * call this method again supplying some more input characters.</li> 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that the 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * output buffer has been filled, while there are still some characters 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * remaining in the input buffer. This method should be invoked again with a 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * non-full output buffer.</li> 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A {@link CoderResult#unmappableForLength(int) unmappable character} 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * result indicates that some unmappable character error was encountered, 384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and the erroneous characters start at the input buffer's position and 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * their number can be got by result's {@link CoderResult#length() length}. 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This kind of result can be returned only on 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li> 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul> 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The <code>endOfInput</code> parameter indicates if the invoker can 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provider further input. This parameter is true if and only if the 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * characters in the current input buffer are all inputs for this encoding 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * operation. Note that it is common and won't cause an error if the invoker 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sets false and then has no more input available, while it may cause an 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * error if the invoker always sets true in several consecutive invocations. 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This would make the remaining input to be treated as malformed input. 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input. 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method invokes the 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implement the basic encode logic for a specific charset. 402eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param endOfInput 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * true if all the input characters have been provided. 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>CoderResult</code> instance indicating the result. 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the encoding operation has already started or no more 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input is needed in this encoding process. 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws CoderMalfunctionError 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method threw an <code>BufferUnderflowException</code> or 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>BufferUnderflowException</code>. 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 418cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) { 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((status == FLUSH) || (!endOfInput && status == END)) { 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(); 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result; 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encodeLoop(in, out); 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (BufferOverflowException e) { 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new CoderMalfunctionError(e); 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (BufferUnderflowException e) { 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new CoderMalfunctionError(e); 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 432eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (result==CoderResult.UNDERFLOW) { 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = endOfInput ? END : ONGOING; 434eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (endOfInput) { 435eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson int remaining = in.remaining(); 436eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (remaining > 0) { 437eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson result = CoderResult.malformedForLength(remaining); 438eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else { 439eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return result; 440eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 444eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else if (result==CoderResult.OVERFLOW) { 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = endOfInput ? END : ONGOING; 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CodingErrorAction action = malformAction; 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result.isUnmappable()) { 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project action = unmapAction; 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If the action is IGNORE or REPLACE, we should continue 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // encoding. 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (action == CodingErrorAction.REPLACE) { 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (out.remaining() < replace.length) { 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CoderResult.OVERFLOW; 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.put(replace); 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (action != CodingErrorAction.IGNORE) { 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.position(in.position() + result.length()); 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Encodes characters into bytes. This method is called by 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will implement the essential encoding operation, and it won't 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * stop encoding until either all the input characters are read, the output 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer is filled, or some exception is encountered. Then it will 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * return a <code>CoderResult</code> object indicating the result of the 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * current encoding operation. The rule to construct the 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult</code> is the same as for 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. When an 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exception is encountered in the encoding operation, most implementations 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of this method will return a relevant result object to the 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * performance optimized implementation may handle the exception and 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implement the error action itself. 484eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p> 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffers are scanned from their current positions, and their positions 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be modified accordingly, while their marks and limits will be 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * intact. At most {@link CharBuffer#remaining() in.remaining()} characters 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be read, and {@link ByteBuffer#remaining() out.remaining()} bytes 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be written. 490eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p> 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that some implementations may pre-scan the input buffer and return 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input. 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>CoderResult</code> instance indicating the result. 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected abstract CoderResult encodeLoop(CharBuffer in, ByteBuffer out); 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this encoder. 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call {@link #implFlush(ByteBuffer) implFlush}. Some 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoders may need to write some bytes to the output buffer when they have 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read all input characters, subclasses can overridden 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implFlush(ByteBuffer) implFlush} to perform writing action. 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The maximum number of written bytes won't larger than 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link ByteBuffer#remaining() out.remaining()}. If some encoder wants to 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write more bytes than the output buffer's available remaining space, then 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code> will be returned, and this method 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be called again with a byte buffer that has free space. Otherwise 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this method will return <code>CoderResult.UNDERFLOW</code>, which 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * means one encoding process has been completed successfully. 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * During the flush, the output buffer's position will be changed 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * accordingly, while its mark and limit will be intact. 520f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given output buffer. 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return <code>CoderResult.UNDERFLOW</code> or 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code>. 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this encoder hasn't read all input characters during one 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding process, which means neither after calling 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer) encode(CharBuffer)} nor after 529f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * calling {@link #encode(CharBuffer, ByteBuffer, boolean) 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encode(CharBuffer, ByteBuffer, boolean)} with {@code true} 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the last boolean parameter. 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CoderResult flush(ByteBuffer out) { 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (status != END && status != INIT) { 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(); 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = implFlush(out); 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == CoderResult.UNDERFLOW) { 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = FLUSH; 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this encoder. The default implementation does nothing and always 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * returns <code>CoderResult.UNDERFLOW</code>; this method can be 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * overridden if needed. 548f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return <code>CoderResult.UNDERFLOW</code> or 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code>. 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected CoderResult implFlush(ByteBuffer out) { 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CoderResult.UNDERFLOW; 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's <code>CodingErrorAction</code> specified 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for malformed input error has been changed. The default implementation 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * does nothing; this method can be overridden if needed. 562f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action. 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implOnMalformedInput(CodingErrorAction newAction) { 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's <code>CodingErrorAction</code> specified 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for unmappable character error 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 newAction 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action. 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implOnUnmappableCharacter(CodingErrorAction newAction) { 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 * Notifies that this encoder's replacement has been changed. The default 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implementation does nothing; this method can be overridden if needed. 585f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newReplacement 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new replacement string. 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implReplaceWith(byte[] newReplacement) { 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Resets this encoder's charset related state. The default implementation 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * does nothing; this method can be overridden if needed. 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implReset() { 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks if the given argument is legal as this encoder's replacement byte 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * array. 604f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The given byte array is legal if and only if it can be decode into 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sixteen bits Unicode characters. 607f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method can be overridden for performance improvement. 609f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 61057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes * @param replacement 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given byte array to be checked. 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the the given argument is legal as this encoder's 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * replacement byte array. 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 61557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes public boolean isLegalReplacement(byte[] replacement) { 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (decoder == null) { 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project decoder = cs.newDecoder(); 61857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes decoder.onMalformedInput(CodingErrorAction.REPORT); 61957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes decoder.onUnmappableCharacter(CodingErrorAction.REPORT); 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 62157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes ByteBuffer in = ByteBuffer.wrap(replacement); 62257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes CharBuffer out = CharBuffer.allocate((int) (replacement.length * decoder.maxCharsPerByte())); 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = decoder.decode(in, out, true); 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return !result.isError(); 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets this encoder's <code>CodingErrorAction</code> when a malformed 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input error occurred during the encoding process. 630f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder's <code>CodingErrorAction</code> when a malformed 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input error occurred during the encoding process. 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CodingErrorAction malformedInputAction() { 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return malformAction; 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the maximum number of bytes which can be created by this encoder for 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * one input character, must be positive. 641f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the maximum number of bytes which can be created by this encoder 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for one input character, must be positive. 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final float maxBytesPerChar() { 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return maxBytes; 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets this encoder's action on malformed input error. 651f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call the 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implOnMalformedInput(CodingErrorAction) implOnMalformedInput} 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method with the given new action as argument. 655f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action on malformed input error. 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given newAction is null. 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) { 6638454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (newAction == null) { 6648454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("newAction == null"); 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project malformAction = newAction; 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implOnMalformedInput(newAction); 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets this encoder's action on unmappable character error. 673f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call the 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implOnUnmappableCharacter(CodingErrorAction) implOnUnmappableCharacter} 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method with the given new action as argument. 677f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action on unmappable character error. 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given newAction is null. 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6848454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes public final CharsetEncoder onUnmappableCharacter(CodingErrorAction newAction) { 6858454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (newAction == null) { 6868454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("newAction == null"); 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project unmapAction = newAction; 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implOnUnmappableCharacter(newAction); 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the replacement byte array, which is never null or empty. 695f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the replacement byte array, cannot be null or empty. 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final byte[] replacement() { 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return replace; 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the new replacement value. 704f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method first checks the given replacement's validity, then changes 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement value and finally calls the 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implReplaceWith(byte[]) implReplaceWith} method with the given 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * new replacement as argument. 709f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param replacement 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement byte array, cannot be null or empty, its 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length cannot be larger than <code>maxBytesPerChar</code>, 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and it must be legal replacement, which can be justified by 7148454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes * calling <code>isLegalReplacement(byte[] replacement)</code>. 715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given replacement cannot satisfy the requirement 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * mentioned above. 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder replaceWith(byte[] replacement) { 72157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (replacement == null) { 72257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes throw new IllegalArgumentException("replacement == null"); 72357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 72457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (replacement.length == 0 || maxBytes < replacement.length) { 72557a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes throw new IllegalArgumentException("bad replacement length: " + replacement.length); 72657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 72757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (!isLegalReplacement(replacement)) { 7288454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("bad replacement: " + Arrays.toString(replacement)); 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 73057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes uncheckedReplaceWith(replacement); 73157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes return this; 73257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 73357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes 73457a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes private final void uncheckedReplaceWith(byte[] replacement) { 735c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // It seems like a bug, but the RI doesn't clone, and we have tests that check we don't. 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project replace = replacement; 737c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes implReplaceWith(replace); 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Resets this encoder. This method will reset the internal status and then 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * calla <code>implReset()</code> to reset any status related to the 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specific charset. 744f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder reset() { 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project status = INIT; 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implReset(); 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets this encoder's <code>CodingErrorAction</code> when unmappable 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character occurred during encoding process. 756f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder's <code>CodingErrorAction</code> when unmappable 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character occurred during encoding process. 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CodingErrorAction unmappableCharacterAction() { 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return unmapAction; 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 764