mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 06:14:25 +02:00
create reference id resolver
This commit is contained in:
parent
e53f294258
commit
31c6ccb90e
@ -24,15 +24,16 @@ import com.reandroid.arsc.header.InfoHeader;
|
|||||||
import com.reandroid.arsc.header.TableHeader;
|
import com.reandroid.arsc.header.TableHeader;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.StagedAliasEntry;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.common.Frameworks;
|
import com.reandroid.common.ReferenceResolver;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class TableBlock extends Chunk<TableHeader>
|
public class TableBlock extends Chunk<TableHeader>
|
||||||
implements MainChunk, JSONConvert<JSONObject>, EntryStore {
|
implements MainChunk, JSONConvert<JSONObject>, EntryStore {
|
||||||
@ -40,6 +41,7 @@ import java.util.*;
|
|||||||
private final PackageArray mPackageArray;
|
private final PackageArray mPackageArray;
|
||||||
private final List<TableBlock> mFrameWorks=new ArrayList<>();
|
private final List<TableBlock> mFrameWorks=new ArrayList<>();
|
||||||
private ApkFile mApkFile;
|
private ApkFile mApkFile;
|
||||||
|
private ReferenceResolver referenceResolver;
|
||||||
public TableBlock() {
|
public TableBlock() {
|
||||||
super(new TableHeader(), 2);
|
super(new TableHeader(), 2);
|
||||||
TableHeader header = getHeaderBlock();
|
TableHeader header = getHeaderBlock();
|
||||||
@ -48,6 +50,25 @@ import java.util.*;
|
|||||||
addChild(mTableStringPool);
|
addChild(mTableStringPool);
|
||||||
addChild(mPackageArray);
|
addChild(mPackageArray);
|
||||||
}
|
}
|
||||||
|
public List<Entry> resolveReference(int referenceId){
|
||||||
|
return resolveReference(referenceId, null);
|
||||||
|
}
|
||||||
|
public List<Entry> resolveReferenceWithConfig(int referenceId, ResConfig resConfig){
|
||||||
|
ReferenceResolver resolver = this.referenceResolver;
|
||||||
|
if(resolver == null){
|
||||||
|
resolver = new ReferenceResolver(this);
|
||||||
|
this.referenceResolver = resolver;
|
||||||
|
}
|
||||||
|
return resolver.resolveWithConfig(referenceId, resConfig);
|
||||||
|
}
|
||||||
|
public List<Entry> resolveReference(int referenceId, Predicate<Entry> filter){
|
||||||
|
ReferenceResolver resolver = this.referenceResolver;
|
||||||
|
if(resolver == null){
|
||||||
|
resolver = new ReferenceResolver(this);
|
||||||
|
this.referenceResolver = resolver;
|
||||||
|
}
|
||||||
|
return resolver.resolveAll(referenceId, filter);
|
||||||
|
}
|
||||||
public void destroy(){
|
public void destroy(){
|
||||||
getPackageArray().destroy();
|
getPackageArray().destroy();
|
||||||
getStringPool().destroy();
|
getStringPool().destroy();
|
||||||
|
129
src/main/java/com/reandroid/common/ReferenceResolver.java
Normal file
129
src/main/java/com/reandroid/common/ReferenceResolver.java
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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.common;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
|
import com.reandroid.arsc.value.ResValue;
|
||||||
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class ReferenceResolver {
|
||||||
|
private final EntryStore entryStore;
|
||||||
|
private final List<Entry> results;
|
||||||
|
private final Set<Integer> resolvedIds;
|
||||||
|
private int limit;
|
||||||
|
public ReferenceResolver(EntryStore entryStore){
|
||||||
|
this.entryStore = entryStore;
|
||||||
|
this.results = new ArrayList<>();
|
||||||
|
this.resolvedIds = new HashSet<>();
|
||||||
|
this.limit = -1;
|
||||||
|
}
|
||||||
|
public Entry resolve(int referenceId){
|
||||||
|
return resolve(referenceId, null);
|
||||||
|
}
|
||||||
|
public synchronized Entry resolve(int referenceId, Predicate<Entry> filter){
|
||||||
|
resolveReference(referenceId, filter);
|
||||||
|
List<Entry> results = new ArrayList<>(this.results);
|
||||||
|
reset();
|
||||||
|
if(results.size() > 0){
|
||||||
|
return results.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Entry> resolveWithConfig(int referenceId, ResConfig resConfig){
|
||||||
|
return resolveAll(referenceId, new ConfigFilter(resConfig));
|
||||||
|
}
|
||||||
|
public List<Entry> resolveAll(int referenceId){
|
||||||
|
return resolveAll(referenceId, (Predicate<Entry>)null);
|
||||||
|
}
|
||||||
|
public synchronized List<Entry> resolveAll(int referenceId, Predicate<Entry> filter){
|
||||||
|
resolveReference(referenceId, filter);
|
||||||
|
List<Entry> results = new ArrayList<>(this.results);
|
||||||
|
reset();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
private void resolveReference(int referenceId, Predicate<Entry> filter){
|
||||||
|
if(referenceId == 0 || isFinished() || this.resolvedIds.contains(referenceId)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.resolvedIds.add(referenceId);
|
||||||
|
List<Entry> entryList = listNonNullEntries(referenceId);
|
||||||
|
List<Entry> results = this.results;
|
||||||
|
for(Entry entry:entryList){
|
||||||
|
if(isFinished()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(results.contains(entry)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(entry.isComplex()){
|
||||||
|
addResult(filter, entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ResValue resValue = entry.getResValue();
|
||||||
|
if(resValue.getValueType() != ValueType.REFERENCE){
|
||||||
|
addResult(filter, entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resolveReference(resValue.getData(), filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void reset(){
|
||||||
|
this.results.clear();
|
||||||
|
this.resolvedIds.clear();
|
||||||
|
this.limit = -1;
|
||||||
|
}
|
||||||
|
private boolean isFinished(){
|
||||||
|
return this.limit >= this.results.size();
|
||||||
|
}
|
||||||
|
private void addResult(Predicate<Entry> filter, Entry entry){
|
||||||
|
if(filter == null || filter.test(entry)){
|
||||||
|
this.results.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private List<Entry> listNonNullEntries(int resourceId){
|
||||||
|
List<Entry> results = new ArrayList<>();
|
||||||
|
EntryGroup entryGroup = this.entryStore.getEntryGroup(resourceId);
|
||||||
|
if(entryGroup==null){
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
Iterator<Entry> itr = entryGroup.iterator(true);
|
||||||
|
while (itr.hasNext()){
|
||||||
|
results.add(itr.next());
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConfigFilter implements Predicate<Entry>{
|
||||||
|
private final ResConfig config;
|
||||||
|
public ConfigFilter(ResConfig config){
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean test(Entry entry) {
|
||||||
|
ResConfig resConfig = entry.getResConfig();
|
||||||
|
if(resConfig == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return resConfig.isEqualOrMoreSpecificThan(this.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user