mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 06:34:26 +02:00
encode XML source correctly
* add 's' suffix on type directories * write uncompressed files at decoding
This commit is contained in:
parent
7651efae55
commit
bb46abb499
@ -53,6 +53,7 @@ import java.util.*;
|
|||||||
throws IOException, XMLException {
|
throws IOException, XMLException {
|
||||||
this.decodedEntries.clear();
|
this.decodedEntries.clear();
|
||||||
logMessage("Decoding ...");
|
logMessage("Decoding ...");
|
||||||
|
decodeUncompressedFiles(outDir);
|
||||||
TableEntryStore entryStore=new TableEntryStore();
|
TableEntryStore entryStore=new TableEntryStore();
|
||||||
entryStore.add(Frameworks.getAndroid());
|
entryStore.add(Frameworks.getAndroid());
|
||||||
TableBlock tableBlock=apkModule.getTableBlock();
|
TableBlock tableBlock=apkModule.getTableBlock();
|
||||||
@ -74,6 +75,12 @@ import java.util.*;
|
|||||||
|
|
||||||
extractRootFiles(outDir);
|
extractRootFiles(outDir);
|
||||||
}
|
}
|
||||||
|
private void decodeUncompressedFiles(File outDir)
|
||||||
|
throws IOException {
|
||||||
|
File file=new File(outDir, UncompressedFiles.JSON_FILE);
|
||||||
|
UncompressedFiles uncompressedFiles = apkModule.getUncompressedFiles();
|
||||||
|
uncompressedFiles.toJson().write(file);
|
||||||
|
}
|
||||||
private void decodeResFile(EntryStore entryStore, File outDir, ResFile resFile)
|
private void decodeResFile(EntryStore entryStore, File outDir, ResFile resFile)
|
||||||
throws IOException, XMLException {
|
throws IOException, XMLException {
|
||||||
if(resFile.isBinaryXml()){
|
if(resFile.isBinaryXml()){
|
||||||
|
@ -19,6 +19,7 @@ package com.reandroid.lib.apk;
|
|||||||
import com.reandroid.archive.FileInputSource;
|
import com.reandroid.archive.FileInputSource;
|
||||||
import com.reandroid.lib.apk.xmlencoder.RESEncoder;
|
import com.reandroid.lib.apk.xmlencoder.RESEncoder;
|
||||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||||
|
import com.reandroid.lib.json.JSONObject;
|
||||||
import com.reandroid.xml.XMLException;
|
import com.reandroid.xml.XMLException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -34,6 +35,7 @@ package com.reandroid.lib.apk;
|
|||||||
this.resEncoder = new RESEncoder(module, tableBlock);
|
this.resEncoder = new RESEncoder(module, tableBlock);
|
||||||
}
|
}
|
||||||
public void scanDirectory(File mainDirectory) throws IOException, XMLException {
|
public void scanDirectory(File mainDirectory) throws IOException, XMLException {
|
||||||
|
loadUncompressedFiles(mainDirectory);
|
||||||
resEncoder.scanDirectory(mainDirectory);
|
resEncoder.scanDirectory(mainDirectory);
|
||||||
File rootDir=new File(mainDirectory, "root");
|
File rootDir=new File(mainDirectory, "root");
|
||||||
scanRootDir(rootDir);
|
scanRootDir(rootDir);
|
||||||
@ -51,6 +53,11 @@ package com.reandroid.lib.apk;
|
|||||||
archive.add(inputSource);
|
archive.add(inputSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void loadUncompressedFiles(File mainDirectory) throws IOException, XMLException {
|
||||||
|
File file=new File(mainDirectory, UncompressedFiles.JSON_FILE);
|
||||||
|
UncompressedFiles uncompressedFiles = getApkModule().getUncompressedFiles();
|
||||||
|
uncompressedFiles.fromJson(file);
|
||||||
|
}
|
||||||
public void setApkLogger(APKLogger apkLogger) {
|
public void setApkLogger(APKLogger apkLogger) {
|
||||||
this.resEncoder.setAPKLogger(apkLogger);
|
this.resEncoder.setAPKLogger(apkLogger);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,11 @@ public class ResFile {
|
|||||||
EntryBlock entryBlock=pickOne();
|
EntryBlock entryBlock=pickOne();
|
||||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(typeBlock.getTypeName());
|
String type=typeBlock.getTypeName();
|
||||||
|
builder.append(type);
|
||||||
|
if(!type.equals("plurals") && !type.endsWith("s")){
|
||||||
|
builder.append('s');
|
||||||
|
}
|
||||||
builder.append(typeBlock.getQualifiers());
|
builder.append(typeBlock.getQualifiers());
|
||||||
builder.append('/');
|
builder.append('/');
|
||||||
builder.append(entryBlock.getName());
|
builder.append(entryBlock.getName());
|
||||||
|
@ -114,6 +114,9 @@ package com.reandroid.lib.apk.xmlencoder;
|
|||||||
if(i>0){
|
if(i>0){
|
||||||
name=name.substring(0, i);
|
name=name.substring(0, i);
|
||||||
}
|
}
|
||||||
|
if(!name.equals("plurals") && name.endsWith("s")){
|
||||||
|
name=name.substring(0, name.length()-1);
|
||||||
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
public static String getTypeNameFromValuesXml(File valuesXml){
|
public static String getTypeNameFromValuesXml(File valuesXml){
|
||||||
|
@ -83,11 +83,16 @@ public class XMLFileEncoder {
|
|||||||
ensureNamespaces(element, resXmlElement);
|
ensureNamespaces(element, resXmlElement);
|
||||||
resXmlElement.setTag(element.getTagName());
|
resXmlElement.setTag(element.getTagName());
|
||||||
buildAttributes(element, resXmlElement);
|
buildAttributes(element, resXmlElement);
|
||||||
int count=element.getChildesCount();
|
for(XMLNode node:element.getChildNodes()){
|
||||||
for(int i=0;i<count;i++){
|
if(node instanceof XMLText){
|
||||||
XMLElement child=element.getChildAt(i);
|
resXmlElement.addResXmlText(((XMLText)node).getText(true));
|
||||||
ResXmlElement childXml=resXmlElement.createChildElement();
|
}else if(node instanceof XMLComment){
|
||||||
buildElement(child, childXml);
|
resXmlElement.setComment(((XMLComment)node).getCommentText());
|
||||||
|
}else if(node instanceof XMLElement){
|
||||||
|
XMLElement child=(XMLElement) node;
|
||||||
|
ResXmlElement childXml=resXmlElement.createChildElement();
|
||||||
|
buildElement(child, childXml);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void buildAttributes(XMLElement element, ResXmlElement resXmlElement){
|
private void buildAttributes(XMLElement element, ResXmlElement resXmlElement){
|
||||||
|
@ -43,7 +43,7 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
|||||||
encodeAttributes(parentElement, resValueBag);
|
encodeAttributes(parentElement, resValueBag);
|
||||||
encodeEnumOrFlag(parentElement, resValueBag);
|
encodeEnumOrFlag(parentElement, resValueBag);
|
||||||
// TODO: re-check if this is necessary
|
// TODO: re-check if this is necessary
|
||||||
resValueBag.getEntryBlock().setEntryTypeShared(true);
|
resValueBag.getEntryBlock().setPublic(true);
|
||||||
}
|
}
|
||||||
private void encodeAttributes(XMLElement parentElement, ResValueBag resValueBag){
|
private void encodeAttributes(XMLElement parentElement, ResValueBag resValueBag){
|
||||||
int count=parentElement.getAttributeCount();
|
int count=parentElement.getAttributeCount();
|
||||||
|
@ -37,7 +37,7 @@ class XMLValuesEncoderId extends XMLValuesEncoder{
|
|||||||
setVisibility(entryBlock);
|
setVisibility(entryBlock);
|
||||||
}
|
}
|
||||||
private void setVisibility(EntryBlock entryBlock){
|
private void setVisibility(EntryBlock entryBlock){
|
||||||
entryBlock.setEntryTypePublic(true);
|
entryBlock.setWeak(true);
|
||||||
entryBlock.setEntryTypeShared(true);
|
entryBlock.setPublic(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ package com.reandroid.lib.arsc.chunk.xml;
|
|||||||
import com.reandroid.lib.arsc.chunk.ChunkType;
|
import com.reandroid.lib.arsc.chunk.ChunkType;
|
||||||
import com.reandroid.lib.arsc.base.Block;
|
import com.reandroid.lib.arsc.base.Block;
|
||||||
import com.reandroid.lib.arsc.container.BlockList;
|
import com.reandroid.lib.arsc.container.BlockList;
|
||||||
import com.reandroid.lib.arsc.container.FixedBlockContainer;
|
|
||||||
import com.reandroid.lib.arsc.container.SingleBlockContainer;
|
import com.reandroid.lib.arsc.container.SingleBlockContainer;
|
||||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.lib.arsc.header.HeaderBlock;
|
import com.reandroid.lib.arsc.header.HeaderBlock;
|
||||||
@ -29,37 +28,37 @@ import com.reandroid.lib.common.EntryStore;
|
|||||||
import com.reandroid.lib.json.JSONConvert;
|
import com.reandroid.lib.json.JSONConvert;
|
||||||
import com.reandroid.lib.json.JSONArray;
|
import com.reandroid.lib.json.JSONArray;
|
||||||
import com.reandroid.lib.json.JSONObject;
|
import com.reandroid.lib.json.JSONObject;
|
||||||
import com.reandroid.xml.NameSpaceItem;
|
import com.reandroid.xml.*;
|
||||||
import com.reandroid.xml.XMLAttribute;
|
|
||||||
import com.reandroid.xml.XMLElement;
|
|
||||||
import com.reandroid.xml.XMLException;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ResXmlElement extends FixedBlockContainer implements JSONConvert<JSONObject> {
|
public class ResXmlElement extends ResXmlNode implements JSONConvert<JSONObject> {
|
||||||
private final BlockList<ResXmlStartNamespace> mStartNamespaceList;
|
private final BlockList<ResXmlStartNamespace> mStartNamespaceList;
|
||||||
private final SingleBlockContainer<ResXmlStartElement> mStartElementContainer;
|
private final SingleBlockContainer<ResXmlStartElement> mStartElementContainer;
|
||||||
private final BlockList<ResXmlElement> mBody;
|
private final BlockList<ResXmlNode> mBody;
|
||||||
private final SingleBlockContainer<ResXmlText> mResXmlTextContainer;
|
|
||||||
private final SingleBlockContainer<ResXmlEndElement> mEndElementContainer;
|
private final SingleBlockContainer<ResXmlEndElement> mEndElementContainer;
|
||||||
private final BlockList<ResXmlEndNamespace> mEndNamespaceList;
|
private final BlockList<ResXmlEndNamespace> mEndNamespaceList;
|
||||||
private int mDepth;
|
private int mDepth;
|
||||||
public ResXmlElement() {
|
public ResXmlElement() {
|
||||||
super(6);
|
super(5);
|
||||||
this.mStartNamespaceList = new BlockList<>();
|
this.mStartNamespaceList = new BlockList<>();
|
||||||
this.mStartElementContainer= new SingleBlockContainer<>();
|
this.mStartElementContainer= new SingleBlockContainer<>();
|
||||||
this.mBody = new BlockList<>();
|
this.mBody = new BlockList<>();
|
||||||
this.mResXmlTextContainer = new SingleBlockContainer<>();
|
|
||||||
this.mEndElementContainer = new SingleBlockContainer<>();
|
this.mEndElementContainer = new SingleBlockContainer<>();
|
||||||
this.mEndNamespaceList = new BlockList<>();
|
this.mEndNamespaceList = new BlockList<>();
|
||||||
addChild(0, mStartNamespaceList);
|
addChild(0, mStartNamespaceList);
|
||||||
addChild(1, mStartElementContainer);
|
addChild(1, mStartElementContainer);
|
||||||
addChild(2, mBody);
|
addChild(2, mBody);
|
||||||
addChild(3, mResXmlTextContainer);
|
addChild(3, mEndElementContainer);
|
||||||
addChild(4, mEndElementContainer);
|
addChild(4, mEndNamespaceList);
|
||||||
addChild(5, mEndNamespaceList);
|
}
|
||||||
|
public String getComment(){
|
||||||
|
return getStartElement().getComment();
|
||||||
|
}
|
||||||
|
public void setComment(String comment){
|
||||||
|
getStartElement().setComment(comment);
|
||||||
}
|
}
|
||||||
public void calculatePositions(){
|
public void calculatePositions(){
|
||||||
ResXmlStartElement start = getStartElement();
|
ResXmlStartElement start = getStartElement();
|
||||||
@ -293,10 +292,53 @@ import java.util.*;
|
|||||||
return mBody.remove(element);
|
return mBody.remove(element);
|
||||||
}
|
}
|
||||||
public int countElements(){
|
public int countElements(){
|
||||||
return mBody.size();
|
int result = 0;
|
||||||
|
for(ResXmlNode xmlNode:listXmlNodes()){
|
||||||
|
if(xmlNode instanceof ResXmlElement){
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public void clearChildes(){
|
||||||
|
List<ResXmlNode> copyOfNodeList=new ArrayList<>(mBody.getChildes());
|
||||||
|
for(ResXmlNode xmlNode:copyOfNodeList){
|
||||||
|
if(xmlNode==null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
xmlNode.onRemove();
|
||||||
|
mBody.remove(xmlNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<ResXmlNode> listXmlNodes(){
|
||||||
|
return mBody.getChildes();
|
||||||
|
}
|
||||||
|
public List<ResXmlText> listXmlText(){
|
||||||
|
List<ResXmlText> results=new ArrayList<>();
|
||||||
|
for(ResXmlNode xmlNode:listXmlNodes()){
|
||||||
|
if(xmlNode instanceof ResXmlTextNode){
|
||||||
|
results.add(((ResXmlTextNode) xmlNode).getResXmlText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
public List<ResXmlTextNode> listXmlTextNodes(){
|
||||||
|
List<ResXmlTextNode> results=new ArrayList<>();
|
||||||
|
for(ResXmlNode xmlNode:listXmlNodes()){
|
||||||
|
if(xmlNode instanceof ResXmlTextNode){
|
||||||
|
results.add((ResXmlTextNode) xmlNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
public List<ResXmlElement> listElements(){
|
public List<ResXmlElement> listElements(){
|
||||||
return mBody.getChildes();
|
List<ResXmlElement> results=new ArrayList<>();
|
||||||
|
for(ResXmlNode xmlNode:listXmlNodes()){
|
||||||
|
if(xmlNode instanceof ResXmlElement){
|
||||||
|
results.add((ResXmlElement) xmlNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
public List<ResXmlElement> listElements(String name){
|
public List<ResXmlElement> listElements(String name){
|
||||||
List<ResXmlElement> results=new ArrayList<>();
|
List<ResXmlElement> results=new ArrayList<>();
|
||||||
@ -432,25 +474,40 @@ import java.util.*;
|
|||||||
mEndElementContainer.setItem(item);
|
mEndElementContainer.setItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use listXmlText() instead to be removed on next version
|
||||||
|
@Deprecated
|
||||||
public ResXmlText getResXmlText(){
|
public ResXmlText getResXmlText(){
|
||||||
return mResXmlTextContainer.getItem();
|
List<ResXmlText> xmlTextList=listXmlText();
|
||||||
}
|
if(xmlTextList.size()==0){
|
||||||
public void setResXmlText(ResXmlText xmlText){
|
return null;
|
||||||
mResXmlTextContainer.setItem(xmlText);
|
|
||||||
}
|
|
||||||
public void setResXmlText(String text){
|
|
||||||
if(text==null){
|
|
||||||
mResXmlTextContainer.setItem(null);
|
|
||||||
}else {
|
|
||||||
ResXmlText xmlText=mResXmlTextContainer.getItem();
|
|
||||||
if(xmlText==null){
|
|
||||||
xmlText=new ResXmlText();
|
|
||||||
mResXmlTextContainer.setItem(xmlText);
|
|
||||||
ResXmlStartElement start = getStartElement();
|
|
||||||
xmlText.setLineNumber(start.getLineNumber());
|
|
||||||
}
|
|
||||||
xmlText.setText(text);
|
|
||||||
}
|
}
|
||||||
|
return xmlTextList.get(0);
|
||||||
|
}
|
||||||
|
public void addResXmlTextNode(ResXmlTextNode xmlTextNode){
|
||||||
|
mBody.add(xmlTextNode);
|
||||||
|
}
|
||||||
|
public void addResXmlText(ResXmlText xmlText){
|
||||||
|
if(xmlText!=null){
|
||||||
|
addResXmlTextNode(new ResXmlTextNode(xmlText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use addResXmlText()
|
||||||
|
@Deprecated
|
||||||
|
public void setResXmlText(ResXmlText xmlText){
|
||||||
|
addResXmlText(xmlText);
|
||||||
|
}
|
||||||
|
@Deprecated
|
||||||
|
public void setResXmlText(String text){
|
||||||
|
clearChildes();
|
||||||
|
addResXmlText(text);
|
||||||
|
}
|
||||||
|
public void addResXmlText(String text){
|
||||||
|
if(text==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResXmlTextNode xmlTextNode=new ResXmlTextNode();
|
||||||
|
addResXmlTextNode(xmlTextNode);
|
||||||
|
xmlTextNode.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isBalanced(){
|
private boolean isBalanced(){
|
||||||
@ -602,7 +659,7 @@ import java.util.*;
|
|||||||
}
|
}
|
||||||
private void onXmlText(BlockReader reader) throws IOException{
|
private void onXmlText(BlockReader reader) throws IOException{
|
||||||
ResXmlText xmlText=new ResXmlText();
|
ResXmlText xmlText=new ResXmlText();
|
||||||
setResXmlText(xmlText);
|
addResXmlText(xmlText);
|
||||||
xmlText.readBytes(reader);
|
xmlText.readBytes(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,6 +701,7 @@ import java.util.*;
|
|||||||
@Override
|
@Override
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
JSONObject jsonObject=new JSONObject();
|
JSONObject jsonObject=new JSONObject();
|
||||||
|
jsonObject.put(NAME_node_type, NAME_element);
|
||||||
ResXmlStartElement start = getStartElement();
|
ResXmlStartElement start = getStartElement();
|
||||||
jsonObject.put(NAME_line, start.getLineNumber());
|
jsonObject.put(NAME_line, start.getLineNumber());
|
||||||
int i=0;
|
int i=0;
|
||||||
@ -663,13 +721,6 @@ import java.util.*;
|
|||||||
if(comment!=null){
|
if(comment!=null){
|
||||||
jsonObject.put(NAME_comment, comment);
|
jsonObject.put(NAME_comment, comment);
|
||||||
}
|
}
|
||||||
ResXmlText xmlText=getResXmlText();
|
|
||||||
if(xmlText!=null){
|
|
||||||
String text=xmlText.getText();
|
|
||||||
if(text!=null){
|
|
||||||
jsonObject.put(NAME_text, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String uri=start.getUri();
|
String uri=start.getUri();
|
||||||
if(uri!=null){
|
if(uri!=null){
|
||||||
jsonObject.put(NAME_namespace_uri, uri);
|
jsonObject.put(NAME_namespace_uri, uri);
|
||||||
@ -678,8 +729,8 @@ import java.util.*;
|
|||||||
jsonObject.put(NAME_attributes, attrArray);
|
jsonObject.put(NAME_attributes, attrArray);
|
||||||
i=0;
|
i=0;
|
||||||
JSONArray childes=new JSONArray();
|
JSONArray childes=new JSONArray();
|
||||||
for(ResXmlElement element:listElements()){
|
for(ResXmlNode xmlNode:listXmlNodes()){
|
||||||
childes.put(i, element.toJson());
|
childes.put(i, xmlNode.toJson());
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if(i>0){
|
if(i>0){
|
||||||
@ -730,12 +781,29 @@ import java.util.*;
|
|||||||
int length=childArray.length();
|
int length=childArray.length();
|
||||||
for(int i=0;i<length;i++){
|
for(int i=0;i<length;i++){
|
||||||
JSONObject childObject=childArray.getJSONObject(i);
|
JSONObject childObject=childArray.getJSONObject(i);
|
||||||
ResXmlElement child = createChildElement();
|
if(isTextNode(childObject)){
|
||||||
child.fromJson(childObject);
|
ResXmlTextNode xmlTextNode=new ResXmlTextNode();
|
||||||
|
addResXmlTextNode(xmlTextNode);
|
||||||
|
xmlTextNode.fromJson(childObject);
|
||||||
|
}else {
|
||||||
|
ResXmlElement childElement = createChildElement();
|
||||||
|
childElement.fromJson(childObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start.calculatePositions();
|
start.calculatePositions();
|
||||||
}
|
}
|
||||||
|
private boolean isTextNode(JSONObject childObject){
|
||||||
|
String type=childObject.optString(NAME_node_type, null);
|
||||||
|
if(ResXmlTextNode.NAME_text.equals(type)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(NAME_element.equals(type)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// support older ARSCLib versions
|
||||||
|
return childObject.has(NAME_text);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes binary {@link ResXmlElement} to readable {@link XMLElement}
|
* Decodes binary {@link ResXmlElement} to readable {@link XMLElement}
|
||||||
@ -745,6 +813,7 @@ import java.util.*;
|
|||||||
* */
|
* */
|
||||||
public XMLElement decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException {
|
public XMLElement decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException {
|
||||||
XMLElement xmlElement = new XMLElement(getTagName());
|
XMLElement xmlElement = new XMLElement(getTagName());
|
||||||
|
xmlElement.setLineNumber(getStartElement().getLineNumber());
|
||||||
for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){
|
for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){
|
||||||
xmlElement.addAttribute(startNamespace.decodeToXml());
|
xmlElement.addAttribute(startNamespace.decodeToXml());
|
||||||
}
|
}
|
||||||
@ -753,15 +822,21 @@ import java.util.*;
|
|||||||
resXmlAttribute.decodeToXml(entryStore, currentPackageId);
|
resXmlAttribute.decodeToXml(entryStore, currentPackageId);
|
||||||
xmlElement.addAttribute(xmlAttribute);
|
xmlElement.addAttribute(xmlAttribute);
|
||||||
}
|
}
|
||||||
for(ResXmlElement childResXmlElement:listElements()){
|
String comment=getComment();
|
||||||
XMLElement childXMLElement =
|
if(comment!=null){
|
||||||
childResXmlElement.decodeToXml(entryStore, currentPackageId);
|
xmlElement.addComment(new XMLComment(comment));
|
||||||
xmlElement.addChild(childXMLElement);
|
|
||||||
}
|
}
|
||||||
ResXmlText resXmlText = getResXmlText();
|
for(ResXmlNode xmlNode:listXmlNodes()){
|
||||||
if(resXmlText!=null){
|
if(xmlNode instanceof ResXmlElement){
|
||||||
xmlElement.setTextContent(
|
ResXmlElement childResXmlElement=(ResXmlElement)xmlNode;
|
||||||
ValueDecoder.escapeSpecialCharacter(resXmlText.getText()));
|
XMLElement childXMLElement =
|
||||||
|
childResXmlElement.decodeToXml(entryStore, currentPackageId);
|
||||||
|
xmlElement.addChild(childXMLElement);
|
||||||
|
}else if(xmlNode instanceof ResXmlTextNode){
|
||||||
|
ResXmlTextNode childResXmlTextNode=(ResXmlTextNode)xmlNode;
|
||||||
|
XMLText xmlText = childResXmlTextNode.decodeToXml();
|
||||||
|
xmlElement.addText(xmlText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return xmlElement;
|
return xmlElement;
|
||||||
}
|
}
|
||||||
@ -799,6 +874,7 @@ import java.util.*;
|
|||||||
public static final String NS_ANDROID_URI = "http://schemas.android.com/apk/res/android";
|
public static final String NS_ANDROID_URI = "http://schemas.android.com/apk/res/android";
|
||||||
public static final String NS_ANDROID_PREFIX = "android";
|
public static final String NS_ANDROID_PREFIX = "android";
|
||||||
|
|
||||||
|
static final String NAME_element = "element";
|
||||||
static final String NAME_name = "name";
|
static final String NAME_name = "name";
|
||||||
static final String NAME_comment = "comment";
|
static final String NAME_comment = "comment";
|
||||||
static final String NAME_text = "text";
|
static final String NAME_text = "text";
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.chunk.xml;
|
||||||
|
|
||||||
|
import com.reandroid.lib.arsc.container.FixedBlockContainer;
|
||||||
|
import com.reandroid.lib.json.JSONConvert;
|
||||||
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
|
||||||
|
public abstract class ResXmlNode extends FixedBlockContainer implements JSONConvert<JSONObject> {
|
||||||
|
ResXmlNode(int childesCount) {
|
||||||
|
super(childesCount);
|
||||||
|
}
|
||||||
|
void onRemove(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String NAME_node_type="node_type";
|
||||||
|
}
|
@ -56,7 +56,9 @@ import java.util.Set;
|
|||||||
if(isEmpty(uri) || isEmpty(prefix)){
|
if(isEmpty(uri) || isEmpty(prefix)){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new SchemaAttr(prefix, uri);
|
SchemaAttr schemaAttr=new SchemaAttr(prefix, uri);
|
||||||
|
schemaAttr.setLineNumber(getLineNumber());
|
||||||
|
return schemaAttr;
|
||||||
}
|
}
|
||||||
private boolean isEmpty(String txt){
|
private boolean isEmpty(String txt){
|
||||||
if(txt==null){
|
if(txt==null){
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.chunk.xml;
|
||||||
|
|
||||||
|
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||||
|
import com.reandroid.lib.json.JSONObject;
|
||||||
|
import com.reandroid.xml.XMLText;
|
||||||
|
|
||||||
|
public class ResXmlTextNode extends ResXmlNode {
|
||||||
|
private final ResXmlText resXmlText;
|
||||||
|
public ResXmlTextNode(ResXmlText resXmlText) {
|
||||||
|
super(1);
|
||||||
|
this.resXmlText = resXmlText;
|
||||||
|
addChild(0, resXmlText);
|
||||||
|
}
|
||||||
|
public ResXmlTextNode() {
|
||||||
|
this(new ResXmlText());
|
||||||
|
}
|
||||||
|
public ResXmlText getResXmlText() {
|
||||||
|
return resXmlText;
|
||||||
|
}
|
||||||
|
public int getLineNumber(){
|
||||||
|
return getResXmlText().getLineNumber();
|
||||||
|
}
|
||||||
|
public void setLineNumber(int lineNumber){
|
||||||
|
getResXmlText().setLineNumber(lineNumber);
|
||||||
|
}
|
||||||
|
public String getText(){
|
||||||
|
return getResXmlText().getText();
|
||||||
|
}
|
||||||
|
public void setText(String text){
|
||||||
|
getResXmlText().setText(text);
|
||||||
|
}
|
||||||
|
public int getTextReference(){
|
||||||
|
return getResXmlText().getTextReference();
|
||||||
|
}
|
||||||
|
public void setTextReference(int ref){
|
||||||
|
getResXmlText().setTextReference(ref);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
String txt=getText();
|
||||||
|
if(txt!=null){
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject jsonObject=new JSONObject();
|
||||||
|
jsonObject.put(NAME_node_type, NAME_text);
|
||||||
|
jsonObject.put(NAME_text, getText());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
setText(json.optString(NAME_text, null));
|
||||||
|
}
|
||||||
|
public XMLText decodeToXml() {
|
||||||
|
XMLText xmlText=new XMLText(ValueDecoder.escapeSpecialCharacter(getText()));
|
||||||
|
xmlText.setLineNumber(getLineNumber());
|
||||||
|
return xmlText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String NAME_text="text";
|
||||||
|
}
|
@ -77,6 +77,23 @@ public class ByteArray extends BlockItem {
|
|||||||
byte[] bts = getBytesInternal();
|
byte[] bts = getBytesInternal();
|
||||||
bts[index]=value;
|
bts[index]=value;
|
||||||
}
|
}
|
||||||
|
public boolean getBit(int byteOffset, int bitIndex){
|
||||||
|
return ((get(byteOffset)>>bitIndex) & 0x1) == 1;
|
||||||
|
}
|
||||||
|
public void putBit(int byteOffset, int bitIndex, boolean bit){
|
||||||
|
int val=get(byteOffset);
|
||||||
|
int left=val>>bitIndex;
|
||||||
|
if(bit){
|
||||||
|
left=left|0x1;
|
||||||
|
}else {
|
||||||
|
left=left & 0xFE;
|
||||||
|
}
|
||||||
|
left=left<<bitIndex;
|
||||||
|
bitIndex=8-bitIndex;
|
||||||
|
int right=(0xFF>>bitIndex) & val;
|
||||||
|
val=left|right;
|
||||||
|
put(byteOffset, (byte) val);
|
||||||
|
}
|
||||||
public final void putShort(int offset, short val){
|
public final void putShort(int offset, short val){
|
||||||
byte[] bts = getBytesInternal();
|
byte[] bts = getBytesInternal();
|
||||||
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
||||||
|
@ -57,7 +57,7 @@ public abstract class BaseResValueItem extends BaseResValue implements ResValueI
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public ReferenceItem getTableStringReference(){
|
public ReferenceItem getTableStringReference(){
|
||||||
if(getValueType()!=ValueType.STRING){
|
if(getValueType()!=ValueType.STRING || getEntryBlock()==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(mReferenceItem==null){
|
if(mReferenceItem==null){
|
||||||
|
@ -35,9 +35,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||||
private ShortItem mHeaderSize;
|
private ByteArray entryHeader;
|
||||||
private ByteItem mFlagEntryType;
|
|
||||||
private ByteItem mByteFlagsB;
|
|
||||||
private IntegerItem mSpecReference;
|
private IntegerItem mSpecReference;
|
||||||
private BaseResValue mResValue;
|
private BaseResValue mResValue;
|
||||||
private boolean mUnLocked;
|
private boolean mUnLocked;
|
||||||
@ -127,20 +125,16 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
return tableString.getHtml();
|
return tableString.getHtml();
|
||||||
}
|
}
|
||||||
public TableString getValueAsTableString(){
|
public TableString getValueAsTableString(){
|
||||||
TableStringPool stringPool=getTableStringPool();
|
TableStringPool stringPool = getTableStringPool();
|
||||||
if(stringPool==null){
|
if(stringPool==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
BaseResValue res = getResValue();
|
BaseResValue baseResValue = getResValue();
|
||||||
if(!(res instanceof ResValueInt)){
|
if(!(baseResValue instanceof ResValueInt)){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueInt resValueInt=(ResValueInt)res;
|
ResValueInt resValueInt = (ResValueInt)baseResValue;
|
||||||
TableString tableString= stringPool.get(resValueInt.getData());
|
return stringPool.get(resValueInt.getData());
|
||||||
if(tableString==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return tableString;
|
|
||||||
}
|
}
|
||||||
private TableStringPool getTableStringPool(){
|
private TableStringPool getTableStringPool(){
|
||||||
PackageBlock pkg=getPackageBlock();
|
PackageBlock pkg=getPackageBlock();
|
||||||
@ -256,27 +250,24 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
removeTableReferences();
|
removeTableReferences();
|
||||||
removeSpecReferences();
|
removeSpecReferences();
|
||||||
}
|
}
|
||||||
public void setEntryTypeBag(boolean b){
|
private void setEntryTypeBag(boolean b){
|
||||||
mFlagEntryType.putBit(0, b);
|
entryHeader.putBit(OFFSET_FLAGS, 0, b);
|
||||||
refreshHeaderSize();
|
refreshHeaderSize();
|
||||||
}
|
}
|
||||||
public boolean isEntryTypeBag(){
|
public boolean isEntryTypeBag(){
|
||||||
return mFlagEntryType.getBit(0);
|
return entryHeader.getBit(OFFSET_FLAGS,0);
|
||||||
}
|
}
|
||||||
public void setEntryTypeShared(boolean b){
|
public void setPublic(boolean b){
|
||||||
mFlagEntryType.putBit(1, b);
|
entryHeader.putBit(OFFSET_FLAGS,1, b);
|
||||||
}
|
}
|
||||||
public boolean isEntryTypeShared(){
|
public boolean isPublic(){
|
||||||
return mFlagEntryType.getBit(1);
|
return entryHeader.getBit(OFFSET_FLAGS,1);
|
||||||
}
|
}
|
||||||
public void setEntryTypePublic(boolean b){
|
public void setWeak(boolean b){
|
||||||
mFlagEntryType.putBit(2, b);
|
entryHeader.putBit(OFFSET_FLAGS, 2, b);
|
||||||
}
|
}
|
||||||
public boolean isEntryTypePublic(){
|
public boolean isWeak(){
|
||||||
return mFlagEntryType.getBit(2);
|
return entryHeader.getBit(OFFSET_FLAGS,2);
|
||||||
}
|
|
||||||
private void setByteFlagsB(byte b){
|
|
||||||
mByteFlagsB.set(b);
|
|
||||||
}
|
}
|
||||||
private IntegerItem getSpecReferenceBlock(){
|
private IntegerItem getSpecReferenceBlock(){
|
||||||
return mSpecReference;
|
return mSpecReference;
|
||||||
@ -341,7 +332,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(resValue!=null){
|
if(resValue!=null){
|
||||||
resValue.setIndex(4);
|
resValue.setIndex(2);
|
||||||
resValue.setParent(this);
|
resValue.setParent(this);
|
||||||
}
|
}
|
||||||
if(mResValue!=null){
|
if(mResValue!=null){
|
||||||
@ -509,47 +500,32 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
if(mUnLocked){
|
if(mUnLocked){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mUnLocked =true;
|
mUnLocked = true;
|
||||||
this.mHeaderSize =new ShortItem();
|
entryHeader = new ByteArray(4);
|
||||||
this.mFlagEntryType =new ByteItem();
|
|
||||||
this.mByteFlagsB=new ByteItem();
|
|
||||||
if(mSpecReference==null){
|
if(mSpecReference==null){
|
||||||
this.mSpecReference = new IntegerItem();
|
this.mSpecReference = new IntegerItem();
|
||||||
}else if(mSpecReference.isNull()){
|
}else if(mSpecReference.isNull()){
|
||||||
mSpecReference.setNull(false);
|
mSpecReference.setNull(false);
|
||||||
}
|
}
|
||||||
|
entryHeader.setIndex(0);
|
||||||
mHeaderSize.setIndex(0);
|
mSpecReference.setIndex(1);
|
||||||
mFlagEntryType.setIndex(1);
|
entryHeader.setParent(this);
|
||||||
mByteFlagsB.setIndex(2);
|
|
||||||
mSpecReference.setIndex(3);
|
|
||||||
|
|
||||||
mHeaderSize.setParent(this);
|
|
||||||
mFlagEntryType.setParent(this);
|
|
||||||
mByteFlagsB.setParent(this);
|
|
||||||
mSpecReference.setParent(this);
|
mSpecReference.setParent(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
private void lockEntry(){
|
private void lockEntry(){
|
||||||
if(!mUnLocked){
|
if(!mUnLocked){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeAllReferences();
|
removeAllReferences();
|
||||||
mUnLocked =false;
|
mUnLocked = false;
|
||||||
mHeaderSize.setParent(null);
|
entryHeader.setParent(null);
|
||||||
mFlagEntryType.setParent(null);
|
|
||||||
mByteFlagsB.setParent(null);
|
|
||||||
mSpecReference.setParent(null);
|
mSpecReference.setParent(null);
|
||||||
|
|
||||||
mHeaderSize.setIndex(-1);
|
entryHeader.setIndex(-1);
|
||||||
mFlagEntryType.setIndex(-1);
|
|
||||||
mByteFlagsB.setIndex(-1);
|
|
||||||
mSpecReference.setIndex(-1);
|
mSpecReference.setIndex(-1);
|
||||||
removeResValue();
|
removeResValue();
|
||||||
|
|
||||||
this.mHeaderSize =null;
|
this.entryHeader = null;
|
||||||
this.mFlagEntryType =null;
|
|
||||||
this.mByteFlagsB =null;
|
|
||||||
this.mSpecReference =null;
|
this.mSpecReference =null;
|
||||||
}
|
}
|
||||||
private void removeResValue(){
|
private void removeResValue(){
|
||||||
@ -560,11 +536,13 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void refreshHeaderSize(){
|
private void refreshHeaderSize(){
|
||||||
|
short size;
|
||||||
if(isEntryTypeBag()){
|
if(isEntryTypeBag()){
|
||||||
mHeaderSize.set(HEADER_SIZE_BAG);
|
size=HEADER_SIZE_BAG;
|
||||||
}else {
|
}else {
|
||||||
mHeaderSize.set(HEADER_SIZE_INT);
|
size=HEADER_SIZE_INT;
|
||||||
}
|
}
|
||||||
|
entryHeader.putShort(OFFSET_SIZE, size);
|
||||||
}
|
}
|
||||||
private void createResValue(){
|
private void createResValue(){
|
||||||
if(getResValue()!=null){
|
if(getResValue()!=null){
|
||||||
@ -599,9 +577,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
if(isNull()){
|
if(isNull()){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
byte[] results=mHeaderSize.getBytes();
|
byte[] results=entryHeader.getBytes();
|
||||||
results=addBytes(results, mFlagEntryType.getBytes());
|
|
||||||
results=addBytes(results, mByteFlagsB.getBytes());
|
|
||||||
results=addBytes(results, mSpecReference.getBytes());
|
results=addBytes(results, mSpecReference.getBytes());
|
||||||
results=addBytes(results, mResValue.getBytes());
|
results=addBytes(results, mResValue.getBytes());
|
||||||
return results;
|
return results;
|
||||||
@ -612,8 +588,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
mHeaderSize -> 2 bytes
|
entryHeader -> 4 bytes
|
||||||
mFlags -> 2 bytes
|
|
||||||
mSpecReference -> 4 bytes
|
mSpecReference -> 4 bytes
|
||||||
-------
|
-------
|
||||||
Total = 8 bytes, thus this value is always fixed no need to re-count
|
Total = 8 bytes, thus this value is always fixed no need to re-count
|
||||||
@ -633,9 +608,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
counter.addCount(countBytes());
|
counter.addCount(countBytes());
|
||||||
mHeaderSize.onCountUpTo(counter);
|
entryHeader.onCountUpTo(counter);
|
||||||
mFlagEntryType.onCountUpTo(counter);
|
|
||||||
mByteFlagsB.onCountUpTo(counter);
|
|
||||||
mSpecReference.onCountUpTo(counter);
|
mSpecReference.onCountUpTo(counter);
|
||||||
mResValue.onCountUpTo(counter);
|
mResValue.onCountUpTo(counter);
|
||||||
}
|
}
|
||||||
@ -644,9 +617,7 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
if(isNull()){
|
if(isNull()){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int result=mHeaderSize.writeBytes(stream);
|
int result=entryHeader.writeBytes(stream);
|
||||||
result+= mFlagEntryType.writeBytes(stream);
|
|
||||||
result+=mByteFlagsB.writeBytes(stream);
|
|
||||||
result+= mSpecReference.writeBytes(stream);
|
result+= mSpecReference.writeBytes(stream);
|
||||||
result+=mResValue.writeBytes(stream);
|
result+=mResValue.writeBytes(stream);
|
||||||
return result;
|
return result;
|
||||||
@ -695,15 +666,12 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
public void onReadBytes(BlockReader reader) throws IOException{
|
public void onReadBytes(BlockReader reader) throws IOException{
|
||||||
setNull(false);
|
setNull(false);
|
||||||
removeResValue();
|
removeResValue();
|
||||||
mHeaderSize.readBytes(reader);
|
entryHeader.readBytes(reader);
|
||||||
mFlagEntryType.readBytes(reader);
|
|
||||||
mByteFlagsB.readBytes(reader);
|
|
||||||
mSpecReference.readBytes(reader);
|
mSpecReference.readBytes(reader);
|
||||||
createResValue();
|
createResValue();
|
||||||
mResValue.readBytes(reader);
|
mResValue.readBytes(reader);
|
||||||
updatePackage();
|
updatePackage();
|
||||||
updateSpecRef();
|
updateSpecRef();
|
||||||
mResValue.onDataLoaded();
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
@ -715,10 +683,10 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
if(isEntryTypeBag()){
|
if(isEntryTypeBag()){
|
||||||
jsonObject.put(NAME_is_bag, true);
|
jsonObject.put(NAME_is_bag, true);
|
||||||
}
|
}
|
||||||
if(isEntryTypePublic()){
|
if(isWeak()){
|
||||||
jsonObject.put(NAME_is_public, true);
|
jsonObject.put(NAME_is_weak, true);
|
||||||
}
|
}
|
||||||
if(isEntryTypeShared()){
|
if(isPublic()){
|
||||||
jsonObject.put(NAME_is_shared, true);
|
jsonObject.put(NAME_is_shared, true);
|
||||||
}
|
}
|
||||||
jsonObject.put(NAME_value, getResValue().toJson());
|
jsonObject.put(NAME_value, getResValue().toJson());
|
||||||
@ -737,8 +705,8 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
baseResValue=new ResValueInt();
|
baseResValue=new ResValueInt();
|
||||||
}
|
}
|
||||||
setResValue(baseResValue);
|
setResValue(baseResValue);
|
||||||
setEntryTypeShared(json.optBoolean(NAME_is_shared, false));
|
setPublic(json.optBoolean(NAME_is_shared, false));
|
||||||
setEntryTypePublic(json.optBoolean(NAME_is_public, false));
|
setWeak(json.optBoolean(NAME_is_weak, false));
|
||||||
setName(json.getString(NAME_entry_name));
|
setName(json.getString(NAME_entry_name));
|
||||||
baseResValue.fromJson(json.getJSONObject(NAME_value));
|
baseResValue.fromJson(json.getJSONObject(NAME_value));
|
||||||
mResValue.onDataLoaded();
|
mResValue.onDataLoaded();
|
||||||
@ -765,8 +733,8 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
SpecString spec = getPackageBlock()
|
SpecString spec = getPackageBlock()
|
||||||
.getSpecStringPool().getOrCreate(name);
|
.getSpecStringPool().getOrCreate(name);
|
||||||
setSpecReference(spec.getIndex());
|
setSpecReference(spec.getIndex());
|
||||||
setEntryTypeShared(entryBlock.isEntryTypeShared());
|
setPublic(entryBlock.isPublic());
|
||||||
setEntryTypePublic(entryBlock.isEntryTypePublic());
|
setWeak(entryBlock.isWeak());
|
||||||
}
|
}
|
||||||
private ResValueBag getOrCreateResValueBag(){
|
private ResValueBag getOrCreateResValueBag(){
|
||||||
if(mResValue instanceof ResValueBag){
|
if(mResValue instanceof ResValueBag){
|
||||||
@ -833,13 +801,15 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static short HEADER_SIZE_BAG = 0x0010;
|
private static final int OFFSET_SIZE = 0;
|
||||||
private final static short HEADER_SIZE_INT = 0x0008;
|
private static final int OFFSET_FLAGS = 2;
|
||||||
|
private static final short HEADER_SIZE_BAG = 0x0010;
|
||||||
|
private static final short HEADER_SIZE_INT = 0x0008;
|
||||||
|
|
||||||
public static final String NAME_entry_name ="entry_name";
|
public static final String NAME_entry_name ="entry_name";
|
||||||
private static final String NAME_is_bag="is_bag";
|
private static final String NAME_is_bag="is_bag";
|
||||||
private static final String NAME_is_shared="is_shared";
|
private static final String NAME_is_shared="is_shared";
|
||||||
private static final String NAME_is_public="is_public";
|
private static final String NAME_is_weak = "is_weak";
|
||||||
private static final String NAME_value="value";
|
private static final String NAME_value="value";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,9 @@ public class ResValueBagItem extends BaseResValueItem{
|
|||||||
}
|
}
|
||||||
void refreshTableReference(){
|
void refreshTableReference(){
|
||||||
if(getValueType()==ValueType.STRING){
|
if(getValueType()==ValueType.STRING){
|
||||||
addTableReference(getTableStringReference());
|
if(!hasTableReference()){
|
||||||
|
addTableReference(getTableStringReference());
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
removeTableReference();
|
removeTableReference();
|
||||||
}
|
}
|
||||||
|
@ -48,11 +48,16 @@ public class XMLElement extends XMLNode{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addText(XMLText text){
|
public void addText(XMLText text){
|
||||||
|
addTextInternal(text, true);
|
||||||
|
}
|
||||||
|
private void addTextInternal(XMLText text, boolean addSupper){
|
||||||
if(text==null){
|
if(text==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mTexts.add(text);
|
mTexts.add(text);
|
||||||
super.addChildNode(text);
|
if(addSupper){
|
||||||
|
super.addChildNodeInternal(text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void appendText(String text){
|
private void appendText(String text){
|
||||||
if(text==null || text.length()==0){
|
if(text==null || text.length()==0){
|
||||||
@ -171,7 +176,7 @@ public class XMLElement extends XMLNode{
|
|||||||
}
|
}
|
||||||
public XMLElement createElement(String tag) {
|
public XMLElement createElement(String tag) {
|
||||||
XMLElement baseElement=new XMLElement(tag);
|
XMLElement baseElement=new XMLElement(tag);
|
||||||
addChildNoCheck(baseElement);
|
addChildNoCheck(baseElement, true);
|
||||||
return baseElement;
|
return baseElement;
|
||||||
}
|
}
|
||||||
public void addChild(Collection<XMLElement> elements) {
|
public void addChild(Collection<XMLElement> elements) {
|
||||||
@ -183,7 +188,7 @@ public class XMLElement extends XMLNode{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void addChild(XMLElement child) {
|
public void addChild(XMLElement child) {
|
||||||
addChildNoCheck(child);
|
addChildNoCheck(child, true);
|
||||||
}
|
}
|
||||||
private void clearChildElements(){
|
private void clearChildElements(){
|
||||||
mChildes.clear();
|
mChildes.clear();
|
||||||
@ -238,6 +243,9 @@ public class XMLElement extends XMLNode{
|
|||||||
mComments=null;
|
mComments=null;
|
||||||
}
|
}
|
||||||
public void addComment(XMLComment commentElement) {
|
public void addComment(XMLComment commentElement) {
|
||||||
|
addCommentInternal(commentElement, true);
|
||||||
|
}
|
||||||
|
void addCommentInternal(XMLComment commentElement, boolean addSuper) {
|
||||||
if(commentElement==null){
|
if(commentElement==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -247,7 +255,9 @@ public class XMLElement extends XMLNode{
|
|||||||
mComments.add(commentElement);
|
mComments.add(commentElement);
|
||||||
commentElement.setIndent(getIndent());
|
commentElement.setIndent(getIndent());
|
||||||
commentElement.setParent(this);
|
commentElement.setParent(this);
|
||||||
super.addChildNode(commentElement);
|
if(addSuper){
|
||||||
|
super.addChildNodeInternal(commentElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void removeChildElements(){
|
public void removeChildElements(){
|
||||||
mChildes.clear();
|
mChildes.clear();
|
||||||
@ -413,14 +423,26 @@ public class XMLElement extends XMLNode{
|
|||||||
void setParent(XMLElement baseElement){
|
void setParent(XMLElement baseElement){
|
||||||
mParent=baseElement;
|
mParent=baseElement;
|
||||||
}
|
}
|
||||||
private void addChildNoCheck(XMLElement child){
|
@Override
|
||||||
|
void onChildAdded(XMLNode xmlNode){
|
||||||
|
if(xmlNode instanceof XMLComment){
|
||||||
|
addCommentInternal((XMLComment) xmlNode, false);
|
||||||
|
}else if(xmlNode instanceof XMLElement){
|
||||||
|
addChildNoCheck((XMLElement) xmlNode, false);
|
||||||
|
}else if(xmlNode instanceof XMLText){
|
||||||
|
addTextInternal((XMLText) xmlNode, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void addChildNoCheck(XMLElement child, boolean addSupper){
|
||||||
if(child==null || child == this){
|
if(child==null || child == this){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
child.setParent(this);
|
child.setParent(this);
|
||||||
child.setIndent(getChildIndent());
|
child.setIndent(getChildIndent());
|
||||||
mChildes.add(child);
|
mChildes.add(child);
|
||||||
super.addChildNode(child);
|
if(addSupper){
|
||||||
|
super.addChildNodeInternal(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public int getLevel(){
|
public int getLevel(){
|
||||||
int rs=0;
|
int rs=0;
|
||||||
@ -579,12 +601,19 @@ public class XMLElement extends XMLNode{
|
|||||||
public boolean hasTextContent() {
|
public boolean hasTextContent() {
|
||||||
return mTexts.size()>0;
|
return mTexts.size()>0;
|
||||||
}
|
}
|
||||||
|
public String getText(){
|
||||||
|
if(mTexts.size()==0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mTexts.get(0).getText();
|
||||||
|
}
|
||||||
public void setTextContent(String text){
|
public void setTextContent(String text){
|
||||||
setTextContent(text, true);
|
setTextContent(text, true);
|
||||||
}
|
}
|
||||||
public void setTextContent(String text, boolean escape){
|
public void setTextContent(String text, boolean escape){
|
||||||
clearChildElements();
|
clearChildElements();
|
||||||
clearTexts();
|
clearTexts();
|
||||||
|
super.getChildNodes().clear();
|
||||||
if(escape){
|
if(escape){
|
||||||
text=XMLUtil.escapeXmlChars(text);
|
text=XMLUtil.escapeXmlChars(text);
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,37 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class XMLNode {
|
public abstract class XMLNode {
|
||||||
|
private int mLineNumber;
|
||||||
|
private int mColumnNumber;
|
||||||
private final List<XMLNode> mChildNodes = new ArrayList<>();
|
private final List<XMLNode> mChildNodes = new ArrayList<>();
|
||||||
|
|
||||||
void addChildNode(XMLNode xmlNode){
|
public int getColumnNumber() {
|
||||||
if(xmlNode!=null && canAdd(xmlNode)){
|
return mColumnNumber;
|
||||||
mChildNodes.add(xmlNode);
|
}
|
||||||
|
public void setColumnNumber(int columnNumber) {
|
||||||
|
this.mColumnNumber = columnNumber;
|
||||||
|
}
|
||||||
|
public int getLineNumber() {
|
||||||
|
return mLineNumber;
|
||||||
|
}
|
||||||
|
public void setLineNumber(int lineNumber) {
|
||||||
|
this.mLineNumber = lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChildNode(XMLNode xmlNode){
|
||||||
|
boolean addOk=addChildNodeInternal(xmlNode);
|
||||||
|
if(addOk){
|
||||||
|
onChildAdded(xmlNode);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
boolean addChildNodeInternal(XMLNode xmlNode){
|
||||||
|
if(xmlNode!=null && canAdd(xmlNode)){
|
||||||
|
return mChildNodes.add(xmlNode);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void onChildAdded(XMLNode xmlNode){
|
||||||
|
|
||||||
}
|
}
|
||||||
boolean canAdd(XMLNode xmlNode){
|
boolean canAdd(XMLNode xmlNode){
|
||||||
return !mChildNodes.contains(xmlNode);
|
return !mChildNodes.contains(xmlNode);
|
||||||
|
@ -26,6 +26,11 @@ public class XMLText extends XMLNode{
|
|||||||
public XMLText(){
|
public XMLText(){
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChildNode(XMLNode xmlNode){
|
||||||
|
throw new IllegalArgumentException("Can not add xml node on text: "+xmlNode);
|
||||||
|
}
|
||||||
public String getText(){
|
public String getText(){
|
||||||
return getText(true);
|
return getText(true);
|
||||||
}
|
}
|
||||||
|
@ -425,6 +425,10 @@ public class MXParser implements XmlPullParser
|
|||||||
public InputStream getInputStream(){
|
public InputStream getInputStream(){
|
||||||
return inputStream;
|
return inputStream;
|
||||||
}
|
}
|
||||||
|
public Reader getReader(){
|
||||||
|
reset();
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
public String getInputEncoding() {
|
public String getInputEncoding() {
|
||||||
return inputEncoding;
|
return inputEncoding;
|
||||||
|
@ -45,7 +45,7 @@ public class XMLDocumentParser {
|
|||||||
public XMLDocument parse() throws XMLParseException {
|
public XMLDocument parse() throws XMLParseException {
|
||||||
try {
|
try {
|
||||||
XMLDocument document= parseDocument();
|
XMLDocument document= parseDocument();
|
||||||
closeFileInputStream();
|
close();
|
||||||
return document;
|
return document;
|
||||||
} catch (XmlPullParserException | IOException e) {
|
} catch (XmlPullParserException | IOException e) {
|
||||||
XMLParseException ex=new XMLParseException(e.getMessage());
|
XMLParseException ex=new XMLParseException(e.getMessage());
|
||||||
@ -53,12 +53,20 @@ public class XMLDocumentParser {
|
|||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void close(){
|
||||||
|
closeReader();
|
||||||
|
closeFileInputStream();
|
||||||
|
mResDocument=null;
|
||||||
|
mCurrentElement=null;
|
||||||
|
mCurrentText=null;
|
||||||
|
mComments=null;
|
||||||
|
}
|
||||||
private void closeFileInputStream(){
|
private void closeFileInputStream(){
|
||||||
if(!(mParser instanceof MXParser)){
|
if(!(mParser instanceof MXParser)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MXParser mxParser=(MXParser) mParser;
|
MXParser parser=(MXParser) mParser;
|
||||||
InputStream inputStream = mxParser.getInputStream();
|
InputStream inputStream = parser.getInputStream();
|
||||||
if(!(inputStream instanceof FileInputStream)){
|
if(!(inputStream instanceof FileInputStream)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -67,6 +75,19 @@ public class XMLDocumentParser {
|
|||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void closeReader(){
|
||||||
|
if(!(mParser instanceof MXParser)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MXParser parser=(MXParser) mParser;
|
||||||
|
Reader reader = parser.getReader();
|
||||||
|
if(reader!=null){
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private XMLDocument parseDocument() throws XmlPullParserException, IOException {
|
private XMLDocument parseDocument() throws XmlPullParserException, IOException {
|
||||||
mResDocument=null;
|
mResDocument=null;
|
||||||
@ -121,6 +142,8 @@ public class XMLDocumentParser {
|
|||||||
}else {
|
}else {
|
||||||
mCurrentElement=mCurrentElement.createElement(name);
|
mCurrentElement=mCurrentElement.createElement(name);
|
||||||
}
|
}
|
||||||
|
mCurrentElement.setColumnNumber(mParser.getColumnNumber());
|
||||||
|
mCurrentElement.setLineNumber(mParser.getLineNumber());
|
||||||
checkIndent();
|
checkIndent();
|
||||||
flushComments(mCurrentElement);
|
flushComments(mCurrentElement);
|
||||||
String ns=mParser.getNamespace();
|
String ns=mParser.getNamespace();
|
||||||
@ -284,6 +307,8 @@ public class XMLDocumentParser {
|
|||||||
}
|
}
|
||||||
XMLComment commentElement=new XMLComment();
|
XMLComment commentElement=new XMLComment();
|
||||||
commentElement.setCommentText(commentText);
|
commentElement.setCommentText(commentText);
|
||||||
|
commentElement.setColumnNumber(mParser.getColumnNumber());
|
||||||
|
commentElement.setLineNumber(mParser.getLineNumber());
|
||||||
addComment(commentElement);
|
addComment(commentElement);
|
||||||
}
|
}
|
||||||
private void addComment(XMLComment ce){
|
private void addComment(XMLComment ce){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user