jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java
changeset 29046 c46ad26fb278
parent 29045 991394bd2448
parent 29044 37c6512bd1df
child 29048 39a3bcf89286
equal deleted inserted replaced
29045:991394bd2448 29046:c46ad26fb278
     1 /*
       
     2  * Copyright (c) 2002, 2012, 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 package sun.nio.cs.ext;
       
    27 
       
    28 import java.nio.ByteBuffer;
       
    29 import java.nio.CharBuffer;
       
    30 import java.nio.charset.Charset;
       
    31 import java.nio.charset.CharsetDecoder;
       
    32 import java.nio.charset.CharsetEncoder;
       
    33 import java.nio.charset.CoderResult;
       
    34 import sun.nio.cs.HistoricallyNamedCharset;
       
    35 import sun.nio.cs.Surrogate;
       
    36 import sun.nio.cs.SingleByte;
       
    37 import static sun.nio.cs.CharsetMapping.*;
       
    38 
       
    39 public class EUC_JP
       
    40     extends Charset
       
    41     implements HistoricallyNamedCharset
       
    42 {
       
    43     public EUC_JP() {
       
    44         super("EUC-JP", ExtendedCharsets.aliasesFor("EUC-JP"));
       
    45     }
       
    46 
       
    47     public String historicalName() {
       
    48         return "EUC_JP";
       
    49     }
       
    50 
       
    51     public boolean contains(Charset cs) {
       
    52         return ((cs.name().equals("US-ASCII"))
       
    53                 || (cs instanceof JIS_X_0201)
       
    54                 || (cs instanceof JIS_X_0208)
       
    55                 || (cs instanceof JIS_X_0212)
       
    56                 || (cs instanceof EUC_JP));
       
    57     }
       
    58 
       
    59     public CharsetDecoder newDecoder() {
       
    60         return new Decoder(this);
       
    61     }
       
    62 
       
    63     public CharsetEncoder newEncoder() {
       
    64         return new Encoder(this);
       
    65     }
       
    66 
       
    67     static class Decoder extends CharsetDecoder
       
    68         implements DelegatableDecoder {
       
    69 
       
    70         final static SingleByte.Decoder DEC0201 =
       
    71             (SingleByte.Decoder)new JIS_X_0201().newDecoder();
       
    72 
       
    73         final static DoubleByte.Decoder DEC0208 =
       
    74             (DoubleByte.Decoder)new JIS_X_0208().newDecoder();
       
    75 
       
    76         final static DoubleByte.Decoder DEC0212 =
       
    77             (DoubleByte.Decoder)new JIS_X_0212().newDecoder();
       
    78 
       
    79         private final SingleByte.Decoder dec0201;
       
    80         private final DoubleByte.Decoder dec0208;
       
    81         private final DoubleByte.Decoder dec0212;
       
    82 
       
    83         protected Decoder(Charset cs) {
       
    84             this(cs, 0.5f, 1.0f, DEC0201, DEC0208, DEC0212);
       
    85         }
       
    86 
       
    87         protected Decoder(Charset cs, float avgCpb, float maxCpb,
       
    88                           SingleByte.Decoder dec0201,
       
    89                           DoubleByte.Decoder dec0208,
       
    90                           DoubleByte.Decoder dec0212) {
       
    91             super(cs, avgCpb, maxCpb);
       
    92             this.dec0201 = dec0201;
       
    93             this.dec0208 = dec0208;
       
    94             this.dec0212 = dec0212;
       
    95         }
       
    96 
       
    97 
       
    98         protected char decodeDouble(int byte1, int byte2) {
       
    99             if (byte1 == 0x8e) {
       
   100                 if (byte2 < 0x80)
       
   101                     return UNMAPPABLE_DECODING;
       
   102                 return dec0201.decode((byte)byte2);
       
   103             }
       
   104             return dec0208.decodeDouble(byte1 - 0x80, byte2 - 0x80);
       
   105         }
       
   106 
       
   107         private CoderResult decodeArrayLoop(ByteBuffer src,
       
   108                                             CharBuffer dst)
       
   109         {
       
   110             byte[] sa = src.array();
       
   111             int sp = src.arrayOffset() + src.position();
       
   112             int sl = src.arrayOffset() + src.limit();
       
   113             assert (sp <= sl);
       
   114             sp = (sp <= sl ? sp : sl);
       
   115 
       
   116             char[] da = dst.array();
       
   117             int dp = dst.arrayOffset() + dst.position();
       
   118             int dl = dst.arrayOffset() + dst.limit();
       
   119             assert (dp <= dl);
       
   120             dp = (dp <= dl ? dp : dl);
       
   121 
       
   122             int b1 = 0, b2 = 0;
       
   123             int inputSize = 0;
       
   124             char outputChar = UNMAPPABLE_DECODING;
       
   125             try {
       
   126                 while (sp < sl) {
       
   127                     b1 = sa[sp] & 0xff;
       
   128                     inputSize = 1;
       
   129 
       
   130                     if ((b1 & 0x80) == 0) {
       
   131                         outputChar = (char)b1;
       
   132                     } else {                        // Multibyte char
       
   133                         if (b1 == 0x8f) {           // JIS0212
       
   134                             if (sp + 3 > sl)
       
   135                                return CoderResult.UNDERFLOW;
       
   136                             b1 = sa[sp + 1] & 0xff;
       
   137                             b2 = sa[sp + 2] & 0xff;
       
   138                             inputSize += 2;
       
   139                             if (dec0212 == null)    // JIS02012 not supported
       
   140                                 return CoderResult.unmappableForLength(inputSize);
       
   141                             outputChar = dec0212.decodeDouble(b1-0x80, b2-0x80);
       
   142                         } else {                     // JIS0201, JIS0208
       
   143                             if (sp + 2 > sl)
       
   144                                return CoderResult.UNDERFLOW;
       
   145                             b2 = sa[sp + 1] & 0xff;
       
   146                             inputSize++;
       
   147                             outputChar = decodeDouble(b1, b2);
       
   148                         }
       
   149                     }
       
   150                     if (outputChar == UNMAPPABLE_DECODING) { // can't be decoded
       
   151                         return CoderResult.unmappableForLength(inputSize);
       
   152                     }
       
   153                     if (dp + 1 > dl)
       
   154                         return CoderResult.OVERFLOW;
       
   155                     da[dp++] = outputChar;
       
   156                     sp += inputSize;
       
   157                 }
       
   158                 return CoderResult.UNDERFLOW;
       
   159             } finally {
       
   160                 src.position(sp - src.arrayOffset());
       
   161                 dst.position(dp - dst.arrayOffset());
       
   162             }
       
   163         }
       
   164 
       
   165         private CoderResult decodeBufferLoop(ByteBuffer src,
       
   166                                              CharBuffer dst)
       
   167         {
       
   168             int mark = src.position();
       
   169             int b1 = 0, b2 = 0;
       
   170             int inputSize = 0;
       
   171             char outputChar = UNMAPPABLE_DECODING;
       
   172 
       
   173             try {
       
   174                 while (src.hasRemaining()) {
       
   175                     b1 = src.get() & 0xff;
       
   176                     inputSize = 1;
       
   177                     if ((b1 & 0x80) == 0) {
       
   178                         outputChar = (char)b1;
       
   179                     } else {                         // Multibyte char
       
   180                         if (b1 == 0x8f) {   // JIS0212
       
   181                             if (src.remaining() < 2)
       
   182                                return CoderResult.UNDERFLOW;
       
   183                             b1 = src.get() & 0xff;
       
   184                             b2 = src.get() & 0xff;
       
   185                             inputSize += 2;
       
   186                             if (dec0212 == null)    // JIS02012 not supported
       
   187                                 return CoderResult.unmappableForLength(inputSize);
       
   188                             outputChar = dec0212.decodeDouble(b1-0x80, b2-0x80);
       
   189                         } else {                     // JIS0201 JIS0208
       
   190                             if (src.remaining() < 1)
       
   191                                return CoderResult.UNDERFLOW;
       
   192                             b2 = src.get() & 0xff;
       
   193                             inputSize++;
       
   194                             outputChar = decodeDouble(b1, b2);
       
   195                         }
       
   196                     }
       
   197                     if (outputChar == UNMAPPABLE_DECODING) {
       
   198                         return CoderResult.unmappableForLength(inputSize);
       
   199                     }
       
   200                 if (dst.remaining() < 1)
       
   201                     return CoderResult.OVERFLOW;
       
   202                 dst.put(outputChar);
       
   203                 mark += inputSize;
       
   204                 }
       
   205                 return CoderResult.UNDERFLOW;
       
   206             } finally {
       
   207                 src.position(mark);
       
   208             }
       
   209         }
       
   210 
       
   211         // Make some protected methods public for use by JISAutoDetect
       
   212         public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
       
   213             if (src.hasArray() && dst.hasArray())
       
   214                 return decodeArrayLoop(src, dst);
       
   215             else
       
   216                 return decodeBufferLoop(src, dst);
       
   217         }
       
   218         public void implReset() {
       
   219             super.implReset();
       
   220         }
       
   221         public CoderResult implFlush(CharBuffer out) {
       
   222             return super.implFlush(out);
       
   223         }
       
   224     }
       
   225 
       
   226 
       
   227     static class Encoder extends CharsetEncoder {
       
   228 
       
   229         final static SingleByte.Encoder ENC0201 =
       
   230             (SingleByte.Encoder)new JIS_X_0201().newEncoder();
       
   231 
       
   232         final static DoubleByte.Encoder ENC0208 =
       
   233             (DoubleByte.Encoder)new JIS_X_0208().newEncoder();
       
   234 
       
   235         final static DoubleByte.Encoder ENC0212 =
       
   236             (DoubleByte.Encoder)new JIS_X_0212().newEncoder();
       
   237 
       
   238         private final Surrogate.Parser sgp = new Surrogate.Parser();
       
   239 
       
   240 
       
   241         private final SingleByte.Encoder enc0201;
       
   242         private final DoubleByte.Encoder enc0208;
       
   243         private final DoubleByte.Encoder enc0212;
       
   244 
       
   245         protected Encoder(Charset cs) {
       
   246             this(cs, 3.0f, 3.0f, ENC0201, ENC0208, ENC0212);
       
   247         }
       
   248 
       
   249         protected Encoder(Charset cs, float avgBpc, float maxBpc,
       
   250                           SingleByte.Encoder enc0201,
       
   251                           DoubleByte.Encoder enc0208,
       
   252                           DoubleByte.Encoder enc0212) {
       
   253             super(cs, avgBpc, maxBpc);
       
   254             this.enc0201 = enc0201;
       
   255             this.enc0208 = enc0208;
       
   256             this.enc0212 = enc0212;
       
   257         }
       
   258 
       
   259         public boolean canEncode(char c) {
       
   260             byte[]  encodedBytes = new byte[3];
       
   261             return encodeSingle(c, encodedBytes) != 0 ||
       
   262                    encodeDouble(c) != UNMAPPABLE_ENCODING;
       
   263         }
       
   264 
       
   265         protected int encodeSingle(char inputChar, byte[] outputByte) {
       
   266             int b = enc0201.encode(inputChar);
       
   267             if (b == UNMAPPABLE_ENCODING)
       
   268                 return 0;
       
   269             if (b >= 0 && b < 128) {
       
   270                 outputByte[0] = (byte)b;
       
   271                 return 1;
       
   272             }
       
   273             outputByte[0] = (byte)0x8e;
       
   274             outputByte[1] = (byte)b;
       
   275             return 2;
       
   276         }
       
   277 
       
   278         protected int encodeDouble(char ch) {
       
   279             int b = enc0208.encodeChar(ch);
       
   280             if (b != UNMAPPABLE_ENCODING)
       
   281                 return b + 0x8080;
       
   282             if (enc0212 != null) {
       
   283                 b = enc0212.encodeChar(ch);
       
   284                 if (b != UNMAPPABLE_ENCODING)
       
   285                     b += 0x8F8080;
       
   286             }
       
   287             return b;
       
   288         }
       
   289 
       
   290         private CoderResult encodeArrayLoop(CharBuffer src,
       
   291                                             ByteBuffer dst)
       
   292         {
       
   293             char[] sa = src.array();
       
   294             int sp = src.arrayOffset() + src.position();
       
   295             int sl = src.arrayOffset() + src.limit();
       
   296             assert (sp <= sl);
       
   297             sp = (sp <= sl ? sp : sl);
       
   298             byte[] da = dst.array();
       
   299             int dp = dst.arrayOffset() + dst.position();
       
   300             int dl = dst.arrayOffset() + dst.limit();
       
   301             assert (dp <= dl);
       
   302             dp = (dp <= dl ? dp : dl);
       
   303 
       
   304             int outputSize = 0;
       
   305             byte[]  outputByte;
       
   306             int     inputSize = 0;                 // Size of input
       
   307             byte[]  tmpBuf = new byte[3];
       
   308 
       
   309             try {
       
   310                 while (sp < sl) {
       
   311                     outputByte = tmpBuf;
       
   312                     char c = sa[sp];
       
   313                     if (Character.isSurrogate(c)) {
       
   314                         if (sgp.parse(c, sa, sp, sl) < 0)
       
   315                             return sgp.error();
       
   316                         return sgp.unmappableResult();
       
   317                     }
       
   318                     outputSize = encodeSingle(c, outputByte);
       
   319                     if (outputSize == 0) { // DoubleByte
       
   320                         int ncode = encodeDouble(c);
       
   321                         if (ncode != UNMAPPABLE_ENCODING) {
       
   322                             if ((ncode & 0xFF0000) == 0) {
       
   323                                 outputByte[0] = (byte) ((ncode & 0xff00) >> 8);
       
   324                                 outputByte[1] = (byte) (ncode & 0xff);
       
   325                                 outputSize = 2;
       
   326                             } else {
       
   327                                 outputByte[0] = (byte) 0x8f;
       
   328                                 outputByte[1] = (byte) ((ncode & 0xff00) >> 8);
       
   329                                 outputByte[2] = (byte) (ncode & 0xff);
       
   330                                 outputSize = 3;
       
   331                             }
       
   332                         } else {
       
   333                             return CoderResult.unmappableForLength(1);
       
   334                         }
       
   335                     }
       
   336                     if (dl - dp < outputSize)
       
   337                         return CoderResult.OVERFLOW;
       
   338                     // Put the byte in the output buffer
       
   339                     for (int i = 0; i < outputSize; i++) {
       
   340                         da[dp++] = outputByte[i];
       
   341                     }
       
   342                     sp++;
       
   343                 }
       
   344                 return CoderResult.UNDERFLOW;
       
   345             } finally {
       
   346                 src.position(sp - src.arrayOffset());
       
   347                 dst.position(dp - dst.arrayOffset());
       
   348             }
       
   349         }
       
   350 
       
   351         private CoderResult encodeBufferLoop(CharBuffer src,
       
   352                                              ByteBuffer dst)
       
   353         {
       
   354             int outputSize = 0;
       
   355             byte[]  outputByte;
       
   356             int     inputSize = 0;                 // Size of input
       
   357             byte[]  tmpBuf = new byte[3];
       
   358 
       
   359             int mark = src.position();
       
   360 
       
   361             try {
       
   362                 while (src.hasRemaining()) {
       
   363                     outputByte = tmpBuf;
       
   364                     char c = src.get();
       
   365                     if (Character.isSurrogate(c)) {
       
   366                         if (sgp.parse(c, src) < 0)
       
   367                             return sgp.error();
       
   368                         return sgp.unmappableResult();
       
   369                     }
       
   370                     outputSize = encodeSingle(c, outputByte);
       
   371                     if (outputSize == 0) { // DoubleByte
       
   372                         int ncode = encodeDouble(c);
       
   373                         if (ncode != UNMAPPABLE_ENCODING) {
       
   374                             if ((ncode & 0xFF0000) == 0) {
       
   375                                 outputByte[0] = (byte) ((ncode & 0xff00) >> 8);
       
   376                                 outputByte[1] = (byte) (ncode & 0xff);
       
   377                                 outputSize = 2;
       
   378                             } else {
       
   379                                 outputByte[0] = (byte) 0x8f;
       
   380                                 outputByte[1] = (byte) ((ncode & 0xff00) >> 8);
       
   381                                 outputByte[2] = (byte) (ncode & 0xff);
       
   382                                 outputSize = 3;
       
   383                             }
       
   384                         } else {
       
   385                             return CoderResult.unmappableForLength(1);
       
   386                         }
       
   387                     }
       
   388                     if (dst.remaining() < outputSize)
       
   389                         return CoderResult.OVERFLOW;
       
   390                     // Put the byte in the output buffer
       
   391                     for (int i = 0; i < outputSize; i++) {
       
   392                         dst.put(outputByte[i]);
       
   393                     }
       
   394                     mark++;
       
   395                 }
       
   396                 return CoderResult.UNDERFLOW;
       
   397             } finally {
       
   398                 src.position(mark);
       
   399             }
       
   400         }
       
   401 
       
   402         protected CoderResult encodeLoop(CharBuffer src,
       
   403                                          ByteBuffer dst)
       
   404         {
       
   405             if (src.hasArray() && dst.hasArray())
       
   406                 return encodeArrayLoop(src, dst);
       
   407             else
       
   408                 return encodeBufferLoop(src, dst);
       
   409         }
       
   410     }
       
   411 }