1 /* 2 * Copyright (c) 2003, 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 /* 27 */ 28 29 30 import java.nio.ByteBuffer; 31 import java.nio.CharBuffer; 32 import java.nio.charset.Charset; 33 import java.nio.charset.CharsetDecoder; 34 import java.nio.charset.CoderResult; 35 36 /** 37 * An abstract base class for subclasses which decode 38 * IBM double byte host encodings such as ibm code 39 * pages 942,943,948, etc. 40 * 41 */ 42 43 abstract class DBCS_IBM_ASCII_Decoder extends CharsetDecoder 44 { 45 protected static final char REPLACE_CHAR='\uFFFD'; 46 47 protected String singleByteToChar; 48 protected boolean leadByte[]; 49 protected short index1[]; 50 protected String index2; 51 protected int mask1; 52 protected int mask2; 53 protected int shift; 54 55 DBCS_IBM_ASCII_Decoder(Charset cs)56 protected DBCS_IBM_ASCII_Decoder(Charset cs) { 57 super(cs, 0.5f, 1.0f); 58 } 59 decodeArrayLoop(ByteBuffer src, CharBuffer dst)60 private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { 61 byte[] sa = src.array(); 62 int sp = src.arrayOffset() + src.position(); 63 int sl = src.arrayOffset() + src.limit(); 64 assert (sp <= sl); 65 sp = (sp <= sl ? sp : sl); 66 char[] da = dst.array(); 67 int dp = dst.arrayOffset() + dst.position(); 68 int dl = dst.arrayOffset() + dst.limit(); 69 assert (dp <= dl); 70 dp = (dp <= dl ? dp : dl); 71 72 try { 73 while (sp < sl) { 74 int b1, b2; 75 b1 = sa[sp]; 76 int inputSize = 1; 77 int v = 0; 78 char outputChar = REPLACE_CHAR; 79 if (b1 < 0) 80 b1 += 256; 81 82 if (!leadByte[b1]) 83 { 84 outputChar = singleByteToChar.charAt(b1); 85 } else { 86 if (sl - sp < 2) 87 return CoderResult.UNDERFLOW; 88 b2 = sa[sp + 1]; 89 if (b2 < 0) 90 b2 += 256; 91 92 inputSize++; 93 94 // Lookup in the two level index 95 v = b1 * 256 + b2; 96 outputChar = index2.charAt(index1[((v & mask1) >> shift)] 97 + (v & mask2)); 98 } 99 if (outputChar == '\uFFFD') 100 return CoderResult.unmappableForLength(inputSize); 101 102 if (dl - dp < 1) 103 return CoderResult.OVERFLOW; 104 da[dp++] = outputChar; 105 sp += inputSize; 106 } 107 return CoderResult.UNDERFLOW; 108 } finally { 109 src.position(sp - src.arrayOffset()); 110 dst.position(dp - dst.arrayOffset()); 111 } 112 } 113 decodeBufferLoop(ByteBuffer src, CharBuffer dst)114 private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { 115 int mark = src.position(); 116 117 118 try { 119 while (src.hasRemaining()) { 120 char outputChar = REPLACE_CHAR; 121 int inputSize = 1; 122 int b1, b2; 123 int v = 0; 124 b1 = src.get(); 125 if (b1 < 0) 126 b1 += 256; 127 128 if (!leadByte[b1]) 129 { 130 outputChar = singleByteToChar.charAt(b1); 131 } else { 132 if (src.remaining() < 1) 133 return CoderResult.UNDERFLOW; 134 b2 = src.get(); 135 if (b2 < 0) 136 b2 += 256; 137 inputSize++; 138 139 // Lookup in the two level index 140 v = b1 * 256 + b2; 141 outputChar = index2.charAt(index1[((v & mask1) >> shift)] 142 + (v & mask2)); 143 } 144 if (outputChar == REPLACE_CHAR) 145 return CoderResult.unmappableForLength(inputSize); 146 147 if (!dst.hasRemaining()) 148 return CoderResult.OVERFLOW; 149 mark += inputSize; 150 dst.put(outputChar); 151 } 152 return CoderResult.UNDERFLOW; 153 } finally { 154 src.position(mark); 155 } 156 } 157 decodeLoop(ByteBuffer src, CharBuffer dst)158 protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { 159 if (src.hasArray() && dst.hasArray()) 160 return decodeArrayLoop(src, dst); 161 else 162 return decodeBufferLoop(src, dst); 163 } 164 } 165