ISO2022.java :  » 6.0-JDK-Modules-sun » nio » sun » nio » cs » ext » Java Open Source

Java Open Source » 6.0 JDK Modules sun » nio 
nio » sun » nio » cs » ext » ISO2022.java
/*
 * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @(#)ISO2022.java  1.14 07/05/05
 */

package sun.nio.cs.ext;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import sun.nio.cs.Surrogate;

abstract class ISO2022
    extends Charset
{

    private static final byte ISO_ESC = 0x1b;
    private static final byte ISO_SI = 0x0f;
    private static final byte ISO_SO = 0x0e;
    private static final byte ISO_SS2_7 = 0x4e;
    private static final byte ISO_SS3_7 = 0x4f;
    private static final byte MSB = (byte)0x80;
    private static final char REPLACE_CHAR = '\uFFFD';
    private static final byte minDesignatorLength = 3; 

    public ISO2022(String csname, String[] aliases) {
  super(csname, aliases);
    }

    public CharsetDecoder newDecoder() {
  return new Decoder(this);
    }

    public CharsetEncoder newEncoder() {
  return new Encoder(this);
    }

    protected static class Decoder extends CharsetDecoder {

  // Value to be filled by subclass
  protected byte SODesig[][];
  protected byte SS2Desig[][] = null;
  protected byte SS3Desig[][] = null;

  protected CharsetDecoder SODecoder[];
  protected CharsetDecoder SS2Decoder[] = null;
  protected CharsetDecoder SS3Decoder[] = null;

  private static final byte SOFlag = 0;
  private static final byte SS2Flag = 1;
  private static final byte SS3Flag = 2;

  private int curSODes, curSS2Des, curSS3Des;
  private boolean shiftout;
  private CharsetDecoder tmpDecoder[];

  protected Decoder(Charset cs) {
      super(cs, 1.0f, 1.0f);
  }

  protected void implReset() {
      curSODes = 0;
      curSS2Des = 0;
      curSS3Des = 0;
      shiftout = false;
  }

  private char decode(byte byte1, byte byte2, byte shiftFlag)
  {
      byte1 |= MSB;
      byte2 |= MSB;

      byte[] tmpByte = { byte1,byte2 };
      char[] tmpChar = new char[1];
      int     i = 0,
        tmpIndex = 0;

      switch(shiftFlag) {
      case SOFlag:
    tmpIndex = curSODes;
    tmpDecoder = (CharsetDecoder [])SODecoder;
    break;
      case SS2Flag:  
    tmpIndex = curSS2Des;
    tmpDecoder = (CharsetDecoder [])SS2Decoder;
    break;
      case SS3Flag:
    tmpIndex = curSS3Des;
    tmpDecoder = (CharsetDecoder [])SS3Decoder;
    break;
      }

            if (tmpDecoder != null) {
           for(i = 0; i < tmpDecoder.length; i++) {
        if(tmpIndex == i) {
            try {
          ByteBuffer bb = ByteBuffer.wrap(tmpByte,0,2);
          CharBuffer cc = CharBuffer.wrap(tmpChar,0,1);
          tmpDecoder[i].decode(bb, cc, true);
          cc.flip();
          return cc.get();
      } catch (Exception e) {}
        }
    }
      }
      return REPLACE_CHAR;
  }

        private int findDesig(byte[] in, int sp, int sl, byte[][] desigs) {
            if (desigs == null) return -1;
            int i = 0;
            while (i < desigs.length) {
          if (desigs[i] != null && sl - sp >= desigs[i].length) {
                    int j = 0;
                    while (j < desigs[i].length && in[sp+j] == desigs[i][j]) { j++; }
                    if (j == desigs[i].length)
                        return i;
    }
    i++;
            }
            return -1;
        }

        private int findDesigBuf(ByteBuffer in, byte[][] desigs) {
            if (desigs == null) return -1;
            int i = 0;
            while (i < desigs.length) {
          if (desigs[i] != null && in.remaining() >= desigs[i].length) {
                    int j = 0;
                    in.mark();
                    while (j < desigs[i].length && in.get() == desigs[i][j]) { j++; }
                    if (j == desigs[i].length)
                        return i;
                    in.reset();
    }
    i++;
            }
            return -1;
        }
  
  private CoderResult decodeArrayLoop(ByteBuffer src,
              CharBuffer dst)
  {
      byte[] sa = src.array();
      int sp = src.arrayOffset() + src.position();
      int sl = src.arrayOffset() + src.limit();
      assert (sp <= sl);
      sp = (sp <= sl ? sp : sl);

      char[] da = dst.array();
      int dp = dst.arrayOffset() + dst.position();
      int dl = dst.arrayOffset() + dst.limit();
      assert (dp <= dl);
      dp = (dp <= dl ? dp : dl);

      int b1 = 0, b2 = 0, b3 = 0;

      try {
    while (sp < sl) {
        b1 = sa[sp] & 0xff;
              int inputSize = 1;
        switch (b1) {
      case ISO_SO:
          shiftout = true;
          inputSize = 1;
          break;
      case ISO_SI:
          shiftout = false;
          inputSize = 1;
          break;
      case ISO_ESC:
          if (sl - sp - 1 < minDesignatorLength)
        return CoderResult.UNDERFLOW;

                            int desig = findDesig(sa, sp + 1, sl, SODesig);
                            if (desig != -1) {
        curSODes = desig;
        inputSize = SODesig[desig].length + 1;
        break;
          }
                            desig = findDesig(sa, sp + 1, sl, SS2Desig);
                            if (desig != -1) {
        curSS2Des = desig;
        inputSize = SS2Desig[desig].length + 1;
        break;
          }
                            desig = findDesig(sa, sp + 1, sl, SS3Desig);
                            if (desig != -1) {
              curSS3Des = desig;
        inputSize = SS3Desig[desig].length + 1;
        break;
          }
          if (sl - sp < 2)
              return CoderResult.UNDERFLOW;
                            b1 = sa[sp + 1];
          switch(b1) {
          case ISO_SS2_7:
              if (sl - sp < 4)
                  return CoderResult.UNDERFLOW;
              b2 = sa[sp +2];
        b3 = sa[sp +3];
        if (dl - dp <1)
            return CoderResult.OVERFLOW;
        da[dp] = decode((byte)b2,
            (byte)b3,
            SS2Flag);
        dp++;
        inputSize = 4;
        break;
          case ISO_SS3_7:
              if (sl - sp < 4)
                  return CoderResult.UNDERFLOW;
              b2 = sa[sp + 2];
        b3 = sa[sp + 3];
        if (dl - dp <1)
            return CoderResult.OVERFLOW;
        da[dp] = decode((byte)b2,
            (byte)b3,
            SS3Flag);
        dp++;
        inputSize = 4;
        break;
          default:
              return CoderResult.malformedForLength(2);
          }
          break;
      default:
          if (dl - dp < 1)
        return CoderResult.OVERFLOW;
          if (!shiftout) {
        da[dp++]=(char)(sa[sp] & 0xff);
          } else {
        if (dl - dp < 1)
            return CoderResult.OVERFLOW;
        if (sl - sp < 2)
            return CoderResult.UNDERFLOW;
        b2 = sa[sp+1] & 0xff;
        da[dp++] = decode((byte)b1,
                    (byte)b2,
               SOFlag);
        inputSize = 2;
          }
          break;
        }        
        sp += inputSize;
    }
    return CoderResult.UNDERFLOW;
      } finally {
    src.position(sp - src.arrayOffset());
    dst.position(dp - dst.arrayOffset());
      }
  }

  private CoderResult decodeBufferLoop(ByteBuffer src,
               CharBuffer dst)
  {
      int mark = src.position();
      int b1 = 0, b2 = 0, b3 = 0;

      try {
    while (src.hasRemaining()) {
        b1 = src.get();
              int inputSize = 1;
        switch (b1) {
      case ISO_SO:
          shiftout = true;
          break;
      case ISO_SI:
          shiftout = false;
          break;
      case ISO_ESC:
          if (src.remaining() < minDesignatorLength)
        return CoderResult.UNDERFLOW;

                            int desig = findDesigBuf(src, SODesig);
                            if (desig != -1) {
        curSODes = desig;
        inputSize = SODesig[desig].length + 1;
        break;
          }
                            desig = findDesigBuf(src, SS2Desig);
                            if (desig != -1) {
        curSS2Des = desig;
        inputSize = SS2Desig[desig].length + 1;
        break;
          }
                            desig = findDesigBuf(src, SS3Desig);
                            if (desig != -1) {
              curSS3Des = desig;
        inputSize = SS3Desig[desig].length + 1;
        break;
          }

          if (src.remaining() < 1)
              return CoderResult.UNDERFLOW;
                            b1 = src.get();
          switch(b1) {
              case ISO_SS2_7:
                  if (src.remaining() < 2)
                      return CoderResult.UNDERFLOW;
            b2 = src.get();
            b3 = src.get();
            if (dst.remaining() < 1)
                return CoderResult.OVERFLOW;
            dst.put(decode((byte)b2,
               (byte)b3,
               SS2Flag));
            inputSize = 4;
            break;
              case ISO_SS3_7:
                  if (src.remaining() < 2)
                      return CoderResult.UNDERFLOW;
            b2 = src.get();
            b3 = src.get();
            if (dst.remaining() < 1)
                return CoderResult.OVERFLOW;
            dst.put(decode((byte)b2,
               (byte)b3,
               SS3Flag));
            inputSize = 4;
            break;
              default:
            return CoderResult.malformedForLength(2);
          }
          break;
      default:
          if (dst.remaining() < 1)
        return CoderResult.OVERFLOW;
          if (!shiftout) {
        dst.put((char)(b1 & 0xff));
          } else {
        if (dst.remaining() < 1)
            return CoderResult.OVERFLOW;
        if (src.remaining() < 1)
            return CoderResult.UNDERFLOW;
        b2 = src.get() & 0xff;
        dst.put(decode((byte)b1,
                  (byte)b2,
              SOFlag));
        inputSize = 2;
          }
          break;
        }
        mark += inputSize;
    }
    return CoderResult.UNDERFLOW;
      } catch (Exception e) { e.printStackTrace(); return CoderResult.OVERFLOW; }
      finally { 
          src.position(mark);
      }
  }

  protected CoderResult decodeLoop(ByteBuffer src,
           CharBuffer dst)
  {
      if (src.hasArray() && dst.hasArray())
    return decodeArrayLoop(src, dst);
      else
    return decodeBufferLoop(src, dst);
  }
    }

    protected static class Encoder extends CharsetEncoder {
        private final Surrogate.Parser sgp = new Surrogate.Parser();
  private final byte SS2 = (byte)0x8e;
  private final byte P2 = (byte)0xA2;
  private final byte P3 = (byte)0xA3;
  private final byte MSB = (byte)0x80;

  protected final byte maximumDesignatorLength = 4;

  protected String SODesig,
       SS2Desig = null,
       SS3Desig = null;

  protected CharsetEncoder ISOEncoder;

  private boolean shiftout = false;
  private boolean SODesDefined = false;
  private boolean SS2DesDefined = false;
  private boolean SS3DesDefined = false;

  private boolean newshiftout = false;
  private boolean newSODesDefined = false;
  private boolean newSS2DesDefined = false;
  private boolean newSS3DesDefined = false;

  protected Encoder(Charset cs) {
      super(cs, 4.0f, 8.0f);
  }

  public boolean canEncode(char c) {
      return (ISOEncoder.canEncode(c));
  }

  protected void implReset() {
      shiftout = false;
      SODesDefined = false;
      SS2DesDefined = false;
      SS3DesDefined = false;
  }

  private int unicodeToNative(char unicode, byte ebyte[])
  {
      int  index = 0;
      byte  tmpByte[];
      char  convChar[] = {unicode};
      byte  convByte[] = new byte[4];
      int   converted;

      try{
    CharBuffer cc = CharBuffer.wrap(convChar);
    ByteBuffer bb = ByteBuffer.allocate(4);
    ISOEncoder.encode(cc, bb, true);
    bb.flip();
    converted = bb.remaining();
    bb.get(convByte,0,converted);
      } catch(Exception e) {
    return -1;
      }

      if (converted == 2) {
    if (!SODesDefined) {
        newSODesDefined = true;
        ebyte[0] = ISO_ESC;
        tmpByte = SODesig.getBytes();
        System.arraycopy(tmpByte,0,ebyte,1,tmpByte.length);
        index = tmpByte.length+1;
    }
    if (!shiftout) {
        newshiftout = true;
        ebyte[index++] = ISO_SO;
    }
    ebyte[index++] = (byte)(convByte[0] & 0x7f);
    ebyte[index++] = (byte)(convByte[1] & 0x7f);
      } else {
    if((convByte[0] == SS2) && (convByte[1] == P2)) {
        if (!SS2DesDefined) {
      newSS2DesDefined = true;
      ebyte[0] = ISO_ESC;
      tmpByte = SS2Desig.getBytes();
      System.arraycopy(tmpByte, 0, ebyte, 1, tmpByte.length);
      index = tmpByte.length+1;
        }
        ebyte[index++] = ISO_ESC;
        ebyte[index++] = ISO_SS2_7;
        ebyte[index++] = (byte)(convByte[2] & 0x7f);
        ebyte[index++] = (byte)(convByte[3] & 0x7f);
    }
    if((convByte[0] == SS2)&&(convByte[1] == 0xA3))
    {
        if(!SS3DesDefined){
      newSS3DesDefined = true;
      ebyte[0] = ISO_ESC;
      tmpByte = SS3Desig.getBytes();
      System.arraycopy(tmpByte, 0, ebyte, 1, tmpByte.length);
      index = tmpByte.length+1;
        }
        ebyte[index++] = ISO_ESC;
        ebyte[index++] = ISO_SS3_7;
        ebyte[index++] = (byte)(convByte[2] & 0x7f);
        ebyte[index++] = (byte)(convByte[3] & 0x7f);
    }
      }
      return index;
  }

  private CoderResult encodeArrayLoop(CharBuffer src,
              ByteBuffer dst)
  {
      char[] sa = src.array();
      int sp = src.arrayOffset() + src.position();
      int sl = src.arrayOffset() + src.limit();
      assert (sp <= sl);
      sp = (sp <= sl ? sp : sl);
      byte[] da = dst.array();
      int dp = dst.arrayOffset() + dst.position();
      int dl = dst.arrayOffset() + dst.limit();
      assert (dp <= dl);
      dp = (dp <= dl ? dp : dl);

      int outputSize = 0;
      byte[]  outputByte = new byte[8];
      newshiftout = shiftout;
      newSODesDefined = SODesDefined;
      newSS2DesDefined = SS2DesDefined;
      newSS3DesDefined = SS3DesDefined;

      try {
    while (sp < sl) {
                    char c = sa[sp];
                    if (Surrogate.is(c)) {
            if (sgp.parse(c, sa, sp, sl) < 0)
          return sgp.error();
                        return sgp.unmappableResult();
        }

        if (c < 0x80) {  // ASCII
      if (shiftout){
          newshiftout = false;
          outputSize = 2;
          outputByte[0] = ISO_SI;
          outputByte[1] = (byte)(c & 0x7f);
      } else {
          outputSize = 1;
          outputByte[0] = (byte)(c & 0x7f);
      }
      if(sa[sp] == '\n'){
          newSODesDefined = false;
          newSS2DesDefined = false;
          newSS3DesDefined = false;
      }
        } else {
      outputSize = unicodeToNative(c, outputByte);
                        if (outputSize == 0) {
          return CoderResult.unmappableForLength(1);
                        }
        }
        if (dl - dp < outputSize)
      return CoderResult.OVERFLOW;

        for (int i = 0; i < outputSize; i++)
      da[dp++] = outputByte[i];
        sp++;
        shiftout = newshiftout;
        SODesDefined = newSODesDefined;
        SS2DesDefined = newSS2DesDefined;
        SS3DesDefined = newSS3DesDefined;
    }
    return CoderResult.UNDERFLOW;
       } finally {
    src.position(sp - src.arrayOffset());
    dst.position(dp - dst.arrayOffset());
       }
  }


  private CoderResult encodeBufferLoop(CharBuffer src,
               ByteBuffer dst)
  {
      int outputSize = 0;
      byte[]  outputByte = new byte[8];
      int     inputSize = 0;           // Size of input
      newshiftout = shiftout;
      newSODesDefined = SODesDefined;
      newSS2DesDefined = SS2DesDefined;
      newSS3DesDefined = SS3DesDefined;
      int mark = src.position();

      try {
    while (src.hasRemaining()) {
        char inputChar = src.get();
                    if (Surrogate.is(inputChar)) {
            if (sgp.parse(inputChar, src) < 0)
          return sgp.error();
                        return sgp.unmappableResult();
        }
        if (inputChar < 0x80) {  // ASCII
      if (shiftout){
          newshiftout = false;
          outputSize = 2;
          outputByte[0] = ISO_SI;
          outputByte[1] = (byte)(inputChar & 0x7f);
      } else {
          outputSize = 1;
          outputByte[0] = (byte)(inputChar & 0x7f);
      }
      if(inputChar == '\n'){
          newSODesDefined = false;
          newSS2DesDefined = false;
          newSS3DesDefined = false;
      }
        } else {
      outputSize = unicodeToNative(inputChar, outputByte);
                        if (outputSize == 0) {
          return CoderResult.unmappableForLength(1);
                        }
        }

        if (dst.remaining() < outputSize)
      return CoderResult.OVERFLOW;
        for (int i = 0; i < outputSize; i++)
      dst.put(outputByte[i]);
        mark++;
        shiftout = newshiftout;
        SODesDefined = newSODesDefined;
        SS2DesDefined = newSS2DesDefined;
        SS3DesDefined = newSS3DesDefined;
    }
    return CoderResult.UNDERFLOW;
      } finally {
    src.position(mark);
      }
  }

  protected CoderResult encodeLoop(CharBuffer src,
           ByteBuffer dst)
  {
      if (src.hasArray() && dst.hasArray())
    return encodeArrayLoop(src, dst);
      else
    return encodeBufferLoop(src, dst);
  }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.