fix merge error

This commit is contained in:
REAndroid 2023-02-10 09:55:48 -05:00
parent eb805b7979
commit 0206c73908
23 changed files with 219 additions and 77 deletions

View File

@ -64,10 +64,10 @@ package com.reandroid.apk.xmlencoder;
public InputSource encodeFileEntry(File resFile){ public InputSource encodeFileEntry(File resFile){
String type = EncodeUtil.getTypeNameFromResFile(resFile); String type = EncodeUtil.getTypeNameFromResFile(resFile);
PackageBlock packageBlock = materials.getCurrentPackage(); PackageBlock packageBlock = materials.getCurrentPackage();
byte typeId=packageBlock int typeId=packageBlock
.getTypeStringPool().idOf(type); .getTypeStringPool().idOf(type);
String qualifiers = EncodeUtil.getQualifiersFromResFile(resFile); String qualifiers = EncodeUtil.getQualifiersFromResFile(resFile);
TypeBlock typeBlock = packageBlock.getOrCreateTypeBlock(typeId, qualifiers); TypeBlock typeBlock = packageBlock.getOrCreateTypeBlock((byte)typeId, qualifiers);
String name = EncodeUtil.getEntryNameFromResFile(resFile); String name = EncodeUtil.getEntryNameFromResFile(resFile);
int resourceId=materials.resolveLocalResourceId(type, name); int resourceId=materials.resolveLocalResourceId(type, name);

View File

@ -92,7 +92,7 @@ class XMLValuesEncoder {
private TypeBlock getTypeBlock(String type, String qualifiers){ private TypeBlock getTypeBlock(String type, String qualifiers){
PackageBlock packageBlock = getMaterials().getCurrentPackage(); PackageBlock packageBlock = getMaterials().getCurrentPackage();
TypeStringPool typeStringPool = packageBlock.getTypeStringPool(); TypeStringPool typeStringPool = packageBlock.getTypeStringPool();
byte typeId = typeStringPool.idOf(type); byte typeId = (byte) typeStringPool.idOf(type);
SpecTypePair specTypePair SpecTypePair specTypePair
= packageBlock.getSpecTypePairArray().getOrCreate(typeId); = packageBlock.getSpecTypePairArray().getOrCreate(typeId);
int highest = specTypePair.getHighestEntryCount(); int highest = specTypePair.getHighestEntryCount();

View File

@ -122,25 +122,9 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
while (itr.hasNext()){ while (itr.hasNext()){
EntryBlock comingBlock=itr.next(); EntryBlock comingBlock=itr.next();
EntryBlock existingBlock=get(comingBlock.getIndex()); EntryBlock existingBlock=get(comingBlock.getIndex());
if(shouldMerge(existingBlock, comingBlock)){ existingBlock.merge(comingBlock);
existingBlock.merge(comingBlock);
}
} }
} }
private boolean shouldMerge(EntryBlock exist, EntryBlock coming){
if(exist.isNull()){
return true;
}
if(coming.isNull()){
return false;
}
BaseResValue resVal = coming.getResValue();
if(resVal instanceof ResValueInt){
ValueType valueType=((ResValueInt)resVal).getValueType();
return valueType!=ValueType.INT_BOOLEAN;
}
return true;
}
@Override @Override
public String toString(){ public String toString(){
return getClass().getSimpleName()+": size="+childesCount(); return getClass().getSimpleName()+": size="+childesCount();

View File

@ -102,10 +102,6 @@ public abstract class OffsetBlockArray<T extends Block> extends BlockArray<T> im
if(item==null || item.isNull()){ if(item==null || item.isNull()){
offset=-1; offset=-1;
}else { }else {
// slow but accurate
//offset=countUpTo(item);
// fast but fails for duplicate items
offset=sum; offset=sum;
sum+=item.countBytes(); sum+=item.countBytes();
} }

View File

@ -182,7 +182,7 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair>
if(pair==null){ if(pair==null){
continue; continue;
} }
int id=pair.getTypeIdInt(); int id=pair.getId();
if(!firstFound){ if(!firstFound){
result=id; result=id;
} }
@ -204,7 +204,7 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair>
if(pair==null){ if(pair==null){
continue; continue;
} }
int id=pair.getTypeIdInt(); int id=pair.getId();
if(id>result){ if(id>result){
result=id; result=id;
} }

View File

@ -20,6 +20,7 @@ import com.reandroid.arsc.base.Block;
import com.reandroid.arsc.base.BlockArray; import com.reandroid.arsc.base.BlockArray;
import com.reandroid.arsc.chunk.SpecBlock; import com.reandroid.arsc.chunk.SpecBlock;
import com.reandroid.arsc.chunk.TypeBlock; import com.reandroid.arsc.chunk.TypeBlock;
import com.reandroid.arsc.container.SpecTypePair;
import com.reandroid.arsc.header.HeaderBlock; import com.reandroid.arsc.header.HeaderBlock;
import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.io.BlockReader;
import com.reandroid.arsc.item.TypeString; import com.reandroid.arsc.item.TypeString;
@ -142,16 +143,12 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
} }
} }
public byte getTypeId(){ public byte getTypeId(){
if(mTypeId != 0){
return mTypeId;
}
SpecBlock specBlock=getSpecBlock(); SpecBlock specBlock=getSpecBlock();
if(specBlock!=null){ if(specBlock!=null){
byte id=specBlock.getTypeId(); return specBlock.getTypeId();
if(id!=0){ }
mTypeId=id; if(mTypeId != 0){
return id; return mTypeId;
}
} }
TypeBlock[] allChildes=getChildes(); TypeBlock[] allChildes=getChildes();
if(allChildes==null){ if(allChildes==null){
@ -192,8 +189,8 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
private SpecBlock getSpecBlock(){ private SpecBlock getSpecBlock(){
Block parent=getParent(); Block parent=getParent();
while(parent!=null){ while(parent!=null){
if(parent instanceof SpecBlock){ if(parent instanceof SpecTypePair){
return (SpecBlock)parent; return ((SpecTypePair) parent).getSpecBlock();
} }
parent=parent.getParent(); parent=parent.getParent();
} }

View File

@ -0,0 +1,7 @@
package com.reandroid.arsc.chunk;
import com.reandroid.arsc.pool.StringPool;
public interface MainChunk {
public StringPool<?> getStringPool();
}

View File

@ -30,6 +30,7 @@ package com.reandroid.arsc.chunk;
import com.reandroid.arsc.pool.TypeStringPool; import com.reandroid.arsc.pool.TypeStringPool;
import com.reandroid.arsc.value.EntryBlock; import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.LibraryInfo; import com.reandroid.arsc.value.LibraryInfo;
import com.reandroid.arsc.value.ResConfig;
import com.reandroid.arsc.value.StagedAliasEntry; import com.reandroid.arsc.value.StagedAliasEntry;
import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONObject; import com.reandroid.json.JSONObject;
@ -51,7 +52,7 @@ package com.reandroid.arsc.chunk;
super(new PackageHeader(), 3); super(new PackageHeader(), 3);
PackageHeader header = getHeaderBlock(); PackageHeader header = getHeaderBlock();
this.mTypeStringPool=new TypeStringPool(false, header.getTypeIdOffset()); this.mTypeStringPool=new TypeStringPool(false, header.getTypeIdOffsetItem());
this.mSpecStringPool=new SpecStringPool(true); this.mSpecStringPool=new SpecStringPool(true);
this.mBody = new PackageBody(); this.mBody = new PackageBody();
@ -62,6 +63,34 @@ package com.reandroid.arsc.chunk;
addChild(mSpecStringPool); addChild(mSpecStringPool);
addChild(mBody); addChild(mBody);
} }
public EntryBlock getOrCreate(String qualifiers, String type, String name){
ResConfig resConfig = new ResConfig();
resConfig.parseQualifiers(qualifiers);
return getOrCreate(resConfig, type, name);
}
public EntryBlock getOrCreate(ResConfig resConfig, String type, String name){
SpecTypePair specTypePair = getOrCreateSpecType(type);
TypeBlock typeBlock = specTypePair.getOrCreateTypeBlock(resConfig);
return typeBlock.getOrCreateEntry(name);
}
public SpecTypePair getOrCreateSpecType(String type){
int last = 0;
for(SpecTypePair specTypePair:listAllSpecTypePair()){
if(type.equals(specTypePair.getTypeName())){
return specTypePair;
}
int id = specTypePair.getId();
if(id>last){
last=id;
}
}
last++;
getTypeStringPool().getOrCreate(last, type);
return getSpecTypePairArray().getOrCreate((byte) last);
}
public int getTypeIdOffset(){
return getHeaderBlock().getTypeIdOffset();
}
public BlockList<UnknownChunk> getUnknownChunkList(){ public BlockList<UnknownChunk> getUnknownChunkList(){
return mBody.getUnknownChunkList(); return mBody.getUnknownChunkList();
} }
@ -270,7 +299,7 @@ package com.reandroid.arsc.chunk;
//int largest=getSpecTypePairArray().getHighestTypeId(); //int largest=getSpecTypePairArray().getHighestTypeId();
//int count=getTypeStringPool().countStrings(); //int count=getTypeStringPool().countStrings();
//getHeaderBlock().getTypeIdOffset().set(count-largest); //getHeaderBlock().getTypeIdOffset().set(count-largest);
getHeaderBlock().getTypeIdOffset().set(0); getHeaderBlock().getTypeIdOffsetItem().set(0);
} }
public void onEntryAdded(EntryBlock entryBlock){ public void onEntryAdded(EntryBlock entryBlock){
updateEntry(entryBlock); updateEntry(entryBlock);

View File

@ -42,14 +42,15 @@
public byte getTypeId(){ public byte getTypeId(){
return getHeaderBlock().getId().get(); return getHeaderBlock().getId().get();
} }
public int getTypeIdInt(){ public int getId(){
return getHeaderBlock().getId().unsignedInt(); return getHeaderBlock().getId().unsignedInt();
} }
public void setTypeId(int id){ public void setId(int id){
setTypeId((byte) (0xff & id)); setTypeId((byte) (0xff & id));
} }
public void setTypeId(byte id){ public void setTypeId(byte id){
getHeaderBlock().getId().set(id); getHeaderBlock().getId().set(id);
getTypeBlockArray().setTypeId(id);
} }
public TypeBlockArray getTypeBlockArray(){ public TypeBlockArray getTypeBlockArray(){
SpecTypePair specTypePair=getSpecTypePair(); SpecTypePair specTypePair=getSpecTypePair();
@ -94,12 +95,12 @@
@Override @Override
public JSONObject toJson() { public JSONObject toJson() {
JSONObject jsonObject=new JSONObject(); JSONObject jsonObject=new JSONObject();
jsonObject.put(TypeBlock.NAME_id, getTypeIdInt()); jsonObject.put(TypeBlock.NAME_id, getId());
return jsonObject; return jsonObject;
} }
@Override @Override
public void fromJson(JSONObject json) { public void fromJson(JSONObject json) {
setTypeId(json.getInt(TypeBlock.NAME_id)); setId(json.getInt(TypeBlock.NAME_id));
} }
} }

View File

@ -22,6 +22,7 @@ import com.reandroid.arsc.header.HeaderBlock;
import com.reandroid.arsc.header.InfoHeader; import com.reandroid.arsc.header.InfoHeader;
import com.reandroid.arsc.header.TableHeader; import com.reandroid.arsc.header.TableHeader;
import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.io.BlockReader;
import com.reandroid.arsc.pool.StringPool;
import com.reandroid.arsc.pool.TableStringPool; import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.arsc.value.StagedAliasEntry; import com.reandroid.arsc.value.StagedAliasEntry;
import com.reandroid.common.Frameworks; import com.reandroid.common.Frameworks;
@ -34,7 +35,8 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class TableBlock extends Chunk<TableHeader> implements JSONConvert<JSONObject> { public class TableBlock extends Chunk<TableHeader>
implements MainChunk, JSONConvert<JSONObject> {
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<>();
@ -55,6 +57,10 @@ public class TableBlock extends Chunk<TableHeader> implements JSONConvert<JSONOb
public Collection<PackageBlock> listPackages(){ public Collection<PackageBlock> listPackages(){
return getPackageArray().listItems(); return getPackageArray().listItems();
} }
@Override
public TableStringPool getStringPool() {
return mTableStringPool;
}
public TableStringPool getTableStringPool(){ public TableStringPool getTableStringPool(){
return mTableStringPool; return mTableStringPool;
} }

View File

@ -25,6 +25,7 @@ import com.reandroid.arsc.item.*;
import com.reandroid.arsc.pool.TypeStringPool; import com.reandroid.arsc.pool.TypeStringPool;
import com.reandroid.arsc.value.EntryBlock; import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResConfig; import com.reandroid.arsc.value.ResConfig;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONObject; import com.reandroid.json.JSONObject;
@ -81,16 +82,16 @@ public class TypeBlock extends Chunk<TypeHeader>
return null; return null;
} }
TypeStringPool typeStringPool=packageBlock.getTypeStringPool(); TypeStringPool typeStringPool=packageBlock.getTypeStringPool();
mTypeString=typeStringPool.getById(getTypeIdInt()); mTypeString=typeStringPool.getById(getId());
return mTypeString; return mTypeString;
} }
public byte getTypeId(){ public byte getTypeId(){
return getHeaderBlock().getId().get(); return getHeaderBlock().getId().get();
} }
public int getTypeIdInt(){ public int getId(){
return getHeaderBlock().getId().unsignedInt(); return getHeaderBlock().getId().unsignedInt();
} }
public void setTypeId(int id){ public void setId(int id){
setTypeId((byte) (0xff & id)); setTypeId((byte) (0xff & id));
} }
public void setTypeId(byte id){ public void setTypeId(byte id){
@ -98,7 +99,7 @@ public class TypeBlock extends Chunk<TypeHeader>
} }
public void setTypeName(String name){ public void setTypeName(String name){
TypeStringPool typeStringPool=getTypeStringPool(); TypeStringPool typeStringPool=getTypeStringPool();
int id=getTypeIdInt(); int id= getId();
TypeString typeString=typeStringPool.getById(id); TypeString typeString=typeStringPool.getById(id);
if(typeString==null){ if(typeString==null){
typeString=typeStringPool.getOrCreate(id, name); typeString=typeStringPool.getOrCreate(id, name);
@ -162,6 +163,29 @@ public class TypeBlock extends Chunk<TypeHeader>
} }
entryBlock.setNull(true); entryBlock.setNull(true);
} }
public EntryBlock getOrCreateEntry(String name){
for(EntryBlock entryBlock:getEntryBlockArray().listItems()){
if(name.equals(entryBlock.getName())){
return entryBlock;
}
}
SpecTypePair specTypePair = getParentSpecTypePair();
EntryBlock exist=specTypePair.getAnyEntry(name);
int id;
if(exist!=null){
id=exist.getIndex();
}else {
id = specTypePair.getHighestEntryCount();
}
SpecString specString = getPackageBlock()
.getSpecStringPool().getOrCreate(name);
EntryBlock entryBlock = getOrCreateEntry((short) id);
if(entryBlock.isNull()){
entryBlock.setValueAsRaw(ValueType.NULL, 0);
}
entryBlock.setSpecReference(specString.getIndex());
return entryBlock;
}
public EntryBlock getOrCreateEntry(short entryId){ public EntryBlock getOrCreateEntry(short entryId){
return getEntryBlockArray().getOrCreate(entryId); return getEntryBlockArray().getOrCreate(entryId);
} }
@ -219,7 +243,7 @@ public class TypeBlock extends Chunk<TypeHeader>
@Override @Override
public JSONObject toJson() { public JSONObject toJson() {
JSONObject jsonObject=new JSONObject(); JSONObject jsonObject=new JSONObject();
jsonObject.put(NAME_id, getTypeIdInt()); jsonObject.put(NAME_id, getId());
jsonObject.put(NAME_name, getTypeName()); jsonObject.put(NAME_name, getTypeName());
jsonObject.put(NAME_config, getResConfig().toJson()); jsonObject.put(NAME_config, getResConfig().toJson());
jsonObject.put(NAME_entries, getEntryBlockArray().toJson()); jsonObject.put(NAME_entries, getEntryBlockArray().toJson());
@ -227,7 +251,7 @@ public class TypeBlock extends Chunk<TypeHeader>
} }
@Override @Override
public void fromJson(JSONObject json) { public void fromJson(JSONObject json) {
setTypeId(json.getInt(NAME_id)); setId(json.getInt(NAME_id));
String name = json.optString(NAME_name); String name = json.optString(NAME_name);
if(name!=null){ if(name!=null){
setTypeName(name); setTypeName(name);
@ -250,8 +274,8 @@ public class TypeBlock extends Chunk<TypeHeader>
} }
@Override @Override
public int compareTo(TypeBlock typeBlock) { public int compareTo(TypeBlock typeBlock) {
int id1=getTypeIdInt(); int id1= getId();
int id2=typeBlock.getTypeIdInt(); int id2=typeBlock.getId();
if(id1!=id2){ if(id1!=id2){
return Integer.compare(id1, id2); return Integer.compare(id1, id2);
} }

View File

@ -17,6 +17,7 @@
import com.reandroid.arsc.chunk.Chunk; import com.reandroid.arsc.chunk.Chunk;
import com.reandroid.arsc.chunk.ChunkType; import com.reandroid.arsc.chunk.ChunkType;
import com.reandroid.arsc.chunk.MainChunk;
import com.reandroid.arsc.container.SingleBlockContainer; import com.reandroid.arsc.container.SingleBlockContainer;
import com.reandroid.arsc.header.HeaderBlock; import com.reandroid.arsc.header.HeaderBlock;
import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.io.BlockReader;
@ -36,7 +37,8 @@
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public class ResXmlDocument extends Chunk<HeaderBlock> implements JSONConvert<JSONObject> { public class ResXmlDocument extends Chunk<HeaderBlock>
implements MainChunk, JSONConvert<JSONObject> {
private final ResXmlStringPool mResXmlStringPool; private final ResXmlStringPool mResXmlStringPool;
private final ResXmlIDMap mResXmlIDMap; private final ResXmlIDMap mResXmlIDMap;
private ResXmlElement mResXmlElement; private ResXmlElement mResXmlElement;
@ -160,6 +162,7 @@
} }
return false; return false;
} }
@Override
public ResXmlStringPool getStringPool(){ public ResXmlStringPool getStringPool(){
return mResXmlStringPool; return mResXmlStringPool;
} }

View File

@ -53,6 +53,15 @@ public class SpecTypePair extends BlockContainer<Block>
public SpecTypePair(){ public SpecTypePair(){
this(new SpecBlock(), new TypeBlockArray()); this(new SpecBlock(), new TypeBlockArray());
} }
public EntryBlock getAnyEntry(String name){
for(TypeBlock typeBlock:listTypeBlocks()){
EntryBlock entryBlock=typeBlock.searchByEntryName(name);
if(entryBlock!=null){
return entryBlock;
}
}
return null;
}
public void sortTypes(){ public void sortTypes(){
getTypeBlockArray().sort(); getTypeBlockArray().sort();
} }
@ -74,6 +83,9 @@ public class SpecTypePair extends BlockContainer<Block>
public TypeBlock getOrCreateTypeBlock(String qualifiers){ public TypeBlock getOrCreateTypeBlock(String qualifiers){
return getTypeBlockArray().getOrCreate(qualifiers); return getTypeBlockArray().getOrCreate(qualifiers);
} }
public TypeBlock getOrCreateTypeBlock(ResConfig resConfig){
return getTypeBlockArray().getOrCreate(resConfig);
}
public TypeBlock getTypeBlock(String qualifiers){ public TypeBlock getTypeBlock(String qualifiers){
return getTypeBlockArray().getTypeBlock(qualifiers); return getTypeBlockArray().getTypeBlock(qualifiers);
} }
@ -84,8 +96,8 @@ public class SpecTypePair extends BlockContainer<Block>
public byte getTypeId(){ public byte getTypeId(){
return mSpecBlock.getTypeId(); return mSpecBlock.getTypeId();
} }
public int getTypeIdInt(){ public int getId(){
return mSpecBlock.getTypeIdInt(); return mSpecBlock.getId();
} }
public void setTypeId(byte id){ public void setTypeId(byte id){
mSpecBlock.setTypeId(id); mSpecBlock.setTypeId(id);
@ -177,13 +189,17 @@ public class SpecTypePair extends BlockContainer<Block>
return typeEntryCount; return typeEntryCount;
} }
public TypeString getTypeString(){ public TypeString getTypeString(){
return getTypeBlockArray().getTypeString(); PackageBlock packageBlock = getPackageBlock();
if(packageBlock!=null){
return packageBlock.getTypeStringPool().getById(getId());
}
return null;
} }
@Override @Override
public JSONObject toJson() { public JSONObject toJson() {
JSONObject jsonObject=new JSONObject(); JSONObject jsonObject=new JSONObject();
jsonObject.put("id", getSpecBlock().getTypeIdInt()); jsonObject.put("id", getSpecBlock().getId());
jsonObject.put("types", getTypeBlockArray().toJson()); jsonObject.put("types", getTypeBlockArray().toJson());
return jsonObject; return jsonObject;
} }
@ -204,7 +220,7 @@ public class SpecTypePair extends BlockContainer<Block>
} }
@Override @Override
public int compareTo(SpecTypePair specTypePair) { public int compareTo(SpecTypePair specTypePair) {
return Integer.compare(getTypeIdInt(), specTypePair.getTypeIdInt()); return Integer.compare(getId(), specTypePair.getId());
} }
@Override @Override
public String toString(){ public String toString(){

View File

@ -72,9 +72,19 @@ public class PackageHeader extends HeaderBlock{
public IntegerItem getSpecStringPoolCount() { public IntegerItem getSpecStringPoolCount() {
return specStringPoolCount; return specStringPoolCount;
} }
public IntegerItem getTypeIdOffset() { public IntegerItem getTypeIdOffsetItem() {
return typeIdOffset; return typeIdOffset;
} }
public void setTypeIdOffset(int offset){
typeIdOffset.set(offset);
typeIdOffsetContainer.setItem(typeIdOffset);
}
public int getTypeIdOffset() {
if(typeIdOffset.getParent()==null){
typeIdOffset.set(0);
}
return typeIdOffset.get();
}
@Override @Override
void onHeaderSizeLoaded(int size){ void onHeaderSizeLoaded(int size){
super.onHeaderSizeLoaded(size); super.onHeaderSizeLoaded(size);

View File

@ -47,6 +47,16 @@ import java.io.*;
public BlockReader(File file) throws IOException { public BlockReader(File file) throws IOException {
this(loadBuffer(file)); this(loadBuffer(file));
} }
public int readUnsignedShort() throws IOException {
return 0x0000ffff & readShort();
}
public short readShort() throws IOException {
int pos = getPosition();
byte[] bts = new byte[2];
readFully(bts);
seek(pos);
return toShort(bts, 0);
}
public InfoHeader readHeaderBlock() throws IOException { public InfoHeader readHeaderBlock() throws IOException {
InfoHeader infoHeader = new InfoHeader(); InfoHeader infoHeader = new InfoHeader();
if(available() < infoHeader.countBytes()){ if(available() < infoHeader.countBytes()){
@ -80,6 +90,10 @@ import java.io.*;
(bts[offset+2] & 0xff) << 16 | (bts[offset+2] & 0xff) << 16 |
(bts[offset+3] & 0xff) << 24; (bts[offset+3] & 0xff) << 24;
} }
private short toShort(byte[] bts, int offset){
return (short) (bts[offset] & 0xff |
(bts[offset+1] & 0xff) << 8);
}
public byte[] getBytes(){ public byte[] getBytes(){
int len = length(); int len = length();
if(this.BUFFER.length == len){ if(this.BUFFER.length == len){

View File

@ -48,7 +48,7 @@ public abstract class BlockItem extends Block {
final void setBytesLength(int length){ final void setBytesLength(int length){
setBytesLength(length, true); setBytesLength(length, true);
} }
final void setBytesLength(int length, boolean notify){ protected final void setBytesLength(int length, boolean notify){
if(length<0){ if(length<0){
length=0; length=0;
} }
@ -122,4 +122,30 @@ public abstract class BlockItem extends Block {
super.notifyBlockLoad(); super.notifyBlockLoad();
return bts.length; return bts.length;
} }
protected static int getInteger(byte[] bts, int offset){
if((offset+4)>bts.length){
return 0;
}
return bts[offset] & 0xff |
(bts[offset+1] & 0xff) << 8 |
(bts[offset+2] & 0xff) << 16 |
(bts[offset+3] & 0xff) << 24;
}
protected static short getShort(byte[] bts, int offset){
return (short) (bts[offset] & 0xff | (bts[offset+1] & 0xff) << 8);
}
protected static void putInteger(byte[] bts, int offset, int val){
if((offset+4)>bts.length){
return;
}
bts[offset+3]= (byte) (val >>> 24 & 0xff);
bts[offset+2]= (byte) (val >>> 16 & 0xff);
bts[offset+1]= (byte) (val >>> 8 & 0xff);
bts[offset]= (byte) (val & 0xff);
}
protected static void putShort(byte[] bts, int offset, short val){
bts[offset+1]= (byte) (val >>> 8 & 0xff);
bts[offset]= (byte) (val & 0xff);
}
} }

View File

@ -105,6 +105,9 @@ public class ByteArray extends BlockItem {
} }
public final void putInteger(int offset, int val){ public final void putInteger(int offset, int val){
byte[] bts = getBytesInternal(); byte[] bts = getBytesInternal();
if((offset+4)>bts.length){
return;
}
bts[offset+3]= (byte) (val >>> 24 & 0xff); bts[offset+3]= (byte) (val >>> 24 & 0xff);
bts[offset+2]= (byte) (val >>> 16 & 0xff); bts[offset+2]= (byte) (val >>> 16 & 0xff);
bts[offset+1]= (byte) (val >>> 8 & 0xff); bts[offset+1]= (byte) (val >>> 8 & 0xff);
@ -112,6 +115,9 @@ public class ByteArray extends BlockItem {
} }
public final int getInteger(int offset){ public final int getInteger(int offset){
byte[] bts = getBytesInternal(); byte[] bts = getBytesInternal();
if((offset+4)>bts.length){
return 0;
}
return bts[offset] & 0xff | return bts[offset] & 0xff |
(bts[offset+1] & 0xff) << 8 | (bts[offset+1] & 0xff) << 8 |
(bts[offset+2] & 0xff) << 16 | (bts[offset+2] & 0xff) << 16 |

View File

@ -17,7 +17,7 @@ package com.reandroid.arsc.item;
import com.reandroid.arsc.base.Block; import com.reandroid.arsc.base.Block;
import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.io.BlockReader;
import com.reandroid.arsc.pool.BaseStringPool; import com.reandroid.arsc.pool.StringPool;
import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONObject; import com.reandroid.json.JSONObject;
@ -212,18 +212,18 @@ public class StringItem extends BlockItem implements JSONConvert<JSONObject> {
return styleItem.getSpanInfoList().size()>0; return styleItem.getSpanInfoList().size()>0;
} }
public StyleItem getStyle(){ public StyleItem getStyle(){
BaseStringPool<?> stringPool=getStringPool(); StringPool<?> stringPool=getStringPool();
if(stringPool==null){ if(stringPool==null){
return null; return null;
} }
int index=getIndex(); int index=getIndex();
return stringPool.getStyle(index); return stringPool.getStyle(index);
} }
private BaseStringPool<?> getStringPool(){ private StringPool<?> getStringPool(){
Block parent=getParent(); Block parent=getParent();
while (parent!=null){ while (parent!=null){
if(parent instanceof BaseStringPool){ if(parent instanceof StringPool){
return (BaseStringPool<?>)parent; return (StringPool<?>)parent;
} }
parent=parent.getParent(); parent=parent.getParent();
} }

View File

@ -18,7 +18,7 @@ package com.reandroid.arsc.item;
import com.reandroid.arsc.base.Block; import com.reandroid.arsc.base.Block;
import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.io.BlockReader;
import com.reandroid.arsc.model.StyleSpanInfo; import com.reandroid.arsc.model.StyleSpanInfo;
import com.reandroid.arsc.pool.BaseStringPool; import com.reandroid.arsc.pool.StringPool;
import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONArray; import com.reandroid.json.JSONArray;
import com.reandroid.json.JSONObject; import com.reandroid.json.JSONObject;
@ -64,7 +64,7 @@ public class StyleItem extends IntegerArray implements JSONConvert<JSONObject> {
super.put(i, val); super.put(i, val);
} }
public void addStylePiece(String tag, int firstChar, int lastChar){ public void addStylePiece(String tag, int firstChar, int lastChar){
BaseStringPool<?> stringPool = getStringPool(); StringPool<?> stringPool = getStringPool();
if(stringPool==null){ if(stringPool==null){
throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first"); throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first");
} }
@ -188,7 +188,7 @@ public class StyleItem extends IntegerArray implements JSONConvert<JSONObject> {
return mSpanInfoList; return mSpanInfoList;
} }
private String getStringFromPool(int ref){ private String getStringFromPool(int ref){
BaseStringPool<?> stringPool = getStringPool(); StringPool<?> stringPool = getStringPool();
if(stringPool==null){ if(stringPool==null){
return null; return null;
} }
@ -198,11 +198,11 @@ public class StyleItem extends IntegerArray implements JSONConvert<JSONObject> {
} }
return stringItem.get(); return stringItem.get();
} }
private BaseStringPool<?> getStringPool(){ private StringPool<?> getStringPool(){
Block parent=getParent(); Block parent=getParent();
while (parent!=null){ while (parent!=null){
if(parent instanceof BaseStringPool){ if(parent instanceof StringPool){
return (BaseStringPool<?>)parent; return (StringPool<?>)parent;
} }
parent=parent.getParent(); parent=parent.getParent();
} }
@ -310,7 +310,7 @@ public class StyleItem extends IntegerArray implements JSONConvert<JSONObject> {
public void addSpanInfo(String tag, int first, int last){ public void addSpanInfo(String tag, int first, int last){
int index=getStylePieceCount(); int index=getStylePieceCount();
setStylePieceCount(index+1); setStylePieceCount(index+1);
BaseStringPool<?> stringPool = getStringPool(); StringPool<?> stringPool = getStringPool();
if(stringPool==null){ if(stringPool==null){
throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first"); throw new IllegalArgumentException("Null string pool, must be added to parent StyleArray first");
} }

View File

@ -23,13 +23,13 @@ package com.reandroid.arsc.item;
public TypeString(boolean utf8) { public TypeString(boolean utf8) {
super(utf8); super(utf8);
} }
public byte getId(){ public int getId(){
TypeStringPool stringPool=getTypeStringPool(); TypeStringPool stringPool=getTypeStringPool();
if(stringPool!=null){ if(stringPool!=null){
return stringPool.idOf(this); return stringPool.idOf(this);
} }
// Should not reach here , this means it not added to string pool // Should not reach here , this means it not added to string pool
return (byte) (getIndex()+1); return getIndex()+1;
} }
@Override @Override
public StyleItem getStyle(){ public StyleItem getStyle(){

View File

@ -475,7 +475,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
return 0; return 0;
} }
int pkgId=packageBlock.getId(); int pkgId=packageBlock.getId();
int typeId=typeBlock.getTypeIdInt(); int typeId=typeBlock.getId();
int entryId=getIndex(); int entryId=getIndex();
return ((pkgId << 24) | (typeId << 16) | entryId); return ((pkgId << 24) | (typeId << 16) | entryId);
} }
@ -607,7 +607,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
if(isNull()){ if(isNull()){
return; return;
} }
counter.addCount(countBytes()); //counter.addCount(countBytes());
entryHeader.onCountUpTo(counter); entryHeader.onCountUpTo(counter);
mSpecReference.onCountUpTo(counter); mSpecReference.onCountUpTo(counter);
mResValue.onCountUpTo(counter); mResValue.onCountUpTo(counter);
@ -712,7 +712,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
mResValue.onDataLoaded(); mResValue.onDataLoaded();
} }
public void merge(EntryBlock entryBlock){ public void merge(EntryBlock entryBlock){
if(entryBlock==null||entryBlock==this||entryBlock.isNull()){ if(!shouldMerge(entryBlock)){
return; return;
} }
String name=entryBlock.getName(); String name=entryBlock.getName();
@ -736,6 +736,27 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
setPublic(entryBlock.isPublic()); setPublic(entryBlock.isPublic());
setWeak(entryBlock.isWeak()); setWeak(entryBlock.isWeak());
} }
private boolean shouldMerge(EntryBlock coming){
if(coming == null || coming == this || coming.isNull()){
return false;
}
if(this.isNull()){
return true;
}
BaseResValue value = this.getResValue();
if(value instanceof ResValueInt){
ValueType valueType = ((ResValueInt)value).getValueType();
if(valueType==null || valueType==ValueType.NULL){
return true;
}
}
value = coming.getResValue();
if(value instanceof ResValueInt){
ValueType valueType = ((ResValueInt)value).getValueType();
return valueType!=null && valueType != ValueType.NULL;
}
return true;
}
private ResValueBag getOrCreateResValueBag(){ private ResValueBag getOrCreateResValueBag(){
if(mResValue instanceof ResValueBag){ if(mResValue instanceof ResValueBag){
return (ResValueBag) mResValue; return (ResValueBag) mResValue;

View File

@ -166,7 +166,7 @@ public class ResValueBag extends BaseResValue {
refreshCount(); refreshCount();
} }
public void merge(ResValueBag resValueBag){ public void merge(ResValueBag resValueBag){
if(resValueBag==null||resValueBag==this){ if(resValueBag==null || resValueBag==this || resValueBag.getCount()==0){
return; return;
} }
setParentId(resValueBag.getParentId()); setParentId(resValueBag.getParentId());

View File

@ -228,6 +228,8 @@ public class ResValueBagItem extends BaseResValueItem{
}else { }else {
builder.append("Unknown"); builder.append("Unknown");
} }
builder.append(" size=").append(getHeaderSize());
builder.append(" bytes=").append(countBytes());
builder.append('('); builder.append('(');
builder.append(String.format("0x%02x", getType())); builder.append(String.format("0x%02x", getType()));
builder.append(") id="); builder.append(") id=");