1 /* 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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.CharsetDecoder; 35 import java.nio.charset.CharsetEncoder; 36 import java.nio.charset.CoderResult; 37 import sun.nio.cs.HistoricallyNamedCharset; 38 39 public class SJIS 40 extends Charset 41 implements HistoricallyNamedCharset 42 { 43 44 public SJIS() { 45 super("Shift_JIS", ExtendedCharsets.aliasesFor("Shift_JIS")); 46 } 47 48 public String historicalName() { 49 return "SJIS"; 50 } 51 52 public boolean contains(Charset cs) { 53 return ((cs.name().equals("US-ASCII")) 54 || (cs instanceof JIS_X_0201) 55 || (cs instanceof SJIS) 56 || (cs instanceof JIS_X_0208)); 57 } 58 59 public CharsetDecoder newDecoder() { 60 return new Decoder(this); 61 } 62 63 public CharsetEncoder newEncoder() { 64 65 // Need to force the replacement byte to 0x3f 66 // because JIS_X_0208_Encoder defines its own 67 // alternative 2 byte substitution to permit it 68 // to exist as a self-standing Encoder 69 70 byte[] replacementBytes = { (byte)0x3f }; 71 return new Encoder(this).replaceWith(replacementBytes); 72 } 73 74 static class Decoder extends JIS_X_0208_Decoder 75 implements DelegatableDecoder { 76 77 JIS_X_0201.Decoder jis0201; 78 79 protected Decoder(Charset cs) { 80 super(cs); 81 jis0201 = new JIS_X_0201.Decoder(cs); 82 } 83 84 protected char decodeSingle(int b) { 85 // If the high bits are all off, it's ASCII == Unicode 86 if ((b & 0xFF80) == 0) { 87 return (char)b; 88 } 89 return jis0201.decode(b); 90 } 91 92 protected char decodeDouble(int c1, int c2) { 93 int adjust = c2 < 0x9F ? 1 : 0; 94 int rowOffset = c1 < 0xA0 ? 0x70 : 0xB0; 95 int cellOffset = (adjust == 1) ? (c2 > 0x7F ? 0x20 : 0x1F) : 0x7E; 96 int b1 = ((c1 - rowOffset) << 1) - adjust; 97 int b2 = c2 - cellOffset; 98 return super.decodeDouble(b1, b2); 99 } 100 101 // Make some protected methods public for use by JISAutoDetect 102 public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { 103 return super.decodeLoop(src, dst); 104 } 105 public void implReset() { 106 super.implReset(); 107 } 108 public CoderResult implFlush(CharBuffer out) { 109 return super.implFlush(out); 110 } 111 } 112 113 static class Encoder extends JIS_X_0208_Encoder { 114 115 private JIS_X_0201.Encoder jis0201; 116 117 private static final short[] j0208Index1 = 118 JIS_X_0208_Encoder.getIndex1(); 119 private static final String[] j0208Index2 = 120 JIS_X_0208_Encoder.getIndex2(); 121 122 protected Encoder(Charset cs) { 123 super(cs); 124 jis0201 = new JIS_X_0201.Encoder(cs); 125 } 126 127 protected int encodeSingle(char inputChar) { 128 byte b; 129 130 // \u0000 - \u007F map straight through 131 if ((inputChar & 0xFF80) == 0) 132 return (byte)inputChar; 133 134 if ((b = jis0201.encode(inputChar)) == 0) 135 return -1; 136 else 137 return b; 138 } 139 140 protected int encodeDouble(char ch) { 141 int offset = j0208Index1[ch >> 8] << 8; 142 int pos = j0208Index2[offset >> 12].charAt((offset & 0xfff) + (ch & 0xff)); 143 if (pos == 0) { 144 /* Zero value indicates this Unicode has no mapping to 145 * JIS0208. 146 * We bail here because the JIS -> SJIS algorithm produces 147 * bogus SJIS values for invalid JIS input. Zero should be 148 * the only invalid JIS value in our table. 149 */ 150 return 0; 151 } 152 /* 153 * This algorithm for converting from JIS to SJIS comes from 154 * Ken Lunde's "Understanding Japanese Information Processing", 155 * pg 163. 156 */ 157 int c1 = (pos >> 8) & 0xff; 158 int c2 = pos & 0xff; 159 int rowOffset = c1 < 0x5F ? 0x70 : 0xB0; 160 int cellOffset = (c1 % 2 == 1) ? (c2 > 0x5F ? 0x20 : 0x1F) : 0x7E; 161 return ((((c1 + 1 ) >> 1) + rowOffset) << 8) | (c2 + cellOffset); 162 } 163 } 164 }