blob: 5f43383cfcb6f9c7107aec60ca4ff9148fe5fa8a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2006 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
26package sun.nio.cs.ext;
27
28import java.nio.ByteBuffer;
29import java.nio.CharBuffer;
30import java.nio.charset.Charset;
31import java.nio.charset.CharsetDecoder;
32import java.nio.charset.CoderResult;
33
34/**
35 * An abstract base class for subclasses which decode
36 * IBM double byte only ebcdic host encodings such as ibm
37 * code pages 834 835 837 300,... etc
38 *
39 * The structure of IBM DBCS-only charsets is defined by the
40 * IBM Character Data Representation Architecture (CDRA) document
41 *
42 * http://www-306.ibm.com/software/globalization/cdra/appendix_a.jsp#HDRHEBDBST
43 *
44 */
45
46public abstract class DBCS_ONLY_IBM_EBCDIC_Decoder extends CharsetDecoder
47{
48 protected static final char REPLACE_CHAR='\uFFFD';
49
50 protected short index1[];
51 protected String index2;
52 protected int mask1;
53 protected int mask2;
54 protected int shift;
55
56 protected DBCS_ONLY_IBM_EBCDIC_Decoder(Charset cs) {
57 super(cs, 0.5f, 1.0f);
58 }
59
60 // Check validity of dbcs ebcdic byte pair values
61 private static boolean isValidDoubleByte(int b1, int b2) {
62 return (b1 == 0x40 && b2 == 0x40) // DBCS-HOST SPACE
63 || (0x41 <= b1 && b1 <= 0xfe &&
64 0x41 <= b2 && b2 <= 0xfe);
65 }
66
67 private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
68 byte[] sa = src.array();
69 int sp = src.arrayOffset() + src.position();
70 int sl = src.arrayOffset() + src.limit();
71 assert (sp <= sl);
72 sp = (sp <= sl ? sp : sl);
73 char[] da = dst.array();
74 int dp = dst.arrayOffset() + dst.position();
75 int dl = dst.arrayOffset() + dst.limit();
76 assert (dp <= dl);
77 dp = (dp <= dl ? dp : dl);
78
79 try {
80 while (sp + 1 < sl) {
81 int b1 = sa[sp] & 0xff;
82 int b2 = sa[sp + 1] & 0xff;
83
84 if (!isValidDoubleByte(b1, b2)) {
85 return CoderResult.malformedForLength(2);
86 }
87 // Lookup in the two level index
88 int v = b1 * 256 + b2;
89 char outputChar = index2.charAt(index1[((v & mask1) >> shift)]
90 + (v & mask2));
91 if (outputChar == REPLACE_CHAR)
92 return CoderResult.unmappableForLength(2);
93 if (dl - dp < 1)
94 return CoderResult.OVERFLOW;
95 da[dp++] = outputChar;
96 sp += 2;
97 }
98 return CoderResult.UNDERFLOW;
99 } finally {
100 src.position(sp - src.arrayOffset());
101 dst.position(dp - dst.arrayOffset());
102 }
103 }
104
105 private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
106 int mark = src.position();
107 try {
108 while (src.remaining() > 1) {
109 int b1 = src.get() & 0xff;
110 int b2 = src.get() & 0xff;
111
112 if (!isValidDoubleByte(b1, b2)) {
113 return CoderResult.malformedForLength(2);
114 }
115 // Lookup in the two level index
116 int v = b1 * 256 + b2;
117 char outputChar = index2.charAt(index1[((v & mask1) >> shift)]
118 + (v & mask2));
119 if (outputChar == REPLACE_CHAR)
120 return CoderResult.unmappableForLength(2);
121
122 if (!dst.hasRemaining())
123 return CoderResult.OVERFLOW;
124 dst.put(outputChar);
125 mark += 2;
126 }
127 return CoderResult.UNDERFLOW;
128 } finally {
129 src.position(mark);
130 }
131 }
132
133 protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
134 if (src.hasArray() && dst.hasArray())
135 return decodeArrayLoop(src, dst);
136 else
137 return decodeBufferLoop(src, dst);
138 }
139}