add fast string pool builder

This commit is contained in:
REAndroid 2023-01-05 10:42:02 -05:00
parent a53466bf9a
commit 7d4f59ba8f
3 changed files with 120 additions and 18 deletions

View File

@ -66,6 +66,7 @@
throw new IOException("No .*/values/" throw new IOException("No .*/values/"
+ApkUtil.FILE_NAME_PUBLIC_XML+" file found in '"+mainDir); +ApkUtil.FILE_NAME_PUBLIC_XML+" file found in '"+mainDir);
} }
preloadStringPool(pubXmlFileList);
for(File pubXmlFile:pubXmlFileList){ for(File pubXmlFile:pubXmlFileList){
EncodeMaterials encodeMaterials = loadPublicXml(pubXmlFile); EncodeMaterials encodeMaterials = loadPublicXml(pubXmlFile);
addParsedFiles(pubXmlFile); addParsedFiles(pubXmlFile);
@ -90,6 +91,20 @@
} }
tableBlock.refresh(); tableBlock.refresh();
} }
private void preloadStringPool(List<File> pubXmlFileList){
logMessage("Loading string pool ...");
ValuesStringPoolBuilder poolBuilder=new ValuesStringPoolBuilder();
for(File pubXml:pubXmlFileList){
File resDir=toResDirectory(pubXml);
logMessage("Scanning: "+resDir.getParentFile().getName());
List<File> valuesDirList = listValuesDir(resDir);
for(File dir:valuesDirList){
logVerbose(poolBuilder.size()+" building pool: "+dir.getName());
poolBuilder.scanValuesDirectory(dir);
}
}
poolBuilder.addTo(tableBlock.getTableStringPool());
}
private EncodeMaterials loadPublicXml(File pubXmlFile) throws IOException, XMLException { private EncodeMaterials loadPublicXml(File pubXmlFile) throws IOException, XMLException {
ResourceIds resourceIds=new ResourceIds(); ResourceIds resourceIds=new ResourceIds();
resourceIds.fromXml(pubXmlFile); resourceIds.fromXml(pubXmlFile);

View File

@ -0,0 +1,104 @@
/*
* 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.apk.xmlencoder;
import com.reandroid.lib.arsc.decoder.ValueDecoder;
import com.reandroid.lib.arsc.pool.TableStringPool;
import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLElement;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
public class ValuesStringPoolBuilder {
private final Set<String> stringList;
public ValuesStringPoolBuilder(){
this.stringList=new HashSet<>();
}
public void addTo(TableStringPool stringPool){
stringPool.addStrings(stringList);
stringList.clear();
}
public void scanValuesDirectory(File dir){
addStringsFile(new File(dir, "strings.xml"));
addBagsFile(new File(dir, "plurals.xml"));
}
public int size(){
return stringList.size();
}
private void addStringsFile(File file) {
if(file==null||!file.isFile()){
return;
}
try {
XMLDocument xmlDocument = XMLDocument.load(file);
addStrings(xmlDocument);
} catch (Exception ignored) {
}
}
private void addBagsFile(File file) {
if(file==null||!file.isFile()){
return;
}
try {
XMLDocument xmlDocument = XMLDocument.load(file);
addBagStrings(xmlDocument);
} catch (Exception ignored) {
}
}
private void addBagStrings(XMLDocument xmlDocument){
if(xmlDocument == null){
return;
}
XMLElement documentElement = xmlDocument.getDocumentElement();
if(documentElement==null){
return;
}
int count = documentElement.getChildesCount();
for(int i=0;i<count;i++){
XMLElement child=documentElement.getChildAt(i);
int childCount=child.getChildesCount();
for(int j=0;j<childCount;j++){
addStrings(child.getChildAt(i));
}
}
}
private void addStrings(XMLDocument xmlDocument){
if(xmlDocument == null){
return;
}
XMLElement documentElement = xmlDocument.getDocumentElement();
if(documentElement==null){
return;
}
int count = documentElement.getChildesCount();
for(int i=0;i<count;i++){
addStrings(documentElement.getChildAt(i));
}
}
private void addStrings(XMLElement element){
String text = ValueDecoder
.unEscapeSpecialCharacter(element.getTextContent());
addString(text);
}
private void addString(String text){
if(text!=null && text.length()>0 && text.charAt(0)!='@'){
stringList.add(text);
}
}
}

View File

@ -27,11 +27,7 @@ class XMLValuesEncoderString extends XMLValuesEncoder{
XMLValuesEncoderString(EncodeMaterials materials) { XMLValuesEncoderString(EncodeMaterials materials) {
super(materials); super(materials);
} }
@Override
public void encode(String type, String qualifiers, XMLDocument xmlDocument){
preloadStringPool(xmlDocument);
super.encode(type, qualifiers, xmlDocument);
}
@Override @Override
void encodeStringValue(EntryBlock entryBlock, String value){ void encodeStringValue(EntryBlock entryBlock, String value){
entryBlock.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value)); entryBlock.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
@ -44,17 +40,4 @@ class XMLValuesEncoderString extends XMLValuesEncoder{
void encodeBooleanValue(EntryBlock entryBlock, String value){ void encodeBooleanValue(EntryBlock entryBlock, String value){
entryBlock.setValueAsString(value); entryBlock.setValueAsString(value);
} }
private void preloadStringPool(XMLDocument xmlDocument){
XMLElement documentElement = xmlDocument.getDocumentElement();
List<String> stringList = new ArrayList<>();
int count = documentElement.getChildesCount();
for(int i=0;i<count;i++){
String value=getValue(documentElement.getChildAt(i));
if(value==null || ValueDecoder.isReference(value)){
continue;
}
stringList.add(ValueDecoder.unEscapeSpecialCharacter(value));
}
getMaterials().addTableStringPool(stringList);
}
} }