blob: ae63720919a0b33da9a37a30eb3175704b4ac6bc [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/*
27 */
28
29package sun.nio.cs.ext;
30
31import java.nio.ByteBuffer;
32import java.nio.CharBuffer;
33import java.nio.charset.Charset;
34import java.nio.charset.CharsetDecoder;
35import java.nio.charset.CoderResult;
36
37abstract 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}