package com.github.nukc.plugin.axml.decode;
import com.github.nukc.plugin.axml.decode.BTagNode.Attribute;
import com.github.nukc.plugin.axml.utils.TypedValue;
public class XMLVisitor implements IVisitor{
private StringBlock mStrings;
private ResBlock mRes;
private int depth;
public XMLVisitor(StringBlock sb){
mStrings = sb;
}
/**
* print header
* print child
* print tail
*/
@Override
public void visit(BNSNode node) {
int prefix = node.getPrefix();
int uri = node.getUri();
String line1 = String.format("xmlns:%s=%s", getStringAt(prefix) , getStringAt(uri));
System.out.println(line1);
if(node.hasChild()){
for(BXMLNode child : node.getChildren()){
child.accept(this);
}
}
}
@Override
public void visit(BTagNode node) {
if(!node.hasChild()){
print("<"+ getStringAt(node.getName()));
printAttribute(node.getAttribute());
print("/>");
}else{
print("<"+ getStringAt(node.getName()));
depth ++;
printAttribute(node.getAttribute());
print(">");
for(BXMLNode child : node.getChildren()){
child.accept(this);
}
depth --;
print("</" + getStringAt(node.getName()) + ">");
}
}
public void visit(BTXTNode node){
print("Text node");
}
private void printAttribute(Attribute[] attrs){
for(Attribute attr : attrs){
StringBuilder sb = new StringBuilder();
if(attr.hasNamespace()){
sb.append("android").append(':');
}
String name = getStringAt(attr.mName);
if("id".equals(name)){
System.out.println("hehe");
}
sb.append(name).append('=');
sb.append('\"').append(getAttributeValue(attr)).append('\"');
print(sb.toString());
}
}
final String intent = " ";
final int step = 4;
private void print(String str){
System.out.println(intent.substring(0, depth*step)+str);
}
private String getStringAt(int index){
return mStrings.getStringFor(index);
}
@SuppressWarnings("unused")
private int getResIdAt(int index){
//TODO final res result in resources.arsc
return mRes.getResourceIdAt(index);
}
private String getAttributeValue(Attribute attr) {
int type = attr.mType >> 24;
int data = attr.mValue;
if (type==TypedValue.TYPE_STRING) {
return mStrings.getStringFor(attr.mString);
}
if (type==TypedValue.TYPE_ATTRIBUTE) {
return String.format("?%s%08X",getPackage(data),data);
}
if (type==TypedValue.TYPE_REFERENCE) {
return String.format("@%s%08X",getPackage(data),data);
}
if (type==TypedValue.TYPE_FLOAT) {
return String.valueOf(Float.intBitsToFloat(data));
}
if (type==TypedValue.TYPE_INT_HEX) {
return String.format("0x%08X",data);
}
if (type==TypedValue.TYPE_INT_BOOLEAN) {
return data!=0?"true":"false";
}
if (type==TypedValue.TYPE_DIMENSION) {
return Float.toString(complexToFloat(data))+
DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
}
if (type==TypedValue.TYPE_FRACTION) {
return Float.toString(complexToFloat(data))+
FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK];
}
if (type>=TypedValue.TYPE_FIRST_COLOR_INT && type<=TypedValue.TYPE_LAST_COLOR_INT) {
return String.format("#%08X",data);
}
if (type>=TypedValue.TYPE_FIRST_INT && type<=TypedValue.TYPE_LAST_INT) {
return String.valueOf(data);
}
return String.format("<0x%X, type 0x%02X>",data,type);
}
private String getPackage(int id) {
if (id>>>24==1) {
return "android:";
}
return "";
}
/////////////////////////////////// ILLEGAL STUFF, DONT LOOK :)
public static float complexToFloat(int complex) {
return (float)(complex & 0xFFFFFF00)*RADIX_MULTS[(complex>>4) & 3];
}
private static final float RADIX_MULTS[]={
0.00390625F,3.051758E-005F,1.192093E-007F,4.656613E-010F
};
private static final String DIMENSION_UNITS[]={
"px","dip","sp","pt","in","mm","",""
};
private static final String FRACTION_UNITS[]={
"%","%p","","","","","",""
};
}