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