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 public abstract class DBCS_IBM_EBCDIC_Encoder extends CharsetEncoder 45 { 46 47 protected static final char REPLACE_CHAR='\uFFFD'; 48 private byte b1; 49 private byte b2; 50 51 protected short index1[]; 52 protected String index2; 53 protected String index2a; 54 protected int mask1; 55 protected int mask2; 56 protected int shift; 57 58 private static final int SBCS = 0; 59 private static final int DBCS = 1; 60 61 private static final byte SO = 0x0e; 62 private static final byte SI = 0x0f; 63 64 private int currentState; 65 66 private final Surrogate.Parser sgp = new Surrogate.Parser(); 67 68 protected DBCS_IBM_EBCDIC_Encoder(Charset cs) { 69 super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}); 70 } 71 72 protected void implReset() { 73 currentState = SBCS; 74 } 75 76 protected CoderResult implFlush(ByteBuffer out) { 77 if (currentState == DBCS) { 78 if (out.remaining() < 1) 79 return CoderResult.OVERFLOW; 80 out.put(SI); 81 } 82 implReset(); 83 return CoderResult.UNDERFLOW; 84 } 85 86 /** 87 * Returns true if the given character can be converted to the 88 * target character encoding. 89 */ 90 public boolean canEncode(char ch) { 91 int index; 92 int theBytes; 93 94 index = index1[((ch & mask1) >> shift)] + (ch & mask2); 95 if (index < 15000) 96 theBytes = (int)(index2.charAt(index)); 97 else 98 theBytes = (int)(index2a.charAt(index-15000)); 99 100 if (theBytes != 0) 101 return (true); 102 103 // only return true if input char was unicode null - all others are 104 // undefined 105 return( ch == '\u0000'); 106 107 } 108 109 private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { 110 char[] sa = src.array(); 111 int sp = src.arrayOffset() + src.position(); 112 int sl = src.arrayOffset() + src.limit(); 113 byte[] da = dst.array(); 114 int dp = dst.arrayOffset() + dst.position(); 115 int dl = dst.arrayOffset() + dst.limit(); 116 int outputSize = 0; // size of output 117 int spaceNeeded; 118 119 try { 120 while (sp < sl) { 121 int index; 122 int theBytes; 123 char c = sa[sp]; 124 if (Surrogate.is(c)) { 125 if (sgp.parse(c, sa, sp, sl) < 0) 126 return sgp.error(); 127 return sgp.unmappableResult(); 128 } 129 if (c >= '\uFFFE') 130 return CoderResult.unmappableForLength(1); 131 132 133 index = index1[((c & mask1) >> shift)] 134 + (c & mask2); 135 if (index < 15000) 136 theBytes = (int)(index2.charAt(index)); 137 else 138 theBytes = (int)(index2a.charAt(index-15000)); 139 b1= (byte)((theBytes & 0x0000ff00)>>8); 140 b2 = (byte)(theBytes & 0x000000ff); 141 142 if (b1 == 0x00 && b2 == 0x00 143 && c != '\u0000') { 144 return CoderResult.unmappableForLength(1); 145 } 146 147 if (currentState == DBCS && b1 == 0x00) { 148 if (dl - dp < 1) 149 return CoderResult.OVERFLOW; 150 currentState = SBCS; 151 da[dp++] = SI; 152 } else if (currentState == SBCS && b1 != 0x00) { 153 if (dl - dp < 1) 154 return CoderResult.OVERFLOW; 155 currentState = DBCS; 156 da[dp++] = SO; 157 } 158 if (currentState == DBCS) 159 spaceNeeded = 2; 160 else 161 spaceNeeded = 1; 162 if (dl - dp < spaceNeeded) 163 return CoderResult.OVERFLOW; 164 165 if (currentState == SBCS) 166 da[dp++] = b2; 167 else { 168 da[dp++] = b1; 169 da[dp++] = b2; 170 } 171 sp++; 172 } 173 return CoderResult.UNDERFLOW; 174 } finally { 175 src.position(sp - src.arrayOffset()); 176 dst.position(dp - dst.arrayOffset()); 177 } 178 } 179 180 private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { 181 int mark = src.position(); 182 int outputSize = 0; // size of output 183 int spaceNeeded; 184 185 try { 186 while (src.hasRemaining()) { 187 int index; 188 int theBytes; 189 char c = src.get(); 190 if (Surrogate.is(c)) { 191 if (sgp.parse(c, src) < 0) 192 return sgp.error(); 193 return sgp.unmappableResult(); 194 } 195 if (c >= '\uFFFE') 196 return CoderResult.unmappableForLength(1); 197 198 index = index1[((c & mask1) >> shift)] 199 + (c & mask2); 200 if (index < 15000) 201 theBytes = (int)(index2.charAt(index)); 202 else 203 theBytes = (int)(index2a.charAt(index-15000)); 204 b1 = (byte)((theBytes & 0x0000ff00)>>8); 205 b2 = (byte)(theBytes & 0x000000ff); 206 207 if (b1== 0x00 && b2 == 0x00 208 && c != '\u0000') { 209 return CoderResult.unmappableForLength(1); 210 } 211 212 if (currentState == DBCS && b1 == 0x00) { 213 if (dst.remaining() < 1) 214 return CoderResult.OVERFLOW; 215 currentState = SBCS; 216 dst.put(SI); 217 } else if (currentState == SBCS && b1 != 0x00) { 218 if (dst.remaining() < 1) 219 return CoderResult.OVERFLOW; 220 currentState = DBCS; 221 dst.put(SO); 222 } 223 224 if (currentState == DBCS) 225 spaceNeeded = 2; 226 else 227 spaceNeeded = 1; 228 229 if (dst.remaining() < spaceNeeded) 230 return CoderResult.OVERFLOW; 231 232 if (currentState == SBCS) 233 dst.put(b2); 234 else { 235 dst.put(b1); 236 dst.put(b2); 237 } 238 mark++; 239 } 240 return CoderResult.UNDERFLOW; 241 } finally { 242 src.position(mark); 243 } 244 } 245 246 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { 247 if (true && src.hasArray() && dst.hasArray()) 248 return encodeArrayLoop(src, dst); 249 else 250 return encodeBufferLoop(src, dst); 251 } 252 253 }