diff --git a/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java b/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java index 8de5199..41cb2a5 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java @@ -64,10 +64,10 @@ package com.reandroid.apk.xmlencoder; public InputSource encodeFileEntry(File resFile){ String type = EncodeUtil.getTypeNameFromResFile(resFile); PackageBlock packageBlock = materials.getCurrentPackage(); - byte typeId=packageBlock + int typeId=packageBlock .getTypeStringPool().idOf(type); String qualifiers = EncodeUtil.getQualifiersFromResFile(resFile); - TypeBlock typeBlock = packageBlock.getOrCreateTypeBlock(typeId, qualifiers); + TypeBlock typeBlock = packageBlock.getOrCreateTypeBlock((byte)typeId, qualifiers); String name = EncodeUtil.getEntryNameFromResFile(resFile); int resourceId=materials.resolveLocalResourceId(type, name); diff --git a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java index a077fce..9a051ef 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java @@ -92,7 +92,7 @@ class XMLValuesEncoder { private TypeBlock getTypeBlock(String type, String qualifiers){ PackageBlock packageBlock = getMaterials().getCurrentPackage(); TypeStringPool typeStringPool = packageBlock.getTypeStringPool(); - byte typeId = typeStringPool.idOf(type); + byte typeId = (byte) typeStringPool.idOf(type); SpecTypePair specTypePair = packageBlock.getSpecTypePairArray().getOrCreate(typeId); int highest = specTypePair.getHighestEntryCount(); diff --git a/src/main/java/com/reandroid/arsc/array/EntryBlockArray.java b/src/main/java/com/reandroid/arsc/array/EntryBlockArray.java index 3e368ac..602854a 100755 --- a/src/main/java/com/reandroid/arsc/array/EntryBlockArray.java +++ b/src/main/java/com/reandroid/arsc/array/EntryBlockArray.java @@ -122,25 +122,9 @@ public class EntryBlockArray extends OffsetBlockArray implements JSO while (itr.hasNext()){ EntryBlock comingBlock=itr.next(); EntryBlock existingBlock=get(comingBlock.getIndex()); - if(shouldMerge(existingBlock, comingBlock)){ - existingBlock.merge(comingBlock); - } + existingBlock.merge(comingBlock); } } - private boolean shouldMerge(EntryBlock exist, EntryBlock coming){ - if(exist.isNull()){ - return true; - } - if(coming.isNull()){ - return false; - } - BaseResValue resVal = coming.getResValue(); - if(resVal instanceof ResValueInt){ - ValueType valueType=((ResValueInt)resVal).getValueType(); - return valueType!=ValueType.INT_BOOLEAN; - } - return true; - } @Override public String toString(){ return getClass().getSimpleName()+": size="+childesCount(); diff --git a/src/main/java/com/reandroid/arsc/array/OffsetBlockArray.java b/src/main/java/com/reandroid/arsc/array/OffsetBlockArray.java index 2e4324c..04e6139 100755 --- a/src/main/java/com/reandroid/arsc/array/OffsetBlockArray.java +++ b/src/main/java/com/reandroid/arsc/array/OffsetBlockArray.java @@ -102,10 +102,6 @@ public abstract class OffsetBlockArray extends BlockArray im if(item==null || item.isNull()){ offset=-1; }else { - // slow but accurate - //offset=countUpTo(item); - - // fast but fails for duplicate items offset=sum; sum+=item.countBytes(); } diff --git a/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java b/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java index c27693d..0d47457 100755 --- a/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java +++ b/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java @@ -182,7 +182,7 @@ public class SpecTypePairArray extends BlockArray if(pair==null){ continue; } - int id=pair.getTypeIdInt(); + int id=pair.getId(); if(!firstFound){ result=id; } @@ -204,7 +204,7 @@ public class SpecTypePairArray extends BlockArray if(pair==null){ continue; } - int id=pair.getTypeIdInt(); + int id=pair.getId(); if(id>result){ result=id; } diff --git a/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java b/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java index cc67a12..bbbcd62 100755 --- a/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java +++ b/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java @@ -20,6 +20,7 @@ import com.reandroid.arsc.base.Block; import com.reandroid.arsc.base.BlockArray; import com.reandroid.arsc.chunk.SpecBlock; import com.reandroid.arsc.chunk.TypeBlock; +import com.reandroid.arsc.container.SpecTypePair; import com.reandroid.arsc.header.HeaderBlock; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.item.TypeString; @@ -142,16 +143,12 @@ public class TypeBlockArray extends BlockArray } } public byte getTypeId(){ - if(mTypeId != 0){ - return mTypeId; - } SpecBlock specBlock=getSpecBlock(); if(specBlock!=null){ - byte id=specBlock.getTypeId(); - if(id!=0){ - mTypeId=id; - return id; - } + return specBlock.getTypeId(); + } + if(mTypeId != 0){ + return mTypeId; } TypeBlock[] allChildes=getChildes(); if(allChildes==null){ @@ -192,8 +189,8 @@ public class TypeBlockArray extends BlockArray private SpecBlock getSpecBlock(){ Block parent=getParent(); while(parent!=null){ - if(parent instanceof SpecBlock){ - return (SpecBlock)parent; + if(parent instanceof SpecTypePair){ + return ((SpecTypePair) parent).getSpecBlock(); } parent=parent.getParent(); } diff --git a/src/main/java/com/reandroid/arsc/chunk/MainChunk.java b/src/main/java/com/reandroid/arsc/chunk/MainChunk.java new file mode 100644 index 0000000..d9700c2 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/chunk/MainChunk.java @@ -0,0 +1,7 @@ +package com.reandroid.arsc.chunk; + +import com.reandroid.arsc.pool.StringPool; + +public interface MainChunk { + public StringPool getStringPool(); +} diff --git a/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java b/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java index fff95ac..d871e6e 100755 --- a/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java @@ -30,6 +30,7 @@ package com.reandroid.arsc.chunk; import com.reandroid.arsc.pool.TypeStringPool; import com.reandroid.arsc.value.EntryBlock; import com.reandroid.arsc.value.LibraryInfo; + import com.reandroid.arsc.value.ResConfig; import com.reandroid.arsc.value.StagedAliasEntry; import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; @@ -51,7 +52,7 @@ package com.reandroid.arsc.chunk; super(new PackageHeader(), 3); PackageHeader header = getHeaderBlock(); - this.mTypeStringPool=new TypeStringPool(false, header.getTypeIdOffset()); + this.mTypeStringPool=new TypeStringPool(false, header.getTypeIdOffsetItem()); this.mSpecStringPool=new SpecStringPool(true); this.mBody = new PackageBody(); @@ -62,6 +63,34 @@ package com.reandroid.arsc.chunk; addChild(mSpecStringPool); addChild(mBody); } + public EntryBlock getOrCreate(String qualifiers, String type, String name){ + ResConfig resConfig = new ResConfig(); + resConfig.parseQualifiers(qualifiers); + return getOrCreate(resConfig, type, name); + } + public EntryBlock getOrCreate(ResConfig resConfig, String type, String name){ + SpecTypePair specTypePair = getOrCreateSpecType(type); + TypeBlock typeBlock = specTypePair.getOrCreateTypeBlock(resConfig); + return typeBlock.getOrCreateEntry(name); + } + public SpecTypePair getOrCreateSpecType(String type){ + int last = 0; + for(SpecTypePair specTypePair:listAllSpecTypePair()){ + if(type.equals(specTypePair.getTypeName())){ + return specTypePair; + } + int id = specTypePair.getId(); + if(id>last){ + last=id; + } + } + last++; + getTypeStringPool().getOrCreate(last, type); + return getSpecTypePairArray().getOrCreate((byte) last); + } + public int getTypeIdOffset(){ + return getHeaderBlock().getTypeIdOffset(); + } public BlockList getUnknownChunkList(){ return mBody.getUnknownChunkList(); } @@ -270,7 +299,7 @@ package com.reandroid.arsc.chunk; //int largest=getSpecTypePairArray().getHighestTypeId(); //int count=getTypeStringPool().countStrings(); //getHeaderBlock().getTypeIdOffset().set(count-largest); - getHeaderBlock().getTypeIdOffset().set(0); + getHeaderBlock().getTypeIdOffsetItem().set(0); } public void onEntryAdded(EntryBlock entryBlock){ updateEntry(entryBlock); diff --git a/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java b/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java index d11ecff..6aba598 100755 --- a/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java @@ -42,14 +42,15 @@ public byte getTypeId(){ return getHeaderBlock().getId().get(); } - public int getTypeIdInt(){ + public int getId(){ return getHeaderBlock().getId().unsignedInt(); } - public void setTypeId(int id){ + public void setId(int id){ setTypeId((byte) (0xff & id)); } public void setTypeId(byte id){ getHeaderBlock().getId().set(id); + getTypeBlockArray().setTypeId(id); } public TypeBlockArray getTypeBlockArray(){ SpecTypePair specTypePair=getSpecTypePair(); @@ -94,12 +95,12 @@ @Override public JSONObject toJson() { JSONObject jsonObject=new JSONObject(); - jsonObject.put(TypeBlock.NAME_id, getTypeIdInt()); + jsonObject.put(TypeBlock.NAME_id, getId()); return jsonObject; } @Override public void fromJson(JSONObject json) { - setTypeId(json.getInt(TypeBlock.NAME_id)); + setId(json.getInt(TypeBlock.NAME_id)); } } diff --git a/src/main/java/com/reandroid/arsc/chunk/TableBlock.java b/src/main/java/com/reandroid/arsc/chunk/TableBlock.java index a7f807b..cc69ce3 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TableBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TableBlock.java @@ -22,6 +22,7 @@ import com.reandroid.arsc.header.HeaderBlock; import com.reandroid.arsc.header.InfoHeader; import com.reandroid.arsc.header.TableHeader; import com.reandroid.arsc.io.BlockReader; +import com.reandroid.arsc.pool.StringPool; import com.reandroid.arsc.pool.TableStringPool; import com.reandroid.arsc.value.StagedAliasEntry; import com.reandroid.common.Frameworks; @@ -34,7 +35,8 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; -public class TableBlock extends Chunk implements JSONConvert { +public class TableBlock extends Chunk + implements MainChunk, JSONConvert { private final TableStringPool mTableStringPool; private final PackageArray mPackageArray; private final Set mFrameWorks=new HashSet<>(); @@ -55,6 +57,10 @@ public class TableBlock extends Chunk implements JSONConvert listPackages(){ return getPackageArray().listItems(); } + @Override + public TableStringPool getStringPool() { + return mTableStringPool; + } public TableStringPool getTableStringPool(){ return mTableStringPool; } diff --git a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java index 97015ee..efac077 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java @@ -25,6 +25,7 @@ import com.reandroid.arsc.item.*; import com.reandroid.arsc.pool.TypeStringPool; import com.reandroid.arsc.value.EntryBlock; import com.reandroid.arsc.value.ResConfig; +import com.reandroid.arsc.value.ValueType; import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; @@ -81,16 +82,16 @@ public class TypeBlock extends Chunk return null; } TypeStringPool typeStringPool=packageBlock.getTypeStringPool(); - mTypeString=typeStringPool.getById(getTypeIdInt()); + mTypeString=typeStringPool.getById(getId()); return mTypeString; } public byte getTypeId(){ return getHeaderBlock().getId().get(); } - public int getTypeIdInt(){ + public int getId(){ return getHeaderBlock().getId().unsignedInt(); } - public void setTypeId(int id){ + public void setId(int id){ setTypeId((byte) (0xff & id)); } public void setTypeId(byte id){ @@ -98,7 +99,7 @@ public class TypeBlock extends Chunk } public void setTypeName(String name){ TypeStringPool typeStringPool=getTypeStringPool(); - int id=getTypeIdInt(); + int id= getId(); TypeString typeString=typeStringPool.getById(id); if(typeString==null){ typeString=typeStringPool.getOrCreate(id, name); @@ -162,6 +163,29 @@ public class TypeBlock extends Chunk } entryBlock.setNull(true); } + public EntryBlock getOrCreateEntry(String name){ + for(EntryBlock entryBlock:getEntryBlockArray().listItems()){ + if(name.equals(entryBlock.getName())){ + return entryBlock; + } + } + SpecTypePair specTypePair = getParentSpecTypePair(); + EntryBlock exist=specTypePair.getAnyEntry(name); + int id; + if(exist!=null){ + id=exist.getIndex(); + }else { + id = specTypePair.getHighestEntryCount(); + } + SpecString specString = getPackageBlock() + .getSpecStringPool().getOrCreate(name); + EntryBlock entryBlock = getOrCreateEntry((short) id); + if(entryBlock.isNull()){ + entryBlock.setValueAsRaw(ValueType.NULL, 0); + } + entryBlock.setSpecReference(specString.getIndex()); + return entryBlock; + } public EntryBlock getOrCreateEntry(short entryId){ return getEntryBlockArray().getOrCreate(entryId); } @@ -219,7 +243,7 @@ public class TypeBlock extends Chunk @Override public JSONObject toJson() { JSONObject jsonObject=new JSONObject(); - jsonObject.put(NAME_id, getTypeIdInt()); + jsonObject.put(NAME_id, getId()); jsonObject.put(NAME_name, getTypeName()); jsonObject.put(NAME_config, getResConfig().toJson()); jsonObject.put(NAME_entries, getEntryBlockArray().toJson()); @@ -227,7 +251,7 @@ public class TypeBlock extends Chunk } @Override public void fromJson(JSONObject json) { - setTypeId(json.getInt(NAME_id)); + setId(json.getInt(NAME_id)); String name = json.optString(NAME_name); if(name!=null){ setTypeName(name); @@ -250,8 +274,8 @@ public class TypeBlock extends Chunk } @Override public int compareTo(TypeBlock typeBlock) { - int id1=getTypeIdInt(); - int id2=typeBlock.getTypeIdInt(); + int id1= getId(); + int id2=typeBlock.getId(); if(id1!=id2){ return Integer.compare(id1, id2); } diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java index 7ab709d..cd703c3 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java @@ -17,6 +17,7 @@ import com.reandroid.arsc.chunk.Chunk; import com.reandroid.arsc.chunk.ChunkType; + import com.reandroid.arsc.chunk.MainChunk; import com.reandroid.arsc.container.SingleBlockContainer; import com.reandroid.arsc.header.HeaderBlock; import com.reandroid.arsc.io.BlockReader; @@ -36,7 +37,8 @@ import java.util.List; import java.util.Set; - public class ResXmlDocument extends Chunk implements JSONConvert { + public class ResXmlDocument extends Chunk + implements MainChunk, JSONConvert { private final ResXmlStringPool mResXmlStringPool; private final ResXmlIDMap mResXmlIDMap; private ResXmlElement mResXmlElement; @@ -160,6 +162,7 @@ } return false; } + @Override public ResXmlStringPool getStringPool(){ return mResXmlStringPool; } diff --git a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java index 54a9a55..16efda5 100755 --- a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java +++ b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java @@ -53,6 +53,15 @@ public class SpecTypePair extends BlockContainer public SpecTypePair(){ this(new SpecBlock(), new TypeBlockArray()); } + public EntryBlock getAnyEntry(String name){ + for(TypeBlock typeBlock:listTypeBlocks()){ + EntryBlock entryBlock=typeBlock.searchByEntryName(name); + if(entryBlock!=null){ + return entryBlock; + } + } + return null; + } public void sortTypes(){ getTypeBlockArray().sort(); } @@ -74,6 +83,9 @@ public class SpecTypePair extends BlockContainer public TypeBlock getOrCreateTypeBlock(String qualifiers){ return getTypeBlockArray().getOrCreate(qualifiers); } + public TypeBlock getOrCreateTypeBlock(ResConfig resConfig){ + return getTypeBlockArray().getOrCreate(resConfig); + } public TypeBlock getTypeBlock(String qualifiers){ return getTypeBlockArray().getTypeBlock(qualifiers); } @@ -84,8 +96,8 @@ public class SpecTypePair extends BlockContainer public byte getTypeId(){ return mSpecBlock.getTypeId(); } - public int getTypeIdInt(){ - return mSpecBlock.getTypeIdInt(); + public int getId(){ + return mSpecBlock.getId(); } public void setTypeId(byte id){ mSpecBlock.setTypeId(id); @@ -177,13 +189,17 @@ public class SpecTypePair extends BlockContainer return typeEntryCount; } public TypeString getTypeString(){ - return getTypeBlockArray().getTypeString(); + PackageBlock packageBlock = getPackageBlock(); + if(packageBlock!=null){ + return packageBlock.getTypeStringPool().getById(getId()); + } + return null; } @Override public JSONObject toJson() { JSONObject jsonObject=new JSONObject(); - jsonObject.put("id", getSpecBlock().getTypeIdInt()); + jsonObject.put("id", getSpecBlock().getId()); jsonObject.put("types", getTypeBlockArray().toJson()); return jsonObject; } @@ -204,7 +220,7 @@ public class SpecTypePair extends BlockContainer } @Override public int compareTo(SpecTypePair specTypePair) { - return Integer.compare(getTypeIdInt(), specTypePair.getTypeIdInt()); + return Integer.compare(getId(), specTypePair.getId()); } @Override public String toString(){ diff --git a/src/main/java/com/reandroid/arsc/header/PackageHeader.java b/src/main/java/com/reandroid/arsc/header/PackageHeader.java index b1f29bd..8094e66 100644 --- a/src/main/java/com/reandroid/arsc/header/PackageHeader.java +++ b/src/main/java/com/reandroid/arsc/header/PackageHeader.java @@ -72,9 +72,19 @@ public class PackageHeader extends HeaderBlock{ public IntegerItem getSpecStringPoolCount() { return specStringPoolCount; } - public IntegerItem getTypeIdOffset() { + public IntegerItem getTypeIdOffsetItem() { return typeIdOffset; } + public void setTypeIdOffset(int offset){ + typeIdOffset.set(offset); + typeIdOffsetContainer.setItem(typeIdOffset); + } + public int getTypeIdOffset() { + if(typeIdOffset.getParent()==null){ + typeIdOffset.set(0); + } + return typeIdOffset.get(); + } @Override void onHeaderSizeLoaded(int size){ super.onHeaderSizeLoaded(size); diff --git a/src/main/java/com/reandroid/arsc/io/BlockReader.java b/src/main/java/com/reandroid/arsc/io/BlockReader.java index bce41a6..a80ed6d 100755 --- a/src/main/java/com/reandroid/arsc/io/BlockReader.java +++ b/src/main/java/com/reandroid/arsc/io/BlockReader.java @@ -47,6 +47,16 @@ import java.io.*; public BlockReader(File file) throws IOException { this(loadBuffer(file)); } + public int readUnsignedShort() throws IOException { + return 0x0000ffff & readShort(); + } + public short readShort() throws IOException { + int pos = getPosition(); + byte[] bts = new byte[2]; + readFully(bts); + seek(pos); + return toShort(bts, 0); + } public InfoHeader readHeaderBlock() throws IOException { InfoHeader infoHeader = new InfoHeader(); if(available() < infoHeader.countBytes()){ @@ -80,6 +90,10 @@ import java.io.*; (bts[offset+2] & 0xff) << 16 | (bts[offset+3] & 0xff) << 24; } + private short toShort(byte[] bts, int offset){ + return (short) (bts[offset] & 0xff | + (bts[offset+1] & 0xff) << 8); + } public byte[] getBytes(){ int len = length(); if(this.BUFFER.length == len){ diff --git a/src/main/java/com/reandroid/arsc/item/BlockItem.java b/src/main/java/com/reandroid/arsc/item/BlockItem.java index 33e1fb0..ad3392c 100755 --- a/src/main/java/com/reandroid/arsc/item/BlockItem.java +++ b/src/main/java/com/reandroid/arsc/item/BlockItem.java @@ -48,7 +48,7 @@ public abstract class BlockItem extends Block { final void setBytesLength(int length){ setBytesLength(length, true); } - final void setBytesLength(int length, boolean notify){ + protected final void setBytesLength(int length, boolean notify){ if(length<0){ length=0; } @@ -122,4 +122,30 @@ public abstract class BlockItem extends Block { super.notifyBlockLoad(); return bts.length; } + + protected static int getInteger(byte[] bts, int offset){ + if((offset+4)>bts.length){ + return 0; + } + return bts[offset] & 0xff | + (bts[offset+1] & 0xff) << 8 | + (bts[offset+2] & 0xff) << 16 | + (bts[offset+3] & 0xff) << 24; + } + protected static short getShort(byte[] bts, int offset){ + return (short) (bts[offset] & 0xff | (bts[offset+1] & 0xff) << 8); + } + protected static void putInteger(byte[] bts, int offset, int val){ + if((offset+4)>bts.length){ + return; + } + bts[offset+3]= (byte) (val >>> 24 & 0xff); + bts[offset+2]= (byte) (val >>> 16 & 0xff); + bts[offset+1]= (byte) (val >>> 8 & 0xff); + bts[offset]= (byte) (val & 0xff); + } + protected static void putShort(byte[] bts, int offset, short val){ + bts[offset+1]= (byte) (val >>> 8 & 0xff); + bts[offset]= (byte) (val & 0xff); + } } diff --git a/src/main/java/com/reandroid/arsc/item/ByteArray.java b/src/main/java/com/reandroid/arsc/item/ByteArray.java index 1d1cd49..9eb530b 100755 --- a/src/main/java/com/reandroid/arsc/item/ByteArray.java +++ b/src/main/java/com/reandroid/arsc/item/ByteArray.java @@ -105,6 +105,9 @@ public class ByteArray extends BlockItem { } public final void putInteger(int offset, int val){ byte[] bts = getBytesInternal(); + if((offset+4)>bts.length){ + return; + } bts[offset+3]= (byte) (val >>> 24 & 0xff); bts[offset+2]= (byte) (val >>> 16 & 0xff); bts[offset+1]= (byte) (val >>> 8 & 0xff); @@ -112,6 +115,9 @@ public class ByteArray extends BlockItem { } public final int getInteger(int offset){ byte[] bts = getBytesInternal(); + if((offset+4)>bts.length){ + return 0; + } return bts[offset] & 0xff | (bts[offset+1] & 0xff) << 8 | (bts[offset+2] & 0xff) << 16 | diff --git a/src/main/java/com/reandroid/arsc/item/StringItem.java b/src/main/java/com/reandroid/arsc/item/StringItem.java index eb37dea..35d2897 100755 --- a/src/main/java/com/reandroid/arsc/item/StringItem.java +++ b/src/main/java/com/reandroid/arsc/item/StringItem.java @@ -17,7 +17,7 @@ package com.reandroid.arsc.item; import com.reandroid.arsc.base.Block; import com.reandroid.arsc.io.BlockReader; -import com.reandroid.arsc.pool.BaseStringPool; +import com.reandroid.arsc.pool.StringPool; import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; @@ -212,18 +212,18 @@ public class StringItem extends BlockItem implements JSONConvert { return styleItem.getSpanInfoList().size()>0; } public StyleItem getStyle(){ - BaseStringPool stringPool=getStringPool(); + StringPool stringPool=getStringPool(); if(stringPool==null){ return null; } int index=getIndex(); return stringPool.getStyle(index); } - private BaseStringPool getStringPool(){ + private StringPool getStringPool(){ Block parent=getParent(); while (parent!=null){ - if(parent instanceof BaseStringPool){ - return (BaseStringPool)parent; + if(parent instanceof StringPool){ + return (StringPool)parent; } parent=parent.getParent(); } diff --git a/src/main/java/com/reandroid/arsc/item/StyleItem.java b/src/main/java/com/reandroid/arsc/item/StyleItem.java index 77890e0..3f18491 100755 --- a/src/main/java/com/reandroid/arsc/item/StyleItem.java +++ b/src/main/java/com/reandroid/arsc/item/StyleItem.java @@ -18,7 +18,7 @@ package com.reandroid.arsc.item; import com.reandroid.arsc.base.Block; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.model.StyleSpanInfo; -import com.reandroid.arsc.pool.BaseStringPool; +import com.reandroid.arsc.pool.StringPool; import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONArray; import com.reandroid.json.JSONObject; @@ -64,7 +64,7 @@ public class StyleItem extends IntegerArray implements JSONConvert { super.put(i, val); } public void addStylePiece(String tag, int firstChar, int lastChar){ - BaseStringPool stringPool = getStringPool(); + StringPool stringPool = getStringPool(); if(stringPool==null){ throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first"); } @@ -188,7 +188,7 @@ public class StyleItem extends IntegerArray implements JSONConvert { return mSpanInfoList; } private String getStringFromPool(int ref){ - BaseStringPool stringPool = getStringPool(); + StringPool stringPool = getStringPool(); if(stringPool==null){ return null; } @@ -198,11 +198,11 @@ public class StyleItem extends IntegerArray implements JSONConvert { } return stringItem.get(); } - private BaseStringPool getStringPool(){ + private StringPool getStringPool(){ Block parent=getParent(); while (parent!=null){ - if(parent instanceof BaseStringPool){ - return (BaseStringPool)parent; + if(parent instanceof StringPool){ + return (StringPool)parent; } parent=parent.getParent(); } @@ -310,7 +310,7 @@ public class StyleItem extends IntegerArray implements JSONConvert { public void addSpanInfo(String tag, int first, int last){ int index=getStylePieceCount(); setStylePieceCount(index+1); - BaseStringPool stringPool = getStringPool(); + StringPool stringPool = getStringPool(); if(stringPool==null){ throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first"); } diff --git a/src/main/java/com/reandroid/arsc/item/TypeString.java b/src/main/java/com/reandroid/arsc/item/TypeString.java index 1c997fb..6ce504c 100755 --- a/src/main/java/com/reandroid/arsc/item/TypeString.java +++ b/src/main/java/com/reandroid/arsc/item/TypeString.java @@ -23,13 +23,13 @@ package com.reandroid.arsc.item; public TypeString(boolean utf8) { super(utf8); } - public byte getId(){ + public int getId(){ TypeStringPool stringPool=getTypeStringPool(); if(stringPool!=null){ return stringPool.idOf(this); } // Should not reach here , this means it not added to string pool - return (byte) (getIndex()+1); + return getIndex()+1; } @Override public StyleItem getStyle(){ diff --git a/src/main/java/com/reandroid/arsc/value/EntryBlock.java b/src/main/java/com/reandroid/arsc/value/EntryBlock.java index 5363134..7364510 100755 --- a/src/main/java/com/reandroid/arsc/value/EntryBlock.java +++ b/src/main/java/com/reandroid/arsc/value/EntryBlock.java @@ -475,7 +475,7 @@ public class EntryBlock extends Block implements JSONConvert { return 0; } int pkgId=packageBlock.getId(); - int typeId=typeBlock.getTypeIdInt(); + int typeId=typeBlock.getId(); int entryId=getIndex(); return ((pkgId << 24) | (typeId << 16) | entryId); } @@ -607,7 +607,7 @@ public class EntryBlock extends Block implements JSONConvert { if(isNull()){ return; } - counter.addCount(countBytes()); + //counter.addCount(countBytes()); entryHeader.onCountUpTo(counter); mSpecReference.onCountUpTo(counter); mResValue.onCountUpTo(counter); @@ -712,7 +712,7 @@ public class EntryBlock extends Block implements JSONConvert { mResValue.onDataLoaded(); } public void merge(EntryBlock entryBlock){ - if(entryBlock==null||entryBlock==this||entryBlock.isNull()){ + if(!shouldMerge(entryBlock)){ return; } String name=entryBlock.getName(); @@ -736,6 +736,27 @@ public class EntryBlock extends Block implements JSONConvert { setPublic(entryBlock.isPublic()); setWeak(entryBlock.isWeak()); } + private boolean shouldMerge(EntryBlock coming){ + if(coming == null || coming == this || coming.isNull()){ + return false; + } + if(this.isNull()){ + return true; + } + BaseResValue value = this.getResValue(); + if(value instanceof ResValueInt){ + ValueType valueType = ((ResValueInt)value).getValueType(); + if(valueType==null || valueType==ValueType.NULL){ + return true; + } + } + value = coming.getResValue(); + if(value instanceof ResValueInt){ + ValueType valueType = ((ResValueInt)value).getValueType(); + return valueType!=null && valueType != ValueType.NULL; + } + return true; + } private ResValueBag getOrCreateResValueBag(){ if(mResValue instanceof ResValueBag){ return (ResValueBag) mResValue; diff --git a/src/main/java/com/reandroid/arsc/value/ResValueBag.java b/src/main/java/com/reandroid/arsc/value/ResValueBag.java index c3798ba..5d72da8 100755 --- a/src/main/java/com/reandroid/arsc/value/ResValueBag.java +++ b/src/main/java/com/reandroid/arsc/value/ResValueBag.java @@ -166,7 +166,7 @@ public class ResValueBag extends BaseResValue { refreshCount(); } public void merge(ResValueBag resValueBag){ - if(resValueBag==null||resValueBag==this){ + if(resValueBag==null || resValueBag==this || resValueBag.getCount()==0){ return; } setParentId(resValueBag.getParentId()); diff --git a/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java b/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java index 425fd3e..0e0bcdb 100755 --- a/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java +++ b/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java @@ -228,6 +228,8 @@ public class ResValueBagItem extends BaseResValueItem{ }else { builder.append("Unknown"); } + builder.append(" size=").append(getHeaderSize()); + builder.append(" bytes=").append(countBytes()); builder.append('('); builder.append(String.format("0x%02x", getType())); builder.append(") id=");