/*
 *******************************************************************************
 * Copyright (C) 2008-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.charset;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;

import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.UTF16;
import com.ibm.icu.text.UnicodeSet;

/**
 * @author krajwade
 *
 */
class CharsetSCSU extends CharsetICU{
    /* SCSU definitions --------------------------------------------------------- */

    /* SCSU command byte values */
    //enum {
    private static final short SQ0=0x01; /* Quote from window pair 0 */
    private static final short SQ7=0x08; /* Quote from window pair 7 */
    private static final short SDX=0x0B; /* Define a window as extended */
    //private static final short Srs=0x0C; /* reserved */
    private static final short SQU=0x0E; /* Quote a single Unicode character */
    private static final short SCU=0x0F; /* Change to Unicode mode */
    private static final short SC0=0x10; /* Select window 0 */
    private static final short SC7=0x17; /* Select window 7 */
    private static final short SD0=0x18; /* Define and select window 0 */
    //private static final short SD7=0x1F; /* Define and select window 7 */
    
    private static final short UC0=0xE0; /* Select window 0 */
    private static final short UC7=0xE7; /* Select window 7 */
    private static final short UD0=0xE8; /* Define and select window 0 */
    private static final short UD7=0xEF; /* Define and select window 7 */
    private static final short UQU=0xF0; /* Quote a single Unicode character */
    private static final short UDX=0xF1; /* Define a Window as extended */
    private static final short Urs=0xF2;  /* reserved */
   // };
   
  //  enum {
        /*
         * Unicode code points from 3400 to E000 are not adressible by
         * dynamic window, since in these areas no short run alphabets are
         * found. Therefore add gapOffset to all values from gapThreshold.
         */
    private static final int gapThreshold=0x68;
    private static final int gapOffset = 0xAC00 ;
    /* values between reservedStart and fixedThreshold are reserved */
    private static final int reservedStart=0xA8;
    /* use table of predefined fixed offsets for values from fixedThreshold */
    private static final int fixedThreshold=0xF9;
    //};
    
    protected byte[] fromUSubstitution = new byte[]{(byte)0x0E,(byte)0xFF, (byte)0xFD};
    
    /* constant offsets for the 8 static windows */
    private static final int staticOffsets[]={
        0x0000, /* ASCII for quoted tags */
        0x0080, /* Latin - 1 Supplement (for access to punctuation) */
        0x0100, /* Latin Extended-A */
        0x0300, /* Combining Diacritical Marks */
        0x2000, /* General Punctuation */
        0x2080, /* Currency Symbols */
        0x2100, /* Letterlike Symbols and Number Forms */
        0x3000  /* CJK Symbols and punctuation */
    };

    /* initial offsets for the 8 dynamic (sliding) windows */
   private static final int initialDynamicOffsets[]={
        0x0080, /* Latin-1 */
        0x00C0, /* Latin Extended A */
        0x0400, /* Cyrillic */
        0x0600, /* Arabic */
        0x0900, /* Devanagari */
        0x3040, /* Hiragana */
        0x30A0, /* Katakana */
        0xFF00  /* Fullwidth ASCII */
    };

    /* Table of fixed predefined Offsets */
    private static final int fixedOffsets[]={
        /* 0xF9 */ 0x00C0, /* Latin-1 Letters + half of Latin Extended A */
        /* 0xFA */ 0x0250, /* IPA extensions */
        /* 0xFB */ 0x0370, /* Greek */
        /* 0xFC */ 0x0530, /* Armenian */
        /* 0xFD */ 0x3040, /* Hiragana */
        /* 0xFE */ 0x30A0, /* Katakana */
        /* 0xFF */ 0xFF60  /* Halfwidth Katakana */
    };

    /* state values */
    //enum {
    private static final int readCommand=0;
    private static final int quotePairOne=1;
    private static final int quotePairTwo=2;
    private static final int quoteOne=3;
    private static final int definePairOne=4;
    private static final int definePairTwo=5;
    private static final int defineOne=6;
  //  };
    
    @SuppressWarnings("unused")
    private final class SCSUData{   
        /* dynamic window offsets, intitialize to default values from initialDynamicOffsets */
        int toUDynamicOffsets[] = new int[8] ;
        int fromUDynamicOffsets[] = new int[8] ; 

        /* state machine state - toUnicode */
        boolean toUIsSingleByteMode;
        short toUState;
        byte toUQuoteWindow, toUDynamicWindow;
        short toUByteOne;
        short toUPadding[];

        /* state machine state - fromUnicode */
        boolean fromUIsSingleByteMode;
        byte fromUDynamicWindow;

        /*
         * windowUse[] keeps track of the use of the dynamic windows:
         * At nextWindowUseIndex there is the least recently used window,
         * and the following windows (in a wrapping manner) are more and more
         * recently used.
         * At nextWindowUseIndex-1 there is the most recently used window.
         */
        byte locale;
        byte nextWindowUseIndex;
        byte windowUse[] = new byte[8];
        
        SCSUData(){
            initialize();
        }
        
        void initialize(){
            for(int i=0;i<8;i++){
                this.toUDynamicOffsets[i] = initialDynamicOffsets[i];
            }
            this.toUIsSingleByteMode = true;
            this.toUState = readCommand;
            this.toUQuoteWindow = 0;
            this.toUDynamicWindow = 0;
            this.toUByteOne = 0;
            this.fromUIsSingleByteMode = true;
            this.fromUDynamicWindow = 0;
            for(int i=0;i<8;i++){
                this.fromUDynamicOffsets[i] = initialDynamicOffsets[i];
            }
            this.nextWindowUseIndex = 0; 
            switch(this.locale){
            /* Note being used right now because "SCSU,locale=ja" does not work in ICU4J. */
            /*    case l_ja:
                    for(int i=0;i<8;i++){
                        this.windowUse[i] = initialWindowUse_ja[i];
                    }
                    break; */
                default:
                    for(int i=0;i<8;i++){
                        this.windowUse[i] = initialWindowUse[i];
                    }
                    
            }
        }
    }
    
    static final byte initialWindowUse[]={ 7, 0, 3, 2, 4, 5, 6, 1 };
    /* Note being used right now because "SCSU,locale=ja" does not work in ICU4J. */
    // static final byte initialWindowUse_ja[]={ 3, 2, 4, 1, 0, 7, 5, 6 };

    //enum {
    //private static final int lGeneric = 0;
    /* Note being used right now because "SCSU,locale=ja" does not work in ICU4J. */
    // private static final int l_ja = 1;
    //};
    
    private SCSUData extraInfo = null; 
    
    public CharsetSCSU(String icuCanonicalName, String javaCanonicalName, String[] aliases){
        super(icuCanonicalName, javaCanonicalName, aliases);
        maxBytesPerChar = 3; 
        minBytesPerChar = 1;
        maxCharsPerByte = 1;
        extraInfo = new SCSUData();
    }
    
    class CharsetDecoderSCSU extends CharsetDecoderICU {       
        /* label values for supporting behavior similar to goto in C */
        private static final int FastSingle=0;
        private static final int SingleByteMode=1;
        private static final int EndLoop=2;
        
        /* Mode Type */
        private static final int ByteMode = 0;
        private static final int UnicodeMode =1;       
        
        public CharsetDecoderSCSU(CharsetICU cs) {
            super(cs);
            implReset();
        }
        
        //private SCSUData data ;
        protected void implReset(){
            super.implReset();
            toULength = 0;
            extraInfo.initialize();
        }
        
        short b;
        
        //Get the state machine state 
        private boolean isSingleByteMode ;
        private short state ;
        private byte quoteWindow ;
        private byte dynamicWindow ;
        private short byteOne;
        
        
        //sourceIndex=-1 if the current character began in the previous buffer
        private int sourceIndex  ;
        private int nextSourceIndex ;
        
        CoderResult cr;
        SCSUData data ;
        private boolean LabelLoop;// used to break the while loop
        
        protected CoderResult decodeLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets,
                boolean flush){
            data = extraInfo;
            
            //Get the state machine state 
            isSingleByteMode = data.toUIsSingleByteMode;
            state = data.toUState;
            quoteWindow = data.toUQuoteWindow;
            dynamicWindow = data.toUDynamicWindow;
            byteOne = data.toUByteOne;
            
            LabelLoop = true;
            
            //sourceIndex=-1 if the current character began in the previous buffer
            sourceIndex = data.toUState == readCommand ? 0: -1 ;
            nextSourceIndex = 0;
            
            cr = CoderResult.UNDERFLOW;
            int labelType = 0;
            while(LabelLoop){
                if(isSingleByteMode){
                    switch(labelType){
                        case FastSingle:
                            /*fast path for single-byte mode*/
                            labelType = fastSingle(source, target, offsets, ByteMode);
                            break;
                        case SingleByteMode:
                            /* normal state machine for single-byte mode, minus handling for what fastSingleCovers */
                            labelType = singleByteMode(source, target, offsets, ByteMode);
                            break;
                        case EndLoop:
                            endLoop(source, target, offsets);
                            break;
                    }
                }else{
                    switch(labelType){
                        case FastSingle:
                            /*fast path for single-byte mode*/
                            labelType = fastSingle(source, target, offsets, UnicodeMode);
                            break;
                        case SingleByteMode:
                            /* normal state machine for single-byte mode, minus handling for what fastSingleCovers */
                            labelType = singleByteMode(source, target, offsets, UnicodeMode);
                            break;
                        case EndLoop:
                            endLoop(source, target, offsets);
                            break;
                    }
                    //LabelLoop = false;
                }
            }
            return cr;
        }
        
        private int fastSingle(ByteBuffer source, CharBuffer target, IntBuffer offsets, int modeType){
            int label = 0;
            if(modeType==ByteMode){
                
                if(state==readCommand){
                    while(source.hasRemaining() && target.hasRemaining() && (b=(short)(source.get(source.position()) & UConverterConstants.UNSIGNED_BYTE_MASK)) >= 0x20){
                        source.position(source.position()+1);
                        ++nextSourceIndex;
                        if(b <= 0x7f){
                            /*Write US graphic character or DEL*/
                            target.put((char)b);
                            if(offsets != null){
                                offsets.put(sourceIndex);
                            }
                        }else{
                            /*Write from dynamic window*/
                            int c = data.toUDynamicOffsets[dynamicWindow] + (b&0x7f);
                            if(c <= 0xffff){
                                target.put((char)c);
                                if(offsets != null){
                                    offsets.put(sourceIndex);
                                }
                            }else{
                                /*Output surrogate pair */
                                target.put((char)(0xd7c0 + (c>>10)));
                                if(target.hasRemaining()){
                                    target.put((char)(0xdc00 | (c&0x3ff)));
                                    if(offsets != null){
                                        offsets.put(sourceIndex);
                                        offsets.put(sourceIndex);
                                    }
                                }else{
                                    /* target overflow */
                                    if(offsets != null){
                                        offsets.put(sourceIndex);
                                    }
                                    charErrorBufferArray[0] = (char)(0xdc00 | (c&0x3ff));
                                    charErrorBufferLength = 1;
                                    label = EndLoop;
                                    cr = CoderResult.OVERFLOW;
                                    return label;
                                }
                            }
                        }
                        sourceIndex = nextSourceIndex;
                    }
                   // label = SingleByteMode;
                }
            }else if(modeType==UnicodeMode){
                /* fast path for unicode mode */
                if(state == readCommand){
                    while((source.position()+1)<source.limit() && target.hasRemaining() && (((b=source.get(source.position()))-UC0)&UConverterConstants.UNSIGNED_BYTE_MASK)>(Urs-UC0)){
                        target.put((char)((b<<8)|(source.get(source.position()+1)&UConverterConstants.UNSIGNED_BYTE_MASK)));
                        if(offsets != null){
                            offsets.put(sourceIndex);
                        }
                        sourceIndex = nextSourceIndex;
                        nextSourceIndex+=2;
                        source.position(source.position()+2);
                    }
                }
            }
            label = SingleByteMode;
            return label;
        }
        
        private int singleByteMode(ByteBuffer source, CharBuffer target, IntBuffer offsets, int modeType){
            int label = SingleByteMode;
            if(modeType == ByteMode){
                while(source.hasRemaining()){
                    if(!target.hasRemaining()){
                        cr = CoderResult.OVERFLOW;
                        LabelLoop = false;
                        return label;
                     }
                    b = (short)(source.get() & UConverterConstants.UNSIGNED_BYTE_MASK);
                    ++nextSourceIndex;
                    switch(state){
                    case readCommand:
                        /*redundant conditions are commented out */
                        if(((1L<<b)&0x2601)!=0){
                            target.put((char)b);
                            if(offsets != null){
                                offsets.put(sourceIndex);
                            }
                            sourceIndex = nextSourceIndex;
                            label = FastSingle;
                            return label;
                        }else if(SC0 <= b){
                            if(b<=SC7){
                                dynamicWindow = (byte)(b-SC0);
                                sourceIndex = nextSourceIndex;
                                label = FastSingle;
                                return label;
                            }else /* if(SD0<=b && b<=SQ7)*/{
                                dynamicWindow = (byte)(b - SD0);
                                state = defineOne;
                            }
                        }else if(/* SQ0<=b &&*/b <= SQ7){
                            quoteWindow = (byte)(b - SQ0);
                            state = quoteOne;
                        }else if(b==SDX){
                            state = definePairOne;
                        }else if(b==SQU){
                            state = quotePairOne;
                        }else if(b==SCU){
                            sourceIndex = nextSourceIndex;
                            isSingleByteMode = false;
                            label = FastSingle;
                            return label;
                        }else{
                            /*callback (illegal)*/
                            cr = CoderResult.malformedForLength(1);
                            toUBytesArray[0] = (byte)b;
                            toULength =1;
                            label = EndLoop;
                            return label;
                        }
                        
                        /* Store the first byte of a multibyte sequence in toUByte[] */
                        toUBytesArray[0] = (byte)b;
                        toULength = 1;
                        break;
                    case quotePairOne:
                        byteOne = b;
                        toUBytesArray[1] = (byte)b;
                        toULength = 2;
                        state = quotePairTwo;
                        break;
                    case quotePairTwo:
                        target.put((char)((byteOne<< 8) | b));
                        if(offsets != null){
                            offsets.put(sourceIndex);
                        }
                        sourceIndex = nextSourceIndex;
                        state = readCommand;
                        label = FastSingle;
                        return label;
                    case quoteOne:
                        if(b<0x80){
                            /* all static offsets are in the BMP */
                            target.put((char)(staticOffsets[quoteWindow] + b));
                            if(offsets != null){
                                offsets.put(sourceIndex);
                            }
                        }else {
                            /*write from dynamic window */
                            int c = data.toUDynamicOffsets[quoteWindow] + (b&0x7f);
                            if(c<=0xffff){
                                target.put((char)c);
                                if(offsets != null){
                                    offsets.put(sourceIndex);
                                }
                            }else {
                                /* output surrogate pair */
                                target.put((char)(0xd7c0+(c>>10)));
                                if(target.hasRemaining()){
                                    target.put((char)(0xdc00 | (c&0x3ff)));
                                    if(offsets != null){
                                        offsets.put(sourceIndex);
                                        offsets.put(sourceIndex);
                                    }
                                }else {
                                    /* target overflow */
                                    if(offsets != null){
                                        offsets.put(sourceIndex);
                                    }
                                    charErrorBufferArray[0] = (char)(0xdc00 | (c&0x3ff));
                                    charErrorBufferLength = 1;
                                    label = EndLoop;
                                    cr = CoderResult.OVERFLOW;
                                    LabelLoop = false;
                                    return label;
                                }
                            }
                        }
                        sourceIndex = nextSourceIndex;
                        state = readCommand;
                        label = FastSingle;
                        return label;
                    case definePairOne:
                        dynamicWindow = (byte)((b>>5)&7);
                        byteOne = (byte)(b&0x1f);
                        toUBytesArray[1] = (byte)b;
                        toULength = 2;
                        state = definePairTwo;
                        break;
                    case definePairTwo:
                        data.toUDynamicOffsets[dynamicWindow] = 0x10000 + (byteOne<<15L | b<<7L);
                        sourceIndex = nextSourceIndex;
                        state = readCommand;
                        label = FastSingle;
                        return label;
                    case defineOne:
                        if(b==0){
                            /*callback (illegal)*/
                            toUBytesArray[1] = (byte)b;
                            toULength =2;
                            label = EndLoop;
                            return label;
                        }else if(b<gapThreshold){
                            data.toUDynamicOffsets[dynamicWindow] = b<<7L;
                        }else if(((b - gapThreshold)&UConverterConstants.UNSIGNED_BYTE_MASK)<(reservedStart - gapThreshold)){
                            data.toUDynamicOffsets[dynamicWindow] = (b<<7L) + gapOffset;
                        }else if(b>=fixedThreshold){
                            data.toUDynamicOffsets[dynamicWindow] = fixedOffsets[b-fixedThreshold];
                        }else{
                            /*callback (illegal)*/
                            toUBytesArray[1] = (byte)b;
                            toULength =2;
                            label = EndLoop;
                            return label;
                        }
                        sourceIndex = nextSourceIndex;
                        state = readCommand;
                        label = FastSingle;
                        return label;
                    }
                }
                
            }else if(modeType==UnicodeMode){
                while(source.hasRemaining()){
                    if(!target.hasRemaining()){
                        cr = CoderResult.OVERFLOW;
                        LabelLoop = false;
                        return label;
                    }
                    b = (short)(source.get() & UConverterConstants.UNSIGNED_BYTE_MASK);
                    ++nextSourceIndex;
                    switch(state){
                    case readCommand:
                        if((short)((b -UC0)&UConverterConstants.UNSIGNED_BYTE_MASK)>(Urs - UC0)){
                            byteOne = b;
                            toUBytesArray[0] = (byte)b;
                            toULength = 1;
                            state = quotePairTwo;
                        }else if((b&UConverterConstants.UNSIGNED_BYTE_MASK) <= UC7){
                            dynamicWindow = (byte)(b - UC0);
                            sourceIndex = nextSourceIndex;
                            isSingleByteMode = true;
                            label = FastSingle;
                            return label;
                        }else if((b&UConverterConstants.UNSIGNED_BYTE_MASK) <= UD7){
                            dynamicWindow = (byte)(b - UD0);
                            isSingleByteMode = true;
                            toUBytesArray[0] = (byte)b;
                            toULength = 1;
                            state = defineOne;
                            label = SingleByteMode;
                            return label;
                        }else if((b&UConverterConstants.UNSIGNED_BYTE_MASK) == UDX){
                            isSingleByteMode = true;
                            toUBytesArray[0] = (byte)b;
                            toULength = 1;
                            state = definePairOne;
                            label = SingleByteMode;
                            return label;
                        }else if((b&UConverterConstants.UNSIGNED_BYTE_MASK) == UQU){
                            toUBytesArray[0] = (byte)b;
                            toULength = 1;
                            state = quotePairOne;
                        }else {
                            /* callback (illegal)*/
                            cr = CoderResult.malformedForLength(1);
                            toUBytesArray[0] = (byte)b;
                            toULength = 1;
                            label = EndLoop;
                            return label;
                        }
                        break;
                    case quotePairOne:
                        byteOne = b;
                        toUBytesArray[1] = (byte)b;
                        toULength = 2;
                        state = quotePairTwo;
                        break;
                    case quotePairTwo:
                        target.put((char)((byteOne<<8) | b));
                        if(offsets != null){
                            offsets.put(sourceIndex);
                        }
                        sourceIndex = nextSourceIndex;
                        state = readCommand;
                        label = FastSingle;
                        return label;
                    }
                }
            }
            label = EndLoop;
            return label;
        }
        
        private void endLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets){
            if(cr==CoderResult.OVERFLOW){
                state = readCommand;
            }else if(state == readCommand){
                toULength = 0;
            }
            data.toUIsSingleByteMode = isSingleByteMode;
            data.toUState = state;
            data.toUQuoteWindow = quoteWindow;
            data.toUDynamicWindow = dynamicWindow;
            data.toUByteOne = byteOne;
            LabelLoop = false;
        }
    }
    
    class CharsetEncoderSCSU extends CharsetEncoderICU{
        public CharsetEncoderSCSU(CharsetICU cs) {
            super(cs, fromUSubstitution);
            implReset();
        }
        
        //private SCSUData data;
        protected void implReset() {
            super.implReset();
            extraInfo.initialize();
        }
        
        /* label values for supporting behavior similar to goto in C */
        private static final int Loop=0; 
        private static final int GetTrailUnicode=1;
        private static final int OutputBytes=2;
        private static final int EndLoop =3;
        
        private int delta;
        private int length;
        
        ///variables of compression heuristics
        private int offset;
        private char lead, trail;
        private int code;
        private byte window;
        
        //Get the state machine state 
        private boolean isSingleByteMode;
        private byte dynamicWindow ;
        private int currentOffset;
        int c;
        
        SCSUData data ;
        
        //sourceIndex=-1 if the current character began in the previous buffer
        private int sourceIndex ;
        private int nextSourceIndex;
        private int targetCapacity;
        
        private boolean LabelLoop;//used to break the while loop
        private boolean AfterGetTrail;// its value is set to true in order to ignore the code before getTrailSingle:
        private boolean AfterGetTrailUnicode;// is value is set to true in order to ignore the code before getTrailUnicode:
        
        CoderResult cr;
        
        protected CoderResult encodeLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
            data = extraInfo;
            cr = CoderResult.UNDERFLOW;
            
            //Get the state machine state 
            isSingleByteMode = data.fromUIsSingleByteMode;
            dynamicWindow = data.fromUDynamicWindow;
            currentOffset = data.fromUDynamicOffsets[dynamicWindow];
            c = fromUChar32;
            
            sourceIndex = c== 0 ? 0: -1 ;
            nextSourceIndex = 0;
                        
            
            targetCapacity = target.limit()-target.position();
            
            //sourceIndex=-1 if the current character began in the previous buffer
            sourceIndex = c== 0 ? 0: -1 ;
            nextSourceIndex = 0;
            
            int labelType = Loop; // set to Loop so that the code starts from loop:
            LabelLoop = true; 
            AfterGetTrail = false; 
            AfterGetTrailUnicode = false; 
            
            while(LabelLoop){
                switch(labelType){
                case Loop:
                    labelType = loop(source, target, offsets);
                    break;
                case GetTrailUnicode:
                    labelType = getTrailUnicode(source, target, offsets);
                    break;
                case OutputBytes:
                    labelType = outputBytes(source, target, offsets);
                    break;
                case EndLoop:
                    endLoop(source, target, offsets);
                    break;
                }
            }
            return cr;
        }
        
        private byte getWindow(int[] offsets){
            int i;
            for (i=0;i<8;i++){
                if(((c-offsets[i]) & UConverterConstants.UNSIGNED_INT_MASK) <= 0x7f){
                    return (byte)i;
                }
            }
            return -1;
        }
        
        private boolean isInOffsetWindowOrDirect(int offsetValue, int a){
            return (a & UConverterConstants.UNSIGNED_INT_MASK)<=(offsetValue & UConverterConstants.UNSIGNED_INT_MASK)+0x7f & 
                    ((a & UConverterConstants.UNSIGNED_INT_MASK)>=(offsetValue & UConverterConstants.UNSIGNED_INT_MASK) || 
                            ((a & UConverterConstants.UNSIGNED_INT_MASK)<=0x7f && ((a & UConverterConstants.UNSIGNED_INT_MASK)>=0x20 
                                    || ((1L<<(a & UConverterConstants.UNSIGNED_INT_MASK))&0x2601)!=0)));
        }
        
        private byte getNextDynamicWindow(){
            byte windowValue = data.windowUse[data.nextWindowUseIndex];
            if(++data.nextWindowUseIndex==8){
                data.nextWindowUseIndex=0;
            }
            return windowValue;
        }
        
        private void useDynamicWindow(byte windowValue){
            /*first find the index of the window*/
            int i,j;
            i = data.nextWindowUseIndex;
            do{
                if(--i<0){
                    i=7;
                }
            }while(data.windowUse[i]!=windowValue);
            
            /*now copy each window[i+1] to [i]*/
            j= i+1;
            if(j==8){
                j=0;
            }
            while(j!=data.nextWindowUseIndex){
                data.windowUse[i] = data.windowUse[j];
                i=j;
                if(++j==8){
                    j=0;
                }
            }
            
            /*finally, set the window into the most recently used index*/
            data.windowUse[i]= windowValue;
        }
        
        
       private int getDynamicOffset(){
            int i;
            for(i=0;i<7;++i){
                if(((c-fixedOffsets[i])&UConverterConstants.UNSIGNED_INT_MASK)<=0x7f){
                    offset = fixedOffsets[i];
                    return 0xf9+i;
                }
            }
            if((c&UConverterConstants.UNSIGNED_INT_MASK)<0x80){
                /*No dynamic window for US-ASCII*/
                return -1;
            }else if((c&UConverterConstants.UNSIGNED_INT_MASK)<0x3400 || ((c-0x10000)&UConverterConstants.UNSIGNED_INT_MASK)<(0x14000-0x10000) || 
                    ((c-0x1d000)&UConverterConstants.UNSIGNED_INT_MASK)<=(0x1ffff-0x1d000)){
                /*This character is in the code range for a "small", i.e, reasonably windowable, script*/
                offset = c&0x7fffff80;
                return (c>>7);
            }else if(0xe000<=(c&UConverterConstants.UNSIGNED_INT_MASK) && (c&UConverterConstants.UNSIGNED_INT_MASK)!=0xfeff && (c&UConverterConstants.UNSIGNED_INT_MASK) < 0xfff0){
                /*for these characters we need to take the gapOffset into account*/
                offset=(c)&0x7fffff80;
                return ((c-gapOffset)>>7);
            }else{
                return -1;
            }
        }
        
        private int loop(CharBuffer source, ByteBuffer target, IntBuffer offsets){
            int label = 0;
            if(isSingleByteMode){
                if(c!=0 && targetCapacity>0 && !AfterGetTrail){
                    label = getTrail(source, target, offsets);
                    return label;
                }
                /*state machine for single byte mode*/
                while(AfterGetTrail || source.hasRemaining()){
                    if(targetCapacity<=0 && !AfterGetTrail){
                        /*target is full*/
                        cr = CoderResult.OVERFLOW;
                        label = EndLoop;
                        return label;
                    }
                    if(!AfterGetTrail){
                        c = source.get();
                        ++nextSourceIndex;
                        
                    }
                    if(((c -0x20)&UConverterConstants.UNSIGNED_INT_MASK)<=0x5f && !AfterGetTrail){
                        /*pass US-ASCII graphic character through*/
                        target.put((byte)c);
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                        --targetCapacity;
                    }else if((c & UConverterConstants.UNSIGNED_INT_MASK)<0x20 && !AfterGetTrail){
                        if(((1L<<(c & UConverterConstants.UNSIGNED_INT_MASK))&0x2601)!=0){
                            /*CR/LF/TAB/NUL*/
                            target.put((byte)c);
                            if(offsets!=null){
                                offsets.put(sourceIndex);
                            }
                            --targetCapacity;
                        } else {
                            /*quote c0 control character*/
                            c|=SQ0<<8;
                            length = 2;
                            label = OutputBytes;
                            return label;
                        }
                    } else if(((delta=(c-currentOffset))&UConverterConstants.UNSIGNED_INT_MASK)<=0x7f && !AfterGetTrail){
                        /*use the current dynamic window*/
                        target.put((byte)(delta|0x80));
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                        --targetCapacity;
                    } else if(AfterGetTrail || UTF16.isSurrogate((char)c)){
                        if(!AfterGetTrail){
                            if(UTF16.isLeadSurrogate((char)c)){
                                label = getTrail(source, target, offsets);
                                if(label==EndLoop){
                                    return label;
                                }
                            } else {
                                /*this is unmatched lead code unit (2nd Surrogate)*/
                                /*callback(illegal)*/
                                cr = CoderResult.malformedForLength(1);
                                label = EndLoop;
                                return label;
                            }
                        }
                                                
                        
                        if(AfterGetTrail){
                            AfterGetTrail = false;
                        }
                        
                        /*Compress supplementary character U+10000...U+10ffff */
                        if(((delta=(c-currentOffset))&UConverterConstants.UNSIGNED_INT_MASK)<=0x7f){
                            /*use the current dynamic window*/
                            target.put((byte)(delta|0x80));
                            if(offsets!=null){
                                offsets.put(sourceIndex);
                            }
                            --targetCapacity;
                        } else if((window=getWindow(data.fromUDynamicOffsets))>=0){
                            /*there is a dynamic window that contains this character, change to it*/
                            dynamicWindow = window;
                            currentOffset = data.fromUDynamicOffsets[dynamicWindow];
                            useDynamicWindow(dynamicWindow);
                            c = ((SC0+dynamicWindow)<<8 | (c-currentOffset)|0x80);
                            length = 2;
                            label  = OutputBytes;
                            return label;
                        } else if((code=getDynamicOffset())>=0){
                            /*might check if there are come character in this window to come */
                            /*define an extended window with this character*/
                            code-=0x200;
                            dynamicWindow=getNextDynamicWindow();
                            currentOffset = data.fromUDynamicOffsets[dynamicWindow]=offset;
                            useDynamicWindow(dynamicWindow);
                            c = ((SDX<<24) | (dynamicWindow<<21)|
                                 (code<<8)| (c- currentOffset) |0x80);
                           // c = (((SDX)<<25) | (dynamicWindow<<21)|
                             //           (code<<8)| (c- currentOffset) |0x80  );
                            length = 4;
                            label = OutputBytes;
                            return label;
                        } else {
                            /*change to unicode mode and output this (lead, trail) pair*/
                            isSingleByteMode = false;
                            target.put((byte)SCU);
                            if(offsets!=null){
                                offsets.put(sourceIndex);
                            }
                            --targetCapacity;
                            c = (lead<<16)|trail;
                            length = 4;
                            label = OutputBytes;
                            return label;
                        }
                    } else if((c&UConverterConstants.UNSIGNED_INT_MASK)<0xa0){
                        /*quote C1 control character*/
                        c = (c&0x7f) | (SQ0+1)<<8; /*SQ0+1 == SQ1*/
                        length = 2;
                        label = OutputBytes;
                        return label;
                    } else if((c&UConverterConstants.UNSIGNED_INT_MASK)==0xfeff || (c&UConverterConstants.UNSIGNED_INT_MASK)>= 0xfff0){
                        /*quote signature character = byte order mark and specials*/
                        c |= SQU<<16;
                        length = 3;
                        label = OutputBytes;
                        return label;
                    } else {
                        /*compress all other BMP characters*/
                        if((window=getWindow(data.fromUDynamicOffsets))>=0){
                            /*there is a window defined that contains this character - switch to it or quote from it*/
                            if(source.position()>=source.limit() || isInOffsetWindowOrDirect(data.fromUDynamicOffsets[window], source.get(source.position()))){
                                /*change to dynamic window*/
                                dynamicWindow = window;
                                currentOffset = data.fromUDynamicOffsets[dynamicWindow];
                                useDynamicWindow(dynamicWindow);
                                c = ((SC0+window)<<8) | (c- currentOffset) | 0x80;
                                length = 2;
                                label = OutputBytes;
                                return label;
                            } else {
                                /*quote from dynamic window*/
                                c = ((SQ0+window)<<8) | (c - data.fromUDynamicOffsets[window]) |
                                    0x80;
                                length = 2;
                                label = OutputBytes;
                                return label;
                            }
                        } else if((window = getWindow(staticOffsets))>=0){
                            /*quote from static window*/
                            c = ((SQ0+window)<<8) | (c - staticOffsets[window]);
                            length = 2;
                            label = OutputBytes;
                            return label;
                        }else if((code=getDynamicOffset())>=0){
                            /*define a dynamic window with this character*/
                            dynamicWindow = getNextDynamicWindow();
                            currentOffset = data.fromUDynamicOffsets[dynamicWindow]=offset;
                            useDynamicWindow(dynamicWindow);
                            c = ((SD0+dynamicWindow)<<16) | (code<<8)|
                                (c - currentOffset) | 0x80;
                            length = 3;
                            label = OutputBytes;
                            return label;
                        } else if(((int)((c-0x3400)&UConverterConstants.UNSIGNED_INT_MASK))<(0xd800-0x3400) && (source.position()>=source.limit() || 
                                ((int)((source.get(source.position())-0x3400)&UConverterConstants.UNSIGNED_INT_MASK))< (0xd800 - 0x3400))){
                            
                            /*
                             * this character is not compressible (a BMP ideograph of similar)
                             * switch to Unicode mode if this is the last character in the block
                             * or there is at least one more ideograph following immediately
                             */
                             isSingleByteMode = false;
                             c|=SCU<<16;
                             length =3;
                             label = OutputBytes;
                             return label;
                        } else {
                            /*quote Unicode*/
                            c|=SQU<<16;
                            length = 3;
                            label = OutputBytes;
                            return label;
                        }
                    }
                    /*normal end of conversion : prepare for new character */
                    c = 0;
                    sourceIndex = nextSourceIndex;
                }
            } else {
                if(c!=0 && targetCapacity>0 && !AfterGetTrailUnicode){
                    label = GetTrailUnicode;
                    return label;
                }
            
                /*state machine for Unicode*/
                /*unicodeByteMode*/
                while(AfterGetTrailUnicode || source.hasRemaining()){
                    if(targetCapacity<=0 && !AfterGetTrailUnicode){
                        /*target is full*/
                        cr = CoderResult.OVERFLOW;
                        LabelLoop = false;
                        break;
                    }
                    if(!AfterGetTrailUnicode){
                        c = source.get();
                        ++nextSourceIndex;
                    }
                    
                    if((((c-0x3400)& UConverterConstants.UNSIGNED_INT_MASK))<(0xd800-0x3400) && !AfterGetTrailUnicode){
                        /*not compressible, write character directly */
                        if(targetCapacity>=2){
                            target.put((byte)(c>>8));
                            target.put((byte)c);
                            if(offsets!=null){
                                offsets.put(sourceIndex);
                                offsets.put(sourceIndex);
                            }
                            targetCapacity-=2;
                        } else {
                            length =2;
                            label = OutputBytes;
                            return label;
                        }
                    } else if((((c-0x3400)& UConverterConstants.UNSIGNED_INT_MASK))>=(0xf300-0x3400) /* c<0x3400 || c>=0xf300*/&& !AfterGetTrailUnicode){
                        /*compress BMP character if the following one is not an uncompressible ideograph*/
                        if(!(source.hasRemaining() && (((source.get(source.position())-0x3400)& UConverterConstants.UNSIGNED_INT_MASK))<(0xd800-0x3400))){
                            if(((((c-0x30)&UConverterConstants.UNSIGNED_INT_MASK))<10 || (((c-0x61)&UConverterConstants.UNSIGNED_INT_MASK))<26 
                                    || (((c-0x41)&UConverterConstants.UNSIGNED_INT_MASK))<26)){
                                /*ASCII digit or letter*/
                                isSingleByteMode = true;
                                c |=((UC0+dynamicWindow)<<8)|c;
                                length = 2;
                                label = OutputBytes;
                                return label;
                            } else if((window=getWindow(data.fromUDynamicOffsets))>=0){
                                /*there is a dynamic window that contains this character, change to it*/
                                isSingleByteMode = true;
                                dynamicWindow = window;
                                currentOffset = data.fromUDynamicOffsets[dynamicWindow];
                                useDynamicWindow(dynamicWindow);
                                c = ((UC0+dynamicWindow)<<8) | (c- currentOffset) | 0x80;
                                length = 2;
                                label = OutputBytes;
                                return label;
                            } else if((code=getDynamicOffset())>=0){
                                /*define a dynamic window with this character*/
                                isSingleByteMode = true;
                                dynamicWindow = getNextDynamicWindow();
                                currentOffset = data.fromUDynamicOffsets[dynamicWindow]=offset;
                                useDynamicWindow(dynamicWindow);
                                c = ((UD0+dynamicWindow)<<16) | (code<<8) 
                                    |(c - currentOffset) | 0x80;
                                length = 3;
                                label = OutputBytes;
                                return label;
                            }
                        }
                        
                        /*don't know how to compress these character, just write it directly*/
                        length = 2;
                        label = OutputBytes;
                        return label;
                    } else if(c<0xe000 && !AfterGetTrailUnicode){
                        label = GetTrailUnicode;
                        return label;
                    } else if (!AfterGetTrailUnicode){
                        /*quote to avoid SCSU tags*/
                        c|=UQU<<16;
                        length = 3;
                        label = OutputBytes;
                        return label;
                    }
                    
                    if(AfterGetTrailUnicode){
                        AfterGetTrailUnicode = false;
                    }
                    /*normal end of conversion, prepare for a new character*/
                    c = 0;
                    sourceIndex = nextSourceIndex;
                }
            }
            label = EndLoop;
            return label;
        }
        
        private int getTrail(CharBuffer source, ByteBuffer target, IntBuffer offsets){
            lead = (char)c;
            int label = Loop;
            if(source.hasRemaining()){
                /*test the following code unit*/
                trail = source.get(source.position());
                if(UTF16.isTrailSurrogate(trail)){
                    source.position(source.position()+1);
                    ++nextSourceIndex;
                    c = UCharacter.getCodePoint((char)c, trail);
                    label = Loop;
                } else {
                    /*this is unmatched lead code unit (1st Surrogate)*/
                    /*callback(illegal)*/
                    cr = CoderResult.malformedForLength(1);
                    label = EndLoop;
                }
            }else {
                /*no more input*/
                label = EndLoop;
            }
            AfterGetTrail = true;
            return label;
        }
        
        private int getTrailUnicode(CharBuffer source, ByteBuffer target, IntBuffer offsets){
            int label = EndLoop;
            AfterGetTrailUnicode = true;
            /*c is surrogate*/
            if(UTF16.isLeadSurrogate((char)c)){
      // getTrailUnicode:   
                lead = (char)c;
                if(source.hasRemaining()){
                    /*test the following code unit*/
                    trail = source.get(source.position());
                    if(UTF16.isTrailSurrogate(trail)){
                        source.get();
                        ++nextSourceIndex;
                        c = UCharacter.getCodePoint((char)c, trail);
                        /*convert this surrogate code point*/
                        /*exit this condition tree*/
                    } else {
                        /*this is unmatched lead code unit(1st surrogate)*/
                        /*callback(illegal)*/
                        cr = CoderResult.malformedForLength(1);
                        label = EndLoop;
                        return label;
                    }
                } else {
                    /*no more input*/
                    label = EndLoop;
                    return label;
                }
            } else {
                /*this is an unmatched trail code point (2nd surrogate)*/
                /*callback (illegal)*/
                cr = CoderResult.malformedForLength(1);
                label = EndLoop;
                return label;
            }
            
            /*compress supplementary character*/
            if((window=getWindow(data.fromUDynamicOffsets))>=0 && 
                    !(source.hasRemaining() && ((source.get(source.position())-0x3400)&UConverterConstants.UNSIGNED_INT_MASK) < 
                            (0xd800 - 0x3400))){
                /*
                 * this is the dynamic window that contains this character and the following
                 * character is not uncompressible,
                 * change to the window
                 */
                isSingleByteMode = true;
                dynamicWindow = window;
                currentOffset = data.fromUDynamicOffsets[dynamicWindow];
                useDynamicWindow(dynamicWindow);
                c = ((UC0+dynamicWindow)<<8 | (c-currentOffset) | 0x80);
                length = 2;
                label = OutputBytes;
                return label;
            } else if(source.hasRemaining() && lead == source.get(source.position()) && (code=getDynamicOffset())>=0){
                /*two supplementary characters in (probably) the same window - define an extended one*/
                isSingleByteMode = true;
                dynamicWindow = getNextDynamicWindow();
                currentOffset = data.fromUDynamicOffsets[dynamicWindow] = offset;
                useDynamicWindow(dynamicWindow);
                c = (UDX<<24) | (dynamicWindow<<21) |(code<<8) |(c - currentOffset) | 0x80;
                length = 4;
                label = OutputBytes;
                return label;
            } else {
                /*don't know how to compress this character, just write it directly*/
                c = (lead<<16)|trail;
                length = 4;
                label = OutputBytes;
                return label;
            }
            
        }
        
        private void endLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets){
            /*set the converter state back to UConverter*/
            data.fromUIsSingleByteMode = isSingleByteMode;
            data.fromUDynamicWindow = dynamicWindow;
            fromUChar32 = c;
            LabelLoop = false;
        }

        @SuppressWarnings("fallthrough")
        private int outputBytes(CharBuffer source, ByteBuffer target, IntBuffer offsets){
            int label;
            //int targetCapacity = target.limit()-target.position();
            /*write the output character byte from c and length*/
            /*from the first if in the loop we know that targetCapacity>0*/
            if(length<=targetCapacity){
                switch(length){
                /*each branch falls through the next one*/
                    case 4:
                        target.put((byte)(c>>24));
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    case 3:
                        target.put((byte)(c>>16));
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    case 2:
                        target.put((byte)(c>>8));
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    case 1:
                        target.put((byte)c);
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    default:
                        /*will never occur*/
                        break;
                }
                targetCapacity-=length;
                
                /*normal end of conversion: prepare for a new character*/
                c = 0;
                sourceIndex = nextSourceIndex;
                label = Loop;
                return label;
            } else {
                ByteBuffer p = ByteBuffer.wrap(errorBuffer);
                /*
                 * We actually do this backwards here:
                 * In order to save an intermediate variable, we output
                 * first to the overflow buffer what does not fit into the 
                 * regular target
                 */
                /* we know that 0<=targetCapacity<length<=4 */
                /* targetCapacity==0 when SCU+supplementary where SCU used up targetCapacity==1 */
                length -= targetCapacity;
                switch(length){
                    /*each branch falls through the next one*/
                    case 4:
                        p.put((byte)(c>>24));
                    case 3:
                        p.put((byte)(c>>16));
                    case 2:
                        p.put((byte)(c>>8));
                    case 1:
                        p.put((byte)c);
                    default:
                        /*will never occur*/
                        break;
                }
                errorBufferLength = length;
                
                /*now output what fits into the regular target*/
                c>>=8*length; //length was reduced by targetCapacity
                switch(targetCapacity){
                    /*each branch falls through the next one*/
                    case 3:
                        target.put((byte)(c>>16));
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    case 2:
                        target.put((byte)(c>>8));
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    case 1:
                        target.put((byte)c);
                        if(offsets!=null){
                            offsets.put(sourceIndex);
                        }
                    default:
                        break;
                }
                
                /*target overflow*/
                targetCapacity = 0;
                cr = CoderResult.OVERFLOW;
                c = 0;
                label = EndLoop;
                return label;
            }
        }
        
    }
    
    public CharsetDecoder newDecoder() {
        return new CharsetDecoderSCSU(this);
    }

    public CharsetEncoder newEncoder() {
        return new CharsetEncoderSCSU(this);
    }
    
    void getUnicodeSetImpl( UnicodeSet setFillIn, int which){
        CharsetICU.getCompleteUnicodeSet(setFillIn);
    }
    
}
