/*
 * jTsSplitter - java based mpeg2ts splitter.
 * Copyright (C) 2009-2012 Yukikaze
 */

package jtssplitter;

/**
 *
 * @author yukikaze
 */
public class calc {
   public String Int2String(int num, int length) {
        String ret = Integer.toBinaryString(num);
        if (ret.length() < length) {
            int it = length - ret.length();
            for (int i = 0; i < it; i++) {
                ret = "0" + ret;
            }
        }
        return ret;
    }
   public String Long2String(long num, int length) {
        String ret = Long.toBinaryString(num);
        if (ret.length() < length) {
            int it = length - ret.length();
            for (int i = 0; i < it; i++) {
                ret = "0" + ret;
            }
        }
        return ret;
    }
    public byte[] String2Byte(String ts) {
        //StringBuffer sb=new StringBuffer(ts);
        int len = ts.length() - ts.length() % 8;
        len = len / 8;
        byte[] ret = new byte[len];
        for (int i = 0; i < len; i++) {
            String tet = ts.substring(i * 8, i * 8 + 8);
            int itt = TSString2Int(tet, 0, 8);
            ret[i] = (byte) itt;
        }
        return ret;
    }
    public byte joinByte(byte b1,byte b2,int b2length){
        byte ret=(byte)(b1<<(b2length)&0xFF+b2&0xFF);
        return ret;
    }
    public byte joinByte(byte b1,byte b2,int b2len,byte b3,int b3len){
        byte ret=joinByte(b1,b2,b2len);
        ret=joinByte(ret, b3, b3len);
        return ret;
    }
    public String byte2String(byte[] b) {
        StringBuffer sb=new StringBuffer(8*b.length);
        for (int i = 0; i < b.length; i++) {
            StringBuffer sb2=new StringBuffer(8);
            sb2.append(Integer.toBinaryString(b[i] & 0xFF));
            if ((sb2.length() < 8) & (sb2.length() > 0)) {
                sb2.insert(0,addzero(8-sb2.length()));
            }
            sb.append(sb2);
        }
        return sb.toString();
    }
    public String byte2String2(byte[] b){
        int bl=b.length;
        bl=bl-bl%8;
        bl=bl/8;
        StringBuffer sb=new StringBuffer();
        for (int i=0;i<bl;i++){
            long retl=0;
            for (int j=0;j<8;j++){
                retl=retl<<8;
                int ri=b[i*8+j]&0xFF;
                retl=retl+ri;
            }
            sb.append(Long2String(retl,64));
        }
        int bl2=b.length%8;
        bl2=(bl2-bl2%4)/4;
        for (int i=0;i<bl2;i++){
            int reti=0;
            for (int j=0;j<4;j++){
                reti=reti<<8;
                reti=reti+(b[bl*8+4*i+j]&0xFF);
            }
            sb.append(Int2String(reti,32));
        }
        for (int i=0;i<(b.length%8)%4;i++){
            sb.append(Int2String(b[bl*8+bl2*4+i]&0xFF,8));
        }
        return sb.toString();
    }

    public String byte2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            ret = ret + Integer.toHexString(b[i] & 0xFF);
        }
        return ret;
    }
    public String addzero(int num){
        switch (num){
            case 0:
                return "";
            case 1:
                return "0";
            case 2:
                return "00";
            case 3:
                return "000";
            case 4:
                return "0000";
            case 5:
                return "00000";
            case 6:
                return "000000";
            case 7:
                return "0000000";
            case 8:
                return "00000000";
            default:
                StringBuffer sb=new StringBuffer();
                for (int i=0;i<num;i++){
                    sb.append("0");
                }
                return sb.toString();
        }
    }
    public int TSString2Int(String s, int begin, int length) {
        String st = s.substring(begin, begin + length);
        int i = Integer.parseInt(st, 2);
        return i;
    }
    public byte[] byte2subbyte(byte[] b,int start,int length){
        byte[] ret=new byte[length];
        System.arraycopy(b,start,ret,0, length);
        return ret;
    }
    public int byte2int(byte[] b,int startbit,int length){
        int a=startbit-startbit%8;
        a=a/8;
        int bb=startbit+length-(startbit+length)%8;
        bb=bb/8;
        int ret=0;
        for (int i=0;i<bb-a+1;i++){
            if (i==0){
                int tt=1;
                for (int j=0;j<(8-(startbit%8));j++){
                    tt=tt*2;
                }
                tt=tt-1;
                int lent=length-8+(startbit%8);
                if (lent<0){
                    lent=0;
                }
                ret=ret+(((b[a]&0xFF)&tt)<<lent);
                if (i==bb-a){
                    int k=0;
                    if ((startbit+length)%8==0){
                        k=0;
                    }else{
                        k=8-(startbit+length)%8;
                }
                    ret=ret>>k;
                }
            }else if (i==bb-a){
                int k=0;
                if ((startbit+length)%8==0){
                    k=8;
                }else{
                    k=8-(startbit+length)%8;
                }
                ret=ret+((b[a+i]&0xFF)>>k);
            }else{
                ret=ret+((b[a+i]&0xFF)<<((bb-a-i-1)*8+((startbit+length)%8)));
            }
            if (b.length-1-a==i){
                i=bb-a+1;
            }
        }
        return ret;
    }
    public long byte2long(byte[] b,int startbit,int length){
        int a=startbit-startbit%8;
        a=a/8;
        int bb=startbit+length-(startbit+length)%8;
        bb=bb/8;
        long ret=0;
        for (int i=0;i<bb-a+1;i++){
            if (i==0){
                int tt=1;
                for (int j=0;j<(8-(startbit%8));j++){
                    tt=tt*2;
                }
                tt=tt-1;
                int lent=length-8+(startbit%8);
                if (lent<0){
                    lent=0;
                }
                ret=ret+(((b[a]&0xFF)&tt)<<lent);
                if (i==bb-a){
                    int k=0;
                    if ((startbit+length)%8==0){
                        k=0;
                    }else{
                        k=8-(startbit+length)%8;
                }
                    ret=ret>>k;
                }
            }else if (i==bb-a){
                int k=0;
                if ((startbit+length)%8==0){
                    k=8;
                }else{
                    k=8-(startbit+length)%8;
                }
                ret=ret+((b[a+i]&0xFF)>>k);
            }else{
                ret=ret+((b[a+i]&0xFF)<<((bb-a-i-1)*8+((startbit+length)%8)));
            }
        }
        return ret;
    }
    public void showPAT(String ts) {
        System.out.println("先頭:" + ts.substring(0, 8));
        System.out.println("" + ts.substring(8, 11));
        System.out.println("PID:" + ts.substring(11, 24));
        System.out.println("" + ts.substring(24, 32));
        System.out.println("Adap_Len:" + ts.substring(32, 40));
        System.out.println("TableID:" + ts.substring(40, 48));
        System.out.println("" + ts.substring(48, 52));
        System.out.println("len : " + ts.substring(52, 64) + "//" + Integer.toString(Integer.parseInt(ts.substring(52, 64), 2)));
        System.out.println("TS ID:" + ts.substring(64, 80));
        System.out.println("11:" + ts.substring(80, 82));
        System.out.println("" + ts.substring(82, 104));
        for (int i = 0; i < 10; i++) {
            System.out.println(Integer.toString(i) + " : " + ts.substring(104 + 32 * i, 136 + 32 * i));
        }
        System.out.println("Length:" + Integer.toString(ts.length()));
    }
    public byte[] getCRC32_byte(byte[] data, int offset) {
        // x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
        int[] g = {1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1};
        int[] shift_reg = new int[32];
        long crc = 0;
        byte crc32[] = new byte[4];

        // Initialize shift register's to '1'
        java.util.Arrays.fill(shift_reg, 1);

        // Calculate nr of data bits, summa of bits
        int nr_bits = (data.length - offset) * 8;

        for (int bit_count = 0, bit_in_byte = 0, data_bit; bit_count < nr_bits; bit_count++) {
            // Fetch bit from bitstream
            data_bit = (data[offset] & 0x80 >>> (bit_in_byte++)) != 0 ? 1 : 0;

            if ((bit_in_byte &= 7) == 0) {
                offset++;
            }

            // Perform the shift and modula 2 addition
            data_bit ^= shift_reg[31];

            for (int i = 31; i > 0; i--) {
                shift_reg[i] = g[i] == 1 ? (shift_reg[i - 1] ^ data_bit) : shift_reg[i - 1];
            }

            shift_reg[0] = data_bit;
        }

        for (int i = 0; i < 32; i++) {
            crc = ((crc << 1) | (shift_reg[31 - i]));
        }

        for (int i = 0; i < 4; i++) {
            crc32[i] = (byte) (0xFF & (crc >>> ((3 - i) * 8)));
        }
        return crc32;
    }
}
