mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 14:44:27 +02:00
make custom header for each chunk
This commit is contained in:
parent
4c9fabc425
commit
9e02964884
@ -15,35 +15,28 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.lib.arsc.chunk;
|
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.container.ExpandableBlockContainer;
|
||||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public abstract class BaseChunk extends ExpandableBlockContainer {
|
public abstract class BaseChunk<T extends HeaderBlock> extends ExpandableBlockContainer {
|
||||||
private final HeaderBlock mHeaderBlock;
|
private final T mHeaderBlock;
|
||||||
protected BaseChunk(short chunkType, int initialChildesCount) {
|
protected BaseChunk(T headerBlock, int initialChildesCount) {
|
||||||
super(initialChildesCount+1);
|
super(initialChildesCount+1);
|
||||||
mHeaderBlock=new HeaderBlock(chunkType);
|
this.mHeaderBlock = headerBlock;
|
||||||
addChild(mHeaderBlock);
|
addChild(headerBlock);
|
||||||
}
|
|
||||||
protected BaseChunk(ChunkType chunkType, int initialChildesCount) {
|
|
||||||
this(chunkType.ID, initialChildesCount);
|
|
||||||
}
|
|
||||||
protected void addToHeader(Block block){
|
|
||||||
mHeaderBlock.addChild(block);
|
|
||||||
}
|
}
|
||||||
void setHeaderLoaded(HeaderBlock.HeaderLoaded headerLoaded){
|
void setHeaderLoaded(HeaderBlock.HeaderLoaded headerLoaded){
|
||||||
mHeaderBlock.setHeaderLoaded(headerLoaded);
|
getHeaderBlock().setHeaderLoaded(headerLoaded);
|
||||||
}
|
}
|
||||||
public HeaderBlock getHeaderBlock(){
|
public final T getHeaderBlock(){
|
||||||
return mHeaderBlock;
|
return mHeaderBlock;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected final void onRefreshed() {
|
protected final void onRefreshed() {
|
||||||
mHeaderBlock.refreshHeader();
|
getHeaderBlock().refreshHeader();
|
||||||
onChunkRefreshed();
|
onChunkRefreshed();
|
||||||
}
|
}
|
||||||
protected abstract void onChunkRefreshed();
|
protected abstract void onChunkRefreshed();
|
||||||
@ -73,7 +66,7 @@ public abstract class BaseChunk extends ExpandableBlockContainer {
|
|||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(getClass().getSimpleName());
|
builder.append(getClass().getSimpleName());
|
||||||
builder.append(": ");
|
builder.append(": ");
|
||||||
builder.append(mHeaderBlock.toString());
|
builder.append(getHeaderBlock());
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,20 @@
|
|||||||
package com.reandroid.lib.arsc.chunk;
|
package com.reandroid.lib.arsc.chunk;
|
||||||
|
|
||||||
import com.reandroid.lib.arsc.array.LibraryInfoArray;
|
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.item.IntegerItem;
|
||||||
import com.reandroid.lib.arsc.value.LibraryInfo;
|
import com.reandroid.lib.arsc.value.LibraryInfo;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class LibraryBlock extends BaseChunk {
|
public class LibraryBlock extends BaseChunk<LibraryHeader> {
|
||||||
private final IntegerItem mLibCount;
|
|
||||||
private final LibraryInfoArray mLibraryInfoArray;
|
private final LibraryInfoArray mLibraryInfoArray;
|
||||||
public LibraryBlock() {
|
public LibraryBlock() {
|
||||||
super(ChunkType.LIBRARY,1);
|
super(new LibraryHeader(),1);
|
||||||
this.mLibCount=new IntegerItem();
|
LibraryHeader header = getHeaderBlock();
|
||||||
this.mLibraryInfoArray=new LibraryInfoArray(mLibCount);
|
this.mLibraryInfoArray = new LibraryInfoArray(header.getCount());
|
||||||
|
|
||||||
addToHeader(mLibCount);
|
|
||||||
addChild(mLibraryInfoArray);
|
addChild(mLibraryInfoArray);
|
||||||
}
|
}
|
||||||
public LibraryInfoArray getLibraryInfoArray(){
|
public LibraryInfoArray getLibraryInfoArray(){
|
||||||
@ -49,7 +48,7 @@ public class LibraryBlock extends BaseChunk {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getLibraryInfoArray().add(info);
|
getLibraryInfoArray().add(info);
|
||||||
mLibCount.set(mLibraryInfoArray.childesCount());
|
getHeaderBlock().getCount().set(mLibraryInfoArray.childesCount());
|
||||||
}
|
}
|
||||||
public Collection<LibraryInfo> listLibraryInfo(){
|
public Collection<LibraryInfo> listLibraryInfo(){
|
||||||
return getLibraryInfoArray().listItems();
|
return getLibraryInfoArray().listItems();
|
||||||
@ -62,12 +61,12 @@ public class LibraryBlock extends BaseChunk {
|
|||||||
return mLibraryInfoArray.childesCount();
|
return mLibraryInfoArray.childesCount();
|
||||||
}
|
}
|
||||||
public void setLibraryCount(int count){
|
public void setLibraryCount(int count){
|
||||||
mLibCount.set(count);
|
getHeaderBlock().getCount().set(count);
|
||||||
mLibraryInfoArray.setChildesCount(count);
|
mLibraryInfoArray.setChildesCount(count);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
mLibCount.set(mLibraryInfoArray.childesCount());
|
getHeaderBlock().getCount().set(mLibraryInfoArray.childesCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void merge(LibraryBlock libraryBlock){
|
public void merge(LibraryBlock libraryBlock){
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
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.BlockLoad;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.ByteArray;
|
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
|
* We didn't test this class with resource table, if someone found a resource/apk please
|
||||||
* create issue on https://github.com/REAndroid/ARSCLib
|
* create issue on https://github.com/REAndroid/ARSCLib
|
||||||
* */
|
* */
|
||||||
public class Overlayable extends BaseChunk implements BlockLoad {
|
public class Overlayable extends BaseChunk<OverlayableHeader> implements BlockLoad {
|
||||||
private final FixedLengthString name;
|
|
||||||
private final FixedLengthString actor;
|
|
||||||
/**
|
/**
|
||||||
* @link body
|
* @link body
|
||||||
* As on AOSP there is only a description of header struct but no mention about
|
* As on AOSP there is only a description of header struct but no mention about
|
||||||
@ -39,33 +38,29 @@
|
|||||||
* */
|
* */
|
||||||
private final ByteArray body;
|
private final ByteArray body;
|
||||||
public Overlayable() {
|
public Overlayable() {
|
||||||
super(ChunkType.OVERLAYABLE, 1);
|
super(new OverlayableHeader(), 1);
|
||||||
this.name = new FixedLengthString(512);
|
|
||||||
this.actor = new FixedLengthString(512);
|
|
||||||
this.body = new ByteArray();
|
this.body = new ByteArray();
|
||||||
addToHeader(this.name);
|
|
||||||
addToHeader(this.actor);
|
|
||||||
addChild(this.body);
|
addChild(this.body);
|
||||||
this.actor.setBlockLoad(this);
|
getHeaderBlock().getActor().setBlockLoad(this);
|
||||||
}
|
}
|
||||||
public ByteArray getBody() {
|
public ByteArray getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
return this.name.get();
|
return getHeaderBlock().getName().get();
|
||||||
}
|
}
|
||||||
public void setName(String str){
|
public void setName(String str){
|
||||||
this.name.set(str);
|
getHeaderBlock().getName().set(str);
|
||||||
}
|
}
|
||||||
public String getActor(){
|
public String getActor(){
|
||||||
return this.actor.get();
|
return getHeaderBlock().getActor().get();
|
||||||
}
|
}
|
||||||
public void setActor(String str){
|
public void setActor(String str){
|
||||||
this.actor.set(str);
|
getHeaderBlock().getActor().set(str);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
||||||
if(sender==this.actor){
|
if(sender==getHeaderBlock().getActor()){
|
||||||
HeaderBlock header = getHeaderBlock();
|
HeaderBlock header = getHeaderBlock();
|
||||||
int bodySize=header.getChunkSize()-header.getHeaderSize();
|
int bodySize=header.getChunkSize()-header.getHeaderSize();
|
||||||
this.body.setSize(bodySize);
|
this.body.setSize(bodySize);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.lib.arsc.chunk;
|
package com.reandroid.lib.arsc.chunk;
|
||||||
|
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
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.BlockLoad;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
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
|
* We didn't test this class with resource table, if someone found a resource/apk please
|
||||||
* create issue on https://github.com/REAndroid/ARSCLib
|
* create issue on https://github.com/REAndroid/ARSCLib
|
||||||
* */
|
* */
|
||||||
public class OverlayablePolicy extends BaseChunk implements BlockLoad {
|
public class OverlayablePolicy extends BaseChunk<OverlayablePolicyHeader> implements BlockLoad {
|
||||||
private final IntegerItem flags;
|
|
||||||
private final IntegerItem entryCount;
|
|
||||||
private final IntegerArray tableRefArray;
|
private final IntegerArray tableRefArray;
|
||||||
public OverlayablePolicy(){
|
public OverlayablePolicy(){
|
||||||
super(ChunkType.OVERLAYABLE_POLICY, 1);
|
super(new OverlayablePolicyHeader(), 1);
|
||||||
this.flags = new IntegerItem();
|
|
||||||
this.entryCount = new IntegerItem();
|
|
||||||
this.tableRefArray = new IntegerArray();
|
this.tableRefArray = new IntegerArray();
|
||||||
|
|
||||||
addToHeader(this.flags);
|
|
||||||
addToHeader(this.entryCount);
|
|
||||||
|
|
||||||
addChild(this.tableRefArray);
|
addChild(this.tableRefArray);
|
||||||
|
|
||||||
this.entryCount.setBlockLoad(this);
|
getHeaderBlock().getEntryCount().setBlockLoad(this);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean isNull() {
|
public boolean isNull() {
|
||||||
@ -61,10 +55,10 @@
|
|||||||
return tableRefArray;
|
return tableRefArray;
|
||||||
}
|
}
|
||||||
public int getFlags() {
|
public int getFlags() {
|
||||||
return flags.get();
|
return getHeaderBlock().getFlags().get();
|
||||||
}
|
}
|
||||||
public void setFlags(int flags){
|
public void setFlags(int flags){
|
||||||
this.flags.set(flags);
|
getHeaderBlock().getFlags().set(flags);
|
||||||
}
|
}
|
||||||
public void setFlags(PolicyFlag[] policyFlags){
|
public void setFlags(PolicyFlag[] policyFlags){
|
||||||
setFlags(PolicyFlag.sum(policyFlags));
|
setFlags(PolicyFlag.sum(policyFlags));
|
||||||
@ -78,11 +72,12 @@
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
this.entryCount.set(getTableRefArray().size());
|
getHeaderBlock().getEntryCount().set(getTableRefArray().size());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
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());
|
this.tableRefArray.setSize(entryCount.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
import com.reandroid.lib.arsc.container.SingleBlockContainer;
|
import com.reandroid.lib.arsc.container.SingleBlockContainer;
|
||||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.lib.arsc.group.EntryGroup;
|
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.BlockLoad;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.FixedLengthString;
|
import com.reandroid.lib.arsc.item.FixedLengthString;
|
||||||
@ -42,17 +43,8 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
public class PackageBlock extends BaseChunk
|
public class PackageBlock extends BaseChunk<PackageHeader>
|
||||||
implements BlockLoad, JSONConvert<JSONObject>, Comparable<PackageBlock> {
|
implements JSONConvert<JSONObject>, Comparable<PackageBlock> {
|
||||||
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<IntegerItem> mTypeIdOffsetContainer;
|
|
||||||
private final IntegerItem mTypeIdOffset;
|
|
||||||
|
|
||||||
private final TypeStringPool mTypeStringPool;
|
private final TypeStringPool mTypeStringPool;
|
||||||
private final SpecStringPool mSpecStringPool;
|
private final SpecStringPool mSpecStringPool;
|
||||||
@ -62,42 +54,19 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
private final Map<Integer, EntryGroup> mEntriesGroup;
|
private final Map<Integer, EntryGroup> mEntriesGroup;
|
||||||
|
|
||||||
public PackageBlock() {
|
public PackageBlock() {
|
||||||
super(ChunkType.PACKAGE, 3);
|
super(new PackageHeader(), 3);
|
||||||
this.mPackageId=new IntegerItem();
|
PackageHeader header = getHeaderBlock();
|
||||||
this.mPackageName = new FixedLengthString(256);
|
|
||||||
|
|
||||||
this.mTypeStringPoolOffset = new IntegerItem();
|
this.mTypeStringPool=new TypeStringPool(false, header.getTypeIdOffset());
|
||||||
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.mSpecStringPool=new SpecStringPool(true);
|
this.mSpecStringPool=new SpecStringPool(true);
|
||||||
|
|
||||||
this.mBody = new PackageBody();
|
this.mBody = new PackageBody();
|
||||||
|
|
||||||
this.mEntriesGroup=new HashMap<>();
|
this.mEntriesGroup=new HashMap<>();
|
||||||
|
|
||||||
mPackageId.setBlockLoad(this);
|
|
||||||
|
|
||||||
addToHeader(mPackageId);
|
|
||||||
addToHeader(mPackageName);
|
|
||||||
addToHeader(mTypeStringPoolOffset);
|
|
||||||
addToHeader(mTypeStringPoolCount);
|
|
||||||
addToHeader(mSpecStringPoolOffset);
|
|
||||||
addToHeader(mSpecStringPoolCount);
|
|
||||||
addToHeader(mTypeIdOffsetContainer);
|
|
||||||
|
|
||||||
addChild(mTypeStringPool);
|
addChild(mTypeStringPool);
|
||||||
addChild(mSpecStringPool);
|
addChild(mSpecStringPool);
|
||||||
|
|
||||||
addChild(mBody);
|
addChild(mBody);
|
||||||
|
|
||||||
}
|
}
|
||||||
public BlockList<UnknownChunk> getUnknownChunkList(){
|
public BlockList<UnknownChunk> getUnknownChunkList(){
|
||||||
return mBody.getUnknownChunkList();
|
return mBody.getUnknownChunkList();
|
||||||
@ -125,16 +94,7 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
public void sortTypes(){
|
public void sortTypes(){
|
||||||
getSpecTypePairArray().sort();
|
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(){
|
public void removeEmpty(){
|
||||||
getSpecTypePairArray().removeEmptyPairs();
|
getSpecTypePairArray().removeEmptyPairs();
|
||||||
}
|
}
|
||||||
@ -142,19 +102,19 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
return getSpecTypePairArray().isEmpty();
|
return getSpecTypePairArray().isEmpty();
|
||||||
}
|
}
|
||||||
public int getId(){
|
public int getId(){
|
||||||
return mPackageId.get();
|
return getHeaderBlock().getPackageId().get();
|
||||||
}
|
}
|
||||||
public void setId(byte id){
|
public void setId(byte id){
|
||||||
setId(0xff & id);
|
setId(0xff & id);
|
||||||
}
|
}
|
||||||
public void setId(int id){
|
public void setId(int id){
|
||||||
mPackageId.set(id);
|
getHeaderBlock().getPackageId().set(id);
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
return mPackageName.get();
|
return getHeaderBlock().getPackageName().get();
|
||||||
}
|
}
|
||||||
public void setName(String name){
|
public void setName(String name){
|
||||||
mPackageName.set(name);
|
getHeaderBlock().getPackageName().set(name);
|
||||||
}
|
}
|
||||||
public TableBlock getTableBlock(){
|
public TableBlock getTableBlock(){
|
||||||
Block parent=getParent();
|
Block parent=getParent();
|
||||||
@ -296,24 +256,24 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
|
|
||||||
private void refreshTypeStringPoolOffset(){
|
private void refreshTypeStringPoolOffset(){
|
||||||
int pos=countUpTo(mTypeStringPool);
|
int pos=countUpTo(mTypeStringPool);
|
||||||
mTypeStringPoolOffset.set(pos);
|
getHeaderBlock().getTypeStringPoolOffset().set(pos);
|
||||||
}
|
}
|
||||||
private void refreshTypeStringPoolCount(){
|
private void refreshTypeStringPoolCount(){
|
||||||
mTypeStringPoolCount.set(mTypeStringPool.countStrings());
|
getHeaderBlock().getTypeStringPoolCount().set(mTypeStringPool.countStrings());
|
||||||
}
|
}
|
||||||
private void refreshSpecStringPoolOffset(){
|
private void refreshSpecStringPoolOffset(){
|
||||||
int pos=countUpTo(mSpecStringPool);
|
int pos=countUpTo(mSpecStringPool);
|
||||||
mSpecStringPoolOffset.set(pos);
|
getHeaderBlock().getSpecStringPoolOffset().set(pos);
|
||||||
}
|
}
|
||||||
private void refreshSpecStringCount(){
|
private void refreshSpecStringCount(){
|
||||||
mSpecStringPoolCount.set(mSpecStringPool.countStrings());
|
getHeaderBlock().getSpecStringPoolCount().set(mSpecStringPool.countStrings());
|
||||||
}
|
}
|
||||||
private void refreshTypeIdOffset(){
|
private void refreshTypeIdOffset(){
|
||||||
// TODO: find solution
|
// TODO: find solution
|
||||||
//int largest=getSpecTypePairArray().getHighestTypeId();
|
//int largest=getSpecTypePairArray().getHighestTypeId();
|
||||||
//int count=getTypeStringPool().countStrings();
|
//int count=getTypeStringPool().countStrings();
|
||||||
//mTypeIdOffset.set(count-largest);
|
//getHeaderBlock().getTypeIdOffset().set(count-largest);
|
||||||
mTypeIdOffset.set(0);
|
getHeaderBlock().getTypeIdOffset().set(0);
|
||||||
}
|
}
|
||||||
public void onEntryAdded(EntryBlock entryBlock){
|
public void onEntryAdded(EntryBlock entryBlock){
|
||||||
updateEntry(entryBlock);
|
updateEntry(entryBlock);
|
||||||
|
@ -18,27 +18,19 @@
|
|||||||
import com.reandroid.lib.arsc.array.TypeBlockArray;
|
import com.reandroid.lib.arsc.array.TypeBlockArray;
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||||
|
import com.reandroid.lib.arsc.header.SpecHeader;
|
||||||
import com.reandroid.lib.arsc.item.*;
|
import com.reandroid.lib.arsc.item.*;
|
||||||
import com.reandroid.lib.json.JSONConvert;
|
import com.reandroid.lib.json.JSONConvert;
|
||||||
import com.reandroid.lib.json.JSONObject;
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SpecBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
public class SpecBlock extends BaseChunk<SpecHeader> implements JSONConvert<JSONObject> {
|
||||||
private final SpecFlagsArray specFlagsArray;
|
private final SpecFlagsArray specFlagsArray;
|
||||||
private final ByteItem mTypeId;
|
|
||||||
public SpecBlock() {
|
public SpecBlock() {
|
||||||
super(ChunkType.SPEC, 1);
|
super(new SpecHeader(), 1);
|
||||||
this.mTypeId=new ByteItem();
|
SpecHeader header = getHeaderBlock();
|
||||||
ByteItem res0 = new ByteItem();
|
this.specFlagsArray = new SpecFlagsArray(header.getEntryCount());
|
||||||
ShortItem res1 = new ShortItem();
|
|
||||||
IntegerItem entryCount = new IntegerItem();
|
|
||||||
this.specFlagsArray = new SpecFlagsArray(entryCount);
|
|
||||||
addToHeader(mTypeId);
|
|
||||||
addToHeader(res0);
|
|
||||||
addToHeader(res1);
|
|
||||||
addToHeader(entryCount);
|
|
||||||
|
|
||||||
addChild(specFlagsArray);
|
addChild(specFlagsArray);
|
||||||
}
|
}
|
||||||
public SpecFlagsArray getSpecFlagsArray(){
|
public SpecFlagsArray getSpecFlagsArray(){
|
||||||
@ -48,16 +40,16 @@
|
|||||||
return specFlagsArray.toList();
|
return specFlagsArray.toList();
|
||||||
}
|
}
|
||||||
public byte getTypeId(){
|
public byte getTypeId(){
|
||||||
return mTypeId.get();
|
return getHeaderBlock().getId().get();
|
||||||
}
|
}
|
||||||
public int getTypeIdInt(){
|
public int getTypeIdInt(){
|
||||||
return (0xff & mTypeId.get());
|
return getHeaderBlock().getId().unsignedInt();
|
||||||
}
|
}
|
||||||
public void setTypeId(int id){
|
public void setTypeId(int id){
|
||||||
setTypeId((byte) (0xff & id));
|
setTypeId((byte) (0xff & id));
|
||||||
}
|
}
|
||||||
public void setTypeId(byte id){
|
public void setTypeId(byte id){
|
||||||
mTypeId.set(id);
|
getHeaderBlock().getId().set(id);
|
||||||
}
|
}
|
||||||
public TypeBlockArray getTypeBlockArray(){
|
public TypeBlockArray getTypeBlockArray(){
|
||||||
SpecTypePair specTypePair=getSpecTypePair();
|
SpecTypePair specTypePair=getSpecTypePair();
|
||||||
|
@ -16,18 +16,19 @@
|
|||||||
package com.reandroid.lib.arsc.chunk;
|
package com.reandroid.lib.arsc.chunk;
|
||||||
|
|
||||||
import com.reandroid.lib.arsc.array.StagedAliasEntryArray;
|
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.item.IntegerItem;
|
||||||
import com.reandroid.lib.arsc.value.StagedAliasEntry;
|
import com.reandroid.lib.arsc.value.StagedAliasEntry;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public class StagedAlias extends BaseChunk{
|
public class StagedAlias extends BaseChunk<StagedAliasHeader>{
|
||||||
private final StagedAliasEntryArray stagedAliasEntryArray;
|
private final StagedAliasEntryArray stagedAliasEntryArray;
|
||||||
public StagedAlias() {
|
public StagedAlias() {
|
||||||
super(ChunkType.STAGED_ALIAS, 1);
|
super(new StagedAliasHeader(), 1);
|
||||||
IntegerItem count = new IntegerItem();
|
StagedAliasHeader header = getHeaderBlock();
|
||||||
addToHeader(count);
|
|
||||||
stagedAliasEntryArray = new StagedAliasEntryArray(count);
|
stagedAliasEntryArray = new StagedAliasEntryArray(header.getCount());
|
||||||
addChild(stagedAliasEntryArray);
|
addChild(stagedAliasEntryArray);
|
||||||
}
|
}
|
||||||
public void merge(StagedAlias stagedAlias){
|
public void merge(StagedAlias stagedAlias){
|
||||||
|
@ -19,6 +19,7 @@ import com.reandroid.lib.arsc.BuildInfo;
|
|||||||
import com.reandroid.lib.arsc.array.PackageArray;
|
import com.reandroid.lib.arsc.array.PackageArray;
|
||||||
import com.reandroid.lib.arsc.group.EntryGroup;
|
import com.reandroid.lib.arsc.group.EntryGroup;
|
||||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
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.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||||
import com.reandroid.lib.arsc.pool.TableStringPool;
|
import com.reandroid.lib.arsc.pool.TableStringPool;
|
||||||
@ -33,17 +34,15 @@ import java.util.Collection;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class TableBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
public class TableBlock extends BaseChunk<TableHeader> implements JSONConvert<JSONObject> {
|
||||||
private final IntegerItem mPackageCount;
|
|
||||||
private final TableStringPool mTableStringPool;
|
private final TableStringPool mTableStringPool;
|
||||||
private final PackageArray mPackageArray;
|
private final PackageArray mPackageArray;
|
||||||
private final Set<TableBlock> mFrameWorks=new HashSet<>();
|
private final Set<TableBlock> mFrameWorks=new HashSet<>();
|
||||||
public TableBlock() {
|
public TableBlock() {
|
||||||
super(ChunkType.TABLE, 2);
|
super(new TableHeader(), 2);
|
||||||
this.mPackageCount=new IntegerItem();
|
TableHeader header = getHeaderBlock();
|
||||||
this.mTableStringPool=new TableStringPool(true);
|
this.mTableStringPool=new TableStringPool(true);
|
||||||
this.mPackageArray=new PackageArray(mPackageCount);
|
this.mPackageArray=new PackageArray(header.getPackageCount());
|
||||||
addToHeader(mPackageCount);
|
|
||||||
addChild(mTableStringPool);
|
addChild(mTableStringPool);
|
||||||
addChild(mPackageArray);
|
addChild(mPackageArray);
|
||||||
}
|
}
|
||||||
@ -68,7 +67,7 @@ public class TableBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
|||||||
|
|
||||||
private void refreshPackageCount(){
|
private void refreshPackageCount(){
|
||||||
int count = getPackageArray().childesCount();
|
int count = getPackageArray().childesCount();
|
||||||
mPackageCount.set(count);
|
getHeaderBlock().getPackageCount().set(count);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
|
@ -19,6 +19,7 @@ import com.reandroid.lib.arsc.array.EntryBlockArray;
|
|||||||
import com.reandroid.lib.arsc.array.TypeBlockArray;
|
import com.reandroid.lib.arsc.array.TypeBlockArray;
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
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.BlockLoad;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.*;
|
import com.reandroid.lib.arsc.item.*;
|
||||||
@ -34,34 +35,20 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TypeBlock extends BaseChunk
|
public class TypeBlock extends BaseChunk<TypeHeader>
|
||||||
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
|
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
|
||||||
private final ByteItem mTypeId;
|
|
||||||
private final ByteItem mTypeFlags;
|
|
||||||
private final IntegerItem mEntryCount;
|
|
||||||
private final ResConfig mResConfig;
|
|
||||||
private final EntryBlockArray mEntryArray;
|
private final EntryBlockArray mEntryArray;
|
||||||
private TypeString mTypeString;
|
private TypeString mTypeString;
|
||||||
public TypeBlock() {
|
public TypeBlock() {
|
||||||
super(ChunkType.TYPE, 2);
|
super(new TypeHeader(), 2);
|
||||||
this.mTypeId=new ByteItem();
|
TypeHeader header = getHeaderBlock();
|
||||||
this.mTypeFlags=new ByteItem();
|
|
||||||
ShortItem reserved = new ShortItem();
|
|
||||||
this.mEntryCount=new IntegerItem();
|
|
||||||
|
|
||||||
IntegerItem entriesStart = new IntegerItem();
|
|
||||||
this.mResConfig =new ResConfig();
|
|
||||||
IntegerArray entryOffsets = new IntegerArray();
|
IntegerArray entryOffsets = new IntegerArray();
|
||||||
this.mEntryArray = new EntryBlockArray(entryOffsets, mEntryCount, entriesStart);
|
this.mEntryArray = new EntryBlockArray(entryOffsets,
|
||||||
|
header.getCount(), header.getEntriesStart());
|
||||||
|
|
||||||
mTypeFlags.setBlockLoad(this);
|
header.getFlags().setBlockLoad(this);
|
||||||
|
|
||||||
addToHeader(mTypeId);
|
|
||||||
addToHeader(mTypeFlags);
|
|
||||||
addToHeader(reserved);
|
|
||||||
addToHeader(mEntryCount);
|
|
||||||
addToHeader(entriesStart);
|
|
||||||
addToHeader(mResConfig);
|
|
||||||
|
|
||||||
addChild(entryOffsets);
|
addChild(entryOffsets);
|
||||||
addChild(mEntryArray);
|
addChild(mEntryArray);
|
||||||
@ -99,16 +86,16 @@ public class TypeBlock extends BaseChunk
|
|||||||
return mTypeString;
|
return mTypeString;
|
||||||
}
|
}
|
||||||
public byte getTypeId(){
|
public byte getTypeId(){
|
||||||
return mTypeId.get();
|
return getHeaderBlock().getId().get();
|
||||||
}
|
}
|
||||||
public int getTypeIdInt(){
|
public int getTypeIdInt(){
|
||||||
return (0xff & mTypeId.get());
|
return getHeaderBlock().getId().unsignedInt();
|
||||||
}
|
}
|
||||||
public void setTypeId(int id){
|
public void setTypeId(int id){
|
||||||
setTypeId((byte) (0xff & id));
|
setTypeId((byte) (0xff & id));
|
||||||
}
|
}
|
||||||
public void setTypeId(byte id){
|
public void setTypeId(byte id){
|
||||||
mTypeId.set(id);
|
getHeaderBlock().getId().set(id);
|
||||||
}
|
}
|
||||||
public void setTypeName(String name){
|
public void setTypeName(String name){
|
||||||
TypeStringPool typeStringPool=getTypeStringPool();
|
TypeStringPool typeStringPool=getTypeStringPool();
|
||||||
@ -127,10 +114,11 @@ public class TypeBlock extends BaseChunk
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public void setEntryCount(int count){
|
public void setEntryCount(int count){
|
||||||
if(count == mEntryCount.get()){
|
IntegerItem entryCount = getHeaderBlock().getCount();
|
||||||
|
if(count == entryCount.get()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mEntryCount.set(count);
|
entryCount.set(count);
|
||||||
onSetEntryCount(count);
|
onSetEntryCount(count);
|
||||||
}
|
}
|
||||||
public boolean isEmpty(){
|
public boolean isEmpty(){
|
||||||
@ -182,7 +170,7 @@ public class TypeBlock extends BaseChunk
|
|||||||
return getEntryBlockArray().getEntry(entryId);
|
return getEntryBlockArray().getEntry(entryId);
|
||||||
}
|
}
|
||||||
public ResConfig getResConfig(){
|
public ResConfig getResConfig(){
|
||||||
return mResConfig;
|
return getHeaderBlock().getConfig();
|
||||||
}
|
}
|
||||||
public EntryBlockArray getEntryBlockArray(){
|
public EntryBlockArray getEntryBlockArray(){
|
||||||
return mEntryArray;
|
return mEntryArray;
|
||||||
@ -212,7 +200,7 @@ public class TypeBlock extends BaseChunk
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onPreRefreshRefresh(){
|
protected void onPreRefreshRefresh(){
|
||||||
mResConfig.refresh();
|
getHeaderBlock().getConfig().refresh();
|
||||||
super.onPreRefreshRefresh();
|
super.onPreRefreshRefresh();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -280,8 +268,8 @@ public class TypeBlock extends BaseChunk
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
||||||
if(sender==mTypeFlags){
|
if(sender==getHeaderBlock().getFlags()){
|
||||||
if(mTypeFlags.get()==0x1){
|
if(getHeaderBlock().getFlags().unsignedInt()==0x1){
|
||||||
//ResTable_sparseTypeEntry ?
|
//ResTable_sparseTypeEntry ?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ package com.reandroid.lib.arsc.chunk;
|
|||||||
* This class can load any valid chunk, aimed to
|
* This class can load any valid chunk, aimed to
|
||||||
* handle any future android changes
|
* handle any future android changes
|
||||||
* */
|
* */
|
||||||
public class UnknownChunk extends BaseChunk implements HeaderBlock.HeaderLoaded {
|
public class UnknownChunk extends BaseChunk<HeaderBlock> implements HeaderBlock.HeaderLoaded {
|
||||||
private final ByteArray body;
|
private final ByteArray body;
|
||||||
public UnknownChunk() {
|
public UnknownChunk() {
|
||||||
super(INITIAL_CHUNK_TYPE, 1);
|
super(new HeaderBlock(INITIAL_CHUNK_TYPE), 1);
|
||||||
this.body = new ByteArray();
|
this.body = new ByteArray();
|
||||||
addChild(body);
|
addChild(body);
|
||||||
setHeaderLoaded(this);
|
setHeaderLoaded(this);
|
||||||
|
@ -18,6 +18,7 @@ package com.reandroid.lib.arsc.chunk.xml;
|
|||||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.chunk.BaseChunk;
|
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.IntegerItem;
|
||||||
import com.reandroid.lib.arsc.item.ResXmlString;
|
import com.reandroid.lib.arsc.item.ResXmlString;
|
||||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||||
@ -26,30 +27,23 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
public class BaseXmlChunk extends BaseChunk {
|
public class BaseXmlChunk extends BaseChunk<XmlNodeHeader> {
|
||||||
|
|
||||||
private final IntegerItem mLineNumber;
|
|
||||||
private final IntegerItem mCommentReference;
|
|
||||||
private final IntegerItem mNamespaceReference;
|
private final IntegerItem mNamespaceReference;
|
||||||
private final IntegerItem mStringReference;
|
private final IntegerItem mStringReference;
|
||||||
BaseXmlChunk(ChunkType chunkType, int initialChildesCount) {
|
BaseXmlChunk(ChunkType chunkType, int initialChildesCount) {
|
||||||
super(chunkType, initialChildesCount+2);
|
super(new XmlNodeHeader(chunkType), initialChildesCount+2);
|
||||||
this.mLineNumber=new IntegerItem();
|
|
||||||
this.mCommentReference =new IntegerItem(-1);
|
|
||||||
|
|
||||||
this.mNamespaceReference=new IntegerItem(-1);
|
this.mNamespaceReference=new IntegerItem(-1);
|
||||||
this.mStringReference=new IntegerItem(-1);
|
this.mStringReference=new IntegerItem(-1);
|
||||||
|
|
||||||
addToHeader(mLineNumber);
|
|
||||||
addToHeader(mCommentReference);
|
|
||||||
|
|
||||||
addChild(mNamespaceReference);
|
addChild(mNamespaceReference);
|
||||||
addChild(mStringReference);
|
addChild(mStringReference);
|
||||||
}
|
}
|
||||||
Set<ResXmlString> clearStringReferences(){
|
Set<ResXmlString> clearStringReferences(){
|
||||||
Set<ResXmlString> results=new HashSet<>();
|
Set<ResXmlString> results=new HashSet<>();
|
||||||
ResXmlString xmlString;
|
ResXmlString xmlString;
|
||||||
xmlString=unLinkStringReference(mCommentReference);
|
xmlString=unLinkStringReference(getHeaderBlock().getCommentReference());
|
||||||
if(xmlString!=null){
|
if(xmlString!=null){
|
||||||
results.add(xmlString);
|
results.add(xmlString);
|
||||||
}
|
}
|
||||||
@ -64,7 +58,7 @@ import java.util.Set;
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
void linkStringReferences(){
|
void linkStringReferences(){
|
||||||
linkStringReference(mCommentReference);
|
linkStringReference(getHeaderBlock().getCommentReference());
|
||||||
linkStringReference(mNamespaceReference);
|
linkStringReference(mNamespaceReference);
|
||||||
linkStringReference(mStringReference);
|
linkStringReference(mStringReference);
|
||||||
}
|
}
|
||||||
@ -82,18 +76,19 @@ import java.util.Set;
|
|||||||
return xmlString;
|
return xmlString;
|
||||||
}
|
}
|
||||||
public void setLineNumber(int val){
|
public void setLineNumber(int val){
|
||||||
mLineNumber.set(val);
|
getHeaderBlock().getLineNumber().set(val);
|
||||||
}
|
}
|
||||||
public int getLineNumber(){
|
public int getLineNumber(){
|
||||||
return mLineNumber.get();
|
return getHeaderBlock().getLineNumber().get();
|
||||||
}
|
}
|
||||||
public void setCommentReference(int val){
|
public void setCommentReference(int val){
|
||||||
unLinkStringReference(mCommentReference);
|
IntegerItem comment=getHeaderBlock().getCommentReference();
|
||||||
mCommentReference.set(val);
|
unLinkStringReference(comment);
|
||||||
linkStringReference(mCommentReference);
|
getHeaderBlock().getCommentReference().set(val);
|
||||||
|
linkStringReference(comment);
|
||||||
}
|
}
|
||||||
public int getCommentReference(){
|
public int getCommentReference(){
|
||||||
return mCommentReference.get();
|
return getHeaderBlock().getCommentReference().get();
|
||||||
}
|
}
|
||||||
public void setNamespaceReference(int val){
|
public void setNamespaceReference(int val){
|
||||||
unLinkStringReference(mNamespaceReference);
|
unLinkStringReference(mNamespaceReference);
|
||||||
|
@ -36,13 +36,13 @@ package com.reandroid.lib.arsc.chunk.xml;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ResXmlBlock extends BaseChunk implements JSONConvert<JSONObject> {
|
public class ResXmlBlock extends BaseChunk<HeaderBlock> implements JSONConvert<JSONObject> {
|
||||||
private final ResXmlStringPool mResXmlStringPool;
|
private final ResXmlStringPool mResXmlStringPool;
|
||||||
private final ResXmlIDMap mResXmlIDMap;
|
private final ResXmlIDMap mResXmlIDMap;
|
||||||
private ResXmlElement mResXmlElement;
|
private ResXmlElement mResXmlElement;
|
||||||
private final SingleBlockContainer<ResXmlElement> mResXmlElementContainer;
|
private final SingleBlockContainer<ResXmlElement> mResXmlElementContainer;
|
||||||
public ResXmlBlock() {
|
public ResXmlBlock() {
|
||||||
super(ChunkType.XML,3);
|
super(new HeaderBlock(ChunkType.XML),3);
|
||||||
this.mResXmlStringPool=new ResXmlStringPool(true);
|
this.mResXmlStringPool=new ResXmlStringPool(true);
|
||||||
this.mResXmlIDMap=new ResXmlIDMap();
|
this.mResXmlIDMap=new ResXmlIDMap();
|
||||||
this.mResXmlElement=new ResXmlElement();
|
this.mResXmlElement=new ResXmlElement();
|
||||||
|
@ -19,6 +19,7 @@ import com.reandroid.lib.arsc.base.Block;
|
|||||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||||
import com.reandroid.lib.arsc.array.ResXmlIDArray;
|
import com.reandroid.lib.arsc.array.ResXmlIDArray;
|
||||||
import com.reandroid.lib.arsc.chunk.BaseChunk;
|
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.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.ResXmlID;
|
import com.reandroid.lib.arsc.item.ResXmlID;
|
||||||
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
||||||
@ -26,10 +27,10 @@ import com.reandroid.lib.arsc.pool.ResXmlStringPool;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public class ResXmlIDMap extends BaseChunk {
|
public class ResXmlIDMap extends BaseChunk<HeaderBlock> {
|
||||||
private final ResXmlIDArray mResXmlIDArray;
|
private final ResXmlIDArray mResXmlIDArray;
|
||||||
public ResXmlIDMap() {
|
public ResXmlIDMap() {
|
||||||
super(ChunkType.XML_RESOURCE_MAP, 1);
|
super(new HeaderBlock(ChunkType.XML_RESOURCE_MAP), 1);
|
||||||
this.mResXmlIDArray=new ResXmlIDArray(getHeaderBlock());
|
this.mResXmlIDArray=new ResXmlIDArray(getHeaderBlock());
|
||||||
addChild(mResXmlIDArray);
|
addChild(mResXmlIDArray);
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,9 @@ import com.reandroid.lib.arsc.item.BlockItem;
|
|||||||
import com.reandroid.lib.arsc.item.ByteArray;
|
import com.reandroid.lib.arsc.item.ByteArray;
|
||||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||||
import com.reandroid.lib.arsc.item.ShortItem;
|
import com.reandroid.lib.arsc.item.ShortItem;
|
||||||
|
import com.reandroid.lib.arsc.util.HexBytesWriter;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HeaderBlock extends ExpandableBlockContainer implements BlockLoad {
|
public class HeaderBlock extends ExpandableBlockContainer implements BlockLoad {
|
||||||
@ -52,6 +50,9 @@ import java.util.List;
|
|||||||
this.mHeaderSize.setBlockLoad(this);
|
this.mHeaderSize.setBlockLoad(this);
|
||||||
this.mChunkSize.setBlockLoad(this);
|
this.mChunkSize.setBlockLoad(this);
|
||||||
}
|
}
|
||||||
|
public HeaderBlock(ChunkType chunkType){
|
||||||
|
this(chunkType.ID);
|
||||||
|
}
|
||||||
public ByteArray getExtraBytes() {
|
public ByteArray getExtraBytes() {
|
||||||
return extraBytes;
|
return extraBytes;
|
||||||
}
|
}
|
||||||
@ -199,7 +200,12 @@ import java.util.List;
|
|||||||
headerLoaded.onChunkSizeLoaded(headerSize, chunkSize);
|
headerLoaded.onChunkSizeLoaded(headerSize, chunkSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Prints bytes in hex for debug/testing
|
||||||
|
* */
|
||||||
|
public String toHex(){
|
||||||
|
return HexBytesWriter.toHex(getBytes());
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
short t = getType();
|
short t = getType();
|
||||||
|
@ -16,11 +16,26 @@
|
|||||||
package com.reandroid.lib.arsc.header;
|
package com.reandroid.lib.arsc.header;
|
||||||
|
|
||||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||||
|
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||||
|
|
||||||
/**No importance of this class, to be removed latter*/
|
public class LibraryHeader extends HeaderBlock{
|
||||||
@Deprecated
|
private final IntegerItem count;
|
||||||
public class AnyHeader extends HeaderBlock{
|
public LibraryHeader() {
|
||||||
public AnyHeader() {
|
super(ChunkType.LIBRARY.ID);
|
||||||
super(ChunkType.NULL.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() + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -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<IntegerItem> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
src/main/java/com/reandroid/lib/arsc/header/SpecHeader.java
Normal file
52
src/main/java/com/reandroid/lib/arsc/header/SpecHeader.java
Normal file
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -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()+ '}';
|
||||||
|
}
|
||||||
|
}
|
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
39
src/main/java/com/reandroid/lib/arsc/header/TableHeader.java
Normal file
39
src/main/java/com/reandroid/lib/arsc/header/TableHeader.java
Normal file
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
76
src/main/java/com/reandroid/lib/arsc/header/TypeHeader.java
Normal file
76
src/main/java/com/reandroid/lib/arsc/header/TypeHeader.java
Normal file
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -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() + '}';
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,12 @@ public class ByteItem extends BlockItem {
|
|||||||
public byte get(){
|
public byte get(){
|
||||||
return getBytesInternal()[0];
|
return getBytesInternal()[0];
|
||||||
}
|
}
|
||||||
|
public int unsignedInt(){
|
||||||
|
return 0xff & get();
|
||||||
|
}
|
||||||
|
public String toHex(){
|
||||||
|
return String.format("0x%02x", unsignedInt());
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return String.valueOf(get());
|
return String.valueOf(get());
|
||||||
|
@ -41,6 +41,9 @@ public class IntegerItem extends BlockItem implements ReferenceItem{
|
|||||||
public int get(){
|
public int get(){
|
||||||
return mCache;
|
return mCache;
|
||||||
}
|
}
|
||||||
|
public String toHex(){
|
||||||
|
return String.format("0x%08x", get());
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onBytesChanged() {
|
protected void onBytesChanged() {
|
||||||
// To save cpu usage, better to calculate once only when bytes changed
|
// To save cpu usage, better to calculate once only when bytes changed
|
||||||
|
@ -40,6 +40,9 @@ public class ShortItem extends BlockItem {
|
|||||||
public int unsignedInt(){
|
public int unsignedInt(){
|
||||||
return 0xffff & get();
|
return 0xffff & get();
|
||||||
}
|
}
|
||||||
|
public String toHex(){
|
||||||
|
return String.format("0x%04x", unsignedInt());
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onBytesChanged() {
|
protected void onBytesChanged() {
|
||||||
// To save cpu usage, better to calculate once only when bytes changed
|
// To save cpu usage, better to calculate once only when bytes changed
|
||||||
|
@ -15,72 +15,58 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.lib.arsc.pool;
|
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.StringArray;
|
import com.reandroid.lib.arsc.array.StyleArray;
|
||||||
import com.reandroid.lib.arsc.array.StyleArray;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.chunk.BaseChunk;
|
||||||
import com.reandroid.lib.arsc.chunk.BaseChunk;
|
import com.reandroid.lib.arsc.group.StringGroup;
|
||||||
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.BlockLoad;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.*;
|
import com.reandroid.lib.arsc.item.*;
|
||||||
import com.reandroid.lib.arsc.model.StyleSpanInfo;
|
import com.reandroid.lib.json.JSONArray;
|
||||||
import com.reandroid.lib.json.JSONConvert;
|
import com.reandroid.lib.json.JSONConvert;
|
||||||
import com.reandroid.lib.json.JSONArray;
|
|
||||||
import com.reandroid.lib.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
public abstract class BaseStringPool<T extends StringItem> extends BaseChunk implements BlockLoad, JSONConvert<JSONArray>, Comparator<String> {
|
public abstract class BaseStringPool<T extends StringItem> extends BaseChunk<StringPoolHeader> implements BlockLoad, JSONConvert<JSONArray>, Comparator<String> {
|
||||||
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;
|
|
||||||
private final StringArray<T> mArrayStrings;
|
private final StringArray<T> mArrayStrings;
|
||||||
private final StyleArray mArrayStyles;
|
private final StyleArray mArrayStyles;
|
||||||
|
|
||||||
private final Map<String, StringGroup<T>> mUniqueMap;
|
private final Map<String, StringGroup<T>> mUniqueMap;
|
||||||
|
|
||||||
|
|
||||||
BaseStringPool(boolean is_utf8){
|
BaseStringPool(boolean is_utf8){
|
||||||
super(ChunkType.STRING, 4);
|
super(new StringPoolHeader(), 4);
|
||||||
|
|
||||||
this.mCountStrings=new IntegerItem(); //header
|
IntegerArray offsetStrings = new IntegerArray();
|
||||||
this.mCountStyles=new IntegerItem(); //header
|
IntegerArray offsetStyles = new IntegerArray();
|
||||||
this.mFlagUtf8 =new ShortItem(); //header
|
|
||||||
this.mFlagSorted=new ShortItem(); //header
|
|
||||||
this.mStartStrings=new IntegerItem(); //header
|
|
||||||
this.mStartStyles=new IntegerItem(); //header
|
|
||||||
|
|
||||||
this.mOffsetStrings=new IntegerArray();//1
|
StringPoolHeader header = getHeaderBlock();
|
||||||
this.mOffsetStyles=new IntegerArray(); //2
|
|
||||||
this.mArrayStrings=newInstance(mOffsetStrings, mCountStrings, mStartStrings, is_utf8); //3
|
|
||||||
this.mArrayStyles=new StyleArray(mOffsetStyles, mCountStyles, mStartStyles); //4
|
|
||||||
|
|
||||||
addToHeader(mCountStrings);
|
this.mArrayStrings = newInstance(
|
||||||
addToHeader(mCountStyles);
|
offsetStrings,
|
||||||
addToHeader(mFlagUtf8);
|
header.getCountStrings(),
|
||||||
addToHeader(mFlagSorted);
|
header.getStartStrings(),
|
||||||
addToHeader(mStartStrings);
|
is_utf8);
|
||||||
addToHeader(mStartStyles);
|
|
||||||
|
|
||||||
addChild(mOffsetStrings);
|
this.mArrayStyles = new StyleArray(
|
||||||
addChild(mOffsetStyles);
|
offsetStyles,
|
||||||
|
header.getCountStyles(),
|
||||||
|
header.getStartStyles());
|
||||||
|
|
||||||
|
|
||||||
|
addChild(offsetStrings);
|
||||||
|
addChild(offsetStyles);
|
||||||
addChild(mArrayStrings);
|
addChild(mArrayStrings);
|
||||||
addChild(mArrayStyles);
|
addChild(mArrayStyles);
|
||||||
|
|
||||||
setUtf8(is_utf8, false);
|
setUtf8(is_utf8, false);
|
||||||
|
|
||||||
mFlagUtf8.setBlockLoad(this);
|
header.getFlagUtf8().setBlockLoad(this);
|
||||||
|
|
||||||
mUniqueMap=new HashMap<>();
|
|
||||||
|
|
||||||
|
mUniqueMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
public List<String> toStringList(){
|
public List<String> toStringList(){
|
||||||
return getStringsArray().toStringList();
|
return getStringsArray().toStringList();
|
||||||
@ -137,13 +123,12 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
|||||||
// call this after modifying string values
|
// call this after modifying string values
|
||||||
public void refreshUniqueIdMap(){
|
public void refreshUniqueIdMap(){
|
||||||
mUniqueMap.clear();
|
mUniqueMap.clear();
|
||||||
T[] allChildes=getStrings();
|
T[] stringsArray = getStrings();
|
||||||
if(allChildes==null){
|
if(stringsArray==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int max=allChildes.length;
|
for(int i=0;i<stringsArray.length;i++){
|
||||||
for(int i=0;i<max;i++){
|
T item=stringsArray[i];
|
||||||
T item=allChildes[i];
|
|
||||||
if(item==null){
|
if(item==null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -237,7 +222,7 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
|||||||
private T createNewString(String str){
|
private T createNewString(String str){
|
||||||
T item=mArrayStrings.createNext();
|
T item=mArrayStrings.createNext();
|
||||||
item.set(str);
|
item.set(str);
|
||||||
mCountStrings.set(mArrayStrings.childesCount());
|
getHeaderBlock().getCountStrings().set(mArrayStrings.childesCount());
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
public final StyleItem getStyle(int index){
|
public final StyleItem getStyle(int index){
|
||||||
@ -249,35 +234,30 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
|||||||
public final int countStyles(){
|
public final int countStyles(){
|
||||||
return mArrayStyles.childesCount();
|
return mArrayStyles.childesCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final T[] getStrings(){
|
public final T[] getStrings(){
|
||||||
return mArrayStrings.getChildes();
|
return mArrayStrings.getChildes();
|
||||||
}
|
}
|
||||||
public final StyleItem[] getStyles(){
|
public final StyleItem[] getStyles(){
|
||||||
return mArrayStyles.getChildes();
|
return mArrayStyles.getChildes();
|
||||||
}
|
}
|
||||||
private void setUtf8Flag(short flag){
|
|
||||||
mFlagUtf8.set(flag);
|
|
||||||
}
|
|
||||||
public void setUtf8(boolean is_utf8){
|
public void setUtf8(boolean is_utf8){
|
||||||
setUtf8(is_utf8, true);
|
setUtf8(is_utf8, true);
|
||||||
}
|
}
|
||||||
private void setSortedFlag(short flag){
|
|
||||||
mFlagSorted.set(flag);
|
|
||||||
}
|
|
||||||
public final void setSorted(boolean sorted){
|
public final void setSorted(boolean sorted){
|
||||||
|
ShortItem flagSorted = getHeaderBlock().getFlagSorted();
|
||||||
if(sorted){
|
if(sorted){
|
||||||
setSortedFlag(FLAG_SORTED);
|
flagSorted.set(FLAG_SORTED);
|
||||||
}else {
|
}else {
|
||||||
setSortedFlag((short)0);
|
flagSorted.set((short)0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void setUtf8(boolean is_utf8, boolean updateAll){
|
private void setUtf8(boolean is_utf8, boolean updateAll){
|
||||||
boolean old= isUtf8Flag();
|
ShortItem flagUtf8 = getHeaderBlock().getFlagUtf8();
|
||||||
|
boolean old = isUtf8Flag();
|
||||||
if(is_utf8){
|
if(is_utf8){
|
||||||
setUtf8Flag(UTF8_FLAG_VALUE);
|
flagUtf8.set(UTF8_FLAG_VALUE);
|
||||||
}else {
|
}else {
|
||||||
setUtf8Flag((short) 0);
|
flagUtf8.set((short) 0);
|
||||||
}
|
}
|
||||||
if(!updateAll || old == isUtf8Flag()){
|
if(!updateAll || old == isUtf8Flag()){
|
||||||
return;
|
return;
|
||||||
@ -285,13 +265,8 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
|||||||
mArrayStrings.setUtf8(is_utf8);
|
mArrayStrings.setUtf8(is_utf8);
|
||||||
}
|
}
|
||||||
private boolean isUtf8Flag(){
|
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<T> newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8);
|
abstract StringArray<T> newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8);
|
||||||
@Override
|
@Override
|
||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
@ -305,7 +280,7 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
||||||
if(sender== mFlagUtf8){
|
if(sender == getHeaderBlock().getFlagUtf8()){
|
||||||
mArrayStrings.setUtf8(isUtf8Flag());
|
mArrayStrings.setUtf8(isUtf8Flag());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,112 +294,15 @@ public abstract class BaseStringPool<T extends StringItem> extends BaseChunk imp
|
|||||||
if(json==null){
|
if(json==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadStyledStrings(json);
|
JsonStringPoolHelper<T> helper=new JsonStringPoolHelper<>(this);
|
||||||
|
helper.loadStyledStrings(json);
|
||||||
refresh();
|
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<StyledString> styledStringList = StyledString.fromJson(jsonArray);
|
|
||||||
loadText(styledStringList);
|
|
||||||
Map<String, Integer> tagIndexMap = loadStyleTags(styledStringList);
|
|
||||||
loadStyles(styledStringList, tagIndexMap);
|
|
||||||
refreshUniqueIdMap();
|
|
||||||
}
|
|
||||||
private void loadText(List<StyledString> styledStringList) {
|
|
||||||
StringArray<T> stringsArray = getStringsArray();
|
|
||||||
int size=styledStringList.size();
|
|
||||||
stringsArray.ensureSize(size);
|
|
||||||
for(int i=0;i<size;i++){
|
|
||||||
StyledString styledString=styledStringList.get(i);
|
|
||||||
T item=stringsArray.get(i);
|
|
||||||
item.set(styledString.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private Map<String, Integer> loadStyleTags(List<StyledString> styledStringList) {
|
|
||||||
Map<String, Integer> indexMap=new HashMap<>();
|
|
||||||
List<String> tagList=new ArrayList<>(getStyleTags(styledStringList));
|
|
||||||
tagList.sort(this);
|
|
||||||
StringArray<T> stringsArray = getStringsArray();
|
|
||||||
int tagsSize = tagList.size();
|
|
||||||
int initialSize = stringsArray.childesCount();
|
|
||||||
stringsArray.ensureSize(initialSize + tagsSize);
|
|
||||||
for(int i=0;i<tagsSize;i++){
|
|
||||||
String tag = tagList.get(i);
|
|
||||||
T item = stringsArray.get(initialSize + i);
|
|
||||||
item.set(tag);
|
|
||||||
indexMap.put(tag, item.getIndex());
|
|
||||||
}
|
|
||||||
return indexMap;
|
|
||||||
}
|
|
||||||
private void loadStyles(List<StyledString> styledStringList, Map<String, Integer> tagIndexMap){
|
|
||||||
StyleArray styleArray = getStyleArray();
|
|
||||||
int size=styledStringList.size();
|
|
||||||
styleArray.ensureSize(size);
|
|
||||||
for(int i=0;i<size;i++){
|
|
||||||
StyledString ss = styledStringList.get(i);
|
|
||||||
StyleItem styleItem = styleArray.get(i);
|
|
||||||
for(StyleSpanInfo spanInfo:ss.spanInfoList){
|
|
||||||
int tagIndex=tagIndexMap.get(spanInfo.getTag());
|
|
||||||
styleItem.addStylePiece(tagIndex, spanInfo.getFirst(), spanInfo.getLast());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static Set<String> getStyleTags(List<StyledString> styledStringList){
|
|
||||||
Set<String> results=new HashSet<>();
|
|
||||||
for(StyledString ss:styledStringList){
|
|
||||||
for(StyleSpanInfo spanInfo:ss.spanInfoList){
|
|
||||||
results.add(spanInfo.getTag());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(String s1, String s2) {
|
public int compare(String s1, String s2) {
|
||||||
return s1.compareTo(s2);
|
return s1.compareTo(s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StyledString{
|
|
||||||
final String text;
|
|
||||||
final List<StyleSpanInfo> spanInfoList;
|
|
||||||
StyledString(String text, List<StyleSpanInfo> spanInfoList){
|
|
||||||
this.text=text;
|
|
||||||
this.spanInfoList=spanInfoList;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
static List<StyledString> fromJson(JSONArray jsonArray){
|
|
||||||
int length = jsonArray.length();
|
|
||||||
List<StyledString> results=new ArrayList<>();
|
|
||||||
for(int i=0;i<length;i++){
|
|
||||||
StyledString styledString=fromJson(jsonArray.getJSONObject(i));
|
|
||||||
results.add(styledString);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
static StyledString fromJson(JSONObject jsonObject){
|
|
||||||
String text= jsonObject.getString(StringItem.NAME_string);
|
|
||||||
JSONObject style=jsonObject.getJSONObject(StringItem.NAME_style);
|
|
||||||
JSONArray spansArray=style.getJSONArray(StyleItem.NAME_spans);
|
|
||||||
List<StyleSpanInfo> spanInfoList = toSpanInfoList(spansArray);
|
|
||||||
return new StyledString(text, spanInfoList);
|
|
||||||
}
|
|
||||||
private static List<StyleSpanInfo> toSpanInfoList(JSONArray jsonArray){
|
|
||||||
int length = jsonArray.length();
|
|
||||||
List<StyleSpanInfo> results=new ArrayList<>(length);
|
|
||||||
for(int i=0;i<length;i++){
|
|
||||||
JSONObject jsonObject = jsonArray.getJSONObject(i);
|
|
||||||
StyleSpanInfo spanInfo=new StyleSpanInfo(null, 0,0);
|
|
||||||
spanInfo.fromJson(jsonObject);
|
|
||||||
results.add(spanInfo);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static final short UTF8_FLAG_VALUE=0x0100;
|
private static final short UTF8_FLAG_VALUE=0x0100;
|
||||||
|
|
||||||
private static final short FLAG_UTF8 = 0x0100;
|
private static final short FLAG_UTF8 = 0x0100;
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
package com.reandroid.lib.arsc.pool;
|
||||||
|
|
||||||
|
import com.reandroid.lib.arsc.array.StringArray;
|
||||||
|
import com.reandroid.lib.arsc.array.StyleArray;
|
||||||
|
import com.reandroid.lib.arsc.item.StringItem;
|
||||||
|
import com.reandroid.lib.arsc.item.StyleItem;
|
||||||
|
import com.reandroid.lib.arsc.model.StyleSpanInfo;
|
||||||
|
import com.reandroid.lib.json.JSONArray;
|
||||||
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
class JsonStringPoolHelper<T extends StringItem> {
|
||||||
|
|
||||||
|
private final BaseStringPool<T> stringPool;
|
||||||
|
JsonStringPoolHelper(BaseStringPool<T> 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<StyledString> styledStringList = StyledString.fromJson(jsonArray);
|
||||||
|
loadText(styledStringList);
|
||||||
|
Map<String, Integer> tagIndexMap = loadStyleTags(styledStringList);
|
||||||
|
loadStyles(styledStringList, tagIndexMap);
|
||||||
|
stringPool.refreshUniqueIdMap();
|
||||||
|
}
|
||||||
|
private void loadText(List<StyledString> styledStringList) {
|
||||||
|
StringArray<T> stringsArray = stringPool.getStringsArray();
|
||||||
|
int size=styledStringList.size();
|
||||||
|
stringsArray.ensureSize(size);
|
||||||
|
for(int i=0;i<size;i++){
|
||||||
|
StyledString styledString=styledStringList.get(i);
|
||||||
|
T item=stringsArray.get(i);
|
||||||
|
item.set(styledString.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Map<String, Integer> loadStyleTags(List<StyledString> styledStringList) {
|
||||||
|
Map<String, Integer> indexMap=new HashMap<>();
|
||||||
|
List<String> tagList=new ArrayList<>(getStyleTags(styledStringList));
|
||||||
|
tagList.sort(stringPool);
|
||||||
|
StringArray<T> stringsArray = stringPool.getStringsArray();
|
||||||
|
int tagsSize = tagList.size();
|
||||||
|
int initialSize = stringsArray.childesCount();
|
||||||
|
stringsArray.ensureSize(initialSize + tagsSize);
|
||||||
|
for(int i=0;i<tagsSize;i++){
|
||||||
|
String tag = tagList.get(i);
|
||||||
|
T item = stringsArray.get(initialSize + i);
|
||||||
|
item.set(tag);
|
||||||
|
indexMap.put(tag, item.getIndex());
|
||||||
|
}
|
||||||
|
return indexMap;
|
||||||
|
}
|
||||||
|
private void loadStyles(List<StyledString> styledStringList, Map<String, Integer> tagIndexMap){
|
||||||
|
StyleArray styleArray = stringPool.getStyleArray();
|
||||||
|
int size=styledStringList.size();
|
||||||
|
styleArray.ensureSize(size);
|
||||||
|
for(int i=0;i<size;i++){
|
||||||
|
StyledString ss = styledStringList.get(i);
|
||||||
|
StyleItem styleItem = styleArray.get(i);
|
||||||
|
for(StyleSpanInfo spanInfo:ss.spanInfoList){
|
||||||
|
int tagIndex=tagIndexMap.get(spanInfo.getTag());
|
||||||
|
styleItem.addStylePiece(tagIndex, spanInfo.getFirst(), spanInfo.getLast());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static Set<String> getStyleTags(List<StyledString> styledStringList){
|
||||||
|
Set<String> 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<StyleSpanInfo> spanInfoList;
|
||||||
|
StyledString(String text, List<StyleSpanInfo> spanInfoList){
|
||||||
|
this.text=text;
|
||||||
|
this.spanInfoList=spanInfoList;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
static List<StyledString> fromJson(JSONArray jsonArray){
|
||||||
|
int length = jsonArray.length();
|
||||||
|
List<StyledString> results=new ArrayList<>();
|
||||||
|
for(int i=0;i<length;i++){
|
||||||
|
StyledString styledString=fromJson(jsonArray.getJSONObject(i));
|
||||||
|
results.add(styledString);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
static StyledString fromJson(JSONObject jsonObject){
|
||||||
|
String text= jsonObject.getString(StringItem.NAME_string);
|
||||||
|
JSONObject style=jsonObject.getJSONObject(StringItem.NAME_style);
|
||||||
|
JSONArray spansArray=style.getJSONArray(StyleItem.NAME_spans);
|
||||||
|
List<StyleSpanInfo> spanInfoList = toSpanInfoList(spansArray);
|
||||||
|
return new StyledString(text, spanInfoList);
|
||||||
|
}
|
||||||
|
private static List<StyleSpanInfo> toSpanInfoList(JSONArray jsonArray){
|
||||||
|
int length = jsonArray.length();
|
||||||
|
List<StyleSpanInfo> results=new ArrayList<>(length);
|
||||||
|
for(int i=0;i<length;i++){
|
||||||
|
JSONObject jsonObject = jsonArray.getJSONObject(i);
|
||||||
|
StyleSpanInfo spanInfo=new StyleSpanInfo(null, 0,0);
|
||||||
|
spanInfo.fromJson(jsonObject);
|
||||||
|
results.add(spanInfo);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.pool;
|
|
||||||
|
|
||||||
public enum PoolType {
|
|
||||||
TABLE,
|
|
||||||
SPEC,
|
|
||||||
TYPE,
|
|
||||||
XML
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import com.reandroid.lib.arsc.array.TableStringArray;
|
|||||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||||
import com.reandroid.lib.arsc.chunk.UnknownChunk;
|
import com.reandroid.lib.arsc.chunk.UnknownChunk;
|
||||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||||
|
import com.reandroid.lib.arsc.header.StringPoolHeader;
|
||||||
import com.reandroid.lib.arsc.io.BlockReader;
|
import com.reandroid.lib.arsc.io.BlockReader;
|
||||||
import com.reandroid.lib.arsc.item.IntegerArray;
|
import com.reandroid.lib.arsc.item.IntegerArray;
|
||||||
import com.reandroid.lib.arsc.item.IntegerItem;
|
import com.reandroid.lib.arsc.item.IntegerItem;
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
package com.reandroid.lib.arsc.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
public class HexBytesWriter {
|
||||||
|
private final byte[] byteArray;
|
||||||
|
private final int width;
|
||||||
|
private final int columns;
|
||||||
|
private final int indent;
|
||||||
|
public HexBytesWriter(byte[] byteArray, int width, int columns, int indent){
|
||||||
|
this.byteArray = byteArray;
|
||||||
|
this.width = (width <= 0) ? DEFAULT_WIDTH : width;
|
||||||
|
this.columns = (columns <= 0) ? width : columns;
|
||||||
|
this.indent = indent;
|
||||||
|
}
|
||||||
|
public HexBytesWriter(byte[] byteArray, int width){
|
||||||
|
this(byteArray, width, DEFAULT_COLUMNS, DEFAULT_INDENT);
|
||||||
|
}
|
||||||
|
public HexBytesWriter(byte[] byteArray){
|
||||||
|
this(byteArray, DEFAULT_WIDTH, DEFAULT_COLUMNS, DEFAULT_INDENT);
|
||||||
|
}
|
||||||
|
public void write(Writer writer) throws IOException{
|
||||||
|
if(byteArray==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write(writer, 0, byteArray.length);
|
||||||
|
}
|
||||||
|
public void write(Writer writer, int offset, int length) throws IOException {
|
||||||
|
byte[] byteArray = this.byteArray;
|
||||||
|
if(byteArray==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int width = this.width;
|
||||||
|
int columns = this.columns;
|
||||||
|
int x = 0;
|
||||||
|
boolean newLineAppended = false;
|
||||||
|
for(int i=0; i < length; i++){
|
||||||
|
if((i%width)==0){
|
||||||
|
if(i!=0){
|
||||||
|
writeNewLine(writer);
|
||||||
|
newLineAppended=true;
|
||||||
|
}
|
||||||
|
writeIndent(writer);
|
||||||
|
x=0;
|
||||||
|
}else if(x%columns==0){
|
||||||
|
writer.write(' ');
|
||||||
|
}
|
||||||
|
if(!newLineAppended && i!=0){
|
||||||
|
writer.write(' ');
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
newLineAppended=false;
|
||||||
|
writeHex(writer, byteArray[offset+i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void writeHex(Writer writer, byte b) throws IOException {
|
||||||
|
String hex = String.format("%02x", (0xff & b)).toUpperCase();
|
||||||
|
writer.write(hex);
|
||||||
|
}
|
||||||
|
private void writeIndent(Writer writer) throws IOException {
|
||||||
|
for(int i=0;i<this.indent;i++){
|
||||||
|
writer.write(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void writeNewLine(Writer writer) throws IOException {
|
||||||
|
writer.write('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toHex(byte[] byteArray){
|
||||||
|
StringWriter writer=new StringWriter();
|
||||||
|
HexBytesWriter hexBytesWriter = new HexBytesWriter(byteArray);
|
||||||
|
try {
|
||||||
|
hexBytesWriter.write(writer);
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int DEFAULT_WIDTH = 16;
|
||||||
|
private static final int DEFAULT_COLUMNS = 4;
|
||||||
|
private static final int DEFAULT_INDENT = 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user