diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8a91a6b..4d33b6c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https://home/d/services.gradle.org/distributions/gradle-6.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java index deda5d1..c31b529 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java @@ -189,7 +189,6 @@ public class PackageBlock extends BaseChunk { return; } updateEntryGroup(entryBlock); - updateEntrySpecReference(entryBlock); updateEntryTableReferences(entryBlock); } private void updateEntryTableReferences(EntryBlock entryBlock){ @@ -201,11 +200,6 @@ public class PackageBlock extends BaseChunk { TableStringPool tableStringPool=tableBlock.getTableStringPool(); tableStringPool.addReferences(tableReferences); } - private void updateEntrySpecReference(EntryBlock entryBlock){ - ReferenceItem specRef=entryBlock.getSpecReferenceBlock(); - SpecStringPool specStringPool=getSpecStringPool(); - specStringPool.addReference(specRef); - } private void updateEntryGroup(EntryBlock entryBlock){ int resId=entryBlock.getResourceId(); EntryGroup group=mEntriesGroup.get(resId); diff --git a/src/main/java/com/reandroid/lib/arsc/group/EntryGroup.java b/src/main/java/com/reandroid/lib/arsc/group/EntryGroup.java index b05d633..ca6b216 100644 --- a/src/main/java/com/reandroid/lib/arsc/group/EntryGroup.java +++ b/src/main/java/com/reandroid/lib/arsc/group/EntryGroup.java @@ -8,6 +8,8 @@ import com.reandroid.lib.arsc.item.TypeString; import com.reandroid.lib.arsc.pool.SpecStringPool; import com.reandroid.lib.arsc.value.EntryBlock; +import java.util.Iterator; + public class EntryGroup extends ItemGroup { private final int resourceId; public EntryGroup(int resId) { @@ -17,43 +19,55 @@ public class EntryGroup extends ItemGroup { public int getResourceId(){ return resourceId; } - public void renameSpec(String name){ + public boolean renameSpec(String name){ EntryBlock[] items=getItems(); - if(items==null){ - return; + if(items==null || name==null){ + return false; } SpecStringPool specStringPool=getSpecStringPool(); if(specStringPool==null){ - return; + return false; + } + String oldName=getSpecName(); + if(name.equals(oldName)){ + return false; } SpecString specString=specStringPool.getOrCreate(name); - renameSpec(specString.getIndex()); + return renameSpec(specString.getIndex()); } - public void renameSpec(int specReference){ + public boolean renameSpec(int specReference){ EntryBlock[] items=getItems(); if(items==null){ - return; + return false; } + boolean renameOk=false; for(EntryBlock block:items){ if(block==null||block.isNull()){ continue; } + if(block.getSpecReference()==specReference){ + continue; + } block.setSpecReference(specReference); + renameOk=true; } + return renameOk; } public TypeString getTypeString(){ - EntryBlock entryBlock=get(0); - if(entryBlock==null){ - return null; + Iterator itr=iterator(true); + while (itr.hasNext()){ + EntryBlock entryBlock=itr.next(); + return entryBlock.getTypeString(); } - return entryBlock.getTypeString(); + return null; } public SpecString getSpecString(){ - EntryBlock entryBlock=get(0); - if(entryBlock==null){ - return null; + Iterator itr=iterator(true); + while (itr.hasNext()){ + EntryBlock entryBlock=itr.next(); + return entryBlock.getSpecString(); } - return entryBlock.getSpecString(); + return null; } public String getTypeName(){ TypeString typeString=getTypeString(); diff --git a/src/main/java/com/reandroid/lib/arsc/group/ItemGroup.java b/src/main/java/com/reandroid/lib/arsc/group/ItemGroup.java index bd84d56..7bddff5 100644 --- a/src/main/java/com/reandroid/lib/arsc/group/ItemGroup.java +++ b/src/main/java/com/reandroid/lib/arsc/group/ItemGroup.java @@ -4,6 +4,7 @@ import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.base.BlockArrayCreator; import java.util.AbstractList; +import java.util.Iterator; import java.util.List; public class ItemGroup { @@ -17,6 +18,12 @@ public class ItemGroup { this.items=blockArrayCreator.newInstance(0); this.hashCode=(getClass().getName()+"-"+name).hashCode(); } + public Iterator iterator(){ + return iterator(false); + } + public Iterator iterator(boolean skipNullBlock){ + return new GroupIterator(skipNullBlock); + } public List listItems(){ return new AbstractList() { @Override @@ -128,4 +135,47 @@ public class ItemGroup { public String toString(){ return items.length+"{"+name+"}"; } + + + private class GroupIterator implements Iterator { + private int mCursor; + private int mMaxSize; + private final boolean mSkipNullBlock; + GroupIterator(boolean skipNullBlock){ + mSkipNullBlock=skipNullBlock; + mCursor=0; + mMaxSize=ItemGroup.this.size(); + } + @Override + public boolean hasNext() { + checkCursor(); + return !isFinished(); + } + @Override + public T next() { + if(!isFinished()){ + T item=ItemGroup.this.get(mCursor); + mCursor++; + checkCursor(); + return item; + } + return null; + } + private boolean isFinished(){ + return mCursor>=mMaxSize; + } + private void checkCursor(){ + if(!mSkipNullBlock || isFinished()){ + return; + } + T item=ItemGroup.this.get(mCursor); + while (item==null||item.isNull()){ + mCursor++; + item=ItemGroup.this.get(mCursor); + if(mCursor>=mMaxSize){ + break; + } + } + } + } } diff --git a/src/main/java/com/reandroid/lib/arsc/item/StringItem.java b/src/main/java/com/reandroid/lib/arsc/item/StringItem.java index 38c40ac..d92ff65 100644 --- a/src/main/java/com/reandroid/lib/arsc/item/StringItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/StringItem.java @@ -24,8 +24,14 @@ public class StringItem extends BlockItem { this.mUtf8=utf8; this.mReferencedList=new ArrayList<>(); } - public void removeReference(IntegerItem ref){ - mReferencedList.remove(ref); + public boolean removeReference(ReferenceItem ref){ + return mReferencedList.remove(ref); + } + public boolean removeAllReference(Collection referenceItems){ + return mReferencedList.removeAll(referenceItems); + } + public void removeAllReference(){ + mReferencedList.clear(); } public List getReferencedList(){ return mReferencedList; diff --git a/src/main/java/com/reandroid/lib/arsc/item/TypeString.java b/src/main/java/com/reandroid/lib/arsc/item/TypeString.java index 28b2605..98beaba 100644 --- a/src/main/java/com/reandroid/lib/arsc/item/TypeString.java +++ b/src/main/java/com/reandroid/lib/arsc/item/TypeString.java @@ -5,8 +5,8 @@ public class TypeString extends StringItem { public TypeString(boolean utf8) { super(utf8); } - public int getId(){ - return getIndex()+1; + public byte getId(){ + return (byte) (getIndex()+1); } @Override StyleItem getStyle(){ diff --git a/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java b/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java index 8e30bec..0f1d73c 100644 --- a/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java +++ b/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java @@ -66,6 +66,16 @@ public abstract class BaseStringPool extends BaseChunk imp } + public boolean removeReference(ReferenceItem ref){ + if(ref==null){ + return false; + } + T item=get(ref.get()); + if(item!=null){ + return item.removeReference(ref); + } + return false; + } public void addReference(ReferenceItem ref){ if(ref==null){ return; diff --git a/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java b/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java index 220eae0..8d7b236 100644 --- a/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java +++ b/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java @@ -1,9 +1,13 @@ package com.reandroid.lib.arsc.value; import com.reandroid.lib.arsc.base.Block; +import com.reandroid.lib.arsc.chunk.PackageBlock; +import com.reandroid.lib.arsc.chunk.TableBlock; import com.reandroid.lib.arsc.item.BlockItem; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.item.ReferenceItem; +import com.reandroid.lib.arsc.pool.SpecStringPool; +import com.reandroid.lib.arsc.pool.TableStringPool; import java.util.List; @@ -24,6 +28,35 @@ public abstract class BaseResValue extends BlockItem { return null; } + boolean removeSpecReference(ReferenceItem ref){ + EntryBlock entryBlock=getEntryBlock(); + if(entryBlock==null){ + return false; + } + return entryBlock.removeSpecReference(ref); + } + boolean removeTableReference(ReferenceItem ref){ + EntryBlock entryBlock=getEntryBlock(); + if(entryBlock==null){ + return false; + } + return entryBlock.removeTableReference(ref); + } + void addSpecReference(ReferenceItem ref){ + EntryBlock entryBlock=getEntryBlock(); + if(entryBlock==null){ + return; + } + entryBlock.addSpecReference(ref); + } + void addTableReference(ReferenceItem ref){ + EntryBlock entryBlock=getEntryBlock(); + if(entryBlock==null){ + return; + } + entryBlock.addTableReference(ref); + } + @Override diff --git a/src/main/java/com/reandroid/lib/arsc/value/BaseResValueItem.java b/src/main/java/com/reandroid/lib/arsc/value/BaseResValueItem.java index 5d90ad6..6b53677 100644 --- a/src/main/java/com/reandroid/lib/arsc/value/BaseResValueItem.java +++ b/src/main/java/com/reandroid/lib/arsc/value/BaseResValueItem.java @@ -17,6 +17,18 @@ public abstract class BaseResValueItem extends BaseResValue implements ResValueI } return mReferenceItem; } + boolean removeTableReference(){ + ReferenceItem ref=mReferenceItem; + if(ref==null){ + return false; + } + EntryBlock entryBlock=getEntryBlock(); + if(entryBlock==null){ + return false; + } + mReferenceItem=null; + return entryBlock.removeTableReference(ref); + } private ReferenceItem createReferenceItem(){ return new ReferenceItem() { @Override diff --git a/src/main/java/com/reandroid/lib/arsc/value/EntryBlock.java b/src/main/java/com/reandroid/lib/arsc/value/EntryBlock.java index b487dff..e4e16d5 100644 --- a/src/main/java/com/reandroid/lib/arsc/value/EntryBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/value/EntryBlock.java @@ -3,10 +3,12 @@ package com.reandroid.lib.arsc.value; import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.base.BlockCounter; import com.reandroid.lib.arsc.chunk.PackageBlock; +import com.reandroid.lib.arsc.chunk.TableBlock; import com.reandroid.lib.arsc.chunk.TypeBlock; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.*; import com.reandroid.lib.arsc.pool.SpecStringPool; +import com.reandroid.lib.arsc.pool.TableStringPool; import java.io.IOException; @@ -43,6 +45,59 @@ public class EntryBlock extends Block { } return results; } + boolean removeSpecReference(ReferenceItem ref){ + if(ref==null){ + return false; + } + PackageBlock packageBlock=getPackageBlock(); + if(packageBlock==null){ + return false; + } + SpecStringPool specStringPool=packageBlock.getSpecStringPool(); + return specStringPool.removeReference(ref); + } + boolean removeTableReference(ReferenceItem ref){ + if(ref==null){ + return false; + } + PackageBlock packageBlock=getPackageBlock(); + if(packageBlock==null){ + return false; + } + TableBlock tableBlock=packageBlock.getTableBlock(); + if(tableBlock==null){ + return false; + } + TableStringPool tableStringPool=tableBlock.getTableStringPool(); + return tableStringPool.removeReference(ref); + } + + void addSpecReference(ReferenceItem ref){ + if(ref==null){ + return; + } + PackageBlock packageBlock=getPackageBlock(); + if(packageBlock==null){ + return; + } + SpecStringPool specStringPool=packageBlock.getSpecStringPool(); + specStringPool.addReference(ref); + } + void addTableReference(ReferenceItem ref){ + if(ref==null){ + return; + } + PackageBlock packageBlock=getPackageBlock(); + if(packageBlock==null){ + return; + } + TableBlock tableBlock=packageBlock.getTableBlock(); + if(tableBlock==null){ + return; + } + TableStringPool tableStringPool=tableBlock.getTableStringPool(); + tableStringPool.addReference(ref); + } public short getFlags(){ return mFlags.get(); @@ -57,7 +112,12 @@ public class EntryBlock extends Block { return mSpecReference.get(); } public void setSpecReference(int ref){ + int old=mSpecReference.get(); + if(ref==old){ + return; + } mSpecReference.set(ref); + updateSpecRef(old, ref); } public BaseResValue getResValue(){ return mResValue; @@ -74,6 +134,7 @@ public class EntryBlock extends Block { boolean is_complex=(resValue instanceof ResValueBag); setFlagComplex(is_complex); updatePackage(); + updateSpecRef(); } } private void setResValueInternal(BaseResValue resValue){ @@ -111,11 +172,7 @@ public class EntryBlock extends Block { return null; } public SpecString getSpecString(){ - TypeBlock typeBlock=getTypeBlock(); - if(typeBlock==null){ - return null; - } - PackageBlock packageBlock=typeBlock.getPackageBlock(); + PackageBlock packageBlock=getPackageBlock(); if(packageBlock==null){ return null; } @@ -173,6 +230,13 @@ public class EntryBlock extends Block { int entryId=getIndex(); return ((pkgId << 24) | (typeId << 16) | entryId); } + public PackageBlock getPackageBlock(){ + TypeBlock typeBlock=getTypeBlock(); + if(typeBlock!=null){ + return typeBlock.getPackageBlock(); + } + return null; + } public TypeBlock getTypeBlock(){ Block parent=getParent(); while (parent!=null){ @@ -326,6 +390,28 @@ public class EntryBlock extends Block { return result; } + private void updateSpecRef(){ + updateSpecRef(-1, getSpecReference()); + } + private void updateSpecRef(int oldRef, int newNef){ + TypeBlock typeBlock=getTypeBlock(); + if(typeBlock==null){ + return; + } + PackageBlock packageBlock=typeBlock.getPackageBlock(); + if(packageBlock==null){ + return; + } + SpecStringPool specStringPool=packageBlock.getSpecStringPool(); + SpecString specString=specStringPool.get(oldRef); + if(specString!=null){ + specString.removeReference(getSpecReferenceBlock()); + } + SpecString specStringNew=specStringPool.get(newNef); + if(specStringNew!=null){ + specStringNew.addReference(getSpecReferenceBlock()); + } + } private void updatePackage(){ TypeBlock typeBlock=getTypeBlock(); if(typeBlock==null){ @@ -347,6 +433,7 @@ public class EntryBlock extends Block { createResValue(); mResValue.readBytes(reader); updatePackage(); + updateSpecRef(); } public String toString(){ StringBuilder builder=new StringBuilder(); diff --git a/src/main/java/com/reandroid/lib/arsc/value/ResValueBagItem.java b/src/main/java/com/reandroid/lib/arsc/value/ResValueBagItem.java index 34ae508..9026d7b 100644 --- a/src/main/java/com/reandroid/lib/arsc/value/ResValueBagItem.java +++ b/src/main/java/com/reandroid/lib/arsc/value/ResValueBagItem.java @@ -1,5 +1,7 @@ package com.reandroid.lib.arsc.value; +import com.reandroid.lib.arsc.item.ReferenceItem; + public class ResValueBagItem extends BaseResValueItem{ public ResValueBagItem() { @@ -41,7 +43,16 @@ public class ResValueBagItem extends BaseResValueItem{ } @Override public void setType(byte type){ + byte old=getType(); + if(type==old){ + return; + } + removeTableReference(); setByte(OFFSET_TYPE, type); + if(type==ValueType.STRING.getByte()){ + ReferenceItem ref=getTableStringReference(); + removeTableReference(ref); + } } @Override public byte getType(){ @@ -53,7 +64,17 @@ public class ResValueBagItem extends BaseResValueItem{ } @Override public void setData(int data){ + int old=getData(); + if(data==old){ + return; + } + if(getValueType()==ValueType.STRING){ + removeTableReference(); + } setInt(OFFSET_DATA, data); + if(getValueType()==ValueType.STRING){ + addTableReference(getTableStringReference()); + } } @Override diff --git a/src/main/java/com/reandroid/lib/arsc/value/ResValueInt.java b/src/main/java/com/reandroid/lib/arsc/value/ResValueInt.java index 1784201..789b053 100644 --- a/src/main/java/com/reandroid/lib/arsc/value/ResValueInt.java +++ b/src/main/java/com/reandroid/lib/arsc/value/ResValueInt.java @@ -29,7 +29,15 @@ public class ResValueInt extends BaseResValueItem { } @Override public void setType(byte type){ + byte old=getType(); + if(type==old){ + return; + } + removeTableReference(); setByte(OFFSET_TYPE, type); + if(type==ValueType.STRING.getByte()){ + addTableReference(getTableStringReference()); + } } @Override public byte getType(){ @@ -41,7 +49,15 @@ public class ResValueInt extends BaseResValueItem { } @Override public void setData(int data){ + int old=getData(); + if(data==old){ + return; + } + removeTableReference(); setInt(OFFSET_DATA, data); + if(getValueType()==ValueType.STRING){ + addTableReference(getTableStringReference()); + } }