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.io.BlockReader;
|
||||
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.Frameworks;
|
||||
import com.reandroid.common.ReferenceResolver;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONArray;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class TableBlock extends Chunk<TableHeader>
|
||||
implements MainChunk, JSONConvert<JSONObject>, EntryStore {
|
||||
@ -40,6 +41,7 @@ import java.util.*;
|
||||
private final PackageArray mPackageArray;
|
||||
private final List<TableBlock> mFrameWorks=new ArrayList<>();
|
||||
private ApkFile mApkFile;
|
||||
private ReferenceResolver referenceResolver;
|
||||
public TableBlock() {
|
||||
super(new TableHeader(), 2);
|
||||
TableHeader header = getHeaderBlock();
|
||||
@ -48,6 +50,25 @@ import java.util.*;
|
||||
addChild(mTableStringPool);
|
||||
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(){
|
||||
getPackageArray().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