mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 22:54:26 +02:00
separate spec and type
This commit is contained in:
parent
14eb36d3b4
commit
dbfb08700f
@ -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();
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user