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