1/* 2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27import java.nio.ByteBuffer; 28import java.nio.CharBuffer; 29import java.nio.charset.Charset; 30import java.nio.charset.CharsetDecoder; 31import java.nio.charset.CoderResult; 32 33/** 34 * An abstract base class for subclasses which decode 35 * IBM double byte only ebcdic host encodings such as ibm 36 * code pages 834 835 837 300,... etc 37 * 38 * The structure of IBM DBCS-only charsets is defined by the 39 * IBM Character Data Representation Architecture (CDRA) document 40 * 41 * http://www-306.ibm.com/software/globalization/cdra/appendix_a.jsp#HDRHEBDBST 42 * 43 */ 44 45public abstract class DBCS_ONLY_IBM_EBCDIC_Decoder extends CharsetDecoder 46{ 47 protected static final char REPLACE_CHAR='\uFFFD'; 48 49 protected short index1[]; 50 protected String index2; 51 protected int mask1; 52 protected int mask2; 53 protected int shift; 54 55 protected DBCS_ONLY_IBM_EBCDIC_Decoder(Charset cs) { 56 super(cs, 0.5f, 1.0f); 57 } 58 59 // Check validity of dbcs ebcdic byte pair values 60 private static boolean isValidDoubleByte(int b1, int b2) { 61 return (b1 == 0x40 && b2 == 0x40) // DBCS-HOST SPACE 62 || (0x41 <= b1 && b1 <= 0xfe && 63 0x41 <= b2 && b2 <= 0xfe); 64 } 65 66 private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { 67 byte[] sa = src.array(); 68 int sp = src.arrayOffset() + src.position(); 69 int sl = src.arrayOffset() + src.limit(); 70 assert (sp <= sl); 71 sp = (sp <= sl ? sp : sl); 72 char[] da = dst.array(); 73 int dp = dst.arrayOffset() + dst.position(); 74 int dl = dst.arrayOffset() + dst.limit(); 75 assert (dp <= dl); 76 dp = (dp <= dl ? dp : dl); 77 78 try { 79 while (sp + 1 < sl) { 80 int b1 = sa[sp] & 0xff; 81 int b2 = sa[sp + 1] & 0xff; 82 83 if (!isValidDoubleByte(b1, b2)) { 84 return CoderResult.malformedForLength(2); 85 } 86 // Lookup in the two level index 87 int v = b1 * 256 + b2; 88 char outputChar = index2.charAt(index1[((v & mask1) >> shift)] 89 + (v & mask2)); 90 if (outputChar == REPLACE_CHAR) 91 return CoderResult.unmappableForLength(2); 92 if (dl - dp < 1) 93 return CoderResult.OVERFLOW; 94 da[dp++] = outputChar; 95 sp += 2; 96 } 97 return CoderResult.UNDERFLOW; 98 } finally { 99 src.position(sp - src.arrayOffset()); 100 dst.position(dp - dst.arrayOffset()); 101 } 102 } 103 104 private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { 105 int mark = src.position(); 106 try { 107 while (src.remaining() > 1) { 108 int b1 = src.get() & 0xff; 109 int b2 = src.get() & 0xff; 110 111 if (!isValidDoubleByte(b1, b2)) { 112 return CoderResult.malformedForLength(2); 113 } 114 // Lookup in the two level index 115 int v = b1 * 256 + b2; 116 char outputChar = index2.charAt(index1[((v & mask1) >> shift)] 117 + (v & mask2)); 118 if (outputChar == REPLACE_CHAR) 119 return CoderResult.unmappableForLength(2); 120 121 if (!dst.hasRemaining()) 122 return CoderResult.OVERFLOW; 123 dst.put(outputChar); 124 mark += 2; 125 } 126 return CoderResult.UNDERFLOW; 127 } finally { 128 src.position(mark); 129 } 130 } 131 132 protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { 133 if (src.hasArray() && dst.hasArray()) 134 return decodeArrayLoop(src, dst); 135 else 136 return decodeBufferLoop(src, dst); 137 } 138} 139