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 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 (Character.isSurrogate(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 (Character.isSurrogate(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} 277