0N/A/*
2362N/A * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.io;
0N/A
0N/Aimport java.io.*;
0N/A
0N/A
0N/A/**
0N/A * An abstract base class for subclasses which convert Unicode
0N/A * characters into an external encoding.
0N/A *
0N/A * @author Asmus Freytag
0N/A * @author Lloyd Honomichl, Novell, Inc.
0N/A *
0N/A * @deprecated Replaced by {@link java.nio.charset}. THIS API WILL BE
0N/A * REMOVED IN J2SE 1.6.
0N/A */
0N/A@Deprecated
0N/Apublic abstract class CharToByteConverter {
0N/A
0N/A /**
0N/A * Substitution mode flag.
0N/A */
0N/A protected boolean subMode = true;
0N/A
0N/A /**
0N/A * Bytes to substitute for unmappable input.
0N/A */
0N/A protected byte[] subBytes = { (byte)'?' };
0N/A
0N/A /**
0N/A * Offset of next character to be converted.
0N/A */
0N/A protected int charOff;
0N/A
0N/A /**
0N/A * Offset of next byte to be output.
0N/A */
0N/A protected int byteOff;
0N/A
0N/A /**
0N/A * Length of bad input that caused conversion to stop.
0N/A */
0N/A protected int badInputLength;
0N/A
0N/A /**
0N/A * Create an instance of the default CharToByteConverter subclass.
0N/A */
0N/A public static CharToByteConverter getDefault() {
0N/A Object cvt;
0N/A cvt = Converters.newDefaultConverter(Converters.CHAR_TO_BYTE);
0N/A return (CharToByteConverter)cvt;
0N/A }
0N/A
0N/A /**
0N/A * Returns appropriate CharToByteConverter subclass instance.
0N/A * @param string represets encoding
0N/A */
0N/A public static CharToByteConverter getConverter(String encoding)
0N/A throws UnsupportedEncodingException
0N/A {
0N/A Object cvt;
0N/A cvt = Converters.newConverter(Converters.CHAR_TO_BYTE, encoding);
0N/A return (CharToByteConverter)cvt;
0N/A }
0N/A
0N/A /**
0N/A * Returns the character set id for the conversion.
0N/A */
0N/A public abstract String getCharacterEncoding();
0N/A
0N/A /**
0N/A * Converts an array of Unicode characters into an array of bytes
0N/A * in the target character encoding. This method allows a buffer by
0N/A * buffer conversion of a data stream. The state of the conversion is
0N/A * saved between calls to convert. If a call to convert results in
0N/A * an exception, the conversion may be continued by calling convert again
0N/A * with suitably modified parameters. All conversions should be finished
0N/A * with a call to the flush method.
0N/A *
0N/A * @return the number of bytes written to output.
0N/A * @param input array containing Unicode characters to be converted.
0N/A * @param inStart begin conversion at this offset in input array.
0N/A * @param inEnd stop conversion at this offset in input array (exclusive).
0N/A * @param output byte array to receive conversion result.
0N/A * @param outStart start writing to output array at this offset.
0N/A * @param outEnd stop writing to output array at this offset (exclusive).
0N/A * @exception MalformedInputException if the input buffer contains any
0N/A * sequence of chars that is illegal in Unicode (principally unpaired
0N/A * surrogates and \uFFFF or \uFFFE). After this exception is thrown,
0N/A * the method nextCharIndex can be called to obtain the index of the
0N/A * first invalid input character. The MalformedInputException can
0N/A * be queried for the length of the invalid input.
0N/A * @exception UnknownCharacterException for any character that
0N/A * that cannot be converted to the external character encoding. Thrown
0N/A * only when converter is not in substitution mode.
0N/A * @exception ConversionBufferFullException if output array is filled prior
0N/A * to converting all the input.
0N/A */
0N/A public abstract int convert(char[] input, int inStart, int inEnd,
0N/A byte[] output, int outStart, int outEnd)
0N/A throws MalformedInputException,
0N/A UnknownCharacterException,
0N/A ConversionBufferFullException;
0N/A
0N/A /*
0N/A * Converts any array of characters, including malformed surrogate
0N/A * pairs, into an array of bytes in the target character encoding.
0N/A * A precondition is that substitution mode is turned on. This method
0N/A * allows a buffer by buffer conversion of a data stream.
0N/A * The state of the conversion is saved between calls to convert.
0N/A * All conversions should be finished with a call to the flushAny method.
0N/A *
0N/A * @return the number of bytes written to output.
0N/A * @param input array containing Unicode characters to be converted.
0N/A * @param inStart begin conversion at this offset in input array.
0N/A * @param inEnd stop conversion at this offset in input array (exclusive).
0N/A * @param output byte array to receive conversion result.
0N/A * @param outStart start writing to output array at this offset.
0N/A * @param outEnd stop writing to output array at this offset (exclusive).
0N/A * @exception ConversionBufferFullException if output array is filled prior
0N/A * to converting all the input.
0N/A */
0N/A public int convertAny(char[] input, int inStart, int inEnd,
0N/A byte[] output, int outStart, int outEnd)
0N/A throws ConversionBufferFullException
0N/A {
0N/A if (!subMode) { /* Precondition: subMode == true */
0N/A throw new IllegalStateException("Substitution mode is not on");
0N/A }
0N/A /* Rely on the untested precondition that the indices are meaningful */
0N/A /* For safety, use the public interface to charOff and byteOff, but
0N/A badInputLength is directly modified.*/
0N/A int localInOff = inStart;
0N/A int localOutOff = outStart;
0N/A while(localInOff < inEnd) {
0N/A try {
0N/A int discard = convert(input, localInOff, inEnd,
0N/A output, localOutOff, outEnd);
0N/A return (nextByteIndex() - outStart);
0N/A } catch (MalformedInputException e) {
0N/A byte[] s = subBytes;
0N/A int subSize = s.length;
0N/A localOutOff = nextByteIndex();
0N/A if ((localOutOff + subSize) > outEnd)
0N/A throw new ConversionBufferFullException();
0N/A for (int i = 0; i < subSize; i++)
0N/A output[localOutOff++] = s[i];
0N/A localInOff = nextCharIndex();
0N/A localInOff += badInputLength;
0N/A badInputLength = 0;
0N/A if (localInOff >= inEnd){
0N/A byteOff = localOutOff;
0N/A return (byteOff - outStart);
0N/A }
0N/A continue;
0N/A }catch (UnknownCharacterException e) {
0N/A /* Should never occur, since subMode == true */
0N/A throw new Error("UnknownCharacterException thrown "
0N/A + "in substititution mode",
0N/A e);
0N/A }
0N/A }
0N/A return (nextByteIndex() - outStart);
0N/A }
0N/A
0N/A
0N/A
0N/A /**
0N/A * Converts an array of Unicode characters into an array of bytes
0N/A * in the target character encoding. Unlike convert, this method
0N/A * does not do incremental conversion. It assumes that the given
0N/A * input array contains all the characters to be converted. The
0N/A * state of the converter is reset at the beginning of this method
0N/A * and is left in the reset state on successful termination.
0N/A * The converter is not reset if an exception is thrown.
0N/A * This allows the caller to determine where the bad input
0N/A * was encountered by calling nextCharIndex.
0N/A * <p>
0N/A * This method uses substitution mode when performing the conversion.
0N/A * The method setSubstitutionBytes may be used to determine what
0N/A * bytes are substituted. Even though substitution mode is used,
0N/A * the state of the converter's substitution mode is not changed
0N/A * at the end of this method.
0N/A *
0N/A * @return an array of bytes containing the converted characters.
0N/A * @param input array containing Unicode characters to be converted.
0N/A * @exception MalformedInputException if the input buffer contains any
0N/A * sequence of chars that is illegal in Unicode (principally unpaired
0N/A * surrogates and \uFFFF or \uFFFE). After this exception is thrown,
0N/A * the method nextCharIndex can be called to obtain the index of the
0N/A * first invalid input character and getBadInputLength can be called
0N/A * to determine the length of the invalid input.
0N/A *
0N/A * @see #nextCharIndex
0N/A * @see #setSubstitutionMode
0N/A * @see #setSubstitutionBytes
0N/A * @see #getBadInputLength
0N/A */
0N/A public byte[] convertAll( char input[] ) throws MalformedInputException {
0N/A reset();
0N/A boolean savedSubMode = subMode;
0N/A subMode = true;
0N/A
0N/A byte[] output = new byte[ getMaxBytesPerChar() * input.length ];
0N/A
0N/A try {
0N/A int outputLength = convert( input, 0, input.length,
0N/A output, 0, output.length );
0N/A outputLength += flush( output, nextByteIndex(), output.length );
0N/A
0N/A byte [] returnedOutput = new byte[ outputLength ];
0N/A System.arraycopy( output, 0, returnedOutput, 0, outputLength );
0N/A return returnedOutput;
0N/A }
0N/A catch( ConversionBufferFullException e ) {
0N/A //Not supposed to happen. If it does, getMaxBytesPerChar() lied.
0N/A throw new
0N/A InternalError("this.getMaxBytesPerChar returned bad value");
0N/A }
0N/A catch( UnknownCharacterException e ) {
0N/A // Not supposed to happen since we're in substitution mode.
0N/A throw new InternalError();
0N/A }
0N/A finally {
0N/A subMode = savedSubMode;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Writes any remaining output to the output buffer and resets the
0N/A * converter to its initial state.
0N/A *
0N/A * @param output byte array to receive flushed output.
0N/A * @param outStart start writing to output array at this offset.
0N/A * @param outEnd stop writing to output array at this offset (exclusive).
0N/A * @exception MalformedInputException if the output to be flushed contained
0N/A * a partial or invalid multibyte character sequence. Will occur if the
0N/A * input buffer on the last call to convert ended with the first character
0N/A * of a surrogate pair. flush will write what it can to the output buffer
0N/A * and reset the converter before throwing this exception. An additional
0N/A * call to flush is not required.
0N/A * @exception ConversionBufferFullException if output array is filled
0N/A * before all the output can be flushed. flush will write what it can
0N/A * to the output buffer and remember its state. An additional call to
0N/A * flush with a new output buffer will conclude the operation.
0N/A */
0N/A public abstract int flush( byte[] output, int outStart, int outEnd )
0N/A throws MalformedInputException, ConversionBufferFullException;
0N/A
0N/A /**
0N/A * Writes any remaining output to the output buffer and resets the
0N/A * converter to its initial state. May only be called when substitution
0N/A * mode is turned on, and never complains about malformed input (always
0N/A * substitutes).
0N/A *
0N/A * @param output byte array to receive flushed output.
0N/A * @param outStart start writing to output array at this offset.
0N/A * @param outEnd stop writing to output array at this offset (exclusive).
0N/A * @return number of bytes writter into output.
0N/A * @exception ConversionBufferFullException if output array is filled
0N/A * before all the output can be flushed. flush will write what it can
0N/A * to the output buffer and remember its state. An additional call to
0N/A * flush with a new output buffer will conclude the operation.
0N/A */
0N/A public int flushAny( byte[] output, int outStart, int outEnd )
0N/A throws ConversionBufferFullException
0N/A {
0N/A if (!subMode) { /* Precondition: subMode == true */
0N/A throw new IllegalStateException("Substitution mode is not on");
0N/A }
0N/A try {
0N/A return flush(output, outStart, outEnd);
0N/A } catch (MalformedInputException e) {
0N/A /* Assume that if a malformed input exception has occurred,
0N/A no useful data has been placed in the output buffer.
0N/A i.e. there is no mixture of left over good + some bad data.
0N/A Usually occurs with a trailing high surrogate pair element.
0N/A Special cases occur in Cp970, 949c and 933 that seem
0N/A to be covered, but may require further investigation */
0N/A int subSize = subBytes.length;
0N/A byte[] s = subBytes;
0N/A int outIndex = outStart;
0N/A if ((outStart + subSize) > outEnd)
0N/A throw new ConversionBufferFullException();
0N/A for (int i = 0; i < subSize; i++)
0N/A output[outIndex++] = s[i];
0N/A byteOff = charOff = 0; // Reset the internal state.
0N/A badInputLength = 0;
0N/A return subSize;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Resets converter to its initial state.
0N/A */
0N/A public abstract void reset();
0N/A
0N/A /**
0N/A * Returns true if the given character can be converted to the
0N/A * target character encoding.
0N/A * @return true if given character is translatable, false otherwise.
0N/A * @param c character to test
0N/A */
0N/A public boolean canConvert(char c) {
0N/A try {
0N/A //FIXME output buffer size should use getMaxBytesPerChar value.
0N/A char[] input = new char[1];
0N/A byte[] output = new byte[3];
0N/A input[0] = c;
0N/A convert(input, 0, 1, output, 0, 3);
0N/A return true;
0N/A } catch(CharConversionException e){
0N/A return false;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the maximum number of bytes needed to convert a char. Useful
0N/A * for calculating the maximum output buffer size needed for a particular
0N/A * input buffer.
0N/A */
0N/A public abstract int getMaxBytesPerChar();
0N/A
0N/A /**
0N/A * Returns the length, in chars, of the input which caused a
0N/A * MalformedInputException. Always refers to the last
0N/A * MalformedInputException thrown by the converter. If none have
0N/A * ever been thrown, returns 0.
0N/A */
0N/A public int getBadInputLength() {
0N/A return badInputLength;
0N/A }
0N/A
0N/A /**
0N/A * Returns the index of the character just past
0N/A * the last character successfully converted by the previous call
0N/A * to convert.
0N/A */
0N/A public int nextCharIndex() {
0N/A return charOff;
0N/A }
0N/A
0N/A /**
0N/A * Returns the index of the byte just past the last byte written by
0N/A * the previous call to convert.
0N/A */
0N/A public int nextByteIndex() {
0N/A return byteOff;
0N/A }
0N/A
0N/A /**
0N/A * Sets converter into substitution mode. In substitution mode,
0N/A * the converter will replace untranslatable characters in the source
0N/A * encoding with the substitution character set by setSubstitutionBytes.
0N/A * When not in substitution mode, the converter will throw an
0N/A * UnknownCharacterException when it encounters untranslatable input.
0N/A *
0N/A * @param doSub if true, enable substitution mode.
0N/A * @see #setSubstitutionBytes
0N/A */
0N/A public void setSubstitutionMode(boolean doSub) {
0N/A subMode = doSub;
0N/A }
0N/A
0N/A /**
0N/A * Sets the substitution bytes to use when the converter is in
0N/A * substitution mode. The given bytes should represent a valid
0N/A * character in the target character encoding and must not be
0N/A * longer than the value returned by getMaxBytesPerChar for this
0N/A * converter.
0N/A *
0N/A * @param newSubBytes the substitution bytes
0N/A * @exception IllegalArgumentException if given byte array is longer than
0N/A * the value returned by the method getMaxBytesPerChar.
0N/A * @see #setSubstitutionMode
0N/A * @see #getMaxBytesPerChar
0N/A */
0N/A public void setSubstitutionBytes( byte[] newSubBytes )
0N/A throws IllegalArgumentException
0N/A {
0N/A if( newSubBytes.length > getMaxBytesPerChar() ) {
0N/A throw new IllegalArgumentException();
0N/A }
0N/A
0N/A subBytes = new byte[ newSubBytes.length ];
0N/A System.arraycopy( newSubBytes, 0, subBytes, 0, newSubBytes.length );
0N/A }
0N/A
0N/A /**
0N/A * Returns a string representation of the class.
0N/A */
0N/A public String toString() {
0N/A return "CharToByteConverter: " + getCharacterEncoding();
0N/A }
0N/A}