jdk/src/share/classes/sun/io/ByteToCharISO2022JP.java
changeset 10372 2f6d68f22eae
parent 10321 64f7ee2f31dd
parent 10371 7da2112e4236
child 10373 d4c5e59b82f8
equal deleted inserted replaced
10321:64f7ee2f31dd 10372:2f6d68f22eae
     1 /*
       
     2  * Copyright (c) 1996, 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 package sun.io;
       
    27 
       
    28 public class ByteToCharISO2022JP extends ByteToCharJIS0208 {
       
    29 
       
    30     private static final int ASCII = 0;                 // ESC ( B
       
    31     private static final int JISX0201_1976 = 1;         // ESC ( J
       
    32     private static final int JISX0208_1978 = 2;         // ESC $ @
       
    33     private static final int JISX0208_1983 = 3;         // ESC $ B
       
    34     private static final int JISX0201_1976_KANA = 4;    // ESC ( I
       
    35     private static final int SHIFTOUT = 5;              // SO (0x0e)
       
    36 
       
    37     private int currentState;
       
    38     private int savedSize;
       
    39     private byte[] savedBytes;
       
    40 
       
    41     public ByteToCharISO2022JP() {
       
    42         super();
       
    43         savedBytes = new byte[2];
       
    44         currentState = ASCII;
       
    45         savedSize = 0;
       
    46     }
       
    47 
       
    48     public int flush(char [] output, int outStart, int outEnd)
       
    49         throws MalformedInputException
       
    50     {
       
    51         if (savedSize != 0) {
       
    52             savedSize = 0;
       
    53             currentState = ASCII;
       
    54             badInputLength = 0;
       
    55             throw new MalformedInputException();
       
    56         }
       
    57         byteOff = charOff = 0;
       
    58         return 0;
       
    59     }
       
    60 
       
    61 
       
    62     /**
       
    63      * Character conversion
       
    64      */
       
    65     public int convert(byte[] input, int inOff, int inEnd,
       
    66                        char[] output, int outOff, int outEnd)
       
    67         throws UnknownCharacterException, MalformedInputException,
       
    68                ConversionBufferFullException
       
    69     {
       
    70         int previousState = ASCII;
       
    71         int inputSize = 0;
       
    72         char outputChar = '\uFFFD';
       
    73         // readOff keeps the actual buffer's pointer.
       
    74         // byteOff keeps original buffer's pointer.
       
    75         int readOff = byteOff = inOff;
       
    76 
       
    77         if (savedSize != 0) {
       
    78             if (savedBytes[0] == 0x1b) { // ESC
       
    79                 if ((savedSize == 2 &&
       
    80                      (savedBytes[1] == 0x28 &&
       
    81                       input[0] != 'B' &&
       
    82                       input[0] != 'J' &&
       
    83                       input[0] != 'I') &&
       
    84                      (savedBytes[1] == 0x24 &&
       
    85                       input[0] != '@' &&
       
    86                       input[0] != 'B')) ||
       
    87                     ((savedSize == 1) &&
       
    88                      (input[0] != 0x28 &&
       
    89                       input[0] != 0x24))) {
       
    90                     badInputLength = 0;
       
    91                     throw new MalformedInputException();
       
    92                 }
       
    93                 if ((inEnd - inOff) == 1 && savedSize == 1 &&
       
    94                     savedBytes[0] == 0x1b) {
       
    95                     savedSize = 2;
       
    96                     savedBytes[1] = input[0];
       
    97                     byteOff++;
       
    98                     return 0;
       
    99                 }
       
   100             }
       
   101             byte[] newBuf = new byte[inEnd - inOff + savedSize];
       
   102             for (int i = 0; i < savedSize; i++) {
       
   103                 newBuf[i] = savedBytes[i];
       
   104             }
       
   105             System.arraycopy(input, inOff, newBuf, savedSize, inEnd - inOff);
       
   106             byteOff -= savedSize;
       
   107             input = newBuf;
       
   108             inOff = 0;
       
   109             inEnd = newBuf.length;
       
   110             savedSize = 0;
       
   111         }
       
   112 
       
   113         charOff = outOff;
       
   114         readOff = inOff;
       
   115 
       
   116         while(readOff < inEnd) {
       
   117             int byte1, byte2, byte3;
       
   118             boolean noOutput = false;
       
   119 
       
   120             // Is there room in the output buffer for the result?
       
   121             if (charOff >= outEnd) {
       
   122                 throw new ConversionBufferFullException();
       
   123             }
       
   124 
       
   125             // Get the input byte
       
   126             byte1 = input[readOff] & 0xFF;
       
   127             inputSize = 1;
       
   128 
       
   129             if ((byte1 & (byte)0x80) != 0){
       
   130                 badInputLength = 1;
       
   131                 throw new MalformedInputException();
       
   132             }
       
   133 
       
   134             // Is this a escape sequence?
       
   135             while (byte1 == 0x1b || byte1 == 0x0e || byte1 == 0x0f) {
       
   136                 if (byte1 == 0x1b){  // ESC
       
   137                     if (readOff + inputSize + 1 >= inEnd) {
       
   138                         if (readOff + inputSize >= inEnd) {
       
   139                             savedSize = 1;
       
   140                             savedBytes[0] = (byte)byte1;
       
   141                         } else {
       
   142                             savedSize = 2;
       
   143                             savedBytes[0] = (byte)byte1;
       
   144                             savedBytes[1] = input[readOff + inputSize];
       
   145                             inputSize++;
       
   146                         }
       
   147                         break;
       
   148                     }
       
   149                     byte2 = input[readOff + inputSize] & 0xFF;
       
   150                     inputSize++;
       
   151                     if ((byte2 & (byte)0x80) != 0){
       
   152                         badInputLength = 2;
       
   153                         throw new MalformedInputException();
       
   154                     }
       
   155                     if (byte2 == 0x28){
       
   156                         byte3 = input[readOff + inputSize] & 0xFF;
       
   157                         inputSize++;
       
   158                         if (byte3 == 'B'){
       
   159                             currentState = ASCII;
       
   160                         } else if (byte3 == 'J'){
       
   161                             currentState = JISX0201_1976;
       
   162                         } else if (byte3 == 'I'){
       
   163                             currentState = JISX0201_1976_KANA;
       
   164                         } else {
       
   165                             // illegal ESC sequence
       
   166                             badInputLength = 3;
       
   167                             throw new MalformedInputException();
       
   168                         }
       
   169                     } else if (byte2 == '$'){
       
   170                         byte3 = input[readOff + inputSize] & 0xFF;
       
   171                         inputSize++;
       
   172                         if ((byte3 & (byte)0x80) != 0){
       
   173                             badInputLength = 3;
       
   174                             throw new MalformedInputException();
       
   175                         }
       
   176                         if (byte3 == '@'){
       
   177                             currentState = JISX0208_1978;
       
   178                         } else if (byte3 == 'B'){
       
   179                             currentState = JISX0208_1983;
       
   180                         } else {
       
   181                             // illegal ESC sequence
       
   182                             badInputLength = 3;
       
   183                             throw new MalformedInputException();
       
   184                         }
       
   185                     } else {
       
   186                         // illegal ESC sequence
       
   187                         badInputLength = 2;
       
   188                         throw new MalformedInputException();
       
   189                     }
       
   190                     if (readOff + inputSize >= inEnd) {
       
   191                         noOutput = true;
       
   192                         break;
       
   193                     } else {
       
   194                         byte1 = input[readOff + inputSize];
       
   195                         inputSize++;
       
   196                     }
       
   197                 } else if (byte1 == 0x0e){  // shift out for one byte kana
       
   198                     previousState = currentState;
       
   199                     currentState = SHIFTOUT;
       
   200                     if (readOff + inputSize >= inEnd) {
       
   201                         noOutput = true;
       
   202                         break;
       
   203                     }
       
   204                     byte1 = input[readOff + inputSize];
       
   205                     inputSize++;
       
   206                     if ((byte1 & (byte)0x80) != 0){
       
   207                         badInputLength = 1;
       
   208                         throw new MalformedInputException();
       
   209                     }
       
   210                 } else if (byte1 == 0x0f){  // shift in for previous mode
       
   211                     currentState = previousState;
       
   212                     if (readOff + inputSize >= inEnd) {
       
   213                         noOutput = true;
       
   214                         break;
       
   215                     }
       
   216                     byte1 = input[readOff + inputSize];
       
   217                     inputSize++;
       
   218                     if ((byte1 & (byte)0x80) != 0){
       
   219                         badInputLength = 1;
       
   220                         throw new MalformedInputException();
       
   221                     }
       
   222                 }
       
   223             }
       
   224             if (noOutput || savedSize != 0) {
       
   225                 byteOff += inputSize;
       
   226                 break;
       
   227             }
       
   228             noOutput = false;
       
   229             switch (currentState){
       
   230               case ASCII:
       
   231                 outputChar = (char)(byte1 & 0xff);
       
   232                 break;
       
   233               case JISX0201_1976:
       
   234                 switch (byte1) {
       
   235                   case 0x5c:
       
   236                     outputChar = '\u00a5';
       
   237                     break;
       
   238                   case 0x7e:
       
   239                     outputChar = '\u203e';
       
   240                     break;
       
   241                   default:
       
   242                     outputChar = (char)byte1;
       
   243                     break;
       
   244                 }
       
   245                 break;
       
   246               case JISX0208_1978:
       
   247               case JISX0208_1983:
       
   248                 if (readOff + inputSize >= inEnd) {
       
   249                     savedSize = 1;
       
   250                     savedBytes[0] = (byte)byte1;
       
   251                     break;
       
   252                 }
       
   253                 byte2 = input[readOff + inputSize] & 0xff;
       
   254                 inputSize++;
       
   255                 if ((byte2 & (byte)0x80) != 0){
       
   256                     badInputLength = 1;
       
   257                     throw new MalformedInputException();
       
   258                 }
       
   259                 // jisx0208Chars table convert FULLWIDTH_REVERSE_SOLIDUS
       
   260                 // 0x2140 to REVERSE_SOLIDUS (BACKSLASH) 0x5c.
       
   261                 // This behavior causes problem because
       
   262                 // 0x5c is special escape character for java.
       
   263                 if (byte1 == 0x21 && byte2 == 0x40) {
       
   264                     outputChar = '\uFF3C';
       
   265                 } else {
       
   266                     try {
       
   267                         outputChar = getUnicode(byte1, byte2);
       
   268                     } catch (ArrayIndexOutOfBoundsException e) {
       
   269                         outputChar = '\uFFFD';
       
   270                     }
       
   271                 }
       
   272                 break;
       
   273               case JISX0201_1976_KANA:
       
   274               case SHIFTOUT:
       
   275                 if (byte1 > 0x60) {
       
   276                     badInputLength = 1;
       
   277                     throw new MalformedInputException();
       
   278                 }
       
   279                 outputChar = (char)(byte1 + 0xff40);
       
   280                 break;
       
   281             }
       
   282 
       
   283             if (savedSize != 0) {
       
   284                 byteOff += inputSize;
       
   285                 break;
       
   286             }
       
   287 
       
   288             if (outputChar == '\uFFFD') {
       
   289                 if (subMode)
       
   290                     outputChar = subChars[0];
       
   291                 else {
       
   292                     badInputLength = inputSize;
       
   293                     throw new UnknownCharacterException();
       
   294                 }
       
   295             }
       
   296             readOff += inputSize;
       
   297             byteOff += inputSize;
       
   298             output[charOff++] = outputChar;
       
   299         }
       
   300 
       
   301         return charOff - outOff;
       
   302     }
       
   303 
       
   304     public void reset() {
       
   305         byteOff = charOff = 0;
       
   306         currentState = ASCII;
       
   307         savedSize = 0;
       
   308     }
       
   309 
       
   310     public String getCharacterEncoding() {
       
   311         return "ISO2022JP";
       
   312     }
       
   313 }