package com.coderising.jvm.attr;
import org.junit.Assert;
import com.coderising.jvm.cmd.ByteCodeCommand;
import com.coderising.jvm.cmd.CommandParser;
import com.coderising.jvm.constant.ConstantPool;
import com.coderising.jvm.loader.ByteCodeIterator;
public class CodeAttr extends AttributeInfo{
private int maxStack ;
private int maxLocals ;
private int codeLength ;
private String code;
private LineNumberTable lineNumTable;
private LocalVariableTable localVariableTable;
private ByteCodeCommand[] cmds;
public void setCmds(ByteCodeCommand[] cmds) {
this.cmds = cmds;
}
public LocalVariableTable getLocalVariableTable() {
return localVariableTable;
}
public void setLocalVariableTable(LocalVariableTable localVariableTable) {
this.localVariableTable = localVariableTable;
}
public CodeAttr(int attrNameIndex, int attrLength) {
super(attrNameIndex, attrLength);
}
public int getMaxStack() {
return maxStack;
}
public void setMaxStack(int maxStack) {
this.maxStack = maxStack;
}
public int getMaxLocals() {
return maxLocals;
}
public void setMaxLocals(int maxLocals) {
this.maxLocals = maxLocals;
}
public int getCodeLength() {
return codeLength;
}
public void setCodeLength(int codeLength) {
this.codeLength = codeLength;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public LineNumberTable getLineNumTable() {
return lineNumTable;
}
public void setLineNumTable(LineNumberTable lineNumTable) {
this.lineNumTable = lineNumTable;
}
public static CodeAttr parse(ByteCodeIterator it, ConstantPool constantPool) {
int attrNameIndex = it.next2ByteToInt();
int attrLength = it.next4ByteToInt();
int maxStack = it.next2ByteToInt();
int maxLocals = it.next2ByteToInt();
int codeLength = it.next4ByteToInt();
String code = it.nextXByteToHexStr(codeLength);
ByteCodeCommand[] cmds = CommandParser.parse(constantPool, code);
int exceptionTableLength = it.next2ByteToInt();
Assert.assertEquals(0, exceptionTableLength);
CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLength);
codeAttr.setMaxStack(maxStack);
codeAttr.setMaxLocals(maxLocals);
codeAttr.setCodeLength(codeLength);
codeAttr.setCode(code);
codeAttr.setCmds(cmds);
int subAttrCount = it.next2ByteToInt();
while(subAttrCount > 0) {
int subAttrNameIndex = it.next2ByteToInt();
String subAttrName = constantPool.getUTF8String(subAttrNameIndex);
if(AttributeInfo.ATTR_LINE_NUMBER_TABLE.equals(subAttrName)) { //LineNumberTable
it.back(2);
codeAttr.setLineNumTable(LineNumberTable.parse(it, constantPool));
} else if (AttributeInfo.ATTR_LOCAL_VARIABLE_TABLE.equals(subAttrName)) { //LocalVariableTable
it.back(2);
codeAttr.setLocalVariableTable(LocalVariableTable.parse(it, constantPool));
} else {
throw new RuntimeException("no implements attrName: " + subAttrName);
}
subAttrCount--;
}
return codeAttr;
}
public ByteCodeCommand[] getCmds() {
return this.cmds;
}
}