codesetconversion.java
来自「java jdk 1.4的源码」· Java 代码 · 共 675 行 · 第 1/2 页
JAVA
675 行
/* * @(#)CodeSetConversion.java 1.16 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.corba.se.internal.core;import java.util.Map;import java.util.HashMap;import java.io.UnsupportedEncodingException;import sun.io.*;import org.omg.CORBA.INTERNAL;import org.omg.CORBA.DATA_CONVERSION;import org.omg.CORBA.CompletionStatus;import com.sun.corba.se.internal.orbutil.MinorCodes;/** * Collection of classes, interfaces, and factory methods for * CORBA code set conversion. * * This is mainly used to shield other code from the sun.io * converters which might change, as well as provide some basic * translation from conversion to CORBA error exceptions. Some * extra work is required here to facilitate the way CORBA * says it uses UTF-16 as of the 00-11-03 spec. */public class CodeSetConversion{ /** * Abstraction for char to byte conversion. * * Must be used in the proper sequence: * * 1) convert * 2) Optional getNumBytes and/or getAlignment (if necessary) * 3) getBytes (see warning) */ public abstract static class CTBConverter { // Perform the conversion of the provided char or String, // allowing the caller to query for more information // before writing. public abstract void convert(char chToConvert); public abstract void convert(String strToConvert); // How many bytes resulted from the conversion? public abstract int getNumBytes(); // What's the maximum number of bytes per character? public abstract int getMaxBytesPerChar(); public abstract boolean isFixedWidthEncoding(); // What byte boundary should the stream align to before // calling writeBytes? For instance, a fixed width // encoding with 2 bytes per char in a stream which // doesn't encapsulate the char's bytes should align // on a 2 byte boundary. (Ex: UTF16 in GIOP1.1) // // Note: This has no effect on the converted bytes. It // is just information available to the caller. public abstract int getAlignment(); // Get the resulting bytes. Warning: You must use getNumBytes() // to determine the end of the data in the byte array instead // of array.length! The array may be used internally, so don't // save references. public abstract byte[] getBytes(); } /** * Abstraction for byte to char conversion. */ public abstract static class BTCConverter { // In GIOP 1.1, interoperability can only be achieved with // fixed width encodings like UTF-16. This is because wstrings // specified how many code points follow rather than specifying // the length in octets. public abstract boolean isFixedWidthEncoding(); public abstract int getFixedCharWidth(); // Called after getChars to determine the true size of the // converted array. public abstract int getNumChars(); // Perform the conversion using length bytes from the given // input stream. Warning: You must use getNumChars() to // determine the correct length of the resulting array. // The same array may be used internally over multiple // calls. public abstract char[] getChars(byte[] bytes, int offset, int length); } /** * Implementation of CTBConverter which uses a sun.io.CharToByteConverter * to do the real work. Handles translation of exceptions to the * appropriate CORBA versions. */ private class JavaCTBConverter extends CTBConverter { // sun.io.CharToByteConverter which actually does the work. We // have to use it directly rather than through String's interface // because we want to know when errors occur during the conversion. // It also allows us to do one less allocation and copy. private CharToByteConverter ctb; // Proper alignment for this type of converter. For instance, // ASCII has alignment of 1 (1 byte per char) but UTF16 has // alignment of 2 (2 bytes per char) private int alignment; // Char buffer to hold the input. Maintained across multiple // conversions to save a memory allocation (maybe a non-issue) // and make single char conversion faster. private char[] chars = null; // How many bytes are generated from the conversion? private int numBytes = 0; // How many characters were converted (temporary variable // for cross method communication) private int numChars = 0; // Byte buffer holding the converted input. This is necessary // since we have to do calculations that require the conversion // before writing the array to the stream. It's reused // across multiple conversions, so don't do another conversion // until you've disposed of your reference! private byte[] buffer; // What code set are we using? private OSFCodeSetRegistry.Entry codeset; public JavaCTBConverter(OSFCodeSetRegistry.Entry codeset, int alignmentForEncoding) { try { ctb = cache.getCharToByteConverter(codeset.getName()); if (ctb == null) { ctb = CharToByteConverter.getConverter(codeset.getName()); cache.setConverter(codeset.getName(), ctb); // When substitution mode is false, the converter // will throw exceptions when it encounters illegal // encodings. ctb.setSubstitutionMode(false); } } catch(UnsupportedEncodingException uee) { // This can only happen if one of our Entries has // an invalid name. throw new INTERNAL("Invalid converter name: " + codeset.getName()); } this.codeset = codeset; alignment = alignmentForEncoding; } public final int getMaxBytesPerChar() { return ctb.getMaxBytesPerChar(); } public void convert(char chToConvert) { if (chars == null) chars = new char[1]; // The CharToByteConverter only takes a char[] chars[0] = chToConvert; numChars = 1; convertCharArray(); } public void convert(String strToConvert) { // Try to save a memory allocation if possible. Usual // space/time trade off. If we could get the char[] out of // the String without copying, that would be great, but // it's forbidden since String is immutable. if (chars == null || chars.length < strToConvert.length()) chars = new char[strToConvert.length()]; numChars = strToConvert.length(); strToConvert.getChars(0, numChars, chars, 0); convertCharArray(); } public final int getNumBytes() { return numBytes; } public final int getAlignment() { return alignment; } public final boolean isFixedWidthEncoding() { return codeset.isFixedWidth(); } public byte[] getBytes() { // Note that you can't use buffer.length since the byte array might // be larger than the actual number of converted bytes depending // on the encoding. // // Warning 2: The byte array is reused across multiple calls to the // converter! return buffer; } private void convertCharArray() { try { // Possible optimization of directly converting into the CDR buffer. // However, that means the CDR code would have to reserve // a 4 byte string length ahead of time, and we'd need a // confusing partial conversion scheme for when we couldn't // fit everything in the buffer but needed to know the // converted length before proceeding due to fragmentation. // Then there's the issue of the chunking code. // // For right now, this is less messy and basic tests don't // show more than a 1 ms penalty worst case. Less than a // factor of 2 increase. if (buffer == null || buffer.length < numChars * ctb.getMaxBytesPerChar()) buffer = new byte[numChars * ctb.getMaxBytesPerChar()]; // Return the converter to its initial state ctb.reset(); // Convert the characters numBytes = ctb.convert(chars, 0, numChars, buffer, 0, buffer.length); // Converters must be flushed to finish up numBytes += ctb.flush(buffer, 0, buffer.length); } catch (MalformedInputException mie) { // There were illegal Unicode char pairs throw new DATA_CONVERSION(mie.getMessage(), MinorCodes.BAD_UNICODE_PAIR, CompletionStatus.COMPLETED_NO); } catch (UnknownCharacterException uce) { // A character doesn't map to the desired code set // CORBA formal 00-11-03. throw new DATA_CONVERSION(uce.getMessage(), MinorCodes.CHAR_NOT_IN_CODESET, CompletionStatus.COMPLETED_NO); } catch (ConversionBufferFullException cbfe) { // If this happens, then the CharToByteConverter was lying // about the maximum bytes per char. throw new INTERNAL(cbfe.getMessage(), MinorCodes.CTB_CONVERTER_FAILURE, CompletionStatus.COMPLETED_NO); } } } /** * Special UTF16 converter which can either always write a BOM * or use a specified byte order without one. */ private class UTF16CTBConverter extends JavaCTBConverter { // Using this constructor, we will always write a BOM public UTF16CTBConverter() { super(OSFCodeSetRegistry.UTF_16, 2); } // Using this constructor, we don't use a BOM and use the // byte order specified public UTF16CTBConverter(boolean littleEndian) { super(littleEndian ? OSFCodeSetRegistry.UTF_16LE : OSFCodeSetRegistry.UTF_16BE, 2); } } /** * Implementation of BTCConverter which uses a sun.io.ByteToCharConverter * for the real work. Handles translation of exceptions to the * appropriate CORBA versions. */ private class JavaBTCConverter extends BTCConverter { protected ByteToCharConverter btc; private char[] buffer; private int resultingNumChars; private OSFCodeSetRegistry.Entry codeset; public JavaBTCConverter(OSFCodeSetRegistry.Entry codeset) { // Obtain a ByteToCharConverter btc = getConverter(codeset.getName()); this.codeset = codeset; } public final boolean isFixedWidthEncoding() { return codeset.isFixedWidth(); } // Should only be called if isFixedWidthEncoding is true public final int getFixedCharWidth() { return codeset.getMaxBytesPerChar(); } public final int getNumChars() { return resultingNumChars; } public char[] getChars(byte[] bytes, int offset, int numBytes) { // Possible optimization of reading directly from the CDR // byte buffer. The sun.io converter supposedly can handle // incremental conversions in which a char is broken across // two convert calls. // // Basic tests didn't show more than a 1 ms increase // worst case. It's less than a factor of 2 increase. // Also makes the interface more difficult. if (buffer == null || buffer.length < numBytes * btc.getMaxCharsPerByte()) buffer = new char[numBytes * btc.getMaxCharsPerByte()]; try { btc.reset(); // WARNING: The signature for convert is // bytes[], offset, endPosition // not // bytes[], offset, total length resultingNumChars = btc.convert(bytes, offset, offset + numBytes, buffer, 0, buffer.length); resultingNumChars += btc.flush(buffer, 0, buffer.length);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?