mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 06:14:25 +02:00
implement sparse type entry
This commit is contained in:
parent
1c810ece26
commit
ecbb2fca2e
@ -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.arsc.array;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.BlockArray;
|
||||||
|
import com.reandroid.arsc.chunk.SparseTypeBlock;
|
||||||
|
|
||||||
|
public class SparseTypeBlockArray extends BlockArray<SparseTypeBlock> {
|
||||||
|
@Override
|
||||||
|
public SparseTypeBlock[] newInstance(int len) {
|
||||||
|
return new SparseTypeBlock[len];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public SparseTypeBlock newInstance() {
|
||||||
|
return new SparseTypeBlock();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void onRefreshed() {
|
||||||
|
}
|
||||||
|
public void merge(SparseTypeBlockArray sparse){
|
||||||
|
if(sparse == null || sparse == this){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addAll(sparse.getChildes());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.array;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.BlockArray;
|
||||||
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.value.SparseTypeEntry;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class SparseTypeEntryArray extends BlockArray<SparseTypeEntry> {
|
||||||
|
@Override
|
||||||
|
public SparseTypeEntry[] newInstance(int len) {
|
||||||
|
return new SparseTypeEntry[len];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public SparseTypeEntry newInstance() {
|
||||||
|
return new SparseTypeEntry();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void onRefreshed() {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
|
int count = reader.available() / 4;
|
||||||
|
setChildesCount(count);
|
||||||
|
super.onReadBytes(reader);
|
||||||
|
}
|
||||||
|
}
|
42
src/main/java/com/reandroid/arsc/chunk/SparseTypeBlock.java
Normal file
42
src/main/java/com/reandroid/arsc/chunk/SparseTypeBlock.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.chunk;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.array.SparseTypeEntryArray;
|
||||||
|
import com.reandroid.arsc.header.TypeHeader;
|
||||||
|
import com.reandroid.arsc.value.SparseTypeEntry;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class SparseTypeBlock extends Chunk<TypeHeader>{
|
||||||
|
private final SparseTypeEntryArray entryArray;
|
||||||
|
public SparseTypeBlock() {
|
||||||
|
super(new TypeHeader(), 1);
|
||||||
|
entryArray = new SparseTypeEntryArray();
|
||||||
|
addChild(entryArray);
|
||||||
|
getHeaderBlock().setSparse(true);
|
||||||
|
}
|
||||||
|
public Collection<SparseTypeEntry> listEntries(){
|
||||||
|
return getEntryArray().listItems();
|
||||||
|
}
|
||||||
|
public SparseTypeEntryArray getEntryArray() {
|
||||||
|
return entryArray;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void onChunkRefreshed() {
|
||||||
|
getHeaderBlock().setSparse(true);
|
||||||
|
}
|
||||||
|
}
|
@ -116,8 +116,14 @@ public class PackageBody extends FixedBlockContainer {
|
|||||||
private void readTypeBlock(BlockReader reader) throws IOException{
|
private void readTypeBlock(BlockReader reader) throws IOException{
|
||||||
TypeHeader typeHeader = reader.readTypeHeader();
|
TypeHeader typeHeader = reader.readTypeHeader();
|
||||||
SpecTypePair specTypePair = mSpecTypePairArray.getOrCreate(typeHeader.getId().get());
|
SpecTypePair specTypePair = mSpecTypePairArray.getOrCreate(typeHeader.getId().get());
|
||||||
TypeBlock typeBlock = specTypePair.getTypeBlockArray().createNext();
|
if(typeHeader.isSparse()){
|
||||||
typeBlock.readBytes(reader);
|
SparseTypeBlock sparseTypeBlock = specTypePair
|
||||||
|
.getSparseTypeBlockArray().createNext();
|
||||||
|
sparseTypeBlock.readBytes(reader);
|
||||||
|
}else {
|
||||||
|
TypeBlock typeBlock = specTypePair.getTypeBlockArray().createNext();
|
||||||
|
typeBlock.readBytes(reader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void readLibraryBlock(BlockReader reader) throws IOException{
|
private void readLibraryBlock(BlockReader reader) throws IOException{
|
||||||
LibraryBlock libraryBlock=new LibraryBlock();
|
LibraryBlock libraryBlock=new LibraryBlock();
|
||||||
|
@ -16,15 +16,14 @@
|
|||||||
package com.reandroid.arsc.container;
|
package com.reandroid.arsc.container;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.EntryArray;
|
import com.reandroid.arsc.array.EntryArray;
|
||||||
import com.reandroid.arsc.chunk.ChunkType;
|
import com.reandroid.arsc.array.SparseTypeBlockArray;
|
||||||
|
import com.reandroid.arsc.chunk.*;
|
||||||
import com.reandroid.arsc.array.TypeBlockArray;
|
import com.reandroid.arsc.array.TypeBlockArray;
|
||||||
import com.reandroid.arsc.base.Block;
|
import com.reandroid.arsc.base.Block;
|
||||||
import com.reandroid.arsc.base.BlockContainer;
|
import com.reandroid.arsc.base.BlockContainer;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
|
||||||
import com.reandroid.arsc.chunk.SpecBlock;
|
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.header.HeaderBlock;
|
import com.reandroid.arsc.header.HeaderBlock;
|
||||||
|
import com.reandroid.arsc.header.TypeHeader;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.item.TypeString;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
@ -40,18 +39,31 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
private final Block[] mChildes;
|
private final Block[] mChildes;
|
||||||
private final SpecBlock mSpecBlock;
|
private final SpecBlock mSpecBlock;
|
||||||
private final TypeBlockArray mTypeBlockArray;
|
private final TypeBlockArray mTypeBlockArray;
|
||||||
|
private final SparseTypeBlockArray sparseTypeBlockArray;
|
||||||
public SpecTypePair(SpecBlock specBlock, TypeBlockArray typeBlockArray){
|
public SpecTypePair(SpecBlock specBlock, TypeBlockArray typeBlockArray){
|
||||||
this.mSpecBlock = specBlock;
|
this.mSpecBlock = specBlock;
|
||||||
this.mTypeBlockArray = typeBlockArray;
|
this.mTypeBlockArray = typeBlockArray;
|
||||||
this.mChildes=new Block[]{specBlock, typeBlockArray};
|
this.sparseTypeBlockArray = new SparseTypeBlockArray();
|
||||||
|
|
||||||
|
this.mChildes=new Block[]{specBlock, typeBlockArray, sparseTypeBlockArray};
|
||||||
mSpecBlock.setIndex(0);
|
mSpecBlock.setIndex(0);
|
||||||
mTypeBlockArray.setIndex(1);
|
mTypeBlockArray.setIndex(1);
|
||||||
|
sparseTypeBlockArray.setIndex(2);
|
||||||
mSpecBlock.setParent(this);
|
mSpecBlock.setParent(this);
|
||||||
mTypeBlockArray.setParent(this);
|
mTypeBlockArray.setParent(this);
|
||||||
|
sparseTypeBlockArray.setParent(this);
|
||||||
}
|
}
|
||||||
public SpecTypePair(){
|
public SpecTypePair(){
|
||||||
this(new SpecBlock(), new TypeBlockArray());
|
this(new SpecBlock(), new TypeBlockArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SparseTypeBlockArray getSparseTypeBlockArray() {
|
||||||
|
return sparseTypeBlockArray;
|
||||||
|
}
|
||||||
|
public Collection<SparseTypeBlock> listSparseTypeBlock(){
|
||||||
|
return sparseTypeBlockArray.listItems();
|
||||||
|
}
|
||||||
|
|
||||||
public Map<Integer, EntryGroup> createEntryGroups(){
|
public Map<Integer, EntryGroup> createEntryGroups(){
|
||||||
Map<Integer, EntryGroup> map = new HashMap<>();
|
Map<Integer, EntryGroup> map = new HashMap<>();
|
||||||
for(TypeBlock typeBlock:listTypeBlocks()){
|
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||||
@ -211,7 +223,7 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
}
|
}
|
||||||
ChunkType chunkType=headerBlock.getChunkType();
|
ChunkType chunkType=headerBlock.getChunkType();
|
||||||
if(chunkType == ChunkType.TYPE){
|
if(chunkType == ChunkType.TYPE){
|
||||||
mTypeBlockArray.readBytes(reader);
|
readTypeBlock(reader);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(chunkType!=ChunkType.SPEC){
|
if(chunkType!=ChunkType.SPEC){
|
||||||
@ -219,6 +231,15 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
}
|
}
|
||||||
mSpecBlock.readBytes(reader);
|
mSpecBlock.readBytes(reader);
|
||||||
}
|
}
|
||||||
|
private void readTypeBlock(BlockReader reader) throws IOException {
|
||||||
|
TypeHeader typeHeader = reader.readTypeHeader();
|
||||||
|
if(typeHeader.isSparse()){
|
||||||
|
SparseTypeBlock sparseTypeBlock = sparseTypeBlockArray.createNext();
|
||||||
|
sparseTypeBlock.readBytes(reader);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mTypeBlockArray.readBytes(reader);
|
||||||
|
}
|
||||||
private void readUnexpectedNonSpecBlock(BlockReader reader, HeaderBlock headerBlock) throws IOException{
|
private void readUnexpectedNonSpecBlock(BlockReader reader, HeaderBlock headerBlock) throws IOException{
|
||||||
throw new IOException("Unexpected block: "+headerBlock.toString()+", Should be: "+ChunkType.SPEC);
|
throw new IOException("Unexpected block: "+headerBlock.toString()+", Should be: "+ChunkType.SPEC);
|
||||||
}
|
}
|
||||||
@ -260,6 +281,7 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
}
|
}
|
||||||
getSpecBlock().merge(typePair.getSpecBlock());
|
getSpecBlock().merge(typePair.getSpecBlock());
|
||||||
getTypeBlockArray().merge(typePair.getTypeBlockArray());
|
getTypeBlockArray().merge(typePair.getTypeBlockArray());
|
||||||
|
getSparseTypeBlockArray().merge(typePair.getSparseTypeBlockArray());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(SpecTypePair specTypePair) {
|
public int compareTo(SpecTypePair specTypePair) {
|
||||||
|
@ -43,6 +43,18 @@ public class TypeHeader extends HeaderBlock{
|
|||||||
addChild(entriesStart);
|
addChild(entriesStart);
|
||||||
addChild(config);
|
addChild(config);
|
||||||
}
|
}
|
||||||
|
public boolean isSparse(){
|
||||||
|
return (getFlags().get() & FLAG_SPARSE) == FLAG_SPARSE;
|
||||||
|
}
|
||||||
|
public void setSparse(boolean sparse){
|
||||||
|
byte flag = getFlags().get();
|
||||||
|
if(sparse){
|
||||||
|
flag = (byte) (flag | FLAG_SPARSE);
|
||||||
|
}else {
|
||||||
|
flag = (byte) (flag & (~FLAG_SPARSE & 0xff));
|
||||||
|
}
|
||||||
|
getFlags().set(flag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMinimumSize(){
|
public int getMinimumSize(){
|
||||||
@ -77,6 +89,8 @@ public class TypeHeader extends HeaderBlock{
|
|||||||
+", config=" + getConfig() + '}';
|
+", config=" + getConfig() + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final byte FLAG_SPARSE = 0x1;
|
||||||
|
|
||||||
//typeHeader.countBytes() - getConfig().countBytes() + ResConfig.SIZE_16
|
//typeHeader.countBytes() - getConfig().countBytes() + ResConfig.SIZE_16
|
||||||
private static final int TYPE_MIN_SIZE = 36;
|
private static final int TYPE_MIN_SIZE = 36;
|
||||||
}
|
}
|
||||||
|
40
src/main/java/com/reandroid/arsc/value/SparseTypeEntry.java
Normal file
40
src/main/java/com/reandroid/arsc/value/SparseTypeEntry.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.item.BlockItem;
|
||||||
|
|
||||||
|
public class SparseTypeEntry extends BlockItem {
|
||||||
|
public SparseTypeEntry() {
|
||||||
|
super(4);
|
||||||
|
}
|
||||||
|
public int getIdx(){
|
||||||
|
return getShort(getBytesInternal(), 0) & 0xffff;
|
||||||
|
}
|
||||||
|
public void setIdx(int idx){
|
||||||
|
putShort(getBytesInternal(), 0, (short) idx);
|
||||||
|
}
|
||||||
|
public int getOffset(){
|
||||||
|
return getShort(getBytesInternal(), 2) & 0xffff;
|
||||||
|
}
|
||||||
|
public void setOffset(int offset){
|
||||||
|
putShort(getBytesInternal(), 2, (short) offset);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "idx=" + getIdx() + ", offset=" + getOffset();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user