1 /* 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 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 /** 38 * An abstract base class for subclasses which encodes 39 * IBM double byte host encodings such as ibm code 40 * pages 942,943,948, etc. 41 * 42 */ 43 44 abstract class DBCS_IBM_ASCII_Encoder extends CharsetEncoder 45 { 46 47 protected static final char REPLACE_CHAR='\uFFFD'; 48 private byte b1; 49 private byte b2; 50 51 52 protected short index1[]; 53 protected String index2; 54 protected String index2a; 55 protected int mask1; 56 protected int mask2; 57 protected int shift; 58 59 private final Surrogate.Parser sgp = new Surrogate.Parser(); 60 61 protected DBCS_IBM_ASCII_Encoder(Charset cs) { 62 super(cs, 2.0f, 2.0f); 63 } 64 65 /** 66 * Returns true if the given character can be converted to the 67 * target character encoding. 68 */ 69 public boolean canEncode(char ch) { 70 int index; 71 int theBytes; 72 73 index = index1[((ch & mask1) >> shift)] + (ch & mask2); 74 if (index < 15000) 75 theBytes = (int)(index2.charAt(index)); 76 else 77 theBytes = (int)(index2a.charAt(index-15000)); 78 79 if (theBytes != 0) 80 return (true); 81 82 // only return true if input char was unicode null - all others are 83 // undefined 84 return( ch == '\u0000'); 85 86 } 87 88 private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { 89 char[] sa = src.array(); 90 int sp = src.arrayOffset() + src.position(); 91 int sl = src.arrayOffset() + src.limit(); 92 byte[] da = dst.array(); 93 int dp = dst.arrayOffset() + dst.position(); 94 int dl = dst.arrayOffset() + dst.limit(); 95 int outputSize = 0; // size of output 96 97 try { 98 while (sp < sl) { 99 int index; 100 int theBytes; 101 char c = sa[sp]; 102 if (Surrogate.is(c)) { 103 if (sgp.parse(c, sa, sp, sl) < 0) 104 return sgp.error(); 105 return sgp.unmappableResult(); 106 } 107 if (c >= '\uFFFE') 108 return CoderResult.unmappableForLength(1); 109 110 index = index1[((c & mask1) >> shift)] 111 + (c & mask2); 112 if (index < 15000) 113 theBytes = (int)(index2.charAt(index)); 114 else 115 theBytes = (int)(index2a.charAt(index-15000)); 116 b1 = (byte)((theBytes & 0x0000ff00)>>8); 117 b2 = (byte)(theBytes & 0x000000ff); 118 119 if (b1 == 0x00 && b2 == 0x00 120 && c != '\u0000') { 121 return CoderResult.unmappableForLength(1); 122 } 123 124 if (b1 == 0) { 125 if (dl - dp < 1) 126 return CoderResult.OVERFLOW; 127 da[dp++] = (byte) b2; 128 } else { 129 if (dl - dp < 2) 130 return CoderResult.OVERFLOW; 131 da[dp++] = (byte) b1; 132 da[dp++] = (byte) b2; 133 } 134 sp++; 135 } 136 return CoderResult.UNDERFLOW; 137 } finally { 138 src.position(sp - src.arrayOffset()); 139 dst.position(dp - dst.arrayOffset()); 140 } 141 } 142 143 private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { 144 int mark = src.position(); 145 int outputSize = 0; // size of output 146 147 try { 148 while (src.hasRemaining()) { 149 int index; 150 int theBytes; 151 char c = src.get(); 152 if (Surrogate.is(c)) { 153 if (sgp.parse(c, src) < 0) 154 return sgp.error(); 155 return sgp.unmappableResult(); 156 } 157 if (c >= '\uFFFE') 158 return CoderResult.unmappableForLength(1); 159 160 index = index1[((c & mask1) >> shift)] 161 + (c & mask2); 162 if (index < 15000) 163 theBytes = (int)(index2.charAt(index)); 164 else 165 theBytes = (int)(index2a.charAt(index-15000)); 166 b1 = (byte)((theBytes & 0x0000ff00)>>8); 167 b2 = (byte)(theBytes & 0x000000ff); 168 169 if (b1 == 0x00 && b2 == 0x00 170 && c != '\u0000') { 171 return CoderResult.unmappableForLength(1); 172 } 173 174 if (b1 == 0) { 175 if (dst.remaining() < 1) 176 return CoderResult.OVERFLOW; 177 dst.put((byte) b2); 178 } else { 179 if (dst.remaining() < 2) 180 return CoderResult.OVERFLOW; 181 dst.put((byte) b1); 182 dst.put((byte) b2); 183 } 184 mark++; 185 } 186 return CoderResult.UNDERFLOW; 187 } finally { 188 src.position(mark); 189 } 190 } 191 192 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { 193 if (true && src.hasArray() && dst.hasArray()) 194 return encodeArrayLoop(src, dst); 195 else 196 return encodeBufferLoop(src, dst); 197 } 198 199 }