1 /*
2 * Copyright (c) 2002, 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 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.CharsetEncoder;
35 import java.nio.charset.CoderResult;
36 import sun.nio.cs.Surrogate;
37
38 public abstract class DoubleByteEncoder
39 extends CharsetEncoder
40 {
41
42 private short index1[];
43 private String index2[];
44
45 private final Surrogate.Parser sgp = new Surrogate.Parser();
46
47 protected DoubleByteEncoder(Charset cs,
48 short[] index1, String[] index2)
49 {
50 super(cs, 2.0f, 2.0f);
51 this.index1 = index1;
52 this.index2 = index2;
53 }
54
55 protected DoubleByteEncoder(Charset cs,
56 short[] index1, String[] index2,
57 float avg, float max)
58 {
59 super(cs, avg, max);
60 this.index1 = index1;
61 this.index2 = index2;
62 }
63
64 protected DoubleByteEncoder(Charset cs,
65 short[] index1, String[] index2, byte[] repl)
66 {
67 super(cs, 2.0f, 2.0f, repl);
68 this.index1 = index1;
69 this.index2 = index2;
70 }
71
72
73 protected DoubleByteEncoder(Charset cs,
74 short[] index1, String[] index2,
75 byte[] repl, float avg, float max)
76 {
77 super(cs, avg, max,repl);
78 this.index1 = index1;
79 this.index2 = index2;
80 }
81
82 public boolean canEncode(char c) {
83 return (encodeSingle(c) != -1 ||
84 encodeDouble(c) != 0);
85 }
86
87 private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
88 char[] sa = src.array();
89 int sp = src.arrayOffset() + src.position();
90 int sl = src.arrayOffset() + src.limit();
91 byte[] da = dst.array();
92 int dp = dst.arrayOffset() + dst.position();
93 int dl = dst.arrayOffset() + dst.limit();
94
95 try {
96 while (sp < sl) {
97 char c = sa[sp];
98 if (Character.isSurrogate(c)) {
99 if (sgp.parse(c, sa, sp, sl) < 0)
100 return sgp.error();
101 if (sl - sp < 2)
102 return CoderResult.UNDERFLOW;
103 char c2 = sa[sp + 1];
104
105 byte[] outputBytes = new byte[2];
106 outputBytes = encodeSurrogate(c, c2);
107
108 if (outputBytes == null) {
109 return sgp.unmappableResult();
110 }
111 else {
112 if (dl - dp < 2)
113 return CoderResult.OVERFLOW;
114 da[dp++] = outputBytes[0];
115 da[dp++] = outputBytes[1];
116 sp += 2;
117 continue;
118 }
119 }
120 if (c >= '\uFFFE')
121 return CoderResult.unmappableForLength(1);
122
123 int b = encodeSingle(c);
124 if (b != -1) { // Single Byte
125 if (dl - dp < 1)
126 return CoderResult.OVERFLOW;
127 da[dp++] = (byte)b;
128 sp++;
129 continue;
130 }
131
132 int ncode = encodeDouble(c);
133 if (ncode != 0 && c != '\u0000' ) {
134 if (dl - dp < 2)
135 return CoderResult.OVERFLOW;
136 da[dp++] = (byte) ((ncode & 0xff00) >> 8);
137 da[dp++] = (byte) (ncode & 0xff);
138 sp++;
139 continue;
140 }
141 return CoderResult.unmappableForLength(1);
142 }
143 return CoderResult.UNDERFLOW;
144 } finally {
145 src.position(sp - src.arrayOffset());
146 dst.position(dp - dst.arrayOffset());
147 }
148 }
149
150 private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
151 int mark = src.position();
152
153 try {
154 while (src.hasRemaining()) {
155 char c = src.get();
156 if (Character.isSurrogate(c)) {
157 int surr;
158 if ((surr = sgp.parse(c, src)) < 0)
159 return sgp.error();
160 char c2 = Surrogate.low(surr);
161 byte[] outputBytes = new byte[2];
162 outputBytes = encodeSurrogate(c, c2);
163
164 if (outputBytes == null) {
165 return sgp.unmappableResult();
166 } else {
167 if (dst.remaining() < 2)
168 return CoderResult.OVERFLOW;
169 mark += 2;
170 dst.put(outputBytes[0]);
171 dst.put(outputBytes[1]);
172 continue;
173 }
174 }
175 if (c >= '\uFFFE')
176 return CoderResult.unmappableForLength(1);
177 int b = encodeSingle(c);
178
179 if (b != -1) { // Single-byte character
180 if (dst.remaining() < 1)
181 return CoderResult.OVERFLOW;
182 mark++;
183 dst.put((byte)b);
184 continue;
185 }
186 // Double Byte character
187
188 int ncode = encodeDouble(c);
189 if (ncode != 0 && c != '\u0000') {
190 if (dst.remaining() < 2)
191 return CoderResult.OVERFLOW;
192 mark++;
193 dst.put((byte) ((ncode & 0xff00) >> 8));
194 dst.put((byte) ncode);
195 continue;
196 }
197 return CoderResult.unmappableForLength(1);
198 }
199
200 return CoderResult.UNDERFLOW;
201 } finally {
202 src.position(mark);
203 }
204 }
205
206 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
207 if (true && src.hasArray() && dst.hasArray())
208 return encodeArrayLoop(src, dst);
209 else
210 return encodeBufferLoop(src, dst);
211 }
212
213 /*
214 * Can be changed by subclass
215 */
216 protected int encodeDouble(char ch) {
217 int offset = index1[((ch & 0xff00) >> 8 )] << 8;
218 return index2[offset >> 12].charAt((offset & 0xfff) + (ch & 0xff));
219 }
220
221 /*
222 * Can be changed by subclass
223 */
224 protected int encodeSingle(char inputChar) {
225 if (inputChar < 0x80)
226 return (byte)inputChar;
227 else
228 return -1;
229 }
230
231 /**
232 * Protected method which should be overridden by concrete DBCS
233 * CharsetEncoder classes which included supplementary characters
234 * within their mapping coverage.
235 * null return value indicates surrogate values could not be
236 * handled or encoded.
237 */
238 protected byte[] encodeSurrogate(char highSurrogate, char lowSurrogate) {
239 return null;
240 }
241 }
--- EOF ---