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,71 +13,101 @@
* See the License for the specific language governing permissions and
* 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.base.Block;
import com.reandroid.lib.arsc.container.SpecTypePair;
import com.reandroid.lib.arsc.io.BlockLoad;
import com.reandroid.lib.arsc.io.BlockReader;
import com.reandroid.lib.arsc.item.IntegerArray;
import com.reandroid.lib.arsc.item.IntegerItem;
import com.reandroid.lib.json.JSONConvert;
import com.reandroid.lib.json.JSONObject;
import com.reandroid.lib.arsc.array.TypeBlockArray;
import com.reandroid.lib.arsc.base.Block;
import com.reandroid.lib.arsc.container.SpecTypePair;
import com.reandroid.lib.arsc.item.*;
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> {
private final IntegerArray mOffsets;
public SpecBlock() {
super(ChunkType.SPEC, 1);
this.mOffsets=new IntegerArray();
addChild(mOffsets);
public class SpecBlock extends BaseChunk implements JSONConvert<JSONObject> {
private final SpecFlagsArray specFlagsArray;
private final ByteItem mTypeId;
public SpecBlock() {
super(ChunkType.SPEC, 1);
this.mTypeId=new ByteItem();
ByteItem res0 = new ByteItem();
ShortItem res1 = new ShortItem();
IntegerItem entryCount = new IntegerItem();
this.specFlagsArray = new SpecFlagsArray(entryCount);
addToHeader(mTypeId);
addToHeader(res0);
addToHeader(res1);
addToHeader(entryCount);
getEntryCountBlock().setBlockLoad(this);
}
public TypeBlockArray getTypeBlockArray(){
SpecTypePair specTypePair=getSpecTypePair();
if(specTypePair!=null){
return specTypePair.getTypeBlockArray();
}
return null;
}
@Override
void onSetEntryCount(int count) {
mOffsets.setSize(count);
}
@Override
protected void onChunkRefreshed() {
}
@Override
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
IntegerItem entryCount=getEntryCountBlock();
if(sender==entryCount){
mOffsets.setSize(entryCount.get());
}
}
@Override
public String toString(){
StringBuilder builder=new StringBuilder();
builder.append(super.toString());
TypeBlockArray typeBlockArray=getTypeBlockArray();
if(typeBlockArray!=null){
builder.append(", typesCount=");
builder.append(typeBlockArray.childesCount());
}
return builder.toString();
}
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(){
SpecTypePair specTypePair=getSpecTypePair();
if(specTypePair!=null){
return specTypePair.getTypeBlockArray();
}
return null;
}
SpecTypePair getSpecTypePair(){
Block parent=getParent();
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
protected void onChunkRefreshed() {
specFlagsArray.refresh();
}
@Override
public String toString(){
StringBuilder builder=new StringBuilder();
builder.append(super.toString());
TypeBlockArray typeBlockArray=getTypeBlockArray();
if(typeBlockArray!=null){
builder.append(", typesCount=");
builder.append(typeBlockArray.childesCount());
}
return builder.toString();
}
@Override
public JSONObject toJson() {
JSONObject jsonObject=new JSONObject();
jsonObject.put(TypeBlock.NAME_id, getTypeIdInt());
return jsonObject;
}
@Override
public JSONObject toJson() {
JSONObject jsonObject=new JSONObject();
jsonObject.put(TypeBlock.NAME_id, getTypeIdInt());
return jsonObject;
}
@Override
public void fromJson(JSONObject json) {
setTypeId(json.getInt(TypeBlock.NAME_id));
}
}
@Override
public void fromJson(JSONObject json) {
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.base.Block;
import com.reandroid.lib.arsc.container.SpecTypePair;
import com.reandroid.lib.arsc.item.IntegerArray;
import com.reandroid.lib.arsc.item.IntegerItem;
import com.reandroid.lib.arsc.item.TypeString;
import com.reandroid.lib.arsc.io.BlockLoad;
import com.reandroid.lib.arsc.io.BlockReader;
import com.reandroid.lib.arsc.item.*;
import com.reandroid.lib.arsc.pool.TypeStringPool;
import com.reandroid.lib.arsc.value.EntryBlock;
import com.reandroid.lib.arsc.value.ResConfig;
import com.reandroid.lib.json.JSONConvert;
@ -33,25 +34,105 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class TypeBlock extends BaseTypeBlock
implements JSONConvert<JSONObject>, Comparable<TypeBlock> {
private final IntegerItem mEntriesStart;
public class TypeBlock extends BaseChunk
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
private final ByteItem mTypeId;
private final ByteItem mTypeFlags;
private final IntegerItem mEntryCount;
private final ResConfig mResConfig;
private final IntegerArray mEntryOffsets;
private final EntryBlockArray mEntryArray;
private TypeString mTypeString;
public TypeBlock() {
super(ChunkType.TYPE, 2);
this.mEntriesStart=new IntegerItem();
this.mResConfig =new ResConfig();
this.mEntryOffsets=new IntegerArray();
this.mEntryArray=new EntryBlockArray(mEntryOffsets, getEntryCountBlock(), mEntriesStart);
this.mTypeId=new ByteItem();
this.mTypeFlags=new ByteItem();
ShortItem reserved = new ShortItem();
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);
addChild(mEntryOffsets);
addChild(entryOffsets);
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(){
return getEntryBlockArray().isEmpty();
}
@ -121,8 +202,8 @@ public class TypeBlock extends BaseTypeBlock
public EntryBlock getEntryBlock(int entryId){
return getEntryBlockArray().get(entryId);
}
@Override
void onSetEntryCount(int count) {
private void onSetEntryCount(int count) {
getEntryBlockArray().setChildesCount(count);
}
@Override
@ -198,6 +279,14 @@ public class TypeBlock extends BaseTypeBlock
return getEntryBlockArray().searchByEntryName(entryName);
}
@Override
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
if(sender==mTypeFlags){
if(mTypeFlags.get()==0x1){
//ResTable_sparseTypeEntry ?
}
}
}
@Override
public String toString(){
StringBuilder builder=new StringBuilder();
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());
}
}