1 /* 2 * Copyright 2008 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 package sun.nio.cs; 27 28 import java.nio.Buffer; 29 import java.nio.ByteBuffer; 30 import java.nio.CharBuffer; 31 import java.nio.charset.Charset; 32 import java.nio.charset.CharsetDecoder; 33 import java.nio.charset.CharsetEncoder; 34 import java.nio.charset.CoderResult; 35 import static sun.nio.cs.CharsetMapping.*; 36 37 public class SingleByte 38 { 39 private static final CoderResult withResult(CoderResult cr, 40 Buffer src, int sp, 41 Buffer dst, int dp) 42 { 43 src.position(sp - src.arrayOffset()); 44 dst.position(dp - dst.arrayOffset()); 45 return cr; 46 } 47 48 public static class Decoder extends CharsetDecoder { 49 private final char[] b2c; 50 51 public Decoder(Charset cs, char[] b2c) { 52 super(cs, 1.0f, 1.0f); 53 this.b2c = b2c; 54 } 55 56 private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) { 57 byte[] sa = src.array(); 58 int sp = src.arrayOffset() + src.position(); 59 int sl = src.arrayOffset() + src.limit(); 60 61 char[] da = dst.array(); 62 int dp = dst.arrayOffset() + dst.position(); 63 int dl = dst.arrayOffset() + dst.limit(); 64 65 CoderResult cr = CoderResult.UNDERFLOW; 66 if ((dl - dp) < (sl - sp)) { 67 sl = sp + (dl - dp); 68 cr = CoderResult.OVERFLOW; 69 } 70 71 while (sp < sl) { 72 char c = decode(sa[sp]); 73 if (c == UNMAPPABLE_DECODING) { 74 return withResult(CoderResult.unmappableForLength(1), 75 src, sp, dst, dp); 76 } 77 da[dp++] = c; 78 sp++; 79 } 80 return withResult(cr, src, sp, dst, dp); 81 } 82 83 private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) { 84 int mark = src.position(); 85 try { 86 while (src.hasRemaining()) { 87 char c = decode(src.get()); 88 if (c == UNMAPPABLE_DECODING) 89 return CoderResult.unmappableForLength(1); 90 if (!dst.hasRemaining()) 91 return CoderResult.OVERFLOW; 92 dst.put(c); 93 mark++; 94 } 95 return CoderResult.UNDERFLOW; 96 } finally { 97 src.position(mark); 98 } 99 } 100 101 protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { 102 if (src.hasArray() && dst.hasArray()) 103 return decodeArrayLoop(src, dst); 104 else 105 return decodeBufferLoop(src, dst); 106 } 107 108 private final char decode(int b) { 109 return b2c[b + 128]; 110 } 111 } 112 113 public static class Encoder extends CharsetEncoder { 114 private Surrogate.Parser sgp; 115 private final char[] c2b; 116 private final char[] c2bIndex; 117 118 public Encoder(Charset cs, char[] c2b, char[] c2bIndex) { 119 super(cs, 1.0f, 1.0f); 120 this.c2b = c2b; 121 this.c2bIndex = c2bIndex; 122 } 123 124 public boolean canEncode(char c) { 125 return encode(c) != UNMAPPABLE_ENCODING; 126 } 127 128 private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) { 129 char[] sa = src.array(); 130 int sp = src.arrayOffset() + src.position(); 131 int sl = src.arrayOffset() + src.limit(); 132 133 byte[] da = dst.array(); 134 int dp = dst.arrayOffset() + dst.position(); 135 int dl = dst.arrayOffset() + dst.limit(); 136 137 CoderResult cr = CoderResult.UNDERFLOW; 138 if ((dl - dp) < (sl - sp)) { 139 sl = sp + (dl - dp); 140 cr = CoderResult.OVERFLOW; 141 } 142 143 while (sp < sl) { 144 char c = sa[sp]; 145 int b = encode(c); 146 if (b == UNMAPPABLE_ENCODING) { 147 if (Surrogate.is(c)) { 148 if (sgp == null) 149 sgp = new Surrogate.Parser(); 150 if (sgp.parse(c, sa, sp, sl) < 0) 151 return withResult(sgp.error(), src, sp, dst, dp); 152 return withResult(sgp.unmappableResult(), src, sp, dst, dp); 153 } 154 return withResult(CoderResult.unmappableForLength(1), 155 src, sp, dst, dp); 156 } 157 da[dp++] = (byte)b; 158 sp++; 159 } 160 return withResult(cr, src, sp, dst, dp); 161 } 162 163 private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) { 164 int mark = src.position(); 165 try { 166 while (src.hasRemaining()) { 167 char c = src.get(); 168 int b = encode(c); 169 if (b == UNMAPPABLE_ENCODING) { 170 if (Surrogate.is(c)) { 171 if (sgp == null) 172 sgp = new Surrogate.Parser(); 173 if (sgp.parse(c, src) < 0) 174 return sgp.error(); 175 return sgp.unmappableResult(); 176 } 177 return CoderResult.unmappableForLength(1); 178 } 179 if (!dst.hasRemaining()) 180 return CoderResult.OVERFLOW; 181 dst.put((byte)b); 182 mark++; 183 } 184 return CoderResult.UNDERFLOW; 185 } finally { 186 src.position(mark); 187 } 188 } 189 190 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { 191 if (src.hasArray() && dst.hasArray()) 192 return encodeArrayLoop(src, dst); 193 else 194 return encodeBufferLoop(src, dst); 195 } 196 197 private final int encode(char ch) { 198 char index = c2bIndex[ch >> 8]; 199 if (index == UNMAPPABLE_ENCODING) 200 return UNMAPPABLE_ENCODING; 201 return c2b[index + (ch & 0xff)]; 202 } 203 } 204 205 // init the c2b and c2bIndex tables from b2c. 206 public static void initC2B(char[] b2c, char[] c2bNR, 207 char[] c2b, char[] c2bIndex) { 208 for (int i = 0; i < c2bIndex.length; i++) 209 c2bIndex[i] = UNMAPPABLE_ENCODING; 210 for (int i = 0; i < c2b.length; i++) 211 c2b[i] = UNMAPPABLE_ENCODING; 212 int off = 0; 213 for (int i = 0; i < b2c.length; i++) { 214 char c = b2c[i]; 215 if (c == UNMAPPABLE_DECODING) 216 continue; 217 int index = (c >> 8); 218 if (c2bIndex[index] == UNMAPPABLE_ENCODING) { 219 c2bIndex[index] = (char)off; 220 off += 0x100; 221 } 222 index = c2bIndex[index] + (c & 0xff); 223 c2b[index] = (char)((i>=0x80)?(i-0x80):(i+0x80)); 224 } 225 if (c2bNR != null) { 226 // c-->b nr entries 227 int i = 0; 228 while (i < c2bNR.length) { 229 char b = c2bNR[i++]; 230 char c = c2bNR[i++]; 231 int index = (c >> 8); 232 if (c2bIndex[index] == UNMAPPABLE_ENCODING) { 233 c2bIndex[index] = (char)off; 234 off += 0x100; 235 } 236 index = c2bIndex[index] + (c & 0xff); 237 c2b[index] = b; 238 } 239 } 240 } 241 }