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