package com.coderising.jvm.loader;
import com.coderising.jvm.clz.AccessFlag;
import com.coderising.jvm.clz.ClassFile;
import com.coderising.jvm.clz.ClassIndex;
import com.coderising.jvm.constant.*;
import java.io.UnsupportedEncodingException;
public class ClassFileParser {
public ClassFile parse(byte[] codes) {
ClassFile clzFile = new ClassFile();
ByteCodeIterator iter = new ByteCodeIterator(codes);
String magicNumber = iter.nextU4ToHexString();
if(!"cafebabe".equals(magicNumber)){
return null;
}
clzFile.setMinorVersion(iter.nextU2ToInt());
clzFile.setMajorVersion(iter.nextU2ToInt());
ConstantPool pool = parseConstantPool(iter);
clzFile.setConstPool(pool);
AccessFlag flag = parseAccessFlag(iter);
clzFile.setAccessFlag(flag);
ClassIndex index = parseClassInfex(iter);
clzFile.setClassIndex(index);
return clzFile;
}
private AccessFlag parseAccessFlag(ByteCodeIterator iter) {
return null;
}
private ClassIndex parseClassInfex(ByteCodeIterator iter) {
return null;
}
private ConstantPool parseConstantPool(ByteCodeIterator iter) {
int constPoolCount = iter.nextU2ToInt();
System.out.println("Constant Pool Size : " + constPoolCount);
ConstantPool pool = new ConstantPool();
pool.addConstantInfo(new NullConstantInfo());
for(int i=1;i<constPoolCount;i++){
int tag = iter.nextU1ToInt();
if(tag==7){
//Class Info
int utf8Index = iter.nextU2ToInt();
ClassInfo clzInfo = new ClassInfo(pool);
clzInfo.setUtf8Index(utf8Index);
pool.addConstantInfo(clzInfo);
}else if(tag==1){
//UTF-8 Info
int len = iter.nextU2ToInt();
byte[] data = iter.getByte(len);
String value = null;
try {
value = new String(data,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
UTF8Info utf8Info = new UTF8Info(pool);
utf8Info.setLength(len);
utf8Info.setValue(value);
pool.addConstantInfo(utf8Info);
}else if(tag==8){
StringInfo stringInfo = new StringInfo(pool);
stringInfo.setIndex(iter.nextU2ToInt());
pool.addConstantInfo(stringInfo);
}else if(tag==9){
FieldRefInfo fieldInfo = new FieldRefInfo(pool);
fieldInfo.setClassInfoIndex(iter.nextU2ToInt());
fieldInfo.setNameAndTypeIndex(iter.nextU2ToInt());
pool.addConstantInfo(fieldInfo);
}else if(tag==10){
MethodRefInfo method = new MethodRefInfo(pool);
method.setClassInfoIndex(iter.nextU2ToInt());
method.setNameAndTypeIndex(iter.nextU2ToInt());
pool.addConstantInfo(method);
}else if(tag==12){
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool);
nameAndTypeInfo.setIndex1(iter.nextU2ToInt());
nameAndTypeInfo.setIndex2(iter.nextU2ToInt());
pool.addConstantInfo(nameAndTypeInfo);
}else{
throw new RuntimeException("the constant pool tag " + tag + "has not been implement");
}
}
return pool;
}
}