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 { 790f702e293cb57da788261a80abc84391543f6791Elliott Hughes private static final String RESET = "RESET"; 800f702e293cb57da788261a80abc84391543f6791Elliott Hughes private static final String ONGOING = "ONGOING"; 810f702e293cb57da788261a80abc84391543f6791Elliott Hughes private static final String END_OF_INPUT = "END_OF_INPUT"; 820f702e293cb57da788261a80abc84391543f6791Elliott Hughes private static final String FLUSHED = "FLUSHED"; 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 840f702e293cb57da788261a80abc84391543f6791Elliott Hughes private final Charset charset; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private final float averageBytesPerChar; 8737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private final float maxBytesPerChar; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes private byte[] replacementBytes; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 910f702e293cb57da788261a80abc84391543f6791Elliott Hughes private String state = RESET; 9230a7ff69872ad0b8de60550a740818b645ba0f29Elliott Hughes 930f702e293cb57da788261a80abc84391543f6791Elliott Hughes private CodingErrorAction malformedInputAction = CodingErrorAction.REPORT; 940f702e293cb57da788261a80abc84391543f6791Elliott Hughes private CodingErrorAction unmappableCharacterAction = CodingErrorAction.REPORT; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes // decoder instance for this encoder's charset, used for replacement value checking 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private CharsetDecoder decoder; 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 100c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * Constructs a new {@code CharsetEncoder} using the given parameters and 101c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * the replacement byte array {@code { (byte) '?' }}. 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 103cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar) { 104cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes this(cs, averageBytesPerChar, maxBytesPerChar, new byte[] { (byte) '?' }); 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new <code>CharsetEncoder</code> using the given 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>Charset</code>, replacement byte array, average number and 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * maximum number of bytes created by this encoder for one input character. 111f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param cs 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the <code>Charset</code> to be used by this encoder. 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param averageBytesPerChar 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * average number of bytes created by this encoder for one single 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character, must be positive. 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param maxBytesPerChar 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * maximum number of bytes which can be created by this encoder 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for one single input character, must be positive. 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param replacement 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement byte array, cannot be null or empty, its 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length cannot be larger than <code>maxBytesPerChar</code>, 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and must be a legal replacement, which can be justified by 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #isLegalReplacement(byte[]) isLegalReplacement}. 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if any parameters are invalid. 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1283664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement) { 1293664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes this(cs, averageBytesPerChar, maxBytesPerChar, replacement, false); 1303664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes } 1313664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes 1323664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement, boolean trusted) { 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (averageBytesPerChar <= 0 || maxBytesPerChar <= 0) { 1348454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("averageBytesPerChar and maxBytesPerChar must both be positive"); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (averageBytesPerChar > maxBytesPerChar) { 1378454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("averageBytesPerChar is greater than maxBytesPerChar"); 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1390f702e293cb57da788261a80abc84391543f6791Elliott Hughes this.charset = cs; 14037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes this.averageBytesPerChar = averageBytesPerChar; 14137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes this.maxBytesPerChar = maxBytesPerChar; 1423664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes if (trusted) { 1433664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes // The RI enforces unnecessary restrictions on the replacement bytes. We trust ICU to 1443664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes // know what it's doing. Doing so lets us support ICU's EUC-JP, SCSU, and Shift_JIS. 1453664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes this.replacementBytes = replacement; 1463664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes } else { 1473664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes replaceWith(replacement); 1483664d8839f0ba794f428119ee7f7304a66861da5Elliott Hughes } 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 15237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the average number of bytes created by this encoder for a single 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input character. 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final float averageBytesPerChar() { 15637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return averageBytesPerChar; 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1605ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * Tests whether the given character can be encoded by this encoder. 1615ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * 1620f702e293cb57da788261a80abc84391543f6791Elliott Hughes * <p>Note that this method may change the internal state of this encoder, so 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it should not be called when another encoding process is ongoing, 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * otherwise it will throw an <code>IllegalStateException</code>. 165eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 1665ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * @throws IllegalStateException if another encode process is ongoing. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode(char c) { 1695ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes return canEncode(CharBuffer.wrap(new char[] { c })); 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1735ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * Tests whether the given <code>CharSequence</code> can be encoded by this 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoder. 175f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 1760f702e293cb57da788261a80abc84391543f6791Elliott Hughes * <p>Note that this method may change the internal state of this encoder, so 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it should not be called when another encode process is ongoing, otherwise 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it will throw an <code>IllegalStateException</code>. 179f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 1805ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * @throws IllegalStateException if another encode process is ongoing. 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode(CharSequence sequence) { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CharBuffer cb; 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (sequence instanceof CharBuffer) { 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cb = ((CharBuffer) sequence).duplicate(); 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cb = CharBuffer.wrap(sequence); 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1895ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes 1900f702e293cb57da788261a80abc84391543f6791Elliott Hughes if (state == FLUSHED) { 1910f702e293cb57da788261a80abc84391543f6791Elliott Hughes reset(); 1925ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } 1930f702e293cb57da788261a80abc84391543f6791Elliott Hughes if (state != RESET) { 1940f702e293cb57da788261a80abc84391543f6791Elliott Hughes throw illegalStateException(); 1955ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } 1960f702e293cb57da788261a80abc84391543f6791Elliott Hughes 1975ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes CodingErrorAction originalMalformedInputAction = malformedInputAction; 1985ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes CodingErrorAction originalUnmappableCharacterAction = unmappableCharacterAction; 1995ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes onMalformedInput(CodingErrorAction.REPORT); 2005ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes onUnmappableCharacter(CodingErrorAction.REPORT); 2015ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes try { 2029edca89080204647492b04f848107bcb90798a1cElliott Hughes encode(cb); 2035ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes return true; 2045ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } catch (CharacterCodingException e) { 2055ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes return false; 2065ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } finally { 2075ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes onMalformedInput(originalMalformedInputAction); 2085ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes onUnmappableCharacter(originalUnmappableCharacterAction); 2095ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes reset(); 2105ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 21437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the {@link Charset} which this encoder uses. 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Charset charset() { 2170f702e293cb57da788261a80abc84391543f6791Elliott Hughes return charset; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This is a facade method for the encoding operation. 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method encodes the remaining character sequence of the given 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character buffer into a new byte buffer. This method performs a complete 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoding operation, resets at first, then encodes, and flushes at last. 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method should not be invoked if another encode operation is ongoing. 228eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new <code>ByteBuffer</code> containing the bytes produced by 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this encoding operation. The buffer's limit will be the position 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the last byte in the buffer, and the position will be zero. 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if another encoding operation is ongoing. 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws MalformedInputException 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an illegal input character sequence for this charset is 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encountered, and the action for malformed error is 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT} 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnmappableCharacterException 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if a legal but unmappable input character sequence for this 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * charset is encountered, and the action for unmappable 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character error is 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}. 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unmappable means the Unicode character sequence at the input 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer's current position cannot be mapped to a equivalent 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * byte sequence. 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws CharacterCodingException 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if other exception happened during the encode operation. 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 25157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException { 2525ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes int length = (int) (in.remaining() * averageBytesPerChar); 2535ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes ByteBuffer out = ByteBuffer.allocate(length); 2545ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reset(); 2565ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes 2570f702e293cb57da788261a80abc84391543f6791Elliott Hughes while (state != FLUSHED) { 2585ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes CoderResult result = encode(in, out, true); 2590f702e293cb57da788261a80abc84391543f6791Elliott Hughes if (result == CoderResult.OVERFLOW) { 2605ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes out = allocateMore(out); 2610f702e293cb57da788261a80abc84391543f6791Elliott Hughes continue; // No point trying to flush to an already-full buffer. 2625ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } else { 2635ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes checkCoderResult(result); 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2665ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes result = flush(out); 2670f702e293cb57da788261a80abc84391543f6791Elliott Hughes if (result == CoderResult.OVERFLOW) { 2685ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes out = allocateMore(out); 2695ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } else { 2705ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes checkCoderResult(result); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2735ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes 2745ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes out.flip(); 2755ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes return out; 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 27857a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes private void checkCoderResult(CoderResult result) throws CharacterCodingException { 2795ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed()) { 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new MalformedInputException(result.length()); 28137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes } else if (unmappableCharacterAction == CodingErrorAction.REPORT && result.isUnmappable()) { 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnmappableCharacterException(result.length()); 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ByteBuffer allocateMore(ByteBuffer output) { 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (output.capacity() == 0) { 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ByteBuffer.allocate(1); 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ByteBuffer result = ByteBuffer.allocate(output.capacity() * 2); 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project output.flip(); 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result.put(output); 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Encodes characters starting at the current position of the given input 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer, and writes the equivalent byte sequence into the given output 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer from its current position. 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffers' position will be changed with the reading and writing 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * operation, but their limits and marks will be kept intact. 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A <code>CoderResult</code> instance will be returned according to 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * following rules: 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <ul> 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A {@link CoderResult#malformedForLength(int) malformed input} result 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * indicates that some malformed input error was encountered, and the 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * erroneous characters start at the input buffer's position and their 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * number can be got by result's {@link CoderResult#length() length}. This 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * kind of result can be returned only if the malformed action is 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li> 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>{@link CoderResult#UNDERFLOW CoderResult.UNDERFLOW} indicates that 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as many characters as possible in the input buffer have been encoded. If 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * there is no further input and no characters left in the input buffer then 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this task is complete. If this is not the case then the client should 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * call this method again supplying some more input characters.</li> 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>{@link CoderResult#OVERFLOW CoderResult.OVERFLOW} indicates that the 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * output buffer has been filled, while there are still some characters 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * remaining in the input buffer. This method should be invoked again with a 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * non-full output buffer.</li> 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <li>A {@link CoderResult#unmappableForLength(int) unmappable character} 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * result indicates that some unmappable character error was encountered, 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and the erroneous characters start at the input buffer's position and 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * their number can be got by result's {@link CoderResult#length() length}. 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This kind of result can be returned only on 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link CodingErrorAction#REPORT CodingErrorAction.REPORT}.</li> 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </ul> 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The <code>endOfInput</code> parameter indicates if the invoker can 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * provider further input. This parameter is true if and only if the 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * characters in the current input buffer are all inputs for this encoding 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * operation. Note that it is common and won't cause an error if the invoker 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * sets false and then has no more input available, while it may cause an 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * error if the invoker always sets true in several consecutive invocations. 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This would make the remaining input to be treated as malformed input. 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input. 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method invokes the 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} method to 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implement the basic encode logic for a specific charset. 342eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param endOfInput 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * true if all the input characters have been provided. 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>CoderResult</code> instance indicating the result. 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the encoding operation has already started or no more 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input is needed in this encoding process. 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws CoderMalfunctionError 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * If the {@link #encodeLoop(CharBuffer, ByteBuffer) encodeLoop} 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method threw an <code>BufferUnderflowException</code> or 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>BufferUnderflowException</code>. 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 358cf6c3a752da274cc5025191d3bcd62e6222f4a4cElliott Hughes public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) { 3590f702e293cb57da788261a80abc84391543f6791Elliott Hughes if (state != RESET && state != ONGOING && !(endOfInput && state == END_OF_INPUT)) { 3600f702e293cb57da788261a80abc84391543f6791Elliott Hughes throw illegalStateException(); 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3630f702e293cb57da788261a80abc84391543f6791Elliott Hughes state = endOfInput ? END_OF_INPUT : ONGOING; 3645ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (true) { 3665ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes CoderResult result; 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = encodeLoop(in, out); 3690f702e293cb57da788261a80abc84391543f6791Elliott Hughes } catch (BufferOverflowException ex) { 3700f702e293cb57da788261a80abc84391543f6791Elliott Hughes throw new CoderMalfunctionError(ex); 3710f702e293cb57da788261a80abc84391543f6791Elliott Hughes } catch (BufferUnderflowException ex) { 3720f702e293cb57da788261a80abc84391543f6791Elliott Hughes throw new CoderMalfunctionError(ex); 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3740f702e293cb57da788261a80abc84391543f6791Elliott Hughes 3755ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes if (result == CoderResult.UNDERFLOW) { 3765ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes if (endOfInput && in.hasRemaining()) { 3775ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes result = CoderResult.malformedForLength(in.remaining()); 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3815ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes } else if (result == CoderResult.OVERFLOW) { 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3840f702e293cb57da788261a80abc84391543f6791Elliott Hughes 3850f702e293cb57da788261a80abc84391543f6791Elliott Hughes // We have a real error, so do what the appropriate action tells us what to do... 3865ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes CodingErrorAction action = 3875ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes result.isUnmappable() ? unmappableCharacterAction : malformedInputAction; 3885ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes if (action == CodingErrorAction.REPORT) { 3895ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes return result; 3900f702e293cb57da788261a80abc84391543f6791Elliott Hughes } else if (action == CodingErrorAction.REPLACE) { 39137871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (out.remaining() < replacementBytes.length) { 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CoderResult.OVERFLOW; 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 39437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes out.put(replacementBytes); 395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.position(in.position() + result.length()); 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Encodes characters into bytes. This method is called by 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will implement the essential encoding operation, and it won't 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * stop encoding until either all the input characters are read, the output 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffer is filled, or some exception is encountered. Then it will 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * return a <code>CoderResult</code> object indicating the result of the 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * current encoding operation. The rule to construct the 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult</code> is the same as for 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. When an 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exception is encountered in the encoding operation, most implementations 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of this method will return a relevant result object to the 4135ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and 4145ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * subclasses may handle the exception and 4155ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * implement the error action themselves. 416eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p> 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The buffers are scanned from their current positions, and their positions 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be modified accordingly, while their marks and limits will be 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * intact. At most {@link CharBuffer#remaining() in.remaining()} characters 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be read, and {@link ByteBuffer#remaining() out.remaining()} bytes 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * will be written. 422eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p> 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Note that some implementations may pre-scan the input buffer and return 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.UNDERFLOW</code> until it receives sufficient input. 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param in 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the input buffer. 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>CoderResult</code> instance indicating the result. 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected abstract CoderResult encodeLoop(CharBuffer in, ByteBuffer out); 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this encoder. 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call {@link #implFlush(ByteBuffer) implFlush}. Some 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoders may need to write some bytes to the output buffer when they have 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read all input characters, subclasses can overridden 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implFlush(ByteBuffer) implFlush} to perform writing action. 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The maximum number of written bytes won't larger than 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link ByteBuffer#remaining() out.remaining()}. If some encoder wants to 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write more bytes than the output buffer's available remaining space, then 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code> will be returned, and this method 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be called again with a byte buffer that has free space. Otherwise 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this method will return <code>CoderResult.UNDERFLOW</code>, which 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * means one encoding process has been completed successfully. 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * During the flush, the output buffer's position will be changed 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * accordingly, while its mark and limit will be intact. 452f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given output buffer. 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return <code>CoderResult.UNDERFLOW</code> or 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code>. 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalStateException 4580f702e293cb57da788261a80abc84391543f6791Elliott Hughes * if this encoder isn't already flushed or at end of input. 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CoderResult flush(ByteBuffer out) { 4610f702e293cb57da788261a80abc84391543f6791Elliott Hughes if (state != FLUSHED && state != END_OF_INPUT) { 4620f702e293cb57da788261a80abc84391543f6791Elliott Hughes throw illegalStateException(); 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = implFlush(out); 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result == CoderResult.UNDERFLOW) { 4660f702e293cb57da788261a80abc84391543f6791Elliott Hughes state = FLUSHED; 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this encoder. The default implementation does nothing and always 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * returns <code>CoderResult.UNDERFLOW</code>; this method can be 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * overridden if needed. 475f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param out 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output buffer. 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return <code>CoderResult.UNDERFLOW</code> or 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>CoderResult.OVERFLOW</code>. 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected CoderResult implFlush(ByteBuffer out) { 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CoderResult.UNDERFLOW; 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's <code>CodingErrorAction</code> specified 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for malformed input error has been changed. The default implementation 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * does nothing; this method can be overridden if needed. 489f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action. 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implOnMalformedInput(CodingErrorAction newAction) { 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's <code>CodingErrorAction</code> specified 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for unmappable character error has been changed. The default 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implementation does nothing; this method can be overridden if needed. 501f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action. 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implOnUnmappableCharacter(CodingErrorAction newAction) { 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies that this encoder's replacement has been changed. The default 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * implementation does nothing; this method can be overridden if needed. 512f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newReplacement 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new replacement string. 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implReplaceWith(byte[] newReplacement) { 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Resets this encoder's charset related state. The default implementation 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * does nothing; this method can be overridden if needed. 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected void implReset() { 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // default implementation is empty 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 5295ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * Tests whether the given argument is legal as this encoder's replacement byte 5305ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * array. The given byte array is legal if and only if it can be decoded into 5315ec6bf8d033754e06a463adb091d2c0afd0755acElliott Hughes * characters. 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 53357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes public boolean isLegalReplacement(byte[] replacement) { 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (decoder == null) { 5350f702e293cb57da788261a80abc84391543f6791Elliott Hughes decoder = charset.newDecoder(); 53657a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes decoder.onMalformedInput(CodingErrorAction.REPORT); 53757a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes decoder.onUnmappableCharacter(CodingErrorAction.REPORT); 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 53957a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes ByteBuffer in = ByteBuffer.wrap(replacement); 54057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes CharBuffer out = CharBuffer.allocate((int) (replacement.length * decoder.maxCharsPerByte())); 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project CoderResult result = decoder.decode(in, out, true); 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return !result.isError(); 543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 54637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns this encoder's <code>CodingErrorAction</code> when a malformed 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * input error occurred during the encoding process. 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CodingErrorAction malformedInputAction() { 55037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return malformedInputAction; 551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 55437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the maximum number of bytes which can be created by this encoder for 555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * one input character, must be positive. 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final float maxBytesPerChar() { 55837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return maxBytesPerChar; 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets this encoder's action on malformed input error. 563f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call the 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implOnMalformedInput(CodingErrorAction) implOnMalformedInput} 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method with the given new action as argument. 567f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action on malformed input error. 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given newAction is null. 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) { 5758454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (newAction == null) { 5768454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("newAction == null"); 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 57837871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes malformedInputAction = newAction; 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implOnMalformedInput(newAction); 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets this encoder's action on unmappable character error. 585f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method will call the 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implOnUnmappableCharacter(CodingErrorAction) implOnUnmappableCharacter} 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method with the given new action as argument. 589f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param newAction 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the new action on unmappable character error. 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given newAction is null. 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5968454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes public final CharsetEncoder onUnmappableCharacter(CodingErrorAction newAction) { 5978454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes if (newAction == null) { 5988454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes throw new IllegalArgumentException("newAction == null"); 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 60037871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes unmappableCharacterAction = newAction; 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implOnUnmappableCharacter(newAction); 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 60637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns the replacement byte array, which is never null or empty. 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final byte[] replacement() { 60937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return replacementBytes; 610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Sets the new replacement value. 614f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This method first checks the given replacement's validity, then changes 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement value and finally calls the 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #implReplaceWith(byte[]) implReplaceWith} method with the given 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * new replacement as argument. 619f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param replacement 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the replacement byte array, cannot be null or empty, its 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length cannot be larger than <code>maxBytesPerChar</code>, 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and it must be legal replacement, which can be justified by 6248454d3c5b9778ae359d11cd98ed81c589e951d0aElliott Hughes * calling <code>isLegalReplacement(byte[] replacement)</code>. 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this encoder. 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the given replacement cannot satisfy the requirement 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * mentioned above. 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder replaceWith(byte[] replacement) { 63157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (replacement == null) { 63257a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes throw new IllegalArgumentException("replacement == null"); 63357a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 63437871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (replacement.length == 0) { 63537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes throw new IllegalArgumentException("replacement.length == 0"); 63637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes } 63737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes if (replacement.length > maxBytesPerChar()) { 638126ab1b546c71137a97cef68cc89267e7f7be634Elliott Hughes throw new IllegalArgumentException("replacement.length > maxBytesPerChar: " + 63937871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes replacement.length + " > " + maxBytesPerChar()); 64057a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes } 64157a151cc43ef3dfc1040fad5581836c66c8e53f3Elliott Hughes if (!isLegalReplacement(replacement)) { 642126ab1b546c71137a97cef68cc89267e7f7be634Elliott Hughes throw new IllegalArgumentException("Bad replacement: " + Arrays.toString(replacement)); 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 644c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes // It seems like a bug, but the RI doesn't clone, and we have tests that check we don't. 64537871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes this.replacementBytes = replacement; 64637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes implReplaceWith(replacementBytes); 64737871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return this; 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 6510f702e293cb57da788261a80abc84391543f6791Elliott Hughes * Resets this encoder. This method will reset the internal state and then 6520f702e293cb57da788261a80abc84391543f6791Elliott Hughes * calls {@link #implReset} to reset any state related to the 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specific charset. 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharsetEncoder reset() { 6560f702e293cb57da788261a80abc84391543f6791Elliott Hughes state = RESET; 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project implReset(); 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this; 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 66237871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes * Returns this encoder's <code>CodingErrorAction</code> when unmappable 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * character occurred during encoding process. 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CodingErrorAction unmappableCharacterAction() { 66637871fb106b08055ad56d7f04d4faccdd163e1afElliott Hughes return unmappableCharacterAction; 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 6680f702e293cb57da788261a80abc84391543f6791Elliott Hughes 6690f702e293cb57da788261a80abc84391543f6791Elliott Hughes private IllegalStateException illegalStateException() { 6700f702e293cb57da788261a80abc84391543f6791Elliott Hughes throw new IllegalStateException("State: " + state); 6710f702e293cb57da788261a80abc84391543f6791Elliott Hughes } 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 673