diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/BaseChunk.java b/src/main/java/com/reandroid/lib/arsc/chunk/BaseChunk.java index 344ab36..0642411 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/BaseChunk.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/BaseChunk.java @@ -15,35 +15,28 @@ */ package com.reandroid.lib.arsc.chunk; -import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.container.ExpandableBlockContainer; import com.reandroid.lib.arsc.header.HeaderBlock; import com.reandroid.lib.arsc.io.BlockReader; import java.io.IOException; -public abstract class BaseChunk extends ExpandableBlockContainer { - private final HeaderBlock mHeaderBlock; - protected BaseChunk(short chunkType, int initialChildesCount) { +public abstract class BaseChunk extends ExpandableBlockContainer { + private final T mHeaderBlock; + protected BaseChunk(T headerBlock, int initialChildesCount) { super(initialChildesCount+1); - mHeaderBlock=new HeaderBlock(chunkType); - addChild(mHeaderBlock); - } - protected BaseChunk(ChunkType chunkType, int initialChildesCount) { - this(chunkType.ID, initialChildesCount); - } - protected void addToHeader(Block block){ - mHeaderBlock.addChild(block); + this.mHeaderBlock = headerBlock; + addChild(headerBlock); } void setHeaderLoaded(HeaderBlock.HeaderLoaded headerLoaded){ - mHeaderBlock.setHeaderLoaded(headerLoaded); + getHeaderBlock().setHeaderLoaded(headerLoaded); } - public HeaderBlock getHeaderBlock(){ + public final T getHeaderBlock(){ return mHeaderBlock; } @Override protected final void onRefreshed() { - mHeaderBlock.refreshHeader(); + getHeaderBlock().refreshHeader(); onChunkRefreshed(); } protected abstract void onChunkRefreshed(); @@ -73,7 +66,7 @@ public abstract class BaseChunk extends ExpandableBlockContainer { StringBuilder builder=new StringBuilder(); builder.append(getClass().getSimpleName()); builder.append(": "); - builder.append(mHeaderBlock.toString()); + builder.append(getHeaderBlock()); return builder.toString(); } } diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/LibraryBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/LibraryBlock.java index 8a32689..302f2be 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/LibraryBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/LibraryBlock.java @@ -16,21 +16,20 @@ package com.reandroid.lib.arsc.chunk; import com.reandroid.lib.arsc.array.LibraryInfoArray; +import com.reandroid.lib.arsc.header.LibraryHeader; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.value.LibraryInfo; import java.util.Collection; import java.util.List; -public class LibraryBlock extends BaseChunk { - private final IntegerItem mLibCount; +public class LibraryBlock extends BaseChunk { private final LibraryInfoArray mLibraryInfoArray; public LibraryBlock() { - super(ChunkType.LIBRARY,1); - this.mLibCount=new IntegerItem(); - this.mLibraryInfoArray=new LibraryInfoArray(mLibCount); + super(new LibraryHeader(),1); + LibraryHeader header = getHeaderBlock(); + this.mLibraryInfoArray = new LibraryInfoArray(header.getCount()); - addToHeader(mLibCount); addChild(mLibraryInfoArray); } public LibraryInfoArray getLibraryInfoArray(){ @@ -49,7 +48,7 @@ public class LibraryBlock extends BaseChunk { return; } getLibraryInfoArray().add(info); - mLibCount.set(mLibraryInfoArray.childesCount()); + getHeaderBlock().getCount().set(mLibraryInfoArray.childesCount()); } public Collection listLibraryInfo(){ return getLibraryInfoArray().listItems(); @@ -62,12 +61,12 @@ public class LibraryBlock extends BaseChunk { return mLibraryInfoArray.childesCount(); } public void setLibraryCount(int count){ - mLibCount.set(count); + getHeaderBlock().getCount().set(count); mLibraryInfoArray.setChildesCount(count); } @Override protected void onChunkRefreshed() { - mLibCount.set(mLibraryInfoArray.childesCount()); + getHeaderBlock().getCount().set(mLibraryInfoArray.childesCount()); } public void merge(LibraryBlock libraryBlock){ diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java b/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java index e311b20..3e4a5ad 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java @@ -17,6 +17,7 @@ import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.header.HeaderBlock; + import com.reandroid.lib.arsc.header.OverlayableHeader; import com.reandroid.lib.arsc.io.BlockLoad; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.ByteArray; @@ -29,9 +30,7 @@ * We didn't test this class with resource table, if someone found a resource/apk please * create issue on https://github.com/REAndroid/ARSCLib * */ - public class Overlayable extends BaseChunk implements BlockLoad { - private final FixedLengthString name; - private final FixedLengthString actor; + public class Overlayable extends BaseChunk implements BlockLoad { /** * @link body * As on AOSP there is only a description of header struct but no mention about @@ -39,33 +38,29 @@ * */ private final ByteArray body; public Overlayable() { - super(ChunkType.OVERLAYABLE, 1); - this.name = new FixedLengthString(512); - this.actor = new FixedLengthString(512); + super(new OverlayableHeader(), 1); this.body = new ByteArray(); - addToHeader(this.name); - addToHeader(this.actor); addChild(this.body); - this.actor.setBlockLoad(this); + getHeaderBlock().getActor().setBlockLoad(this); } public ByteArray getBody() { return body; } public String getName(){ - return this.name.get(); + return getHeaderBlock().getName().get(); } public void setName(String str){ - this.name.set(str); + getHeaderBlock().getName().set(str); } public String getActor(){ - return this.actor.get(); + return getHeaderBlock().getActor().get(); } public void setActor(String str){ - this.actor.set(str); + getHeaderBlock().getActor().set(str); } @Override public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { - if(sender==this.actor){ + if(sender==getHeaderBlock().getActor()){ HeaderBlock header = getHeaderBlock(); int bodySize=header.getChunkSize()-header.getHeaderSize(); this.body.setSize(bodySize); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java b/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java index 8bed73d..f40a497 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java @@ -16,6 +16,7 @@ package com.reandroid.lib.arsc.chunk; import com.reandroid.lib.arsc.base.Block; + import com.reandroid.lib.arsc.header.OverlayablePolicyHeader; import com.reandroid.lib.arsc.io.BlockLoad; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.IntegerArray; @@ -29,22 +30,15 @@ * We didn't test this class with resource table, if someone found a resource/apk please * create issue on https://github.com/REAndroid/ARSCLib * */ - public class OverlayablePolicy extends BaseChunk implements BlockLoad { - private final IntegerItem flags; - private final IntegerItem entryCount; + public class OverlayablePolicy extends BaseChunk implements BlockLoad { private final IntegerArray tableRefArray; public OverlayablePolicy(){ - super(ChunkType.OVERLAYABLE_POLICY, 1); - this.flags = new IntegerItem(); - this.entryCount = new IntegerItem(); + super(new OverlayablePolicyHeader(), 1); this.tableRefArray = new IntegerArray(); - addToHeader(this.flags); - addToHeader(this.entryCount); - addChild(this.tableRefArray); - this.entryCount.setBlockLoad(this); + getHeaderBlock().getEntryCount().setBlockLoad(this); } @Override public boolean isNull() { @@ -61,10 +55,10 @@ return tableRefArray; } public int getFlags() { - return flags.get(); + return getHeaderBlock().getFlags().get(); } public void setFlags(int flags){ - this.flags.set(flags); + getHeaderBlock().getFlags().set(flags); } public void setFlags(PolicyFlag[] policyFlags){ setFlags(PolicyFlag.sum(policyFlags)); @@ -78,11 +72,12 @@ } @Override protected void onChunkRefreshed() { - this.entryCount.set(getTableRefArray().size()); + getHeaderBlock().getEntryCount().set(getTableRefArray().size()); } @Override public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { - if(sender==this.entryCount){ + IntegerItem entryCount = getHeaderBlock().getEntryCount(); + if(sender==entryCount){ this.tableRefArray.setSize(entryCount.get()); } } 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 966fa76..be4467c 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java @@ -24,6 +24,7 @@ package com.reandroid.lib.arsc.chunk; import com.reandroid.lib.arsc.container.SingleBlockContainer; import com.reandroid.lib.arsc.container.SpecTypePair; import com.reandroid.lib.arsc.group.EntryGroup; + import com.reandroid.lib.arsc.header.PackageHeader; import com.reandroid.lib.arsc.io.BlockLoad; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.FixedLengthString; @@ -42,17 +43,8 @@ package com.reandroid.lib.arsc.chunk; import java.util.*; - public class PackageBlock extends BaseChunk - implements BlockLoad, JSONConvert, Comparable { - private final IntegerItem mPackageId; - private final FixedLengthString mPackageName; - - private final IntegerItem mTypeStringPoolOffset; - private final IntegerItem mTypeStringPoolCount; - private final IntegerItem mSpecStringPoolOffset; - private final IntegerItem mSpecStringPoolCount; - private final SingleBlockContainer mTypeIdOffsetContainer; - private final IntegerItem mTypeIdOffset; + public class PackageBlock extends BaseChunk + implements JSONConvert, Comparable { private final TypeStringPool mTypeStringPool; private final SpecStringPool mSpecStringPool; @@ -62,42 +54,19 @@ package com.reandroid.lib.arsc.chunk; private final Map mEntriesGroup; public PackageBlock() { - super(ChunkType.PACKAGE, 3); - this.mPackageId=new IntegerItem(); - this.mPackageName = new FixedLengthString(256); + super(new PackageHeader(), 3); + PackageHeader header = getHeaderBlock(); - this.mTypeStringPoolOffset = new IntegerItem(); - this.mTypeStringPoolCount = new IntegerItem(); - this.mSpecStringPoolOffset = new IntegerItem(); - this.mSpecStringPoolCount = new IntegerItem(); - - this.mTypeIdOffsetContainer = new SingleBlockContainer<>(); - this.mTypeIdOffset = new IntegerItem(); - this.mTypeIdOffsetContainer.setItem(mTypeIdOffset); - - - this.mTypeStringPool=new TypeStringPool(false, mTypeIdOffset); + this.mTypeStringPool=new TypeStringPool(false, header.getTypeIdOffset()); this.mSpecStringPool=new SpecStringPool(true); this.mBody = new PackageBody(); this.mEntriesGroup=new HashMap<>(); - mPackageId.setBlockLoad(this); - - addToHeader(mPackageId); - addToHeader(mPackageName); - addToHeader(mTypeStringPoolOffset); - addToHeader(mTypeStringPoolCount); - addToHeader(mSpecStringPoolOffset); - addToHeader(mSpecStringPoolCount); - addToHeader(mTypeIdOffsetContainer); - addChild(mTypeStringPool); addChild(mSpecStringPool); - addChild(mBody); - } public BlockList getUnknownChunkList(){ return mBody.getUnknownChunkList(); @@ -125,16 +94,7 @@ package com.reandroid.lib.arsc.chunk; public void sortTypes(){ getSpecTypePairArray().sort(); } - @Override - public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { - if(sender==mPackageId){ - int headerSize=getHeaderBlock().getHeaderSize(); - if(headerSize<288){ - mTypeIdOffset.set(0); - mTypeIdOffsetContainer.setItem(null); - } - } - } + public void removeEmpty(){ getSpecTypePairArray().removeEmptyPairs(); } @@ -142,19 +102,19 @@ package com.reandroid.lib.arsc.chunk; return getSpecTypePairArray().isEmpty(); } public int getId(){ - return mPackageId.get(); + return getHeaderBlock().getPackageId().get(); } public void setId(byte id){ setId(0xff & id); } public void setId(int id){ - mPackageId.set(id); + getHeaderBlock().getPackageId().set(id); } public String getName(){ - return mPackageName.get(); + return getHeaderBlock().getPackageName().get(); } public void setName(String name){ - mPackageName.set(name); + getHeaderBlock().getPackageName().set(name); } public TableBlock getTableBlock(){ Block parent=getParent(); @@ -296,24 +256,24 @@ package com.reandroid.lib.arsc.chunk; private void refreshTypeStringPoolOffset(){ int pos=countUpTo(mTypeStringPool); - mTypeStringPoolOffset.set(pos); + getHeaderBlock().getTypeStringPoolOffset().set(pos); } private void refreshTypeStringPoolCount(){ - mTypeStringPoolCount.set(mTypeStringPool.countStrings()); + getHeaderBlock().getTypeStringPoolCount().set(mTypeStringPool.countStrings()); } private void refreshSpecStringPoolOffset(){ int pos=countUpTo(mSpecStringPool); - mSpecStringPoolOffset.set(pos); + getHeaderBlock().getSpecStringPoolOffset().set(pos); } private void refreshSpecStringCount(){ - mSpecStringPoolCount.set(mSpecStringPool.countStrings()); + getHeaderBlock().getSpecStringPoolCount().set(mSpecStringPool.countStrings()); } private void refreshTypeIdOffset(){ // TODO: find solution //int largest=getSpecTypePairArray().getHighestTypeId(); //int count=getTypeStringPool().countStrings(); - //mTypeIdOffset.set(count-largest); - mTypeIdOffset.set(0); + //getHeaderBlock().getTypeIdOffset().set(count-largest); + getHeaderBlock().getTypeIdOffset().set(0); } public void onEntryAdded(EntryBlock entryBlock){ updateEntry(entryBlock); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/SpecBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/SpecBlock.java index 0e17f3d..cc1b730 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/SpecBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/SpecBlock.java @@ -18,27 +18,19 @@ import com.reandroid.lib.arsc.array.TypeBlockArray; import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.container.SpecTypePair; + import com.reandroid.lib.arsc.header.SpecHeader; import com.reandroid.lib.arsc.item.*; import com.reandroid.lib.json.JSONConvert; import com.reandroid.lib.json.JSONObject; import java.util.List; - public class SpecBlock extends BaseChunk implements JSONConvert { + public class SpecBlock extends BaseChunk implements JSONConvert { private final SpecFlagsArray specFlagsArray; - private final ByteItem mTypeId; public SpecBlock() { - super(ChunkType.SPEC, 1); - this.mTypeId=new ByteItem(); - ByteItem res0 = new ByteItem(); - ShortItem res1 = new ShortItem(); - IntegerItem entryCount = new IntegerItem(); - this.specFlagsArray = new SpecFlagsArray(entryCount); - addToHeader(mTypeId); - addToHeader(res0); - addToHeader(res1); - addToHeader(entryCount); - + super(new SpecHeader(), 1); + SpecHeader header = getHeaderBlock(); + this.specFlagsArray = new SpecFlagsArray(header.getEntryCount()); addChild(specFlagsArray); } public SpecFlagsArray getSpecFlagsArray(){ @@ -48,16 +40,16 @@ return specFlagsArray.toList(); } public byte getTypeId(){ - return mTypeId.get(); + return getHeaderBlock().getId().get(); } public int getTypeIdInt(){ - return (0xff & mTypeId.get()); + return getHeaderBlock().getId().unsignedInt(); } public void setTypeId(int id){ setTypeId((byte) (0xff & id)); } public void setTypeId(byte id){ - mTypeId.set(id); + getHeaderBlock().getId().set(id); } public TypeBlockArray getTypeBlockArray(){ SpecTypePair specTypePair=getSpecTypePair(); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/StagedAlias.java b/src/main/java/com/reandroid/lib/arsc/chunk/StagedAlias.java index 35a1d1a..845c2e6 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/StagedAlias.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/StagedAlias.java @@ -16,18 +16,19 @@ package com.reandroid.lib.arsc.chunk; import com.reandroid.lib.arsc.array.StagedAliasEntryArray; + import com.reandroid.lib.arsc.header.StagedAliasHeader; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.value.StagedAliasEntry; import java.util.Collection; - public class StagedAlias extends BaseChunk{ + public class StagedAlias extends BaseChunk{ private final StagedAliasEntryArray stagedAliasEntryArray; public StagedAlias() { - super(ChunkType.STAGED_ALIAS, 1); - IntegerItem count = new IntegerItem(); - addToHeader(count); - stagedAliasEntryArray = new StagedAliasEntryArray(count); + super(new StagedAliasHeader(), 1); + StagedAliasHeader header = getHeaderBlock(); + + stagedAliasEntryArray = new StagedAliasEntryArray(header.getCount()); addChild(stagedAliasEntryArray); } public void merge(StagedAlias stagedAlias){ diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/TableBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/TableBlock.java index 9223a9d..29971c9 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/TableBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/TableBlock.java @@ -19,6 +19,7 @@ import com.reandroid.lib.arsc.BuildInfo; import com.reandroid.lib.arsc.array.PackageArray; import com.reandroid.lib.arsc.group.EntryGroup; import com.reandroid.lib.arsc.header.HeaderBlock; +import com.reandroid.lib.arsc.header.TableHeader; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.pool.TableStringPool; @@ -33,17 +34,15 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; -public class TableBlock extends BaseChunk implements JSONConvert { - private final IntegerItem mPackageCount; +public class TableBlock extends BaseChunk implements JSONConvert { private final TableStringPool mTableStringPool; private final PackageArray mPackageArray; private final Set mFrameWorks=new HashSet<>(); public TableBlock() { - super(ChunkType.TABLE, 2); - this.mPackageCount=new IntegerItem(); + super(new TableHeader(), 2); + TableHeader header = getHeaderBlock(); this.mTableStringPool=new TableStringPool(true); - this.mPackageArray=new PackageArray(mPackageCount); - addToHeader(mPackageCount); + this.mPackageArray=new PackageArray(header.getPackageCount()); addChild(mTableStringPool); addChild(mPackageArray); } @@ -68,7 +67,7 @@ public class TableBlock extends BaseChunk implements JSONConvert { private void refreshPackageCount(){ int count = getPackageArray().childesCount(); - mPackageCount.set(count); + getHeaderBlock().getPackageCount().set(count); } @Override protected void onChunkRefreshed() { diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java index 30f850e..379de53 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java @@ -19,6 +19,7 @@ import com.reandroid.lib.arsc.array.EntryBlockArray; import com.reandroid.lib.arsc.array.TypeBlockArray; import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.container.SpecTypePair; +import com.reandroid.lib.arsc.header.TypeHeader; import com.reandroid.lib.arsc.io.BlockLoad; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.*; @@ -34,34 +35,20 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class TypeBlock extends BaseChunk +public class TypeBlock extends BaseChunk implements BlockLoad, JSONConvert, Comparable { - private final ByteItem mTypeId; - private final ByteItem mTypeFlags; - private final IntegerItem mEntryCount; - private final ResConfig mResConfig; + private final EntryBlockArray mEntryArray; private TypeString mTypeString; public TypeBlock() { - super(ChunkType.TYPE, 2); - this.mTypeId=new ByteItem(); - this.mTypeFlags=new ByteItem(); - ShortItem reserved = new ShortItem(); - this.mEntryCount=new IntegerItem(); + super(new TypeHeader(), 2); + TypeHeader header = getHeaderBlock(); - IntegerItem entriesStart = new IntegerItem(); - this.mResConfig =new ResConfig(); IntegerArray entryOffsets = new IntegerArray(); - this.mEntryArray = new EntryBlockArray(entryOffsets, mEntryCount, entriesStart); + this.mEntryArray = new EntryBlockArray(entryOffsets, + header.getCount(), header.getEntriesStart()); - mTypeFlags.setBlockLoad(this); - - addToHeader(mTypeId); - addToHeader(mTypeFlags); - addToHeader(reserved); - addToHeader(mEntryCount); - addToHeader(entriesStart); - addToHeader(mResConfig); + header.getFlags().setBlockLoad(this); addChild(entryOffsets); addChild(mEntryArray); @@ -99,16 +86,16 @@ public class TypeBlock extends BaseChunk return mTypeString; } public byte getTypeId(){ - return mTypeId.get(); + return getHeaderBlock().getId().get(); } public int getTypeIdInt(){ - return (0xff & mTypeId.get()); + return getHeaderBlock().getId().unsignedInt(); } public void setTypeId(int id){ setTypeId((byte) (0xff & id)); } public void setTypeId(byte id){ - mTypeId.set(id); + getHeaderBlock().getId().set(id); } public void setTypeName(String name){ TypeStringPool typeStringPool=getTypeStringPool(); @@ -127,10 +114,11 @@ public class TypeBlock extends BaseChunk return null; } public void setEntryCount(int count){ - if(count == mEntryCount.get()){ + IntegerItem entryCount = getHeaderBlock().getCount(); + if(count == entryCount.get()){ return; } - mEntryCount.set(count); + entryCount.set(count); onSetEntryCount(count); } public boolean isEmpty(){ @@ -182,7 +170,7 @@ public class TypeBlock extends BaseChunk return getEntryBlockArray().getEntry(entryId); } public ResConfig getResConfig(){ - return mResConfig; + return getHeaderBlock().getConfig(); } public EntryBlockArray getEntryBlockArray(){ return mEntryArray; @@ -212,7 +200,7 @@ public class TypeBlock extends BaseChunk } @Override protected void onPreRefreshRefresh(){ - mResConfig.refresh(); + getHeaderBlock().getConfig().refresh(); super.onPreRefreshRefresh(); } /* @@ -280,8 +268,8 @@ public class TypeBlock extends BaseChunk } @Override public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { - if(sender==mTypeFlags){ - if(mTypeFlags.get()==0x1){ + if(sender==getHeaderBlock().getFlags()){ + if(getHeaderBlock().getFlags().unsignedInt()==0x1){ //ResTable_sparseTypeEntry ? } } diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java b/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java index 1d63da7..a78e09e 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/UnknownChunk.java @@ -24,10 +24,10 @@ package com.reandroid.lib.arsc.chunk; * This class can load any valid chunk, aimed to * handle any future android changes * */ -public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded { +public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded { private final ByteArray body; public UnknownChunk() { - super(INITIAL_CHUNK_TYPE, 1); + super(new HeaderBlock(INITIAL_CHUNK_TYPE), 1); this.body = new ByteArray(); addChild(body); setHeaderLoaded(this); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java index d72c2a0..bfbb139 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/BaseXmlChunk.java @@ -18,6 +18,7 @@ package com.reandroid.lib.arsc.chunk.xml; import com.reandroid.lib.arsc.chunk.ChunkType; import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.chunk.BaseChunk; +import com.reandroid.lib.arsc.header.XmlNodeHeader; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.item.ResXmlString; import com.reandroid.lib.arsc.pool.ResXmlStringPool; @@ -26,30 +27,23 @@ import java.util.HashSet; import java.util.Set; - public class BaseXmlChunk extends BaseChunk { + public class BaseXmlChunk extends BaseChunk { - private final IntegerItem mLineNumber; - private final IntegerItem mCommentReference; private final IntegerItem mNamespaceReference; private final IntegerItem mStringReference; BaseXmlChunk(ChunkType chunkType, int initialChildesCount) { - super(chunkType, initialChildesCount+2); - this.mLineNumber=new IntegerItem(); - this.mCommentReference =new IntegerItem(-1); + super(new XmlNodeHeader(chunkType), initialChildesCount+2); this.mNamespaceReference=new IntegerItem(-1); this.mStringReference=new IntegerItem(-1); - addToHeader(mLineNumber); - addToHeader(mCommentReference); - addChild(mNamespaceReference); addChild(mStringReference); } Set clearStringReferences(){ Set results=new HashSet<>(); ResXmlString xmlString; - xmlString=unLinkStringReference(mCommentReference); + xmlString=unLinkStringReference(getHeaderBlock().getCommentReference()); if(xmlString!=null){ results.add(xmlString); } @@ -64,7 +58,7 @@ import java.util.Set; return results; } void linkStringReferences(){ - linkStringReference(mCommentReference); + linkStringReference(getHeaderBlock().getCommentReference()); linkStringReference(mNamespaceReference); linkStringReference(mStringReference); } @@ -82,18 +76,19 @@ import java.util.Set; return xmlString; } public void setLineNumber(int val){ - mLineNumber.set(val); + getHeaderBlock().getLineNumber().set(val); } public int getLineNumber(){ - return mLineNumber.get(); + return getHeaderBlock().getLineNumber().get(); } public void setCommentReference(int val){ - unLinkStringReference(mCommentReference); - mCommentReference.set(val); - linkStringReference(mCommentReference); + IntegerItem comment=getHeaderBlock().getCommentReference(); + unLinkStringReference(comment); + getHeaderBlock().getCommentReference().set(val); + linkStringReference(comment); } public int getCommentReference(){ - return mCommentReference.get(); + return getHeaderBlock().getCommentReference().get(); } public void setNamespaceReference(int val){ unLinkStringReference(mNamespaceReference); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java index 9c20645..75b69bf 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java @@ -36,13 +36,13 @@ package com.reandroid.lib.arsc.chunk.xml; import java.util.List; import java.util.Set; - public class ResXmlBlock extends BaseChunk implements JSONConvert { + public class ResXmlBlock extends BaseChunk implements JSONConvert { private final ResXmlStringPool mResXmlStringPool; private final ResXmlIDMap mResXmlIDMap; private ResXmlElement mResXmlElement; private final SingleBlockContainer mResXmlElementContainer; public ResXmlBlock() { - super(ChunkType.XML,3); + super(new HeaderBlock(ChunkType.XML),3); this.mResXmlStringPool=new ResXmlStringPool(true); this.mResXmlIDMap=new ResXmlIDMap(); this.mResXmlElement=new ResXmlElement(); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlIDMap.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlIDMap.java index 1638d0d..6854a77 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlIDMap.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlIDMap.java @@ -19,6 +19,7 @@ import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.chunk.ChunkType; import com.reandroid.lib.arsc.array.ResXmlIDArray; import com.reandroid.lib.arsc.chunk.BaseChunk; +import com.reandroid.lib.arsc.header.HeaderBlock; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.ResXmlID; import com.reandroid.lib.arsc.pool.ResXmlStringPool; @@ -26,10 +27,10 @@ import com.reandroid.lib.arsc.pool.ResXmlStringPool; import java.io.IOException; import java.util.Collection; -public class ResXmlIDMap extends BaseChunk { +public class ResXmlIDMap extends BaseChunk { private final ResXmlIDArray mResXmlIDArray; public ResXmlIDMap() { - super(ChunkType.XML_RESOURCE_MAP, 1); + super(new HeaderBlock(ChunkType.XML_RESOURCE_MAP), 1); this.mResXmlIDArray=new ResXmlIDArray(getHeaderBlock()); addChild(mResXmlIDArray); } diff --git a/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java b/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java index ef3099b..0318bfc 100755 --- a/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java @@ -26,11 +26,9 @@ import com.reandroid.lib.arsc.item.BlockItem; import com.reandroid.lib.arsc.item.ByteArray; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.item.ShortItem; +import com.reandroid.lib.arsc.util.HexBytesWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.List; public class HeaderBlock extends ExpandableBlockContainer implements BlockLoad { @@ -52,6 +50,9 @@ import java.util.List; this.mHeaderSize.setBlockLoad(this); this.mChunkSize.setBlockLoad(this); } + public HeaderBlock(ChunkType chunkType){ + this(chunkType.ID); + } public ByteArray getExtraBytes() { return extraBytes; } @@ -199,7 +200,12 @@ import java.util.List; headerLoaded.onChunkSizeLoaded(headerSize, chunkSize); } } - + /** + * Prints bytes in hex for debug/testing + * */ + public String toHex(){ + return HexBytesWriter.toHex(getBytes()); + } @Override public String toString(){ short t = getType(); diff --git a/src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java b/src/main/java/com/reandroid/lib/arsc/header/LibraryHeader.java similarity index 56% rename from src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java rename to src/main/java/com/reandroid/lib/arsc/header/LibraryHeader.java index a5767a1..fbde016 100644 --- a/src/main/java/com/reandroid/lib/arsc/header/AnyHeader.java +++ b/src/main/java/com/reandroid/lib/arsc/header/LibraryHeader.java @@ -16,11 +16,26 @@ package com.reandroid.lib.arsc.header; import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.IntegerItem; -/**No importance of this class, to be removed latter*/ -@Deprecated -public class AnyHeader extends HeaderBlock{ - public AnyHeader() { - super(ChunkType.NULL.ID); +public class LibraryHeader extends HeaderBlock{ + private final IntegerItem count; + public LibraryHeader() { + super(ChunkType.LIBRARY.ID); + this.count = new IntegerItem(); + + addChild(this.count); + } + + public IntegerItem getCount() { + return count; + } + @Override + public String toString(){ + if(getChunkType()!=ChunkType.LIBRARY){ + return super.toString(); + } + return getClass().getSimpleName() + +" {count="+getCount() + '}'; } } diff --git a/src/main/java/com/reandroid/lib/arsc/header/OverlayableHeader.java b/src/main/java/com/reandroid/lib/arsc/header/OverlayableHeader.java new file mode 100644 index 0000000..d8887ae --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/OverlayableHeader.java @@ -0,0 +1,49 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.FixedLengthString; + +public class OverlayableHeader extends HeaderBlock{ + private final FixedLengthString name; + private final FixedLengthString actor; + public OverlayableHeader() { + super(ChunkType.OVERLAYABLE.ID); + this.name = new FixedLengthString(512); + this.actor = new FixedLengthString(512); + + addChild(this.name); + addChild(this.actor); + } + + public FixedLengthString getName() { + return name; + } + public FixedLengthString getActor() { + return actor; + } + + @Override + public String toString(){ + if(getChunkType()!=ChunkType.OVERLAYABLE){ + return super.toString(); + } + return getClass().getSimpleName() + +" {count="+getName() + +", actor=" + getActor() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/OverlayablePolicyHeader.java b/src/main/java/com/reandroid/lib/arsc/header/OverlayablePolicyHeader.java new file mode 100644 index 0000000..978a959 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/OverlayablePolicyHeader.java @@ -0,0 +1,47 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.IntegerItem; + +public class OverlayablePolicyHeader extends HeaderBlock{ + private final IntegerItem flags; + private final IntegerItem entryCount; + public OverlayablePolicyHeader() { + super(ChunkType.OVERLAYABLE_POLICY.ID); + this.flags = new IntegerItem(); + this.entryCount = new IntegerItem(); + + addChild(this.flags); + addChild(this.entryCount); + } + public IntegerItem getFlags() { + return flags; + } + public IntegerItem getEntryCount() { + return entryCount; + } + @Override + public String toString(){ + if(getChunkType()!=ChunkType.OVERLAYABLE_POLICY){ + return super.toString(); + } + return getClass().getSimpleName() + +" {flags="+getFlags().toHex() + +", entryCount=" + getEntryCount() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/PackageHeader.java b/src/main/java/com/reandroid/lib/arsc/header/PackageHeader.java new file mode 100644 index 0000000..cc4b784 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/PackageHeader.java @@ -0,0 +1,86 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.container.SingleBlockContainer; +import com.reandroid.lib.arsc.item.FixedLengthString; +import com.reandroid.lib.arsc.item.IntegerItem; + +public class PackageHeader extends HeaderBlock{ + private final IntegerItem packageId; + private final FixedLengthString packageName; + + private final IntegerItem typeStringPoolOffset; + private final IntegerItem typeStringPoolCount; + private final IntegerItem specStringPoolOffset; + private final IntegerItem specStringPoolCount; + private final SingleBlockContainer typeIdOffsetContainer; + private final IntegerItem typeIdOffset; + + public PackageHeader() { + super(ChunkType.PACKAGE.ID); + this.packageId = new IntegerItem(); + this.packageName = new FixedLengthString(256); + + this.typeStringPoolOffset = new IntegerItem(); + this.typeStringPoolCount = new IntegerItem(); + this.specStringPoolOffset = new IntegerItem(); + this.specStringPoolCount = new IntegerItem(); + + this.typeIdOffsetContainer = new SingleBlockContainer<>(); + this.typeIdOffset = new IntegerItem(); + this.typeIdOffsetContainer.setItem(typeIdOffset); + + addChild(this.packageId); + addChild(this.packageName); + addChild(this.typeStringPoolOffset); + addChild(this.typeStringPoolCount); + addChild(this.specStringPoolOffset); + addChild(this.specStringPoolCount); + addChild(this.typeIdOffsetContainer); + } + + public IntegerItem getPackageId() { + return packageId; + } + public FixedLengthString getPackageName() { + return packageName; + } + public IntegerItem getTypeStringPoolOffset() { + return typeStringPoolOffset; + } + public IntegerItem getTypeStringPoolCount() { + return typeStringPoolCount; + } + public IntegerItem getSpecStringPoolOffset() { + return specStringPoolOffset; + } + public IntegerItem getSpecStringPoolCount() { + return specStringPoolCount; + } + public IntegerItem getTypeIdOffset() { + return typeIdOffset; + } + @Override + void onHeaderSizeLoaded(int size){ + super.onHeaderSizeLoaded(size); + if(size<288){ + typeIdOffset.set(0); + typeIdOffsetContainer.setItem(null); + } + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/SpecHeader.java b/src/main/java/com/reandroid/lib/arsc/header/SpecHeader.java new file mode 100644 index 0000000..f54a139 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/SpecHeader.java @@ -0,0 +1,52 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.ByteItem; +import com.reandroid.lib.arsc.item.IntegerItem; +import com.reandroid.lib.arsc.item.ShortItem; + +public class SpecHeader extends HeaderBlock{ + private final ByteItem id; + private final IntegerItem entryCount; + public SpecHeader() { + super(ChunkType.SPEC.ID); + this.id = new ByteItem(); + ByteItem res0 = new ByteItem(); + ShortItem res1 = new ShortItem(); + this.entryCount = new IntegerItem(); + addChild(id); + addChild(res0); + addChild(res1); + addChild(entryCount); + } + public ByteItem getId() { + return id; + } + public IntegerItem getEntryCount() { + return entryCount; + } + @Override + public String toString(){ + if(getChunkType() != ChunkType.SPEC){ + return super.toString(); + } + return getClass().getSimpleName() + +" {id="+getId().toHex() + +", entryCount=" + getEntryCount() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/StagedAliasHeader.java b/src/main/java/com/reandroid/lib/arsc/header/StagedAliasHeader.java new file mode 100644 index 0000000..52b9a15 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/StagedAliasHeader.java @@ -0,0 +1,41 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.IntegerItem; + +public class StagedAliasHeader extends HeaderBlock{ + private final IntegerItem count; + public StagedAliasHeader() { + super(ChunkType.STAGED_ALIAS.ID); + this.count = new IntegerItem(); + + addChild(count); + } + + public IntegerItem getCount() { + return count; + } + @Override + public String toString(){ + if(getChunkType()!=ChunkType.STAGED_ALIAS){ + return super.toString(); + } + return getClass().getSimpleName() + +" {count="+getCount()+ '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/StringPoolHeader.java b/src/main/java/com/reandroid/lib/arsc/header/StringPoolHeader.java new file mode 100644 index 0000000..e40da7e --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/StringPoolHeader.java @@ -0,0 +1,76 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.IntegerItem; +import com.reandroid.lib.arsc.item.ShortItem; + +public class StringPoolHeader extends HeaderBlock{ + private final IntegerItem countStrings; + private final IntegerItem countStyles; + private final ShortItem flagUtf8; + private final ShortItem flagSorted; + private final IntegerItem startStrings; + private final IntegerItem startStyles; + public StringPoolHeader() { + super(ChunkType.STRING.ID); + this.countStrings = new IntegerItem(); + this.countStyles = new IntegerItem(); + this.flagUtf8 = new ShortItem(); + this.flagSorted = new ShortItem(); + this.startStrings = new IntegerItem(); + this.startStyles = new IntegerItem(); + + addChild(countStrings); + addChild(countStyles); + addChild(flagUtf8); + addChild(flagSorted); + addChild(startStrings); + addChild(startStyles); + } + public IntegerItem getCountStrings() { + return countStrings; + } + public IntegerItem getCountStyles() { + return countStyles; + } + public ShortItem getFlagUtf8() { + return flagUtf8; + } + public ShortItem getFlagSorted() { + return flagSorted; + } + public IntegerItem getStartStrings() { + return startStrings; + } + public IntegerItem getStartStyles() { + return startStyles; + } + @Override + public String toString(){ + if(getChunkType()!=ChunkType.STRING){ + return super.toString(); + } + return getClass().getSimpleName() + +" {strings="+getCountStrings() + +", styles="+getCountStyles() + +", utf8="+getFlagUtf8().toHex() + +", sorted="+getFlagSorted().toHex() + +", offset-strings="+getStartStrings().get() + +", offset-styles="+getStartStyles().get() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/TableHeader.java b/src/main/java/com/reandroid/lib/arsc/header/TableHeader.java new file mode 100644 index 0000000..d823963 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/TableHeader.java @@ -0,0 +1,39 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.IntegerItem; + +public class TableHeader extends HeaderBlock{ + private final IntegerItem packageCount; + public TableHeader() { + super(ChunkType.TABLE.ID); + this.packageCount = new IntegerItem(); + addChild(packageCount); + } + public IntegerItem getPackageCount() { + return packageCount; + } + @Override + public String toString(){ + if(getChunkType()!=ChunkType.TABLE){ + return super.toString(); + } + return getClass().getSimpleName() + +" {packageCount=" + getPackageCount() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/TypeHeader.java b/src/main/java/com/reandroid/lib/arsc/header/TypeHeader.java new file mode 100644 index 0000000..6b70f20 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/TypeHeader.java @@ -0,0 +1,76 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.ByteItem; +import com.reandroid.lib.arsc.item.IntegerItem; +import com.reandroid.lib.arsc.item.ShortItem; +import com.reandroid.lib.arsc.value.ResConfig; + +public class TypeHeader extends HeaderBlock{ + private final ByteItem id; + private final ByteItem flags; + private final IntegerItem count; + private final IntegerItem entriesStart; + private final ResConfig config; + public TypeHeader() { + super(ChunkType.TYPE.ID); + this.id = new ByteItem(); + this.flags = new ByteItem(); + ShortItem reserved = new ShortItem(); + this.count = new IntegerItem(); + this.entriesStart = new IntegerItem(); + this.config = new ResConfig(); + + addChild(id); + addChild(flags); + addChild(reserved); + addChild(count); + addChild(entriesStart); + addChild(config); + } + + public ByteItem getId() { + return id; + } + public ByteItem getFlags() { + return flags; + } + public IntegerItem getCount() { + return count; + } + public IntegerItem getEntriesStart() { + return entriesStart; + } + public ResConfig getConfig() { + return config; + } + + @Override + public String toString(){ + if(getChunkType()!=ChunkType.TYPE){ + return super.toString(); + } + return getClass().getSimpleName() + +" {id="+getId().toHex() + +", flags=" + getFlags().toHex() + +", count=" + getCount() + +", entriesStart=" + getEntriesStart() + +", config=" + getConfig() + +", flags=" + getFlags().toHex() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/header/XmlNodeHeader.java b/src/main/java/com/reandroid/lib/arsc/header/XmlNodeHeader.java new file mode 100644 index 0000000..2703f12 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/header/XmlNodeHeader.java @@ -0,0 +1,49 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.lib.arsc.header; + +import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.item.IntegerItem; + +public class XmlNodeHeader extends HeaderBlock{ + private final IntegerItem lineNumber; + private final IntegerItem commentReference; + private final ChunkType chunkType; + public XmlNodeHeader(ChunkType chunkType) { + super(chunkType.ID); + this.chunkType = chunkType; + this.lineNumber = new IntegerItem(); + this.commentReference = new IntegerItem(-1); + + addChild(lineNumber); + addChild(commentReference); + } + public IntegerItem getLineNumber() { + return lineNumber; + } + public IntegerItem getCommentReference() { + return commentReference; + } + @Override + public String toString(){ + if(getChunkType() != chunkType){ + return super.toString(); + } + return getClass().getSimpleName() + +" {lineNumber="+getLineNumber() + +", commentReference=" + getCommentReference() + '}'; + } +} diff --git a/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java b/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java index 73ed2bf..0775745 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java @@ -43,6 +43,12 @@ public class ByteItem extends BlockItem { public byte get(){ return getBytesInternal()[0]; } + public int unsignedInt(){ + return 0xff & get(); + } + public String toHex(){ + return String.format("0x%02x", unsignedInt()); + } @Override public String toString(){ return String.valueOf(get()); diff --git a/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java b/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java index 86d87aa..b1aabf7 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java @@ -41,6 +41,9 @@ public class IntegerItem extends BlockItem implements ReferenceItem{ public int get(){ return mCache; } + public String toHex(){ + return String.format("0x%08x", get()); + } @Override protected void onBytesChanged() { // To save cpu usage, better to calculate once only when bytes changed diff --git a/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java b/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java index a6c8d48..0fc7e1d 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java @@ -40,6 +40,9 @@ public class ShortItem extends BlockItem { public int unsignedInt(){ return 0xffff & get(); } + public String toHex(){ + return String.format("0x%04x", unsignedInt()); + } @Override protected void onBytesChanged() { // To save cpu usage, better to calculate once only when bytes changed 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 0d477fc..4674463 100755 --- a/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java +++ b/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java @@ -15,72 +15,58 @@ */ package com.reandroid.lib.arsc.pool; -import com.reandroid.lib.arsc.chunk.ChunkType; -import com.reandroid.lib.arsc.array.StringArray; -import com.reandroid.lib.arsc.array.StyleArray; -import com.reandroid.lib.arsc.base.Block; -import com.reandroid.lib.arsc.chunk.BaseChunk; -import com.reandroid.lib.arsc.group.StringGroup; -import com.reandroid.lib.arsc.io.BlockLoad; -import com.reandroid.lib.arsc.io.BlockReader; -import com.reandroid.lib.arsc.item.*; -import com.reandroid.lib.arsc.model.StyleSpanInfo; -import com.reandroid.lib.json.JSONConvert; -import com.reandroid.lib.json.JSONArray; -import com.reandroid.lib.json.JSONObject; + import com.reandroid.lib.arsc.array.StringArray; + import com.reandroid.lib.arsc.array.StyleArray; + import com.reandroid.lib.arsc.base.Block; + import com.reandroid.lib.arsc.chunk.BaseChunk; + import com.reandroid.lib.arsc.group.StringGroup; + import com.reandroid.lib.arsc.header.StringPoolHeader; + import com.reandroid.lib.arsc.io.BlockLoad; + import com.reandroid.lib.arsc.io.BlockReader; + import com.reandroid.lib.arsc.item.*; + import com.reandroid.lib.json.JSONArray; + import com.reandroid.lib.json.JSONConvert; -import java.io.IOException; -import java.util.*; + import java.io.IOException; + import java.util.*; -public abstract class BaseStringPool extends BaseChunk implements BlockLoad, JSONConvert, Comparator { - private final IntegerItem mCountStrings; - private final IntegerItem mCountStyles; - private final ShortItem mFlagUtf8; - private final ShortItem mFlagSorted; - private final IntegerItem mStartStrings; - private final IntegerItem mStartStyles; - private final IntegerArray mOffsetStrings; - private final IntegerArray mOffsetStyles; + public abstract class BaseStringPool extends BaseChunk implements BlockLoad, JSONConvert, Comparator { private final StringArray mArrayStrings; private final StyleArray mArrayStyles; private final Map> mUniqueMap; - BaseStringPool(boolean is_utf8){ - super(ChunkType.STRING, 4); + super(new StringPoolHeader(), 4); - this.mCountStrings=new IntegerItem(); //header - this.mCountStyles=new IntegerItem(); //header - this.mFlagUtf8 =new ShortItem(); //header - this.mFlagSorted=new ShortItem(); //header - this.mStartStrings=new IntegerItem(); //header - this.mStartStyles=new IntegerItem(); //header + IntegerArray offsetStrings = new IntegerArray(); + IntegerArray offsetStyles = new IntegerArray(); - this.mOffsetStrings=new IntegerArray();//1 - this.mOffsetStyles=new IntegerArray(); //2 - this.mArrayStrings=newInstance(mOffsetStrings, mCountStrings, mStartStrings, is_utf8); //3 - this.mArrayStyles=new StyleArray(mOffsetStyles, mCountStyles, mStartStyles); //4 + StringPoolHeader header = getHeaderBlock(); - addToHeader(mCountStrings); - addToHeader(mCountStyles); - addToHeader(mFlagUtf8); - addToHeader(mFlagSorted); - addToHeader(mStartStrings); - addToHeader(mStartStyles); + this.mArrayStrings = newInstance( + offsetStrings, + header.getCountStrings(), + header.getStartStrings(), + is_utf8); - addChild(mOffsetStrings); - addChild(mOffsetStyles); + this.mArrayStyles = new StyleArray( + offsetStyles, + header.getCountStyles(), + header.getStartStyles()); + + + addChild(offsetStrings); + addChild(offsetStyles); addChild(mArrayStrings); addChild(mArrayStyles); setUtf8(is_utf8, false); - mFlagUtf8.setBlockLoad(this); - - mUniqueMap=new HashMap<>(); + header.getFlagUtf8().setBlockLoad(this); + mUniqueMap = new HashMap<>(); } public List toStringList(){ return getStringsArray().toStringList(); @@ -137,13 +123,12 @@ public abstract class BaseStringPool extends BaseChunk imp // call this after modifying string values public void refreshUniqueIdMap(){ mUniqueMap.clear(); - T[] allChildes=getStrings(); - if(allChildes==null){ + T[] stringsArray = getStrings(); + if(stringsArray==null){ return; } - int max=allChildes.length; - for(int i=0;i extends BaseChunk imp private T createNewString(String str){ T item=mArrayStrings.createNext(); item.set(str); - mCountStrings.set(mArrayStrings.childesCount()); + getHeaderBlock().getCountStrings().set(mArrayStrings.childesCount()); return item; } public final StyleItem getStyle(int index){ @@ -249,35 +234,30 @@ public abstract class BaseStringPool extends BaseChunk imp public final int countStyles(){ return mArrayStyles.childesCount(); } - public final T[] getStrings(){ return mArrayStrings.getChildes(); } public final StyleItem[] getStyles(){ return mArrayStyles.getChildes(); } - private void setUtf8Flag(short flag){ - mFlagUtf8.set(flag); - } public void setUtf8(boolean is_utf8){ setUtf8(is_utf8, true); } - private void setSortedFlag(short flag){ - mFlagSorted.set(flag); - } public final void setSorted(boolean sorted){ + ShortItem flagSorted = getHeaderBlock().getFlagSorted(); if(sorted){ - setSortedFlag(FLAG_SORTED); + flagSorted.set(FLAG_SORTED); }else { - setSortedFlag((short)0); + flagSorted.set((short)0); } } private void setUtf8(boolean is_utf8, boolean updateAll){ - boolean old= isUtf8Flag(); + ShortItem flagUtf8 = getHeaderBlock().getFlagUtf8(); + boolean old = isUtf8Flag(); if(is_utf8){ - setUtf8Flag(UTF8_FLAG_VALUE); + flagUtf8.set(UTF8_FLAG_VALUE); }else { - setUtf8Flag((short) 0); + flagUtf8.set((short) 0); } if(!updateAll || old == isUtf8Flag()){ return; @@ -285,13 +265,8 @@ public abstract class BaseStringPool extends BaseChunk imp mArrayStrings.setUtf8(is_utf8); } private boolean isUtf8Flag(){ - return (mFlagUtf8.get() & FLAG_UTF8) !=0; + return (getHeaderBlock().getFlagUtf8().get() & FLAG_UTF8) !=0; } - private boolean isSortedFlag(){ - return (mFlagSorted.get() & FLAG_SORTED) !=0; - } - - abstract StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8); @Override protected void onChunkRefreshed() { @@ -305,7 +280,7 @@ public abstract class BaseStringPool extends BaseChunk imp @Override public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { - if(sender== mFlagUtf8){ + if(sender == getHeaderBlock().getFlagUtf8()){ mArrayStrings.setUtf8(isUtf8Flag()); } } @@ -319,112 +294,15 @@ public abstract class BaseStringPool extends BaseChunk imp if(json==null){ return; } - loadStyledStrings(json); + JsonStringPoolHelper helper=new JsonStringPoolHelper<>(this); + helper.loadStyledStrings(json); refresh(); } - public void loadStyledStrings(JSONArray jsonArray) { - //Styled strings should be at first rows of string pool thus we clear all before adding - getStringsArray().clearChildes(); - getStyleArray().clearChildes(); - - List styledStringList = StyledString.fromJson(jsonArray); - loadText(styledStringList); - Map tagIndexMap = loadStyleTags(styledStringList); - loadStyles(styledStringList, tagIndexMap); - refreshUniqueIdMap(); - } - private void loadText(List styledStringList) { - StringArray stringsArray = getStringsArray(); - int size=styledStringList.size(); - stringsArray.ensureSize(size); - for(int i=0;i loadStyleTags(List styledStringList) { - Map indexMap=new HashMap<>(); - List tagList=new ArrayList<>(getStyleTags(styledStringList)); - tagList.sort(this); - StringArray stringsArray = getStringsArray(); - int tagsSize = tagList.size(); - int initialSize = stringsArray.childesCount(); - stringsArray.ensureSize(initialSize + tagsSize); - for(int i=0;i styledStringList, Map tagIndexMap){ - StyleArray styleArray = getStyleArray(); - int size=styledStringList.size(); - styleArray.ensureSize(size); - for(int i=0;i getStyleTags(List styledStringList){ - Set results=new HashSet<>(); - for(StyledString ss:styledStringList){ - for(StyleSpanInfo spanInfo:ss.spanInfoList){ - results.add(spanInfo.getTag()); - } - } - return results; - } @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } - private static class StyledString{ - final String text; - final List spanInfoList; - StyledString(String text, List spanInfoList){ - this.text=text; - this.spanInfoList=spanInfoList; - } - @Override - public String toString(){ - return text; - } - static List fromJson(JSONArray jsonArray){ - int length = jsonArray.length(); - List results=new ArrayList<>(); - for(int i=0;i spanInfoList = toSpanInfoList(spansArray); - return new StyledString(text, spanInfoList); - } - private static List toSpanInfoList(JSONArray jsonArray){ - int length = jsonArray.length(); - List results=new ArrayList<>(length); - for(int i=0;i { + + private final BaseStringPool stringPool; + JsonStringPoolHelper(BaseStringPool stringPool){ + this.stringPool=stringPool; + } + void loadStyledStrings(JSONArray jsonArray) { + //Styled strings should be at first rows of string pool thus we clear all before adding + stringPool.getStringsArray().clearChildes(); + stringPool.getStyleArray().clearChildes(); + + List styledStringList = StyledString.fromJson(jsonArray); + loadText(styledStringList); + Map tagIndexMap = loadStyleTags(styledStringList); + loadStyles(styledStringList, tagIndexMap); + stringPool.refreshUniqueIdMap(); + } + private void loadText(List styledStringList) { + StringArray stringsArray = stringPool.getStringsArray(); + int size=styledStringList.size(); + stringsArray.ensureSize(size); + for(int i=0;i loadStyleTags(List styledStringList) { + Map indexMap=new HashMap<>(); + List tagList=new ArrayList<>(getStyleTags(styledStringList)); + tagList.sort(stringPool); + StringArray stringsArray = stringPool.getStringsArray(); + int tagsSize = tagList.size(); + int initialSize = stringsArray.childesCount(); + stringsArray.ensureSize(initialSize + tagsSize); + for(int i=0;i styledStringList, Map tagIndexMap){ + StyleArray styleArray = stringPool.getStyleArray(); + int size=styledStringList.size(); + styleArray.ensureSize(size); + for(int i=0;i getStyleTags(List styledStringList){ + Set results=new HashSet<>(); + for(StyledString ss:styledStringList){ + for(StyleSpanInfo spanInfo:ss.spanInfoList){ + results.add(spanInfo.getTag()); + } + } + return results; + } + private static class StyledString{ + final String text; + final List spanInfoList; + StyledString(String text, List spanInfoList){ + this.text=text; + this.spanInfoList=spanInfoList; + } + @Override + public String toString(){ + return text; + } + static List fromJson(JSONArray jsonArray){ + int length = jsonArray.length(); + List results=new ArrayList<>(); + for(int i=0;i spanInfoList = toSpanInfoList(spansArray); + return new StyledString(text, spanInfoList); + } + private static List toSpanInfoList(JSONArray jsonArray){ + int length = jsonArray.length(); + List results=new ArrayList<>(length); + for(int i=0;i