blob: 308087376c90312580307726b64d8adcadb24cbd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-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
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.CharsetEncoder;
35import java.nio.charset.CoderResult;
36import sun.nio.cs.Surrogate;
37
38
39public abstract class SimpleEUCEncoder
40 extends CharsetEncoder
41{
42
43 protected short index1[];
44 protected String index2;
45 protected String index2a;
46 protected String index2b;
47 protected String index2c;
48 protected int mask1;
49 protected int mask2;
50 protected int shift;
51
52 private byte[] outputByte = new byte[4];
53 private final Surrogate.Parser sgp = new Surrogate.Parser();
54
55 protected SimpleEUCEncoder(Charset cs)
56 {
57 super(cs, 3.0f, 4.0f);
58 }
59
60 /**
61 * Returns true if the given character can be converted to the
62 * target character encoding.
63 */
64
65 public boolean canEncode(char ch) {
66 int index;
67 String theChars;
68
69 index = index1[((ch & mask1) >> shift)] + (ch & mask2);
70
71 if (index < 7500)
72 theChars = index2;
73 else
74 if (index < 15000) {
75 index = index - 7500;
76 theChars = index2a;
77 }
78 else
79 if (index < 22500){
80 index = index - 15000;
81 theChars = index2b;
82 }
83 else {
84 index = index - 22500;
85 theChars = index2c;
86 }
87
88 if (theChars.charAt(2*index) != '\u0000' ||
89 theChars.charAt(2*index + 1) != '\u0000')
90 return (true);
91
92 // only return true if input char was unicode null - all others are
93 // undefined
94 return( ch == '\u0000');
95
96 }
97 private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
98 char[] sa = src.array();
99 int sp = src.arrayOffset() + src.position();
100 int sl = src.arrayOffset() + src.limit();
101 assert (sp <= sl);
102 sp = (sp <= sl ? sp : sl);
103 byte[] da = dst.array();
104 int dp = dst.arrayOffset() + dst.position();
105 int dl = dst.arrayOffset() + dst.limit();
106 assert (dp <= dl);
107 dp = (dp <= dl ? dp : dl);
108
109 int index;
110 int spaceNeeded;
111 int i;
112
113 try {
114 while (sp < sl) {
115 boolean allZeroes = true;
116 char inputChar = sa[sp];
117 if (Surrogate.is(inputChar)) {
118 if (sgp.parse(inputChar, sa, sp, sl) < 0)
119 return sgp.error();
120 return sgp.unmappableResult();
121 }
122
123 if (inputChar >= '\uFFFE')
124 return CoderResult.unmappableForLength(1);
125
126 String theChars;
127 char aChar;
128
129 // We have a valid character, get the bytes for it
130 index = index1[((inputChar & mask1) >> shift)] + (inputChar & mask2);
131
132 if (index < 7500)
133 theChars = index2;
134 else if (index < 15000) {
135 index = index - 7500;
136 theChars = index2a;
137 } else if (index < 22500){
138 index = index - 15000;
139 theChars = index2b;
140 }
141 else {
142 index = index - 22500;
143 theChars = index2c;
144 }
145
146 aChar = theChars.charAt(2*index);
147 outputByte[0] = (byte)((aChar & 0xff00)>>8);
148 outputByte[1] = (byte)(aChar & 0x00ff);
149 aChar = theChars.charAt(2*index + 1);
150 outputByte[2] = (byte)((aChar & 0xff00)>>8);
151 outputByte[3] = (byte)(aChar & 0x00ff);
152
153 for (i = 0; i < outputByte.length; i++) {
154 if (outputByte[i] != 0x00) {
155 allZeroes = false;
156 break;
157 }
158 }
159
160 if (allZeroes && inputChar != '\u0000') {
161 return CoderResult.unmappableForLength(1);
162 }
163
164 int oindex = 0;
165
166 for (spaceNeeded = outputByte.length;
167 spaceNeeded > 1; spaceNeeded--){
168 if (outputByte[oindex++] != 0x00 )
169 break;
170 }
171
172 if (dp + spaceNeeded > dl)
173 return CoderResult.OVERFLOW;
174
175 for (i = outputByte.length - spaceNeeded;
176 i < outputByte.length; i++) {
177 da[dp++] = outputByte[i];
178 }
179 sp++;
180 }
181 return CoderResult.UNDERFLOW;
182 } finally {
183 src.position(sp - src.arrayOffset());
184 dst.position(dp - dst.arrayOffset());
185 }
186 }
187
188 private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
189 int index;
190 int spaceNeeded;
191 int i;
192 int mark = src.position();
193 try {
194 while (src.hasRemaining()) {
195 char inputChar = src.get();
196 boolean allZeroes = true;
197 if (Surrogate.is(inputChar)) {
198 if (sgp.parse(inputChar, src) < 0)
199 return sgp.error();
200 return sgp.unmappableResult();
201 }
202
203 if (inputChar >= '\uFFFE')
204 return CoderResult.unmappableForLength(1);
205
206 String theChars;
207 char aChar;
208
209 // We have a valid character, get the bytes for it
210 index = index1[((inputChar & mask1) >> shift)] + (inputChar & mask2);
211
212 if (index < 7500)
213 theChars = index2;
214 else if (index < 15000) {
215 index = index - 7500;
216 theChars = index2a;
217 } else if (index < 22500){
218 index = index - 15000;
219 theChars = index2b;
220 }
221 else {
222 index = index - 22500;
223 theChars = index2c;
224 }
225
226 aChar = theChars.charAt(2*index);
227 outputByte[0] = (byte)((aChar & 0xff00)>>8);
228 outputByte[1] = (byte)(aChar & 0x00ff);
229 aChar = theChars.charAt(2*index + 1);
230 outputByte[2] = (byte)((aChar & 0xff00)>>8);
231 outputByte[3] = (byte)(aChar & 0x00ff);
232
233 for (i = 0; i < outputByte.length; i++) {
234 if (outputByte[i] != 0x00) {
235 allZeroes = false;
236 break;
237 }
238 }
239 if (allZeroes && inputChar != '\u0000') {
240 return CoderResult.unmappableForLength(1);
241 }
242
243 int oindex = 0;
244
245 for (spaceNeeded = outputByte.length;
246 spaceNeeded > 1; spaceNeeded--){
247 if (outputByte[oindex++] != 0x00 )
248 break;
249 }
250 if (dst.remaining() < spaceNeeded)
251 return CoderResult.OVERFLOW;
252
253 for (i = outputByte.length - spaceNeeded;
254 i < outputByte.length; i++) {
255 dst.put(outputByte[i]);
256 }
257 mark++;
258 }
259 return CoderResult.UNDERFLOW;
260 } finally {
261 src.position(mark);
262 }
263 }
264
265 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
266 if (true && src.hasArray() && dst.hasArray())
267 return encodeArrayLoop(src, dst);
268 else
269 return encodeBufferLoop(src, dst);
270 }
271
272 public byte encode(char inputChar) {
273 return (byte)index2.charAt(index1[(inputChar & mask1) >> shift] +
274 (inputChar & mask2));
275 }
276}