mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-29 22:04: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{
|
||||
TypeHeader typeHeader = reader.readTypeHeader();
|
||||
SpecTypePair specTypePair = mSpecTypePairArray.getOrCreate(typeHeader.getId().get());
|
||||
TypeBlock typeBlock = specTypePair.getTypeBlockArray().createNext();
|
||||
typeBlock.readBytes(reader);
|
||||
if(typeHeader.isSparse()){
|
||||
SparseTypeBlock sparseTypeBlock = specTypePair
|
||||
.getSparseTypeBlockArray().createNext();
|
||||
sparseTypeBlock.readBytes(reader);
|
||||
}else {
|
||||
TypeBlock typeBlock = specTypePair.getTypeBlockArray().createNext();
|
||||
typeBlock.readBytes(reader);
|
||||
}
|
||||
}
|
||||
private void readLibraryBlock(BlockReader reader) throws IOException{
|
||||
LibraryBlock libraryBlock=new LibraryBlock();
|
||||
|
@ -16,15 +16,14 @@
|
||||
package com.reandroid.arsc.container;
|
||||
|
||||
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.base.Block;
|
||||
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.header.HeaderBlock;
|
||||
import com.reandroid.arsc.header.TypeHeader;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.TypeString;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
@ -40,18 +39,31 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
private final Block[] mChildes;
|
||||
private final SpecBlock mSpecBlock;
|
||||
private final TypeBlockArray mTypeBlockArray;
|
||||
private final SparseTypeBlockArray sparseTypeBlockArray;
|
||||
public SpecTypePair(SpecBlock specBlock, TypeBlockArray typeBlockArray){
|
||||
this.mSpecBlock = specBlock;
|
||||
this.mTypeBlockArray = typeBlockArray;
|
||||
this.mChildes=new Block[]{specBlock, typeBlockArray};
|
||||
this.sparseTypeBlockArray = new SparseTypeBlockArray();
|
||||
|
||||
this.mChildes=new Block[]{specBlock, typeBlockArray, sparseTypeBlockArray};
|
||||
mSpecBlock.setIndex(0);
|
||||
mTypeBlockArray.setIndex(1);
|
||||
sparseTypeBlockArray.setIndex(2);
|
||||
mSpecBlock.setParent(this);
|
||||
mTypeBlockArray.setParent(this);
|
||||
sparseTypeBlockArray.setParent(this);
|
||||
}
|
||||
public SpecTypePair(){
|
||||
this(new SpecBlock(), new TypeBlockArray());
|
||||
}
|
||||
|
||||
public SparseTypeBlockArray getSparseTypeBlockArray() {
|
||||
return sparseTypeBlockArray;
|
||||
}
|
||||
public Collection<SparseTypeBlock> listSparseTypeBlock(){
|
||||
return sparseTypeBlockArray.listItems();
|
||||
}
|
||||
|
||||
public Map<Integer, EntryGroup> createEntryGroups(){
|
||||
Map<Integer, EntryGroup> map = new HashMap<>();
|
||||
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||
@ -211,7 +223,7 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
}
|
||||
ChunkType chunkType=headerBlock.getChunkType();
|
||||
if(chunkType == ChunkType.TYPE){
|
||||
mTypeBlockArray.readBytes(reader);
|
||||
readTypeBlock(reader);
|
||||
return;
|
||||
}
|
||||
if(chunkType!=ChunkType.SPEC){
|
||||
@ -219,6 +231,15 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
}
|
||||
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{
|
||||
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());
|
||||
getTypeBlockArray().merge(typePair.getTypeBlockArray());
|
||||
getSparseTypeBlockArray().merge(typePair.getSparseTypeBlockArray());
|
||||
}
|
||||
@Override
|
||||
public int compareTo(SpecTypePair specTypePair) {
|
||||
|
@ -43,6 +43,18 @@ public class TypeHeader extends HeaderBlock{
|
||||
addChild(entriesStart);
|
||||
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
|
||||
public int getMinimumSize(){
|
||||
@ -77,6 +89,8 @@ public class TypeHeader extends HeaderBlock{
|
||||
+", config=" + getConfig() + '}';
|
||||
}
|
||||
|
||||
private static final byte FLAG_SPARSE = 0x1;
|
||||
|
||||
//typeHeader.countBytes() - getConfig().countBytes() + ResConfig.SIZE_16
|
||||
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