package main.coding_170416.jvm.loader;
import main.coding_170416.jvm.clz.AccessFlag;
import main.coding_170416.jvm.clz.ClassFile;
import main.coding_170416.jvm.clz.ClassIndex;
import main.coding_170416.jvm.constant.*;
import main.coding_170416.jvm.field.Field;
import main.coding_170416.jvm.method.Method;
import java.io.UnsupportedEncodingException;
/**
* Created by peter on 2017/4/21.
*/
public class ClassFileParse {
public ClassFile parse(byte[] codes){
ClassFile clzFile = new ClassFile();
ByteCodeIterator iterator = new ByteCodeIterator(codes);
String magicNumber = iterator.nextU4ToHexString();
if(!"cafebabe".equals(magicNumber)){
return null;
}
clzFile.setMinorVersion(iterator.nextU2ToInt());
clzFile.setMajorVersion(iterator.nextU2ToInt());
ConstantPool pool = parseConstantPool(iterator);
clzFile.setConstantPool(pool);
AccessFlag flag = parseAccessFlag(iterator);
clzFile.setAccessFlag(flag);
parseInterfaces(iterator);
parseFields(clzFile,iterator);
parseMethods(clzFile,iterator);
return clzFile;
}
public AccessFlag parseAccessFlag(ByteCodeIterator iterator){
AccessFlag flag = new AccessFlag(iterator.nextU2ToInt());
return flag;
}
public ClassIndex parseClassIndex(ByteCodeIterator iterator){
int thisClassIndex = iterator.nextU2ToInt();
int superClassIndex = iterator.nextU2ToInt();
ClassIndex clzIndex = new ClassIndex();
clzIndex.setThisClassIndex(thisClassIndex);
clzIndex.setSuperClassIndex(superClassIndex);
return clzIndex;
}
public ConstantPool parseConstantPool(ByteCodeIterator iterator){
int constantPoolCount = iterator.nextU2ToInt();
ConstantPool pool = new ConstantPool();
pool.addConstantInfo(new NullConstantInfo());
for(int i =1;i<=constantPoolCount-1;i++){
int tag = iterator.nextU1ToInt();
if(tag==7){
//Class Info
int utf8Index = iterator.nextU2ToInt();
ClassInfo classInfo = new ClassInfo(pool);
classInfo.setUtf8Index(utf8Index);
pool.addConstantInfo(classInfo);
}else if(tag==1){
//UTF-8 String
int len = iterator.nextU2ToInt();
byte[] data = iterator.getBytes(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 info = new StringInfo(pool);
info.setIndex(iterator.nextU2ToInt());
pool.addConstantInfo(info);
}else if(tag==9){
FieldRefInfo field = new FieldRefInfo(pool);
field.setClassInfoIndex(iterator.nextU2ToInt());
field.setNameAndTypeIndex(iterator.nextU2ToInt());
pool.addConstantInfo(field);
}else if(tag==10){
//MethodRef
MethodRefInfo method = new MethodRefInfo(pool);
method.setClassInfoIndex(iterator.nextU2ToInt());
method.setNameAndTypeIndex(iterator.nextU2ToInt());
pool.addConstantInfo(method);
}else if(tag==12){
//Name and Type Info
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool);
nameAndTypeInfo.setIndexA(iterator.nextU2ToInt());
nameAndTypeInfo.setIndexB(iterator.nextU2ToInt());
pool.addConstantInfo(nameAndTypeInfo);
}else {
throw new RuntimeException("the constant pool tag "+tag+" has not implemented");
}
}
System.out.println("Finished reading Constant pool");
return pool;
}
public void parseInterfaces(ByteCodeIterator iterator){
int interfaxrCount = iterator.nextU2ToInt();
System.out.println("interfaceCount:"+interfaxrCount);
//如果实现了接口这里需要实现
}
public void parseFields(ClassFile clzFile, ByteCodeIterator iterator){
int fieldCount = iterator.nextU2ToInt();
for(int i=1;i<=fieldCount;i++){
Field f = Field.parse(clzFile.getConstantPool(),iterator);
clzFile.addField(f);
}
}
public void parseMethods(ClassFile clzfFile, ByteCodeIterator iterator){
int methodCount = iterator.nextU2ToInt();
for(int i=0;i<=methodCount;i++){
Method m = Method.parse(clzfFile,iterator);
clzfFile.addMethod(m);
}
}
}