1 /* 2 * Copyright (c) 2002, 2005, 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 //package sun.nio.cs.ext; 30 31 import java.nio.ByteBuffer; 32 import java.nio.CharBuffer; 33 import java.nio.charset.Charset; 34 import java.nio.charset.CharsetDecoder; 35 import java.nio.charset.CoderResult; 36 37 abstract class DoubleByteDecoder 38 extends CharsetDecoder 39 { 40 41 private short index1[]; 42 43 /* 44 * 2nd level index, provided by subclass 45 * every string has 0x10*(end-start+1) characters. 46 */ 47 private String index2[]; 48 49 protected int start; 50 protected int end; 51 52 protected static final char REPLACE_CHAR = '\uFFFD'; 53 protected char highSurrogate; 54 protected char lowSurrogate; 55 56 protected DoubleByteDecoder(Charset cs, short[] index1, String[] index2, 57 int start, int end ) { 58 super(cs, 0.5f, 1.0f); 59 this.index1 = index1; 60 this.index2 = index2; 61 this.start = start; 62 this.end = end; 63 } 64 65 private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { 66 byte[] sa = src.array(); 67 int sp = src.arrayOffset() + src.position(); 68 int sl = src.arrayOffset() + src.limit(); 69 assert (sp <= sl); 70 sp = (sp <= sl ? sp : sl); 71 char[] da = dst.array(); 72 int dp = dst.arrayOffset() + dst.position(); 73 int dl = dst.arrayOffset() + dst.limit(); 74 assert (dp <= dl); 75 dp = (dp <= dl ? dp : dl); 76 77 try { 78 while (sp < sl) { 79 int b1, b2; 80 b1 = sa[sp]; 81 int inputSize = 1; 82 int outputSize = 1; 83 highSurrogate = lowSurrogate = 0; 84 char c = decodeSingle(b1); 85 if (c == REPLACE_CHAR) { 86 b1 &= 0xff; 87 if (sl - sp < 2) 88 return CoderResult.UNDERFLOW; 89 b2 = sa[sp + 1] & 0xff; 90 c = decodeDouble(b1, b2); 91 inputSize = 2; 92 if (c == REPLACE_CHAR) 93 return CoderResult.unmappableForLength(inputSize); 94 outputSize = (highSurrogate > 0) ? 2: 1; 95 } 96 97 if (dl - dp < outputSize) 98 return CoderResult.OVERFLOW; 99 if (outputSize == 2) { 100 da[dp++] = highSurrogate; 101 da[dp++] = lowSurrogate; 102 } else { 103 da[dp++] = c; 104 } 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 114 private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { 115 int mark = src.position(); 116 int inputSize = 0; 117 int outputSize = 0; 118 try { 119 while (src.hasRemaining()) { 120 int b1 = src.get(); 121 inputSize = 1; 122 outputSize = 1; 123 highSurrogate = lowSurrogate = 0; 124 125 char c = decodeSingle(b1); 126 127 if (c == REPLACE_CHAR) { 128 if (src.remaining() < 1) 129 return CoderResult.UNDERFLOW; 130 b1 &= 0xff; 131 int b2 = src.get() & 0xff; 132 inputSize = 2; 133 134 c = decodeDouble(b1, b2); 135 136 if (c == REPLACE_CHAR) 137 return CoderResult.unmappableForLength(2); 138 139 outputSize = (highSurrogate > 0) ? 2: 1; 140 } 141 if (dst.remaining() < outputSize) 142 return CoderResult.OVERFLOW; 143 mark += inputSize; 144 145 if (outputSize == 2) { 146 dst.put(highSurrogate); 147 dst.put(lowSurrogate); 148 } else { 149 dst.put(c); 150 } 151 } 152 return CoderResult.UNDERFLOW; 153 } finally { 154 src.position(mark); 155 } 156 } 157 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 /* 166 * Can be changed by subclass 167 */ 168 protected char decodeSingle(int b) { 169 if (b >= 0) 170 return (char) b; 171 return REPLACE_CHAR; 172 } 173 174 protected char decodeDouble(int byte1, int byte2) { 175 if (((byte1 < 0) || (byte1 > index1.length)) 176 || ((byte2 < start) || (byte2 > end))) 177 return REPLACE_CHAR; 178 179 int n = (index1[byte1] & 0xf) * (end - start + 1) + (byte2 - start); 180 return index2[index1[byte1] >> 4].charAt(n); 181 } 182 }