add memory efficient XML string/file as input source

This commit is contained in:
REAndroid 2023-01-03 11:41:16 -05:00
parent 6075ebe9c8
commit 986c5c1ccd
13 changed files with 275 additions and 2 deletions

View File

@ -21,7 +21,7 @@ import java.io.InputStream;
import java.io.OutputStream;
public class ByteInputSource extends InputSource{
private final byte[] inBytes;
private byte[] inBytes;
public ByteInputSource(byte[] inBytes, String name) {
super(name);
this.inBytes=inBytes;
@ -39,4 +39,8 @@ public class ByteInputSource extends InputSource{
public byte[] getBytes() {
return inBytes;
}
@Override
public void disposeInputSource(){
inBytes=new byte[0];
}
}

View File

@ -32,6 +32,8 @@ public abstract class InputSource {
this.name = name;
this.alias = InputSourceUtil.sanitize(name);
}
public void disposeInputSource(){
}
public int getSort() {
return sort;
}

View File

@ -47,6 +47,7 @@ public class ZipArchive {
FileOutputStream outputStream=new FileOutputStream(file);
inputSource.write(outputStream);
outputStream.close();
inputSource.disposeInputSource();
}
private File toOutFile(File outDir, String path){
path=path.replace('/', File.separatorChar);

View File

@ -57,6 +57,7 @@ public class ZipSerializer {
}
length+=write(zipOutputStream, inputSource);
zipOutputStream.closeEntry();
inputSource.disposeInputSource();
}
zipOutputStream.close();
return length;

View File

@ -0,0 +1,80 @@
/*
* 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.archive.ByteInputSource;
import com.reandroid.lib.apk.CrcOutputStream;
import com.reandroid.lib.arsc.chunk.xml.ResXmlBlock;
import com.reandroid.xml.XMLException;
import com.reandroid.xml.source.XMLSource;
import java.io.IOException;
import java.io.OutputStream;
public class XMLEncodeSource extends ByteInputSource {
private final EncodeMaterials encodeMaterials;
private final XMLSource xmlSource;
private ResXmlBlock resXmlBlock;
public XMLEncodeSource(EncodeMaterials encodeMaterials, XMLSource xmlSource){
super(new byte[0], xmlSource.getPath());
this.encodeMaterials=encodeMaterials;
this.xmlSource=xmlSource;
}
@Override
public long getLength() throws IOException{
return getResXmlBlock().countBytes();
}
@Override
public long getCrc() throws IOException{
ResXmlBlock resXmlBlock = getResXmlBlock();
CrcOutputStream outputStream=new CrcOutputStream();
resXmlBlock.writeBytes(outputStream);
return outputStream.getCrcValue();
}
@Override
public long write(OutputStream outputStream) throws IOException {
return getResXmlBlock().writeBytes(outputStream);
}
@Override
public byte[] getBytes() {
try {
return getResXmlBlock().getBytes();
} catch (IOException ignored) {
}
//should not reach here
return new byte[0];
}
public ResXmlBlock getResXmlBlock() throws IOException{
if(resXmlBlock!=null){
return resXmlBlock;
}
try {
XMLFileEncoder xmlFileEncoder=new XMLFileEncoder(encodeMaterials);
encodeMaterials.logVerbose("Encoding xml: "+xmlSource.getPath());
resXmlBlock = xmlFileEncoder.encode(xmlSource.getXMLDocument());
} catch (XMLException ex) {
throw new IOException(ex.getMessage(), ex);
}
return resXmlBlock;
}
@Override
public void disposeInputSource(){
this.xmlSource.disposeXml();
if(this.resXmlBlock!=null){
resXmlBlock=null;
}
}
}

View File

@ -36,6 +36,25 @@ public class PackageArray extends BlockArray<PackageBlock>
this.mPackageCount=packageCount;
mPackageCount.setBlockLoad(this);
}
public PackageBlock pickOne(){
PackageBlock[] items=getChildes();
if(items==null||items.length==0){
return null;
}
if(items.length==1){
return items[0];
}
PackageBlock largest=null;
for(PackageBlock packageBlock:items){
if(largest==null){
largest=packageBlock;
}else if(packageBlock.getEntriesGroupMap().size() >
largest.getEntriesGroupMap().size()){
largest=packageBlock;
}
}
return largest;
}
public void sort(){
for(PackageBlock packageBlock:listItems()){
packageBlock.sortTypes();

View File

@ -47,6 +47,9 @@ public class TableBlock extends BaseChunk implements JSONConvert<JSONObject> {
addChild(mTableStringPool);
addChild(mPackageArray);
}
public PackageBlock pickOne(){
return getPackageArray().pickOne();
}
public void sortPackages(){
getPackageArray().sort();
}

View File

@ -35,6 +35,12 @@ import java.util.regex.Pattern;
if(txt==null){
return null;
}
if("@empty".equals(txt)){
return new EncodeResult(ValueType.NULL, 0);
}
if("@null".equals(txt)){
return new EncodeResult(ValueType.REFERENCE, 0);
}
EncodeResult result=encodeColor(txt);
if(result!=null){
return result;
@ -807,7 +813,7 @@ import java.util.regex.Pattern;
1.0f / (1 << 15) * MANTISSA_MULT, 1.0f / (1 << 23) * MANTISSA_MULT };
public static final Pattern PATTERN_COLOR = Pattern.compile("^#([0-9a-fA-F]{6,8})$");
public static final Pattern PATTERN_DIMEN = Pattern.compile("^(-?)([0-9]+\\.[0-9E\\-+]+)([dimnpstx%]{0,3})$");
public static final Pattern PATTERN_DIMEN = Pattern.compile("^(-?)([0-9]+\\.[0-9E+]+)([dimnpstx%]{0,3})$");
private static final Pattern PATTERN_INTEGER = Pattern.compile("^(-?)([0-9]+)$");
private static final Pattern PATTERN_HEX = Pattern.compile("^0x[0-9a-fA-F]+$");
public static final Pattern PATTERN_REFERENCE = Pattern.compile("^([?@])(([^\\s:@?/]+:)?)([^\\s:@?/]+)/([^\\s:@?/]+)$");

View File

@ -82,6 +82,10 @@ public class ResValueBagItem extends BaseResValueItem{
return getInt(OFFSET_ID);
}
public void setTypeAndData(ValueType valueType, int data){
setType(valueType);
setData(data);
}
@Override
public void setType(ValueType valueType){
byte type=0;

View File

@ -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.xml.source;
import com.reandroid.xml.XMLDocument;
public class XMLDocumentSource implements XMLSource{
private final String path;
private XMLDocument xmlDocument;
public XMLDocumentSource(String path, XMLDocument xmlDocument){
this.path=path;
this.xmlDocument=xmlDocument;
}
@Override
public String getPath() {
return path;
}
@Override
public XMLDocument getXMLDocument(){
return xmlDocument;
}
@Override
public void disposeXml() {
xmlDocument=null;
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.xml.source;
import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLException;
import java.io.File;
public class XMLFileSource implements XMLSource{
private final String path;
private final File file;
public XMLFileSource(String path, File file){
this.path=path;
this.file=file;
}
public File getFile(){
return this.file;
}
@Override
public String getPath() {
return path;
}
@Override
public XMLDocument getXMLDocument() throws XMLException {
return XMLDocument.load(getFile());
}
@Override
public void disposeXml() {
}
}

View File

@ -0,0 +1,25 @@
/*
* 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.xml.source;
import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLException;
public interface XMLSource {
public void disposeXml();
public String getPath();
public XMLDocument getXMLDocument() throws XMLException;
}

View File

@ -0,0 +1,43 @@
/*
* 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.xml.source;
import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLException;
public class XMLStringSource implements XMLSource{
private final String path;
private String xmlString;
public XMLStringSource(String path, String xmlString){
this.path=path;
this.xmlString=xmlString;
}
public String getXmlString() {
return xmlString;
}
@Override
public String getPath() {
return path;
}
@Override
public XMLDocument getXMLDocument() throws XMLException {
return XMLDocument.load(xmlString);
}
@Override
public void disposeXml() {
this.xmlString=null;
}
}