1 /*
   2  * Copyright 1997 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 package sun.io;
  26 
  27 import sun.nio.cs.ext.DoubleByte;
  28 import static sun.nio.cs.CharsetMapping.*;
  29 
  30 public abstract class ByteToCharEUC2 extends ByteToCharConverter
  31 {
  32     private final int G0 = 0;
  33     private final int G1 = 1;
  34     private final int SS2 =  0x8E;
  35     private final int SS3 =  0x8F;
  36 
  37     private int firstByte, state;
  38 
  39     private DoubleByte.Decoder dec;
  40 
  41     public ByteToCharEUC2(DoubleByte.Decoder dec) {
  42         super();
  43         state = G0;
  44         this.dec = dec;
  45     }
  46 
  47     char decodeSingle(int b) {
  48         return dec.decodeSingle(b);
  49     }
  50 
  51     char decodeDouble(int b1, int b2) {
  52         return dec.decodeDouble(b1, b2);
  53     }
  54 
  55     /**
  56       * flush out any residual data and reset the buffer state
  57       */
  58     public int flush(char[] output, int outStart, int outEnd)
  59        throws MalformedInputException
  60     {
  61        if (state != G0) {
  62           reset();
  63           badInputLength = 0;
  64           throw new MalformedInputException();
  65        }
  66 
  67        reset();
  68        return 0;
  69     }
  70 
  71     /**
  72      *  Resets the converter.
  73      */
  74     public void reset() {
  75        state = G0;
  76        charOff = byteOff = 0;
  77     }
  78 
  79     /**
  80      * Character conversion
  81      */
  82     public int convert(byte[] input, int inOff, int inEnd,
  83                        char[] output, int outOff, int outEnd)
  84         throws UnknownCharacterException, MalformedInputException,
  85                ConversionBufferFullException
  86     {
  87         int       byte1;
  88         char      outputChar = UNMAPPABLE_DECODING;
  89         byteOff = inOff;
  90         charOff = outOff;
  91 
  92         while (byteOff < inEnd) {
  93             byte1 = input[byteOff] & 0xff;
  94             switch (state) {
  95             case G0:
  96                 if (byte1 == SS2 ||                // no general support
  97                     byte1 == SS3 ) {               //    for g2 or g3
  98                     badInputLength = 1;
  99                     throw new MalformedInputException();
 100                 }
 101                 if ( byte1 <= 0x9f )               // < 0x9f has its own table
 102                     outputChar = decodeSingle(byte1);
 103                 else
 104                     if (byte1 < 0xa1 || byte1 > 0xfe) {  // byte within range?
 105                         badInputLength = 1;
 106                         throw new MalformedInputException();
 107                     } else {                       // G1 set first byte
 108                         firstByte = byte1;
 109                         state = G1;
 110                     }
 111                 break;
 112             case G1:
 113                 state = G0;
 114                 if ( byte1 < 0xa1 || byte1 > 0xfe) {  // valid G1 set second byte
 115                     badInputLength = 1;
 116                     throw new MalformedInputException();
 117                 }
 118                 outputChar = decodeDouble(firstByte, byte1);
 119                 break;
 120             }
 121             if (state == G0) {
 122                 if (outputChar == UNMAPPABLE_DECODING) {
 123                     if (subMode)
 124                         outputChar = subChars[0];
 125                     else {
 126                         badInputLength = 1;
 127                         throw new UnknownCharacterException();
 128                     }
 129                 }
 130                 if (charOff >= outEnd)
 131                     throw new ConversionBufferFullException();
 132                 output[charOff++] = outputChar;
 133             }
 134             byteOff++;
 135          }
 136          return charOff - outOff;
 137     }
 138 }