import java.util.*;
import java.io.*;
import java.lang.*;


public class huffman {

 /*==========================================================================*/
    
    private byte[] buf;								/*1*/
    
    private byte[] outbuf;							/*2*/
    
    private hufftree tree;							/*3*/
    
    private int outoffset;							/*4*/

    public void reset() {							/*5*/
	outoffset = 0;								/*6*/
    } 

    private boolean is_zero_bit(int offset) {					/*7*/
	int byte_offset, bit_offset;						/*8*/
	byte_offset = offset >> 3;						/*9*/
	bit_offset = 7-(offset & 7);						/*10*/
	return (((1 << bit_offset) & buf[byte_offset]) == 0);			/*11*/
    }
    
    private class hufftree {							/*12*/
	public hufftree left;							/*13*/
	public hufftree right;							/*14*/
	public byte val;							/*15*/
	public hufftree(hufftree l, hufftree r) {				/*16*/
	    left=l;								/*17*/
	    right=r;								/*18*/
	}
	public hufftree(byte v) {						/*19*/
	    left=null;								/*20*/
	    right=null;								/*21*/
	    val = v;								/*22*/
	}
	public boolean is_leaf() {						/*23*/
	    return left==null;							/*24*/
	}
    }

    public void decode(int bitoffset, int limit) {				/*25*/
	hufftree pres=tree;							/*26*/
	while (true) {								/*27*/
	    if (pres.is_leaf()) {						/*28*/
		outbuf[outoffset++] = pres.val;					/*29*/
		if (bitoffset >= limit) {					/*30*/
		    break;
		}
		pres = tree;							/*31*/
	    }
	    else {
		if(is_zero_bit(bitoffset++)) {					/*32*/
		    pres = pres.left;						/*33*/
		}
		else {
		    pres = pres.right;						/*34*/
		}
	    }
	}
    }
		

    public huffman(String filename) throws IOException {			/*35*/
	FileInputStream fis = new FileInputStream(filename);			/*36*/
	int bytesize;								/*37*/
	buf = new byte[1000000];						/*38*/
	bytesize = fis.read(buf, 0, 1000000);					/*39*/
	outoffset = 0;								/*40*/
	outbuf = new byte[8000000];						/*41*/
    }

    private void run() {							/*42*/
	int h,u,f1,f2,offset=0;							/*43*/
	int bitoffset,limit; 							/*44*/
	h=buf[offset];								/*45*/
	u=buf[offset+1];							/*46*/
	f1=buf[offset+2];							/*47*/
	f2=buf[offset+3];							/*48*/
	offset +=4;								/*49*/
	offset = init_tree(offset);						/*50*/
	limit=get_32_bit_int(offset);						/*51*/
	bitoffset = 8*(offset+4);						/*52*/
	limit = limit+bitoffset;						/*53*/
	decode(bitoffset, limit);						/*54*/
    }	
    
    private int init_tree(int offset) {						/*55*/
	int size,bitsize;							/*56*/
	size = get_16_bit_int(offset);						/*57*/
	tree = build_tree(offset+2);						/*58*/
	return offset+(size+2);							/*59*/
    }

    private hufftree build_tree(int poffset) {					/*60*/
	int leftsize,rightsize;							/*61*/
	leftsize = get_16_bit_int(poffset);					/*62*/
	rightsize = get_16_bit_int(poffset+leftsize+2);				/*63*/
	return new hufftree(create_subtree(poffset+2,leftsize),			/*64*/
			    create_subtree(poffset+4+leftsize,rightsize));	/*65*/
    }
    
    private hufftree create_subtree(int poffset, int size) {			/*66*/
	if (size == 1) {							/*67*/
	    return new hufftree(buf[poffset]);					/*68*/
	 }
	return build_tree(poffset);						/*69*/
    }
	 
    private int get_32_bit_int(int offs) {					/*70*/
	return (((int) (buf[offs] & 255) << 24) | 				/*71*/
		((int) (buf[offs+1] & 255) << 16) |				/*72*/
		((int) (buf[offs+2] & 255) << 8) | 				/*73*/
		((int) (buf[offs+3] & 255)));  					/*74*/
    } 

    private int get_16_bit_int(int offs) {					/*75*/
	int t1,t2,t3,res;							/*76*/
	t1 = (int) buf[offs];							/*77*/
	t2 = (t1 & 255) << 8;							/*78*/
	t3 = (int) buf[offs+1];							/*79*/
	res =  t2 | (t3 & 255);							/*80*/
	return res;								/*81*/
    }

     /*==========================================================================*/

    private void write_file(String filename) throws IOException {
	FileOutputStream fos = new FileOutputStream(filename+".java");
	fos.write(outbuf,0,outoffset);
    }
    
    public static void main(String[] args) {
	huffman bin;
	long time;
	try {
	    bin = new huffman(args[0]);
	}
	catch (IOException e) {return;}
	long start = System.currentTimeMillis();
	for(int i=0; i<10; i+=1){
	    bin.reset();
	    bin.run();
	}
	long end = System.currentTimeMillis();
	time = end-start;
	System.out.print("" + (float)time/1000.0);
	try {
	    bin.write_file(args[0]);
	}
	catch (IOException e) {return;}
    }

}

