separate spec and type

This commit is contained in:
REAndroid 2023-01-10 14:45:32 -05:00
parent 14eb36d3b4
commit dbfb08700f
4 changed files with 248 additions and 230 deletions

View File

@ -1,153 +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.chunk;
import com.reandroid.lib.arsc.base.Block;
import com.reandroid.lib.arsc.container.SpecTypePair;
import com.reandroid.lib.arsc.item.ByteItem;
import com.reandroid.lib.arsc.item.IntegerItem;
import com.reandroid.lib.arsc.item.TypeString;
import com.reandroid.lib.arsc.pool.TypeStringPool;
abstract class BaseTypeBlock extends BaseChunk {
private final ByteItem mTypeId;
private final ByteItem mTypeFlags;
private final ByteItem mReserved1;
private final ByteItem mReserved2;
private final IntegerItem mEntryCount;
private TypeString mTypeString;
BaseTypeBlock(ChunkType chunkType, int initialChildesCount) {
super(chunkType, initialChildesCount);
this.mTypeId=new ByteItem();
this.mTypeFlags=new ByteItem();
this.mReserved1=new ByteItem();
this.mReserved2=new ByteItem();
this.mEntryCount=new IntegerItem();
addToHeader(mTypeId);
addToHeader(mTypeFlags);
addToHeader(mReserved1);
addToHeader(mReserved2);
addToHeader(mEntryCount);
}
public byte getTypeId(){
return mTypeId.get();
}
public int getTypeIdInt(){
return (0xff & mTypeId.get());
}
public void setTypeId(int id){
setTypeId((byte) (0xff & id));
}
public void setTypeId(byte id){
mTypeId.set(id);
}
public void setTypeName(String name){
TypeStringPool typeStringPool=getTypeStringPool();
int id=getTypeIdInt();
TypeString typeString=typeStringPool.getById(id);
if(typeString==null){
typeString=typeStringPool.getOrCreate(id, name);
}
typeString.set(name);
}
public void setEntryCount(int count){
if(count == mEntryCount.get()){
return;
}
mEntryCount.set(count);
onSetEntryCount(count);
}
public int getEntryCount(){
return mEntryCount.get();
}
public PackageBlock getPackageBlock(){
Block parent=getParent();
while (parent!=null){
if(parent instanceof SpecTypePair){
return ((SpecTypePair)parent).getPackageBlock();
}
parent=parent.getParent();
}
return null;
}
public String getTypeName(){
TypeString typeString=getTypeString();
if(typeString==null){
return null;
}
return typeString.get();
}
public TypeString getTypeString(){
if(mTypeString!=null){
if(mTypeString.getId()==getTypeId()){
return mTypeString;
}
mTypeString=null;
}
PackageBlock packageBlock=getPackageBlock();
if(packageBlock==null){
return null;
}
TypeStringPool typeStringPool=packageBlock.getTypeStringPool();
mTypeString=typeStringPool.getById(getTypeIdInt());
return mTypeString;
}
SpecTypePair getSpecTypePair(){
Block parent=getParent();
while (parent!=null){
if(parent instanceof SpecTypePair){
return (SpecTypePair)parent;
}
parent=parent.getParent();
}
return null;
}
abstract void onSetEntryCount(int count);
IntegerItem getEntryCountBlock(){
return mEntryCount;
}
private TypeStringPool getTypeStringPool(){
PackageBlock packageBlock=getPackageBlock();
if(packageBlock!=null){
return packageBlock.getTypeStringPool();
}
return null;
}
@Override
public String toString(){
StringBuilder builder=new StringBuilder();
builder.append(getClass().getSimpleName());
builder.append(": ");
PackageBlock packageBlock=getPackageBlock();
if(packageBlock!=null){
builder.append("PKG=");
builder.append(String.format("0x%02x", packageBlock.getId()));
builder.append(" ");
}
builder.append(getHeaderBlock().toString());
builder.append(" entries=");
builder.append(getEntryCount());
builder.append(", id=");
builder.append(String.format("0x%02x", getTypeId()));
TypeString typeString=getTypeString();
if(typeString!=null){
builder.append('(');
builder.append(typeString.get());
builder.append(')');
}
return builder.toString();
}
}

View File

@ -13,28 +13,51 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.reandroid.lib.arsc.chunk; package com.reandroid.lib.arsc.chunk;
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.io.BlockLoad; import com.reandroid.lib.arsc.item.*;
import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.json.JSONConvert;
import com.reandroid.lib.arsc.item.IntegerArray; import com.reandroid.lib.json.JSONObject;
import com.reandroid.lib.arsc.item.IntegerItem;
import com.reandroid.lib.json.JSONConvert;
import com.reandroid.lib.json.JSONObject;
import java.io.IOException; import java.util.List;
public class SpecBlock extends BaseTypeBlock implements BlockLoad , JSONConvert<JSONObject> { public class SpecBlock extends BaseChunk implements JSONConvert<JSONObject> {
private final IntegerArray mOffsets; private final SpecFlagsArray specFlagsArray;
private final ByteItem mTypeId;
public SpecBlock() { public SpecBlock() {
super(ChunkType.SPEC, 1); super(ChunkType.SPEC, 1);
this.mOffsets=new IntegerArray(); this.mTypeId=new ByteItem();
addChild(mOffsets); ByteItem res0 = new ByteItem();
ShortItem res1 = new ShortItem();
IntegerItem entryCount = new IntegerItem();
this.specFlagsArray = new SpecFlagsArray(entryCount);
addToHeader(mTypeId);
addToHeader(res0);
addToHeader(res1);
addToHeader(entryCount);
getEntryCountBlock().setBlockLoad(this); addChild(specFlagsArray);
}
public SpecFlagsArray getSpecFlagsArray(){
return specFlagsArray;
}
public List<Integer> listSpecFlags(){
return specFlagsArray.toList();
}
public byte getTypeId(){
return mTypeId.get();
}
public int getTypeIdInt(){
return (0xff & mTypeId.get());
}
public void setTypeId(int id){
setTypeId((byte) (0xff & id));
}
public void setTypeId(byte id){
mTypeId.set(id);
} }
public TypeBlockArray getTypeBlockArray(){ public TypeBlockArray getTypeBlockArray(){
SpecTypePair specTypePair=getSpecTypePair(); SpecTypePair specTypePair=getSpecTypePair();
@ -43,19 +66,26 @@ public class SpecBlock extends BaseTypeBlock implements BlockLoad , JSONConvert<
} }
return null; return null;
} }
@Override SpecTypePair getSpecTypePair(){
void onSetEntryCount(int count) { Block parent=getParent();
mOffsets.setSize(count); while (parent!=null){
if(parent instanceof SpecTypePair){
return (SpecTypePair)parent;
}
parent=parent.getParent();
}
return null;
}
public int getEntryCount() {
return specFlagsArray.size();
}
public void setEntryCount(int count){
specFlagsArray.setSize(count);
specFlagsArray.refresh();
} }
@Override @Override
protected void onChunkRefreshed() { protected void onChunkRefreshed() {
} specFlagsArray.refresh();
@Override
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
IntegerItem entryCount=getEntryCountBlock();
if(sender==entryCount){
mOffsets.setSize(entryCount.get());
}
} }
@Override @Override
public String toString(){ public String toString(){
@ -80,4 +110,4 @@ public class SpecBlock extends BaseTypeBlock implements BlockLoad , JSONConvert<
public void fromJson(JSONObject json) { public void fromJson(JSONObject json) {
setTypeId(json.getInt(TypeBlock.NAME_id)); setTypeId(json.getInt(TypeBlock.NAME_id));
} }
} }

View File

@ -19,9 +19,10 @@ 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.item.IntegerArray; import com.reandroid.lib.arsc.io.BlockLoad;
import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.io.BlockReader;
import com.reandroid.lib.arsc.item.TypeString; import com.reandroid.lib.arsc.item.*;
import com.reandroid.lib.arsc.pool.TypeStringPool;
import com.reandroid.lib.arsc.value.EntryBlock; import com.reandroid.lib.arsc.value.EntryBlock;
import com.reandroid.lib.arsc.value.ResConfig; import com.reandroid.lib.arsc.value.ResConfig;
import com.reandroid.lib.json.JSONConvert; import com.reandroid.lib.json.JSONConvert;
@ -33,25 +34,105 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class TypeBlock extends BaseTypeBlock public class TypeBlock extends BaseChunk
implements JSONConvert<JSONObject>, Comparable<TypeBlock> { implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
private final IntegerItem mEntriesStart; private final ByteItem mTypeId;
private final ByteItem mTypeFlags;
private final IntegerItem mEntryCount;
private final ResConfig mResConfig; private final ResConfig mResConfig;
private final IntegerArray mEntryOffsets;
private final EntryBlockArray mEntryArray; private final EntryBlockArray mEntryArray;
private TypeString mTypeString;
public TypeBlock() { public TypeBlock() {
super(ChunkType.TYPE, 2); super(ChunkType.TYPE, 2);
this.mEntriesStart=new IntegerItem(); this.mTypeId=new ByteItem();
this.mResConfig =new ResConfig(); this.mTypeFlags=new ByteItem();
this.mEntryOffsets=new IntegerArray(); ShortItem reserved = new ShortItem();
this.mEntryArray=new EntryBlockArray(mEntryOffsets, getEntryCountBlock(), mEntriesStart); this.mEntryCount=new IntegerItem();
addToHeader(mEntriesStart); IntegerItem entriesStart = new IntegerItem();
this.mResConfig =new ResConfig();
IntegerArray entryOffsets = new IntegerArray();
this.mEntryArray = new EntryBlockArray(entryOffsets, mEntryCount, entriesStart);
mTypeFlags.setBlockLoad(this);
addToHeader(mTypeId);
addToHeader(mTypeFlags);
addToHeader(reserved);
addToHeader(mEntryCount);
addToHeader(entriesStart);
addToHeader(mResConfig); addToHeader(mResConfig);
addChild(mEntryOffsets); addChild(entryOffsets);
addChild(mEntryArray); addChild(mEntryArray);
} }
public PackageBlock getPackageBlock(){
Block parent=getParent();
while (parent!=null){
if(parent instanceof SpecTypePair){
return ((SpecTypePair)parent).getPackageBlock();
}
parent=parent.getParent();
}
return null;
}
public String getTypeName(){
TypeString typeString=getTypeString();
if(typeString==null){
return null;
}
return typeString.get();
}
public TypeString getTypeString(){
if(mTypeString!=null){
if(mTypeString.getId()==getTypeId()){
return mTypeString;
}
mTypeString=null;
}
PackageBlock packageBlock=getPackageBlock();
if(packageBlock==null){
return null;
}
TypeStringPool typeStringPool=packageBlock.getTypeStringPool();
mTypeString=typeStringPool.getById(getTypeIdInt());
return mTypeString;
}
public byte getTypeId(){
return mTypeId.get();
}
public int getTypeIdInt(){
return (0xff & mTypeId.get());
}
public void setTypeId(int id){
setTypeId((byte) (0xff & id));
}
public void setTypeId(byte id){
mTypeId.set(id);
}
public void setTypeName(String name){
TypeStringPool typeStringPool=getTypeStringPool();
int id=getTypeIdInt();
TypeString typeString=typeStringPool.getById(id);
if(typeString==null){
typeString=typeStringPool.getOrCreate(id, name);
}
typeString.set(name);
}
private TypeStringPool getTypeStringPool(){
PackageBlock packageBlock=getPackageBlock();
if(packageBlock!=null){
return packageBlock.getTypeStringPool();
}
return null;
}
public void setEntryCount(int count){
if(count == mEntryCount.get()){
return;
}
mEntryCount.set(count);
onSetEntryCount(count);
}
public boolean isEmpty(){ public boolean isEmpty(){
return getEntryBlockArray().isEmpty(); return getEntryBlockArray().isEmpty();
} }
@ -121,8 +202,8 @@ public class TypeBlock extends BaseTypeBlock
public EntryBlock getEntryBlock(int entryId){ public EntryBlock getEntryBlock(int entryId){
return getEntryBlockArray().get(entryId); return getEntryBlockArray().get(entryId);
} }
@Override
void onSetEntryCount(int count) { private void onSetEntryCount(int count) {
getEntryBlockArray().setChildesCount(count); getEntryBlockArray().setChildesCount(count);
} }
@Override @Override
@ -198,6 +279,14 @@ public class TypeBlock extends BaseTypeBlock
return getEntryBlockArray().searchByEntryName(entryName); return getEntryBlockArray().searchByEntryName(entryName);
} }
@Override @Override
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
if(sender==mTypeFlags){
if(mTypeFlags.get()==0x1){
//ResTable_sparseTypeEntry ?
}
}
}
@Override
public String toString(){ public String toString(){
StringBuilder builder=new StringBuilder(); StringBuilder builder=new StringBuilder();
builder.append(getResConfig().toString()); builder.append(getResConfig().toString());

View 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.item;
import com.reandroid.lib.arsc.base.Block;
import com.reandroid.lib.arsc.io.BlockLoad;
import com.reandroid.lib.arsc.io.BlockReader;
import java.io.IOException;
public class SpecFlagsArray extends IntegerArray implements BlockLoad {
private final IntegerItem entryCount;
public SpecFlagsArray(IntegerItem entryCount) {
super();
this.entryCount = entryCount;
this.entryCount.setBlockLoad(this);
setBlockLoad(this);
}
public void set(int entryId, int value){
entryId = 0xffff & entryId;
ensureArraySize(entryId);
super.put(entryId, value);
refresh();
}
@Override
public Integer get(int entryId){
entryId = 0xffff & entryId;
return super.get(entryId);
}
@Override
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
if(sender==this.entryCount){
super.setSize(entryCount.get());
}
}
public void refresh(){
entryCount.set(size());
}
}