jdk/src/share/classes/sun/io/ByteToCharISO2022.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) 1997, 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 /**
       
    29  * An algorithmic conversion from ISO 2022 to Unicode
       
    30  *
       
    31  * @author Tom Zhou
       
    32  */
       
    33 public abstract class ByteToCharISO2022 extends ByteToCharConverter
       
    34 {
       
    35     // Value to be filled by subclass
       
    36     protected String SODesignator[];
       
    37     protected String SS2Designator[] = null;
       
    38     protected String SS3Designator[] = null;
       
    39 
       
    40     protected ByteToCharConverter SOConverter[];
       
    41     protected ByteToCharConverter SS2Converter[] = null;
       
    42     protected ByteToCharConverter SS3Converter[] = null;
       
    43 
       
    44     private static final byte ISO_ESC = 0x1b;
       
    45     private static final byte ISO_SI = 0x0f;
       
    46     private static final byte ISO_SO = 0x0e;
       
    47     private static final byte ISO_SS2_7 = 0x4e;
       
    48     private static final byte ISO_SS3_7 = 0x4f;
       
    49     private static final byte MSB = (byte)0x80;
       
    50     private static final char REPLACE_CHAR = '\uFFFD';
       
    51     private static final byte maximumDesignatorLength = 3;
       
    52 
       
    53     private static final byte SOFlag = 0;
       
    54     private static final byte SS2Flag = 1;
       
    55     private static final byte SS3Flag = 2;
       
    56     private static final byte G0 = 0;
       
    57     private static final byte G1 = 1;
       
    58 
       
    59     private ByteToCharConverter tmpConverter[];
       
    60 
       
    61     private int curSODes, curSS2Des, curSS3Des;
       
    62     private boolean shiftout;
       
    63 
       
    64     private byte remainByte[] = new byte[10];
       
    65     private int remainIndex = -1;
       
    66     private byte state, firstByte;
       
    67 
       
    68     public void reset()
       
    69     {
       
    70         int i = 0;
       
    71 
       
    72         shiftout = false;
       
    73         state = G0;
       
    74         firstByte = 0;
       
    75 
       
    76         curSODes = 0;
       
    77         curSS2Des = 0;
       
    78         curSS3Des = 0;
       
    79 
       
    80         charOff = byteOff = 0;
       
    81         remainIndex = -1;
       
    82 
       
    83         for(i = 0; i < remainByte.length; i++)
       
    84             remainByte[i] = 0;
       
    85     }
       
    86 
       
    87     public int flush(char[] output, int outStart, int outEnd)
       
    88         throws MalformedInputException
       
    89     {
       
    90         int i;
       
    91         if (state != G0) {
       
    92             badInputLength = 0;
       
    93             throw new MalformedInputException();
       
    94         }
       
    95         reset();
       
    96         return 0;
       
    97     }
       
    98 
       
    99     private byte[] savetyGetSrc(byte[] input, int inOff, int inEnd, int nbytes)
       
   100     {
       
   101         int i;
       
   102         byte tmp[];
       
   103 
       
   104         if(inOff <= (inEnd-nbytes+1))
       
   105             tmp = new byte[nbytes];
       
   106         else
       
   107             tmp = new byte[inEnd-inOff];
       
   108 
       
   109         for(i = 0; i < tmp.length; i++)
       
   110             tmp[i] = input[inOff+i];
       
   111         return tmp;
       
   112     }
       
   113 
       
   114     private char getUnicode(byte byte1, byte byte2, byte shiftFlag)
       
   115     {
       
   116         byte1 |= MSB;
       
   117         byte2 |= MSB;
       
   118 
       
   119         byte[] tmpByte = {byte1,byte2};
       
   120         char[] tmpChar = new char[1];
       
   121         int     i = 0,
       
   122                 tmpIndex = 0;
       
   123 
       
   124         switch(shiftFlag) {
       
   125         case SOFlag:
       
   126             tmpIndex = curSODes;
       
   127             tmpConverter = SOConverter;
       
   128             break;
       
   129         case SS2Flag:
       
   130             tmpIndex = curSS2Des;
       
   131             tmpConverter = SS2Converter;
       
   132             break;
       
   133         case SS3Flag:
       
   134             tmpIndex = curSS3Des;
       
   135             tmpConverter = SS3Converter;
       
   136             break;
       
   137         }
       
   138 
       
   139         for(i = 0; i < tmpConverter.length; i++) {
       
   140             if(tmpIndex == i) {
       
   141                 try {
       
   142                     tmpConverter[i].convert(tmpByte, 0, 2, tmpChar, 0, 1);
       
   143                 } catch (Exception e) {}
       
   144                 return tmpChar[0];
       
   145             }
       
   146         }
       
   147         return REPLACE_CHAR;
       
   148     }
       
   149 
       
   150     public final int convert(byte[] input, int inOff, int inEnd,
       
   151                              char[] output, int outOff, int outEnd)
       
   152                              throws ConversionBufferFullException,
       
   153                                     MalformedInputException
       
   154     {
       
   155         int i;
       
   156         int DesignatorLength = 0;
       
   157         charOff  =  outOff;
       
   158         byteOff  =  inOff;
       
   159 
       
   160         // Loop until we hit the end of the input
       
   161         while (byteOff < inEnd) {
       
   162             // If we don't have room for the output, throw an exception
       
   163             if (charOff >= outEnd)
       
   164                 throw new ConversionBufferFullException();
       
   165             if(remainIndex < 0) {
       
   166                 remainByte[0] = input[byteOff];
       
   167                 remainIndex = 0;
       
   168                 byteOff++;
       
   169             }
       
   170             switch (remainByte[0]) {
       
   171             case ISO_SO:
       
   172                 shiftout = true;
       
   173                 if(remainIndex > 0)
       
   174                     System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
       
   175                 remainIndex--;
       
   176                 break;
       
   177             case ISO_SI:
       
   178                 shiftout = false;
       
   179                 if(remainIndex > 0)
       
   180                     System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
       
   181                 remainIndex--;
       
   182                 break;
       
   183              case ISO_ESC:
       
   184                 byte tmp[] = savetyGetSrc(input, byteOff, inEnd,
       
   185                                (maximumDesignatorLength-remainIndex));
       
   186                 System.arraycopy(tmp, 0, remainByte, remainIndex+1, tmp.length);
       
   187                 remainIndex += tmp.length;
       
   188                 byteOff += tmp.length;
       
   189                 if(tmp.length<(maximumDesignatorLength-remainIndex))
       
   190                     break;
       
   191                 String tmpString = new String(remainByte, 1, remainIndex);
       
   192                 for (i = 0; i < SODesignator.length; i++) {
       
   193                     if(tmpString.indexOf(SODesignator[i]) == 0) {
       
   194                         curSODes = i;
       
   195                         DesignatorLength = SODesignator[i].length();
       
   196                         break;
       
   197                     }
       
   198                 }
       
   199 
       
   200                 if (DesignatorLength == 0 ) { // Designator not recognized
       
   201                    badInputLength = tmp.length;
       
   202                    throw new MalformedInputException();
       
   203                 }
       
   204 
       
   205                 if (i == SODesignator.length) {
       
   206                     for (i = 0; i < SS2Designator.length; i++) {
       
   207                         if(tmpString.indexOf(SS2Designator[i]) == 0) {
       
   208                             curSS2Des = i;
       
   209                             DesignatorLength = SS2Designator[i].length();
       
   210                             break;
       
   211                         }
       
   212                     }
       
   213                     if(i == SS2Designator.length) {
       
   214                         for(i = 0; i < SS3Designator.length; i++) {
       
   215                             if (tmpString.indexOf(SS3Designator[i]) == 0) {
       
   216                                 curSS3Des = i;
       
   217                                 DesignatorLength = SS3Designator[i].length();
       
   218                                 break;
       
   219                             }
       
   220                         }
       
   221                         if (i == SS3Designator.length) {
       
   222                             switch(remainByte[1]) {
       
   223                             case ISO_SS2_7:
       
   224                                 output[charOff] = getUnicode(remainByte[2],
       
   225                                                           remainByte[3],
       
   226                                                           SS2Flag);
       
   227                                 charOff++;
       
   228                                 DesignatorLength = 3;
       
   229                                 break;
       
   230                             case ISO_SS3_7:
       
   231                                 output[charOff] = getUnicode(remainByte[2],
       
   232                                                           remainByte[3],
       
   233                                                           SS3Flag);
       
   234                                 charOff++;
       
   235                                 DesignatorLength = 3;
       
   236                                 break;
       
   237                             default:
       
   238                                 DesignatorLength = 0;
       
   239                             }
       
   240                         }
       
   241                     }
       
   242                 }
       
   243                 if (remainIndex > DesignatorLength) {
       
   244                     for(i = 0; i < remainIndex-DesignatorLength; i++)
       
   245                         remainByte[i] = remainByte[DesignatorLength+1+i];
       
   246                     remainIndex = i-1;
       
   247                 } else {
       
   248                     remainIndex = -1;
       
   249                 }
       
   250                 break;
       
   251             default:
       
   252                 if (!shiftout) {
       
   253                     output[charOff] = (char)remainByte[0];
       
   254                     charOff++;
       
   255                 } else {
       
   256                     switch (state) {
       
   257                     case G0:
       
   258                         firstByte = remainByte[0];
       
   259                         state = G1;
       
   260                         break;
       
   261                     case G1:
       
   262                         output[charOff] = getUnicode(firstByte, remainByte[0],
       
   263                                                   SOFlag);
       
   264                         charOff++;
       
   265                         state = G0;
       
   266                         break;
       
   267                     }
       
   268                 }
       
   269                 if (remainIndex > 0)
       
   270                     System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
       
   271                 remainIndex--;
       
   272             }
       
   273         }
       
   274         return charOff - outOff;
       
   275     }
       
   276 }