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