package sophomore.classfile.attributes;

import java.io.IOException;
import java.io.RandomAccessFile;

import sophomore.classfile.Attributes;
import sophomore.classfile.ConstantPool;
import sophomore.classfile.bytecode.OpcodeInfo;
import sophomore.classfile.bytecode.MnemonicTable;
import sophomore.classfile.constantpool.Utf8Info;

/**
 *
 * @author inagaki
 */
public class Code extends AttributeInfo {
	/**
	 *
	 */
	int maxStack;
	/**
	 *
	 */
	int maxLocals;
	/**
	 *
	 */
	byte[] code;
	/**
	 *
	 */
	ExceptionTable[] exceptionTable;
	/**
	 *
	 */
	Attributes attr;

	/**
	 *
	 * @param nameIndex
	 * @param length
	 */
	public Code(int nameIndex, int length) {
		super(AttributeType.Code, nameIndex, length);
	}

	/**
	 *
	 * @return
	 */
	public int getMaxStack() {
		return maxStack;
	}

	/**
	 *
	 * @return
	 */
	public int maxLocals() {
		return maxLocals;
	}

	/**
	 *
	 * @return
	 */
	public byte[] getCode() {
		return code;
	}

	/**
	 *
	 * @return
	 */
	public ExceptionTable[] getExceptionTable() {
		return exceptionTable;
	}

	/**
	 *
	 * @return
	 */
	public Attributes getAttr() {
		return attr;
	}

	public void read(RandomAccessFile raf, ConstantPool pool)
	throws IOException, AttributeTypeException {
		this.maxStack = raf.readShort(); // this.dataStream.readShort();
		this.maxLocals = raf.readShort();
		int codeLen = raf.readInt();
		long p = raf.getFilePointer();
		this.code = new byte[codeLen];
		for(int i = 0; i < code.length; i++) {
			System.out.println("pc: "+(raf.getFilePointer() - p));
			code[i] = raf.readByte();
		}
//		raf.readFully(code);
		int tableLen = raf.readShort();
		this.exceptionTable = new ExceptionTable[tableLen];
		for(int i = 0; i < tableLen; i++) {
			exceptionTable[i] = new ExceptionTable(raf);
		}
		int count = raf.readShort();
		this.attr = new Attributes(count);
		AttributeInfoBuilder builder = AttributeInfoBuilder.getInstance();
		for(int i = 0; i < count; i++) {
			int index = raf.readShort();
			int length = raf.readInt();
			String attrName = ((Utf8Info)pool.get(index-1)).getValue();
			AttributeInfo info = builder.build(attrName, index, length);
			System.out.println(index + ", " + length + ", "+info.getType());
			info.read(raf);
			attr.add(i, info);
		}
	}

	@Override
	public void read(RandomAccessFile raf) throws IOException {}

	/**
	 *
	 */
	public class ExceptionTable {
		/**
		 *
		 */
		int startPc;
		/**
		 *
		 */
		int endPc;
		/**
		 *
		 */
		int handlerPc;
		/**
		 *
		 */
		int catchType;

		/**
		 *
		 * @param raf
		 * @throws IOException
		 */
		ExceptionTable(RandomAccessFile raf) throws IOException {
			this.startPc = raf.readShort();
			this.endPc = raf.readShort();
			this.handlerPc = raf.readShort();
			this.catchType = raf.readShort();
		}

		/**
		 *
		 * @param key
		 * @return
		 */
		public int getNumber(String key) {
			switch(key) {
				case "start_pc":   return startPc;
				case "end_pc":     return endPc;
				case "handler_pc": return handlerPc;
				case "catch_type": return catchType;
				default:
					System.out.println("invalid key: " + key);
					return -10000;
			}
		}
	}
}

@@ -216,69 +216,176 @@
 ode.
-OpcodeInfo;%0Aimport sophomore.classfile.bytecode.MnemonicTable
+MnemonicTable;%0Aimport sophomore.classfile.bytecode.OpcodeInfo;%0Aimport sophomore.classfile.bytecode.Opcodes;%0Aimport sophomore.classfile.bytecode.UndefinedOpcodeException
 ;%0Aim
@@ -583,19 +583,23 @@
 */%0A%09
-byte%5B%5D 
+Opcodes op
 code
+s
 ;%0A%09/
@@ -1015,14 +1015,15 @@
 lic 
-byte%5B%5D
+Opcodes
  get
@@ -1040,20 +1040,23 @@
 %09return 
+op
 code
+s
 ;%0A%09%7D%0A%0A%09/
@@ -1374,40 +1374,8 @@
 t();
- // this.dataStream.readShort();
 %0A%09%09t
@@ -1444,17 +1444,21 @@
 ;%0A%09%09
-long
+int
  p = 
+(int)
 raf.
@@ -1486,157 +1486,380 @@
 his.
+op
 code
+s
  = new 
-byte%5BcodeLen%5D;%0A%09%09for(int i = 0; i %3C code.length; i++) %7B%0A%09%09%09System.out.println(%22pc: %22+(raf.getFilePointer() - p));%0A%09%09%09code%5Bi%5D = raf.readByt
+Opcodes();%0A//%09%09System.out.println(codeLen + %22, %22 + p);%0A%09%09try %7B%0A%09%09%09int i;%0A%09%09%09while((i = (int)raf.getFilePointer()) %3C codeLen + p) %7B%0A%09%09%09%09int pc = (i - p);%0A%09%09%09%09int op = Byte.toUnsignedInt(raf.readByte());%0A%09%09%09%09OpcodeInfo info = MnemonicTable.get(op, pc);%0A%09%09%09%09info.read(raf);%0A%09%09%09%09opcodes.add(info);%0A%09%09%09%7D%0A%09%09%7D catch(UndefinedOpcodeException e) %7B%0A%09%09%09e.printStackTrac
 e();

change to be able to read opcodes.