mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 14:24:25 +02:00
rename classes
This commit is contained in:
parent
3f7dc3bf9f
commit
7430b40c54
@ -24,7 +24,7 @@ import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
|||||||
import com.reandroid.arsc.group.StringGroup;
|
import com.reandroid.arsc.group.StringGroup;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -180,11 +180,11 @@ public class ApkModule {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for(TableString tableString:groupTableString.listItems()){
|
for(TableString tableString:groupTableString.listItems()){
|
||||||
List<EntryBlock> entryBlockList = tableString.listReferencedEntries(true);
|
List<Entry> entryList = tableString.listReferencedEntries(true);
|
||||||
if(entryBlockList.size()==0){
|
if(entryList.size()==0){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ResFile resFile=new ResFile(inputSource, entryBlockList);
|
ResFile resFile=new ResFile(inputSource, entryList);
|
||||||
results.add(resFile);
|
results.add(resFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,8 +107,8 @@ import java.util.*;
|
|||||||
}
|
}
|
||||||
private void decodeResRaw(File outDir, ResFile resFile)
|
private void decodeResRaw(File outDir, ResFile resFile)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
EntryBlock entryBlock=resFile.pickOne();
|
Entry entry =resFile.pickOne();
|
||||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
PackageBlock packageBlock= entry.getPackageBlock();
|
||||||
|
|
||||||
File pkgDir=new File(outDir, getPackageDirName(packageBlock));
|
File pkgDir=new File(outDir, getPackageDirName(packageBlock));
|
||||||
File resDir=new File(pkgDir, ApkUtil.RES_DIR_NAME);
|
File resDir=new File(pkgDir, ApkUtil.RES_DIR_NAME);
|
||||||
@ -128,8 +128,8 @@ import java.util.*;
|
|||||||
}
|
}
|
||||||
private void decodeResXml(EntryStore entryStore, File outDir, ResFile resFile)
|
private void decodeResXml(EntryStore entryStore, File outDir, ResFile resFile)
|
||||||
throws IOException, XMLException{
|
throws IOException, XMLException{
|
||||||
EntryBlock entryBlock=resFile.pickOne();
|
Entry entry =resFile.pickOne();
|
||||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
PackageBlock packageBlock= entry.getPackageBlock();
|
||||||
ResXmlDocument resXmlDocument =new ResXmlDocument();
|
ResXmlDocument resXmlDocument =new ResXmlDocument();
|
||||||
resXmlDocument.readBytes(resFile.getInputSource().openStream());
|
resXmlDocument.readBytes(resFile.getInputSource().openStream());
|
||||||
|
|
||||||
@ -181,24 +181,24 @@ import java.util.*;
|
|||||||
xmlDocument.save(file, true);
|
xmlDocument.save(file, true);
|
||||||
addDecodedPath(AndroidManifestBlock.FILE_NAME);
|
addDecodedPath(AndroidManifestBlock.FILE_NAME);
|
||||||
}
|
}
|
||||||
private void addDecodedEntry(EntryBlock entryBlock){
|
private void addDecodedEntry(Entry entry){
|
||||||
if(entryBlock.isNull()){
|
if(entry.isNull()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int resourceId=entryBlock.getResourceId();
|
int resourceId= entry.getResourceId();
|
||||||
Set<ResConfig> resConfigSet=decodedEntries.get(resourceId);
|
Set<ResConfig> resConfigSet=decodedEntries.get(resourceId);
|
||||||
if(resConfigSet==null){
|
if(resConfigSet==null){
|
||||||
resConfigSet=new HashSet<>();
|
resConfigSet=new HashSet<>();
|
||||||
decodedEntries.put(resourceId, resConfigSet);
|
decodedEntries.put(resourceId, resConfigSet);
|
||||||
}
|
}
|
||||||
resConfigSet.add(entryBlock.getResConfig());
|
resConfigSet.add(entry.getResConfig());
|
||||||
}
|
}
|
||||||
private boolean containsDecodedEntry(EntryBlock entryBlock){
|
private boolean containsDecodedEntry(Entry entry){
|
||||||
Set<ResConfig> resConfigSet=decodedEntries.get(entryBlock.getResourceId());
|
Set<ResConfig> resConfigSet=decodedEntries.get(entry.getResourceId());
|
||||||
if(resConfigSet==null){
|
if(resConfigSet==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return resConfigSet.contains(entryBlock.getResConfig());
|
return resConfigSet.contains(entry.getResConfig());
|
||||||
}
|
}
|
||||||
private void decodeValues(EntryStore entryStore, File outDir, TableBlock tableBlock) throws IOException {
|
private void decodeValues(EntryStore entryStore, File outDir, TableBlock tableBlock) throws IOException {
|
||||||
for(PackageBlock packageBlock:tableBlock.listPackages()){
|
for(PackageBlock packageBlock:tableBlock.listPackages()){
|
||||||
@ -221,11 +221,11 @@ import java.util.*;
|
|||||||
private void decodeValues(EntryStore entryStore, File outDir, TypeBlock typeBlock) throws IOException {
|
private void decodeValues(EntryStore entryStore, File outDir, TypeBlock typeBlock) throws IOException {
|
||||||
XMLDocument xmlDocument = new XMLDocument("resources");
|
XMLDocument xmlDocument = new XMLDocument("resources");
|
||||||
XMLElement docElement = xmlDocument.getDocumentElement();
|
XMLElement docElement = xmlDocument.getDocumentElement();
|
||||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
if(containsDecodedEntry(entryBlock)){
|
if(containsDecodedEntry(entry)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
docElement.addChild(decodeValue(entryStore, entryBlock));
|
docElement.addChild(decodeValue(entryStore, entry));
|
||||||
}
|
}
|
||||||
if(docElement.getChildesCount()==0){
|
if(docElement.getChildesCount()==0){
|
||||||
return;
|
return;
|
||||||
@ -240,28 +240,28 @@ import java.util.*;
|
|||||||
file=new File(file, type+".xml");
|
file=new File(file, type+".xml");
|
||||||
xmlDocument.save(file, false);
|
xmlDocument.save(file, false);
|
||||||
}
|
}
|
||||||
private XMLElement decodeValue(EntryStore entryStore, EntryBlock entryBlock){
|
private XMLElement decodeValue(EntryStore entryStore, Entry entry){
|
||||||
XMLElement element=new XMLElement(entryBlock.getTypeName());
|
XMLElement element=new XMLElement(entry.getTypeName());
|
||||||
int resourceId=entryBlock.getResourceId();
|
int resourceId= entry.getResourceId();
|
||||||
XMLAttribute attribute=new XMLAttribute("name", entryBlock.getName());
|
XMLAttribute attribute=new XMLAttribute("name", entry.getName());
|
||||||
element.addAttribute(attribute);
|
element.addAttribute(attribute);
|
||||||
attribute.setNameId(resourceId);
|
attribute.setNameId(resourceId);
|
||||||
element.setResourceId(resourceId);
|
element.setResourceId(resourceId);
|
||||||
if(!entryBlock.isEntryTypeBag()){
|
if(!entry.isComplex()){
|
||||||
ResValueInt resValueInt=(ResValueInt) entryBlock.getResValue();
|
ResValue resValue =(ResValue) entry.getTableEntry().getValue();
|
||||||
if(resValueInt.getValueType()== ValueType.STRING){
|
if(resValue.getValueType()== ValueType.STRING){
|
||||||
XmlHelper.setTextContent(element,
|
XmlHelper.setTextContent(element,
|
||||||
resValueInt.getValueAsPoolString());
|
resValue.getDataAsPoolString());
|
||||||
}else {
|
}else {
|
||||||
String value = ValueDecoder.decodeEntryValue(entryStore,
|
String value = ValueDecoder.decodeEntryValue(entryStore,
|
||||||
entryBlock.getPackageBlock(),
|
entry.getPackageBlock(),
|
||||||
resValueInt.getValueType(),
|
resValue.getValueType(),
|
||||||
resValueInt.getData());
|
resValue.getData());
|
||||||
element.setTextContent(value);
|
element.setTextContent(value);
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
ResValueBag resValueBag=(ResValueBag) entryBlock.getResValue();
|
ResTableMapEntry mapEntry = (ResTableMapEntry) entry.getTableEntry();
|
||||||
xmlBagDecoder.decode(resValueBag, element);
|
xmlBagDecoder.decode(mapEntry, element);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
|
@ -19,7 +19,7 @@ import com.reandroid.archive.InputSource;
|
|||||||
import com.reandroid.apk.xmlencoder.XMLEncodeSource;
|
import com.reandroid.apk.xmlencoder.XMLEncodeSource;
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
import com.reandroid.arsc.chunk.TypeBlock;
|
||||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -28,23 +28,23 @@ import java.io.InputStream;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ResFile {
|
public class ResFile {
|
||||||
private final List<EntryBlock> entryBlockList;
|
private final List<Entry> entryList;
|
||||||
private final InputSource inputSource;
|
private final InputSource inputSource;
|
||||||
private boolean mBinXml;
|
private boolean mBinXml;
|
||||||
private boolean mBinXmlChecked;
|
private boolean mBinXmlChecked;
|
||||||
private String mFileExtension;
|
private String mFileExtension;
|
||||||
private boolean mFileExtensionChecked;
|
private boolean mFileExtensionChecked;
|
||||||
private EntryBlock mSelectedEntryBlock;
|
private Entry mSelectedEntry;
|
||||||
public ResFile(InputSource inputSource, List<EntryBlock> entryBlockList){
|
public ResFile(InputSource inputSource, List<Entry> entryList){
|
||||||
this.inputSource=inputSource;
|
this.inputSource=inputSource;
|
||||||
this.entryBlockList=entryBlockList;
|
this.entryList = entryList;
|
||||||
}
|
}
|
||||||
public List<EntryBlock> getEntryBlockList(){
|
public List<Entry> getEntryList(){
|
||||||
return entryBlockList;
|
return entryList;
|
||||||
}
|
}
|
||||||
public String validateTypeDirectoryName(){
|
public String validateTypeDirectoryName(){
|
||||||
EntryBlock entryBlock=pickOne();
|
Entry entry =pickOne();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String path=getFilePath();
|
String path=getFilePath();
|
||||||
@ -61,34 +61,34 @@ public class ResFile {
|
|||||||
i++;
|
i++;
|
||||||
name=path.substring(i);
|
name=path.substring(i);
|
||||||
}
|
}
|
||||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
TypeBlock typeBlock= entry.getTypeBlock();
|
||||||
String typeName=typeBlock.getTypeName()+typeBlock.getResConfig().getQualifiers();
|
String typeName=typeBlock.getTypeName()+typeBlock.getResConfig().getQualifiers();
|
||||||
return root+typeName+"/"+name;
|
return root+typeName+"/"+name;
|
||||||
}
|
}
|
||||||
public EntryBlock pickOne(){
|
public Entry pickOne(){
|
||||||
if(mSelectedEntryBlock==null){
|
if(mSelectedEntry ==null){
|
||||||
mSelectedEntryBlock=selectOne();
|
mSelectedEntry =selectOne();
|
||||||
}
|
}
|
||||||
return mSelectedEntryBlock;
|
return mSelectedEntry;
|
||||||
}
|
}
|
||||||
private EntryBlock selectOne(){
|
private Entry selectOne(){
|
||||||
List<EntryBlock> entryList = entryBlockList;
|
List<Entry> entryList = this.entryList;
|
||||||
if(entryList.size()==0){
|
if(entryList.size()==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for(EntryBlock entryBlock:entryList){
|
for(Entry entry :entryList){
|
||||||
if(!entryBlock.isNull() && entryBlock.isDefault()){
|
if(!entry.isNull() && entry.isDefault()){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(EntryBlock entryBlock:entryList){
|
for(Entry entry :entryList){
|
||||||
if(!entryBlock.isNull()){
|
if(!entry.isNull()){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(EntryBlock entryBlock:entryList){
|
for(Entry entry :entryList){
|
||||||
if(entryBlock.isDefault()){
|
if(entry.isDefault()){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return entryList.get(0);
|
return entryList.get(0);
|
||||||
@ -98,8 +98,13 @@ public class ResFile {
|
|||||||
}
|
}
|
||||||
public void setFilePath(String filePath){
|
public void setFilePath(String filePath){
|
||||||
getInputSource().setAlias(filePath);
|
getInputSource().setAlias(filePath);
|
||||||
for(EntryBlock entryBlock:entryBlockList){
|
for(Entry entry : entryList){
|
||||||
entryBlock.getValueAsTableString().set(filePath);
|
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||||
|
if(!(tableEntry instanceof ResTableEntry)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ResValue resValue = ((ResTableEntry) tableEntry).getValue();
|
||||||
|
resValue.setValueAsString(filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public InputSource getInputSource() {
|
public InputSource getInputSource() {
|
||||||
@ -143,13 +148,13 @@ public class ResFile {
|
|||||||
return new File(dir, path);
|
return new File(dir, path);
|
||||||
}
|
}
|
||||||
public String buildPath(){
|
public String buildPath(){
|
||||||
EntryBlock entryBlock=pickOne();
|
Entry entry =pickOne();
|
||||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
TypeBlock typeBlock= entry.getTypeBlock();
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(typeBlock.getTypeName());
|
builder.append(typeBlock.getTypeName());
|
||||||
builder.append(typeBlock.getQualifiers());
|
builder.append(typeBlock.getQualifiers());
|
||||||
builder.append('/');
|
builder.append('/');
|
||||||
builder.append(entryBlock.getName());
|
builder.append(entry.getName());
|
||||||
String ext=getFileExtension();
|
String ext=getFileExtension();
|
||||||
if(ext!=null){
|
if(ext!=null){
|
||||||
builder.append(ext);
|
builder.append(ext);
|
||||||
|
@ -19,7 +19,7 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Header;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
import com.reandroid.json.JSONException;
|
import com.reandroid.json.JSONException;
|
||||||
@ -90,8 +90,8 @@ public class StringPoolBuilder {
|
|||||||
return mSpecNameMap.get(pkgId);
|
return mSpecNameMap.get(pkgId);
|
||||||
}
|
}
|
||||||
private void scan(JSONObject jsonObject){
|
private void scan(JSONObject jsonObject){
|
||||||
if(jsonObject.has(EntryBlock.NAME_entry_name)){
|
if(jsonObject.has(Header.NAME_entry_name)){
|
||||||
addSpecName(jsonObject.optString(EntryBlock.NAME_entry_name));
|
addSpecName(jsonObject.optString(Header.NAME_entry_name));
|
||||||
}
|
}
|
||||||
if(jsonObject.has(ApkUtil.NAME_value_type)){
|
if(jsonObject.has(ApkUtil.NAME_value_type)){
|
||||||
if(ValueType.STRING.name().equals(jsonObject.getString(ApkUtil.NAME_value_type))){
|
if(ValueType.STRING.name().equals(jsonObject.getString(ApkUtil.NAME_value_type))){
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmldecoder;
|
package com.reandroid.apk.xmldecoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
|
|
||||||
@ -27,6 +27,6 @@ abstract class BagDecoder {
|
|||||||
EntryStore getEntryStore(){
|
EntryStore getEntryStore(){
|
||||||
return entryStore;
|
return entryStore;
|
||||||
}
|
}
|
||||||
public abstract void decode(ResValueBag resValueBag, XMLElement parentElement);
|
public abstract void decode(ResTableMapEntry mapEntry, XMLElement parentElement);
|
||||||
public abstract boolean canDecode(ResValueBag resValueBag);
|
public abstract boolean canDecode(ResTableMapEntry mapEntry);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ package com.reandroid.apk.xmldecoder;
|
|||||||
import com.reandroid.apk.ApkUtil;
|
import com.reandroid.apk.ApkUtil;
|
||||||
import com.reandroid.apk.XmlHelper;
|
import com.reandroid.apk.XmlHelper;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -33,16 +33,16 @@ import java.util.Set;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
|
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
|
||||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||||
EntryStore entryStore=getEntryStore();
|
EntryStore entryStore=getEntryStore();
|
||||||
Set<ValueType> valueTypes = new HashSet<>();
|
Set<ValueType> valueTypes = new HashSet<>();
|
||||||
for(int i=0;i<bagItems.length;i++){
|
for(int i=0;i<bagItems.length;i++){
|
||||||
ResValueBagItem bagItem = bagItems[i];
|
ResValueMap bagItem = bagItems[i];
|
||||||
ValueType valueType = bagItem.getValueType();
|
ValueType valueType = bagItem.getValueType();
|
||||||
XMLElement child = new XMLElement("item");
|
XMLElement child = new XMLElement("item");
|
||||||
if(valueType == ValueType.STRING){
|
if(valueType == ValueType.STRING){
|
||||||
XmlHelper.setTextContent(child, bagItem.getValueAsPoolString());
|
XmlHelper.setTextContent(child, bagItem.getDataAsPoolString());
|
||||||
}else {
|
}else {
|
||||||
String value = ValueDecoder.decodeIntEntry(entryStore, bagItem);
|
String value = ValueDecoder.decodeIntEntry(entryStore, bagItem);
|
||||||
child.setTextContent(value);
|
child.setTextContent(value);
|
||||||
@ -57,25 +57,28 @@ import java.util.Set;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean canDecode(ResValueBag resValueBag) {
|
public boolean canDecode(ResTableMapEntry mapEntry) {
|
||||||
return isResBagArrayValue(resValueBag);
|
return isArrayValue(mapEntry);
|
||||||
}
|
}
|
||||||
public static boolean isResBagArrayValue(ResValueBag resValueBag){
|
public static boolean isArrayValue(ResTableMapEntry mapEntry){
|
||||||
int parentId=resValueBag.getParentId();
|
int parentId=mapEntry.getParentId();
|
||||||
if(parentId!=0){
|
if(parentId!=0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||||
if(bagItems==null||bagItems.length==0){
|
if(bagItems==null||bagItems.length==0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int len=bagItems.length;
|
int len=bagItems.length;
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
ResValueBagItem item=bagItems[i];
|
ResValueMap item=bagItems[i];
|
||||||
if(item.getIdHigh()!=0x0100 && item.getIdHigh()!=0x0200){
|
int name = item.getName();
|
||||||
|
int high = (name >> 16) & 0xffff;
|
||||||
|
if(high!=0x0100 && high!=0x0200){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int id=item.getIdLow()-1;
|
int low = name & 0xffff;
|
||||||
|
int id = low - 1;
|
||||||
if(id!=i){
|
if(id!=i){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmldecoder;
|
package com.reandroid.apk.xmldecoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBagItem;
|
import com.reandroid.arsc.value.attribute.AttributeBagItem;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
@ -26,8 +26,8 @@ class XMLAttrDecoder extends BagDecoder{
|
|||||||
super(entryStore);
|
super(entryStore);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void decode(ResValueBag resValueBag, XMLElement parentElement){
|
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement){
|
||||||
AttributeBag attributeBag=AttributeBag.create(resValueBag);
|
AttributeBag attributeBag=AttributeBag.create(mapEntry.getValue());
|
||||||
decodeParentAttributes(parentElement, attributeBag);
|
decodeParentAttributes(parentElement, attributeBag);
|
||||||
|
|
||||||
boolean is_flag=attributeBag.isFlag();
|
boolean is_flag=attributeBag.isFlag();
|
||||||
@ -55,8 +55,8 @@ class XMLAttrDecoder extends BagDecoder{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean canDecode(ResValueBag resValueBag) {
|
public boolean canDecode(ResTableMapEntry mapEntry) {
|
||||||
return AttributeBag.isAttribute(resValueBag);
|
return AttributeBag.isAttribute(mapEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decodeParentAttributes(XMLElement element, AttributeBag attributeBag){
|
private void decodeParentAttributes(XMLElement element, AttributeBag attributeBag){
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmldecoder;
|
package com.reandroid.apk.xmldecoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
|
|
||||||
@ -34,13 +35,13 @@ public class XMLBagDecoder {
|
|||||||
this.decoderList.add(new XMLArrayDecoder(entryStore));
|
this.decoderList.add(new XMLArrayDecoder(entryStore));
|
||||||
this.commonBagDecoder = new XMLCommonBagDecoder(entryStore);
|
this.commonBagDecoder = new XMLCommonBagDecoder(entryStore);
|
||||||
}
|
}
|
||||||
public void decode(ResValueBag resValueBag, XMLElement parentElement){
|
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement){
|
||||||
BagDecoder bagDecoder=getFor(resValueBag);
|
BagDecoder bagDecoder=getFor(mapEntry);
|
||||||
bagDecoder.decode(resValueBag, parentElement);
|
bagDecoder.decode(mapEntry, parentElement);
|
||||||
}
|
}
|
||||||
private BagDecoder getFor(ResValueBag resValueBag){
|
private BagDecoder getFor(ResTableMapEntry mapEntry){
|
||||||
for(BagDecoder bagDecoder:decoderList){
|
for(BagDecoder bagDecoder:decoderList){
|
||||||
if(bagDecoder.canDecode(resValueBag)){
|
if(bagDecoder.canDecode(mapEntry)){
|
||||||
return bagDecoder;
|
return bagDecoder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ package com.reandroid.apk.xmldecoder;
|
|||||||
import com.reandroid.apk.XmlHelper;
|
import com.reandroid.apk.XmlHelper;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -30,12 +30,12 @@ class XMLCommonBagDecoder extends BagDecoder{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
|
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
|
||||||
|
|
||||||
PackageBlock currentPackage=resValueBag
|
PackageBlock currentPackage= mapEntry
|
||||||
.getEntryBlock().getPackageBlock();
|
.getParentEntry().getPackageBlock();
|
||||||
|
|
||||||
int parentId = resValueBag.getParentId();
|
int parentId = mapEntry.getParentId();
|
||||||
String parent;
|
String parent;
|
||||||
if(parentId!=0){
|
if(parentId!=0){
|
||||||
parent = ValueDecoder.decodeEntryValue(getEntryStore(),
|
parent = ValueDecoder.decodeEntryValue(getEntryStore(),
|
||||||
@ -47,20 +47,20 @@ class XMLCommonBagDecoder extends BagDecoder{
|
|||||||
parentElement.setAttribute("parent", parent);
|
parentElement.setAttribute("parent", parent);
|
||||||
}
|
}
|
||||||
int currentPackageId=currentPackage.getId();
|
int currentPackageId=currentPackage.getId();
|
||||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||||
EntryStore entryStore = getEntryStore();
|
EntryStore entryStore = getEntryStore();
|
||||||
for(int i=0;i< bagItems.length;i++){
|
for(int i=0;i< bagItems.length;i++){
|
||||||
ResValueBagItem item=bagItems[i];
|
ResValueMap item=bagItems[i];
|
||||||
int resourceId=item.getId();
|
int resourceId=item.getName();
|
||||||
XMLElement child=new XMLElement("item");
|
XMLElement child=new XMLElement("item");
|
||||||
String name = ValueDecoder.decodeAttributeName(
|
String name = ValueDecoder.decodeAttributeName(
|
||||||
entryStore, currentPackage, item.getId());
|
entryStore, currentPackage, item.getName());
|
||||||
|
|
||||||
child.setAttribute("name", name);
|
child.setAttribute("name", name);
|
||||||
|
|
||||||
ValueType valueType = item.getValueType();
|
ValueType valueType = item.getValueType();
|
||||||
if(valueType == ValueType.STRING){
|
if(valueType == ValueType.STRING){
|
||||||
XmlHelper.setTextContent(child, item.getValueAsPoolString());
|
XmlHelper.setTextContent(child, item.getDataAsPoolString());
|
||||||
}else {
|
}else {
|
||||||
String value = ValueDecoder.decode(entryStore, currentPackageId,
|
String value = ValueDecoder.decode(entryStore, currentPackageId,
|
||||||
resourceId, item.getValueType(), item.getData());
|
resourceId, item.getValueType(), item.getData());
|
||||||
@ -70,7 +70,7 @@ class XMLCommonBagDecoder extends BagDecoder{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean canDecode(ResValueBag resValueBag) {
|
public boolean canDecode(ResTableMapEntry mapEntry) {
|
||||||
return resValueBag!=null;
|
return mapEntry !=null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,7 @@ package com.reandroid.apk.xmldecoder;
|
|||||||
|
|
||||||
import com.reandroid.apk.XmlHelper;
|
import com.reandroid.apk.XmlHelper;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.BaseResValue;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
|
||||||
import com.reandroid.arsc.value.ValueType;
|
|
||||||
import com.reandroid.arsc.value.plurals.PluralsQuantity;
|
import com.reandroid.arsc.value.plurals.PluralsQuantity;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -30,19 +27,19 @@ class XMLPluralsDecoder extends BagDecoder{
|
|||||||
super(entryStore);
|
super(entryStore);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
|
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
|
||||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||||
int len=bagItems.length;
|
int len=bagItems.length;
|
||||||
EntryStore entryStore=getEntryStore();
|
EntryStore entryStore=getEntryStore();
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
ResValueBagItem item = bagItems[i];
|
ResValueMap item = bagItems[i];
|
||||||
|
int low = item.getName() & 0xffff;
|
||||||
PluralsQuantity quantity = PluralsQuantity.valueOf(item.getIdLow());
|
PluralsQuantity quantity = PluralsQuantity.valueOf((short) low);
|
||||||
XMLElement child=new XMLElement("item");
|
XMLElement child=new XMLElement("item");
|
||||||
child.setAttribute("quantity", quantity.toString());
|
child.setAttribute("quantity", quantity.toString());
|
||||||
|
|
||||||
if(item.getValueType() == ValueType.STRING){
|
if(item.getValueType() == ValueType.STRING){
|
||||||
XmlHelper.setTextContent(child, item.getValueAsPoolString());
|
XmlHelper.setTextContent(child, item.getDataAsPoolString());
|
||||||
}else {
|
}else {
|
||||||
String value = ValueDecoder.decodeIntEntry(entryStore, item);
|
String value = ValueDecoder.decodeIntEntry(entryStore, item);
|
||||||
child.setTextContent(value);
|
child.setTextContent(value);
|
||||||
@ -53,27 +50,29 @@ class XMLPluralsDecoder extends BagDecoder{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canDecode(ResValueBag resValueBag) {
|
public boolean canDecode(ResTableMapEntry mapEntry) {
|
||||||
return isResBagPluralsValue(resValueBag);
|
return isResBagPluralsValue(mapEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isResBagPluralsValue(BaseResValue baseResValue){
|
public static boolean isResBagPluralsValue(ResTableMapEntry valueItem){
|
||||||
ResValueBag resValueBag=(ResValueBag)baseResValue;
|
int parentId=valueItem.getParentId();
|
||||||
int parentId=resValueBag.getParentId();
|
|
||||||
if(parentId!=0){
|
if(parentId!=0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
ResValueMap[] bagItems = valueItem.listResValueMap();
|
||||||
if(bagItems==null||bagItems.length==0){
|
if(bagItems==null||bagItems.length==0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int len=bagItems.length;
|
int len=bagItems.length;
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
ResValueBagItem item=bagItems[i];
|
ResValueMap item=bagItems[i];
|
||||||
if(item.getIdHigh()!=0x0100){
|
int name = item.getName();
|
||||||
|
int high = (name >> 16) & 0xffff;
|
||||||
|
if(high!=0x0100){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PluralsQuantity pq=PluralsQuantity.valueOf(item.getIdLow());
|
int low = name & 0xffff;
|
||||||
|
PluralsQuantity pq=PluralsQuantity.valueOf((short) low);
|
||||||
if(pq==null){
|
if(pq==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
import com.reandroid.arsc.item.SpecString;
|
import com.reandroid.arsc.item.SpecString;
|
||||||
import com.reandroid.arsc.util.FrameworkTable;
|
import com.reandroid.arsc.util.FrameworkTable;
|
||||||
import com.reandroid.arsc.util.ResNameMap;
|
import com.reandroid.arsc.util.ResNameMap;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.common.Frameworks;
|
import com.reandroid.common.Frameworks;
|
||||||
import com.reandroid.common.ResourceResolver;
|
import com.reandroid.common.ResourceResolver;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@
|
|||||||
private APKLogger apkLogger;
|
private APKLogger apkLogger;
|
||||||
private boolean mForceCreateNamespaces = true;
|
private boolean mForceCreateNamespaces = true;
|
||||||
private Set<String> mFrameworkPackageNames;
|
private Set<String> mFrameworkPackageNames;
|
||||||
private final ResNameMap<EntryBlock> mLocalResNameMap = new ResNameMap<>();
|
private final ResNameMap<Entry> mLocalResNameMap = new ResNameMap<>();
|
||||||
public EncodeMaterials(){
|
public EncodeMaterials(){
|
||||||
}
|
}
|
||||||
public SpecString getSpecString(String name){
|
public SpecString getSpecString(String name){
|
||||||
@ -49,7 +49,7 @@
|
|||||||
.get(name)
|
.get(name)
|
||||||
.get(0);
|
.get(0);
|
||||||
}
|
}
|
||||||
public EntryBlock getAttributeBlock(String refString){
|
public Entry getAttributeBlock(String refString){
|
||||||
String packageName = null;
|
String packageName = null;
|
||||||
String type = "attr";
|
String type = "attr";
|
||||||
String name = refString;
|
String name = refString;
|
||||||
@ -62,7 +62,7 @@
|
|||||||
|| packageName.equals(getCurrentPackageName())
|
|| packageName.equals(getCurrentPackageName())
|
||||||
|| !isFrameworkPackageName(packageName)){
|
|| !isFrameworkPackageName(packageName)){
|
||||||
|
|
||||||
return getLocalEntryBlock(type, name);
|
return getLocalEntry(type, name);
|
||||||
}
|
}
|
||||||
return getFrameworkEntry(type, name);
|
return getFrameworkEntry(type, name);
|
||||||
}
|
}
|
||||||
@ -105,9 +105,9 @@
|
|||||||
", name="+name);
|
", name="+name);
|
||||||
}
|
}
|
||||||
public int resolveFrameworkResourceId(String packageName, String type, String name){
|
public int resolveFrameworkResourceId(String packageName, String type, String name){
|
||||||
EntryBlock entryBlock = getFrameworkEntry(packageName, type, name);
|
Entry entry = getFrameworkEntry(packageName, type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock.getResourceId();
|
return entry.getResourceId();
|
||||||
}
|
}
|
||||||
throw new EncodeException("Framework entry not found: " +
|
throw new EncodeException("Framework entry not found: " +
|
||||||
"package="+packageName+
|
"package="+packageName+
|
||||||
@ -115,9 +115,9 @@
|
|||||||
", name="+name);
|
", name="+name);
|
||||||
}
|
}
|
||||||
public int resolveFrameworkResourceId(int packageId, String type, String name){
|
public int resolveFrameworkResourceId(int packageId, String type, String name){
|
||||||
EntryBlock entryBlock = getFrameworkEntry(packageId, type, name);
|
Entry entry = getFrameworkEntry(packageId, type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock.getResourceId();
|
return entry.getResourceId();
|
||||||
}
|
}
|
||||||
throw new EncodeException("Framework entry not found: " +
|
throw new EncodeException("Framework entry not found: " +
|
||||||
"packageId="+String.format("0x%02x", packageId)+
|
"packageId="+String.format("0x%02x", packageId)+
|
||||||
@ -141,23 +141,23 @@
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public EntryBlock getLocalEntryBlock(String type, String name){
|
public Entry getLocalEntry(String type, String name){
|
||||||
EntryBlock entryBlock=mLocalResNameMap.get(type, name);
|
Entry entry =mLocalResNameMap.get(type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
loadLocalEntryBlockMap(type);
|
loadLocalEntryMap(type);
|
||||||
entryBlock=mLocalResNameMap.get(type, name);
|
entry =mLocalResNameMap.get(type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
entryBlock= searchLocalEntryBlock(type, name);
|
entry = searchLocalEntry(type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
mLocalResNameMap.add(type, name, entryBlock);
|
mLocalResNameMap.add(type, name, entry);
|
||||||
}
|
}
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
private EntryBlock searchLocalEntryBlock(String type, String name){
|
private Entry searchLocalEntry(String type, String name){
|
||||||
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
||||||
if(type.equals(entryGroup.getTypeName()) &&
|
if(type.equals(entryGroup.getTypeName()) &&
|
||||||
name.equals(entryGroup.getSpecName())){
|
name.equals(entryGroup.getSpecName())){
|
||||||
@ -167,9 +167,9 @@
|
|||||||
SpecTypePair specTypePair=currentPackage.searchByTypeName(type);
|
SpecTypePair specTypePair=currentPackage.searchByTypeName(type);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
if(name.equals(entryBlock.getName())){
|
if(name.equals(entry.getName())){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -182,9 +182,9 @@
|
|||||||
specTypePair=packageBlock.searchByTypeName(type);
|
specTypePair=packageBlock.searchByTypeName(type);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
if(name.equals(entryBlock.getName())){
|
if(name.equals(entry.getName())){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -193,25 +193,25 @@
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private void loadLocalEntryBlockMap(String type){
|
private void loadLocalEntryMap(String type){
|
||||||
ResNameMap<EntryBlock> localMap = mLocalResNameMap;
|
ResNameMap<Entry> localMap = mLocalResNameMap;
|
||||||
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
||||||
SpecTypePair specTypePair=packageBlock.searchByTypeName(type);
|
SpecTypePair specTypePair=packageBlock.searchByTypeName(type);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
localMap.add(entryBlock.getTypeName(),
|
localMap.add(entry.getTypeName(),
|
||||||
entryBlock.getName(), entryBlock);
|
entry.getName(), entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public EntryBlock getFrameworkEntry(String type, String name){
|
public Entry getFrameworkEntry(String type, String name){
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
EntryBlock entryBlock = table.searchEntryBlock(type, name);
|
Entry entry = table.searchEntry(type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -232,26 +232,26 @@
|
|||||||
mFrameworkPackageNames=results;
|
mFrameworkPackageNames=results;
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
public EntryBlock getFrameworkEntry(String packageName, String type, String name){
|
public Entry getFrameworkEntry(String packageName, String type, String name){
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
for(PackageBlock packageBlock:table.listPackages()){
|
for(PackageBlock packageBlock:table.listPackages()){
|
||||||
if(packageName.equals(packageBlock.getName())){
|
if(packageName.equals(packageBlock.getName())){
|
||||||
EntryBlock entryBlock = table.searchEntryBlock(type, name);
|
Entry entry = table.searchEntry(type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public EntryBlock getFrameworkEntry(int packageId, String type, String name){
|
public Entry getFrameworkEntry(int packageId, String type, String name){
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
for(PackageBlock packageBlock:table.listPackages()){
|
for(PackageBlock packageBlock:table.listPackages()){
|
||||||
if(packageId==packageBlock.getId()){
|
if(packageId==packageBlock.getId()){
|
||||||
EntryBlock entryBlock = table.searchEntryBlock(type, name);
|
Entry entry = table.searchEntry(type, name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ package com.reandroid.apk.xmlencoder;
|
|||||||
import com.reandroid.apk.UncompressedFiles;
|
import com.reandroid.apk.UncompressedFiles;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
import com.reandroid.arsc.chunk.TypeBlock;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.xml.source.XMLFileSource;
|
import com.reandroid.xml.source.XMLFileSource;
|
||||||
import com.reandroid.xml.source.XMLSource;
|
import com.reandroid.xml.source.XMLSource;
|
||||||
|
|
||||||
@ -71,12 +71,12 @@ package com.reandroid.apk.xmlencoder;
|
|||||||
String name = EncodeUtil.getEntryNameFromResFile(resFile);
|
String name = EncodeUtil.getEntryNameFromResFile(resFile);
|
||||||
int resourceId=materials.resolveLocalResourceId(type, name);
|
int resourceId=materials.resolveLocalResourceId(type, name);
|
||||||
|
|
||||||
EntryBlock entryBlock=typeBlock
|
Entry entry =typeBlock
|
||||||
.getOrCreateEntry((short) (0xffff & resourceId));
|
.getOrCreateEntry((short) (0xffff & resourceId));
|
||||||
|
|
||||||
String path=EncodeUtil.getEntryPathFromResFile(resFile);
|
String path=EncodeUtil.getEntryPathFromResFile(resFile);
|
||||||
entryBlock.setValueAsString(path);
|
entry.setValueAsString(path);
|
||||||
entryBlock.setSpecReference(materials.getSpecString(name));
|
entry.setSpecReference(materials.getSpecString(name));
|
||||||
InputSource inputSource=createInputSource(path, resFile);
|
InputSource inputSource=createInputSource(path, resFile);
|
||||||
addInputSource(inputSource);
|
addInputSource(inputSource);
|
||||||
return inputSource;
|
return inputSource;
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
import com.reandroid.arsc.chunk.xml.*;
|
import com.reandroid.arsc.chunk.xml.*;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeValueType;
|
import com.reandroid.arsc.value.attribute.AttributeValueType;
|
||||||
@ -105,11 +105,11 @@ public class XMLFileEncoder {
|
|||||||
}
|
}
|
||||||
String name=attribute.getNameWoPrefix();
|
String name=attribute.getNameWoPrefix();
|
||||||
int resourceId=decodeUnknownAttributeHex(name);
|
int resourceId=decodeUnknownAttributeHex(name);
|
||||||
EntryBlock entryBlock=null;
|
Entry entry =null;
|
||||||
if(resourceId==0){
|
if(resourceId==0){
|
||||||
entryBlock=getAttributeBlock(attribute);
|
entry =getAttributeBlock(attribute);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
resourceId=entryBlock.getResourceId();
|
resourceId= entry.getResourceId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResXmlAttribute xmlAttribute =
|
ResXmlAttribute xmlAttribute =
|
||||||
@ -139,9 +139,9 @@ public class XMLFileEncoder {
|
|||||||
xmlAttribute.setData(materials.resolveReference(valueText));
|
xmlAttribute.setData(materials.resolveReference(valueText));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
AttributeBag attributeBag=AttributeBag
|
AttributeBag attributeBag=AttributeBag
|
||||||
.create((ResValueBag) entryBlock.getResValue());
|
.create((ResValueMapArray) entry.getTableEntry().getValue());
|
||||||
|
|
||||||
ValueDecoder.EncodeResult encodeResult =
|
ValueDecoder.EncodeResult encodeResult =
|
||||||
attributeBag.encodeEnumOrFlagValue(valueText);
|
attributeBag.encodeEnumOrFlagValue(valueText);
|
||||||
@ -205,9 +205,9 @@ public class XMLFileEncoder {
|
|||||||
idBuilder.add(id, name);
|
idBuilder.add(id, name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock = getAttributeBlock(attribute);
|
Entry entry = getAttributeBlock(attribute);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
idBuilder.add(entryBlock.getResourceId(), entryBlock.getName());
|
idBuilder.add(entry.getResourceId(), entry.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private int decodeUnknownAttributeHex(String name){
|
private int decodeUnknownAttributeHex(String name){
|
||||||
@ -220,7 +220,7 @@ public class XMLFileEncoder {
|
|||||||
}
|
}
|
||||||
return ValueDecoder.parseHex(name);
|
return ValueDecoder.parseHex(name);
|
||||||
}
|
}
|
||||||
private EntryBlock getAttributeBlock(XMLAttribute attribute){
|
private Entry getAttributeBlock(XMLAttribute attribute){
|
||||||
if(attribute instanceof SchemaAttr){
|
if(attribute instanceof SchemaAttr){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import com.reandroid.arsc.container.SpecTypePair;
|
|||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.item.SpecString;
|
import com.reandroid.arsc.item.SpecString;
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.xml.XMLDocument;
|
import com.reandroid.xml.XMLDocument;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -37,7 +37,7 @@ class XMLValuesEncoder {
|
|||||||
|
|
||||||
int count = documentElement.getChildesCount();
|
int count = documentElement.getChildesCount();
|
||||||
|
|
||||||
typeBlock.getEntryBlockArray().ensureSize(count);
|
typeBlock.getEntryArray().ensureSize(count);
|
||||||
|
|
||||||
for(int i=0;i<count;i++){
|
for(int i=0;i<count;i++){
|
||||||
XMLElement element = documentElement.getChildAt(i);
|
XMLElement element = documentElement.getChildAt(i);
|
||||||
@ -48,45 +48,46 @@ class XMLValuesEncoder {
|
|||||||
String name = element.getAttributeValue("name");
|
String name = element.getAttributeValue("name");
|
||||||
int resourceId = getMaterials()
|
int resourceId = getMaterials()
|
||||||
.resolveLocalResourceId(typeBlock.getTypeName(), name);
|
.resolveLocalResourceId(typeBlock.getTypeName(), name);
|
||||||
EntryBlock entryBlock = typeBlock
|
Entry entry = typeBlock
|
||||||
.getOrCreateEntry((short) (0xffff & resourceId));
|
.getOrCreateEntry((short) (0xffff & resourceId));
|
||||||
|
|
||||||
encodeValue(entryBlock, element);
|
encodeValue(entry, element);
|
||||||
|
|
||||||
SpecString specString = getMaterials().getSpecString(name);
|
SpecString specString = getMaterials().getSpecString(name);
|
||||||
entryBlock.setSpecReference(specString);
|
entry.setSpecReference(specString);
|
||||||
|
entry.getPackageBlock().onEntryAdded(entry);
|
||||||
}
|
}
|
||||||
void encodeValue(EntryBlock entryBlock, XMLElement element){
|
void encodeValue(Entry entry, XMLElement element){
|
||||||
String value = getValue(element);
|
String value = getValue(element);
|
||||||
encodeValue(entryBlock, value);
|
encodeValue(entry, value);
|
||||||
}
|
}
|
||||||
void encodeValue(EntryBlock entryBlock, String value){
|
void encodeValue(Entry entry, String value){
|
||||||
if(EncodeUtil.isEmpty(value)){
|
if(EncodeUtil.isEmpty(value)){
|
||||||
encodeNullValue(entryBlock);
|
encodeNullValue(entry);
|
||||||
}else if(isLiteralEmpty(value)){
|
}else if(isLiteralEmpty(value)){
|
||||||
encodeLiteralEmptyValue(entryBlock, value);
|
encodeLiteralEmptyValue(entry, value);
|
||||||
}else if(isBoolean(value)){
|
}else if(isBoolean(value)){
|
||||||
encodeBooleanValue(entryBlock, value);
|
encodeBooleanValue(entry, value);
|
||||||
}else if(ValueDecoder.isReference(value)){
|
}else if(ValueDecoder.isReference(value)){
|
||||||
encodeReferenceValue(entryBlock, value);
|
encodeReferenceValue(entry, value);
|
||||||
}else {
|
}else {
|
||||||
encodeStringValue(entryBlock, value);
|
encodeStringValue(entry, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void encodeNullValue(EntryBlock entryBlock){
|
void encodeNullValue(Entry entry){
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
void encodeLiteralEmptyValue(EntryBlock entryBlock, String value){
|
void encodeLiteralEmptyValue(Entry entry, String value){
|
||||||
entryBlock.setValueAsRaw(ValueType.NULL, 0);
|
entry.setValueAsRaw(ValueType.NULL, 0);
|
||||||
}
|
}
|
||||||
void encodeBooleanValue(EntryBlock entryBlock, String value){
|
void encodeBooleanValue(Entry entry, String value){
|
||||||
entryBlock.setValueAsBoolean("true".equals(value.toLowerCase()));
|
entry.setValueAsBoolean("true".equals(value.toLowerCase()));
|
||||||
}
|
}
|
||||||
void encodeReferenceValue(EntryBlock entryBlock, String value){
|
void encodeReferenceValue(Entry entry, String value){
|
||||||
int resourceId = getMaterials().resolveReference(value);
|
int resourceId = getMaterials().resolveReference(value);
|
||||||
entryBlock.setValueAsReference(resourceId);
|
entry.setValueAsReference(resourceId);
|
||||||
}
|
}
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
|
|
||||||
}
|
}
|
||||||
private TypeBlock getTypeBlock(String type, String qualifiers){
|
private TypeBlock getTypeBlock(String type, String qualifiers){
|
||||||
@ -98,7 +99,7 @@ class XMLValuesEncoder {
|
|||||||
int highest = specTypePair.getHighestEntryCount();
|
int highest = specTypePair.getHighestEntryCount();
|
||||||
TypeBlock typeBlock = specTypePair
|
TypeBlock typeBlock = specTypePair
|
||||||
.getOrCreateTypeBlock(qualifiers);
|
.getOrCreateTypeBlock(qualifiers);
|
||||||
typeBlock.getEntryBlockArray().ensureSize(highest);
|
typeBlock.getEntryArray().ensureSize(highest);
|
||||||
return typeBlock;
|
return typeBlock;
|
||||||
}
|
}
|
||||||
EncodeMaterials getMaterials() {
|
EncodeMaterials getMaterials() {
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.apk.ApkUtil;
|
import com.reandroid.apk.ApkUtil;
|
||||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
|
|||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
void encodeChildes(XMLElement parentElement, ResTableMapEntry mapEntry){
|
||||||
int count = parentElement.getChildesCount();
|
int count = parentElement.getChildesCount();
|
||||||
String tagName = parentElement.getTagName();
|
String tagName = parentElement.getTagName();
|
||||||
boolean force_string = false;
|
boolean force_string = false;
|
||||||
@ -38,12 +38,12 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
|
|||||||
}else if(ApkUtil.TAG_INTEGER_ARRAY.equals(tagName)){
|
}else if(ApkUtil.TAG_INTEGER_ARRAY.equals(tagName)){
|
||||||
force_integer = true;
|
force_integer = true;
|
||||||
}
|
}
|
||||||
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
|
ResValueMapArray itemArray = mapEntry.getValue();
|
||||||
for(int i=0;i<count;i++){
|
for(int i=0;i<count;i++){
|
||||||
XMLElement child=parentElement.getChildAt(i);
|
XMLElement child=parentElement.getChildAt(i);
|
||||||
ResValueBagItem bagItem = itemArray.get(i);
|
ResValueMap bagItem = itemArray.get(i);
|
||||||
bagItem.setIdHigh((short) 0x0100);
|
bagItem.setNameHigh((short) 0x0100);
|
||||||
bagItem.setIdLow((short) (i+1));
|
bagItem.setNameLow((short) (i+1));
|
||||||
|
|
||||||
String valueText=child.getTextContent();
|
String valueText=child.getTextContent();
|
||||||
|
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeItemType;
|
import com.reandroid.arsc.value.attribute.AttributeItemType;
|
||||||
@ -39,21 +39,21 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
void encodeChildes(XMLElement parentElement, ResTableMapEntry mapEntry){
|
||||||
encodeAttributes(parentElement, resValueBag);
|
encodeAttributes(parentElement, mapEntry);
|
||||||
encodeEnumOrFlag(parentElement, resValueBag);
|
encodeEnumOrFlag(parentElement, mapEntry);
|
||||||
// TODO: re-check if this is necessary
|
// TODO: re-check if this is necessary
|
||||||
resValueBag.getEntryBlock().setPublic(true);
|
mapEntry.getHeader().setPublic(true);
|
||||||
}
|
}
|
||||||
private void encodeAttributes(XMLElement parentElement, ResValueBag resValueBag){
|
private void encodeAttributes(XMLElement parentElement, ResTableMapEntry mapEntry){
|
||||||
ResValueBagItemArray bagItemArray = resValueBag.getResValueBagItemArray();
|
ResValueMapArray mapArray = mapEntry.getValue();
|
||||||
|
|
||||||
int bagIndex=0;
|
int bagIndex=0;
|
||||||
|
|
||||||
ResValueBagItem formatItem = bagItemArray.get(bagIndex);
|
ResValueMap formatItem = mapArray.get(bagIndex);
|
||||||
|
|
||||||
formatItem.setIdHigh((short) 0x0100);
|
formatItem.setNameHigh((short) 0x0100);
|
||||||
formatItem.setIdLow(AttributeItemType.FORMAT.getValue());
|
formatItem.setNameLow(AttributeItemType.FORMAT.getValue());
|
||||||
formatItem.setValueType(ValueType.INT_DEC);
|
formatItem.setValueType(ValueType.INT_DEC);
|
||||||
formatItem.setDataHigh(getChildTypes(parentElement));
|
formatItem.setDataHigh(getChildTypes(parentElement));
|
||||||
|
|
||||||
@ -75,15 +75,15 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
|||||||
throw new EncodeException("Unknown attribute: '"+name
|
throw new EncodeException("Unknown attribute: '"+name
|
||||||
+"', on attribute: "+attribute.toString());
|
+"', on attribute: "+attribute.toString());
|
||||||
}
|
}
|
||||||
ResValueBagItem bagItem = bagItemArray.get(bagIndex);
|
ResValueMap bagItem = mapArray.get(bagIndex);
|
||||||
bagItem.setIdHigh((short) 0x0100);
|
bagItem.setNameHigh((short) 0x0100);
|
||||||
bagItem.setIdLow(itemType.getValue());
|
bagItem.setNameLow(itemType.getValue());
|
||||||
bagItem.setValueType(ValueType.INT_DEC);
|
bagItem.setValueType(ValueType.INT_DEC);
|
||||||
bagItem.setData(ValueDecoder.parseInteger(attribute.getValue()));
|
bagItem.setData(ValueDecoder.parseInteger(attribute.getValue()));
|
||||||
bagIndex++;
|
bagIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void encodeEnumOrFlag(XMLElement element, ResValueBag resValueBag){
|
private void encodeEnumOrFlag(XMLElement element, ResTableMapEntry mapEntry){
|
||||||
int count=element.getChildesCount();
|
int count=element.getChildesCount();
|
||||||
if(count==0){
|
if(count==0){
|
||||||
return;
|
return;
|
||||||
@ -94,7 +94,7 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
|||||||
}
|
}
|
||||||
|
|
||||||
EncodeMaterials materials = getMaterials();
|
EncodeMaterials materials = getMaterials();
|
||||||
ResValueBagItemArray bagItemArray = resValueBag.getResValueBagItemArray();
|
ResValueMapArray mapArray = mapEntry.getValue();
|
||||||
|
|
||||||
for(int i=0;i<count;i++){
|
for(int i=0;i<count;i++){
|
||||||
XMLElement child=element.getChildAt(i);
|
XMLElement child=element.getChildAt(i);
|
||||||
@ -113,8 +113,8 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
|||||||
throw new EncodeException("Unknown value for element '"+child.toText()+"'");
|
throw new EncodeException("Unknown value for element '"+child.toText()+"'");
|
||||||
}
|
}
|
||||||
|
|
||||||
ResValueBagItem bagItem = bagItemArray.get(i+offset);
|
ResValueMap bagItem = mapArray.get(i+offset);
|
||||||
bagItem.setId(resourceId);
|
bagItem.setName(resourceId);
|
||||||
bagItem.setValueType(encodeResult.valueType);
|
bagItem.setValueType(encodeResult.valueType);
|
||||||
bagItem.setData(encodeResult.value);
|
bagItem.setData(encodeResult.value);
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
|
|
||||||
class XMLValuesEncoderBag extends XMLValuesEncoder{
|
class XMLValuesEncoderBag extends XMLValuesEncoder{
|
||||||
@ -24,18 +24,19 @@ class XMLValuesEncoderBag extends XMLValuesEncoder{
|
|||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeValue(EntryBlock entryBlock, XMLElement element){
|
void encodeValue(Entry entry, XMLElement element){
|
||||||
ResValueBag resValueBag=new ResValueBag();
|
ResTableMapEntry tableMapEntry = new ResTableMapEntry();
|
||||||
entryBlock.setResValue(resValueBag);
|
entry.setTableEntry(tableMapEntry);
|
||||||
String parent=element.getAttributeValue("parent");
|
String parent=element.getAttributeValue("parent");
|
||||||
if(!EncodeUtil.isEmpty(parent)){
|
if(!EncodeUtil.isEmpty(parent)){
|
||||||
int parentId=getMaterials().resolveReference(parent);
|
int parentId=getMaterials().resolveReference(parent);
|
||||||
resValueBag.setParentId(parentId);
|
tableMapEntry.getHeader().setParentId(parentId);
|
||||||
}
|
}
|
||||||
resValueBag.setCount(getChildesCount(element));
|
tableMapEntry.getValue().setChildesCount(getChildesCount(element));
|
||||||
encodeChildes(element, resValueBag);
|
encodeChildes(element, tableMapEntry);
|
||||||
|
tableMapEntry.refresh();
|
||||||
}
|
}
|
||||||
void encodeChildes(XMLElement element, ResValueBag resValueBag){
|
void encodeChildes(XMLElement element, ResTableMapEntry mapEntry){
|
||||||
throw new EncodeException("Unimplemented bag type encoder: "
|
throw new EncodeException("Unimplemented bag type encoder: "
|
||||||
+element.getTagName());
|
+element.getTagName());
|
||||||
|
|
||||||
|
@ -16,21 +16,21 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
class XMLValuesEncoderColor extends XMLValuesEncoder{
|
class XMLValuesEncoderColor extends XMLValuesEncoder{
|
||||||
XMLValuesEncoderColor(EncodeMaterials materials) {
|
XMLValuesEncoderColor(EncodeMaterials materials) {
|
||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeColor(value);
|
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeColor(value);
|
||||||
if(encodeResult!=null){
|
if(encodeResult!=null){
|
||||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||||
}else {
|
}else {
|
||||||
// If reaches here the value might be
|
// If reaches here the value might be
|
||||||
// file path e.g. res/color/something.xml
|
// file path e.g. res/color/something.xml
|
||||||
entryBlock.setValueAsString(value);
|
entry.setValueAsString(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,22 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
class XMLValuesEncoderCommon extends XMLValuesEncoder{
|
class XMLValuesEncoderCommon extends XMLValuesEncoder{
|
||||||
XMLValuesEncoderCommon(EncodeMaterials materials) {
|
XMLValuesEncoderCommon(EncodeMaterials materials) {
|
||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
if(ValueDecoder.isReference(value)){
|
if(ValueDecoder.isReference(value)){
|
||||||
entryBlock.setValueAsReference(getMaterials().resolveReference(value));
|
entry.setValueAsReference(getMaterials().resolveReference(value));
|
||||||
}else {
|
}else {
|
||||||
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeGuessAny(value);
|
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeGuessAny(value);
|
||||||
if(encodeResult!=null){
|
if(encodeResult!=null){
|
||||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||||
}else {
|
}else {
|
||||||
entryBlock.setValueAsString(ValueDecoder
|
entry.setValueAsString(ValueDecoder
|
||||||
.unEscapeSpecialCharacter(value));
|
.unEscapeSpecialCharacter(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,21 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
class XMLValuesEncoderDimen extends XMLValuesEncoder{
|
class XMLValuesEncoderDimen extends XMLValuesEncoder{
|
||||||
XMLValuesEncoderDimen(EncodeMaterials materials) {
|
XMLValuesEncoderDimen(EncodeMaterials materials) {
|
||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
ValueDecoder.EncodeResult encodeResult =
|
ValueDecoder.EncodeResult encodeResult =
|
||||||
ValueDecoder.encodeDimensionOrFloat(value);
|
ValueDecoder.encodeDimensionOrFloat(value);
|
||||||
if(encodeResult==null){
|
if(encodeResult==null){
|
||||||
encodeResult=ValueDecoder.encodeHexOrInt(value);
|
encodeResult=ValueDecoder.encodeHexOrInt(value);
|
||||||
}
|
}
|
||||||
if(encodeResult!=null){
|
if(encodeResult!=null){
|
||||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||||
}else {
|
}else {
|
||||||
throw new EncodeException("Unknown dimen value: "+value);
|
throw new EncodeException("Unknown dimen value: "+value);
|
||||||
}
|
}
|
||||||
|
@ -15,29 +15,31 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Header;
|
||||||
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
class XMLValuesEncoderId extends XMLValuesEncoder{
|
class XMLValuesEncoderId extends XMLValuesEncoder{
|
||||||
public XMLValuesEncoderId(EncodeMaterials materials) {
|
public XMLValuesEncoderId(EncodeMaterials materials) {
|
||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
throw new EncodeException("Unexpected value for id: "+value);
|
throw new EncodeException("Unexpected value for id: "+value);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeNullValue(EntryBlock entryBlock){
|
void encodeNullValue(Entry entry){
|
||||||
entryBlock.setValueAsString("");
|
entry.setValueAsString("");
|
||||||
setVisibility(entryBlock);
|
setVisibility(entry);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeBooleanValue(EntryBlock entryBlock, String value){
|
void encodeBooleanValue(Entry entry, String value){
|
||||||
super.encodeBooleanValue(entryBlock, value);
|
super.encodeBooleanValue(entry, value);
|
||||||
setVisibility(entryBlock);
|
setVisibility(entry);
|
||||||
}
|
}
|
||||||
private void setVisibility(EntryBlock entryBlock){
|
private void setVisibility(Entry entry){
|
||||||
entryBlock.setWeak(true);
|
Header header = entry.getHeader();
|
||||||
entryBlock.setPublic(true);
|
header.setWeak(true);
|
||||||
|
header.setPublic(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
class XMLValuesEncoderInteger extends XMLValuesEncoder{
|
class XMLValuesEncoderInteger extends XMLValuesEncoder{
|
||||||
@ -24,16 +24,16 @@ class XMLValuesEncoderInteger extends XMLValuesEncoder{
|
|||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
value=value.trim();
|
value=value.trim();
|
||||||
if(ValueDecoder.isInteger(value)){
|
if(ValueDecoder.isInteger(value)){
|
||||||
entryBlock.setValueAsRaw(ValueType.INT_DEC, ValueDecoder.parseInteger(value));
|
entry.setValueAsRaw(ValueType.INT_DEC, ValueDecoder.parseInteger(value));
|
||||||
}else if(ValueDecoder.isHex(value)){
|
}else if(ValueDecoder.isHex(value)){
|
||||||
entryBlock.setValueAsRaw(ValueType.INT_HEX, ValueDecoder.parseHex(value));
|
entry.setValueAsRaw(ValueType.INT_HEX, ValueDecoder.parseHex(value));
|
||||||
}else {
|
}else {
|
||||||
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeDimensionOrFloat(value);
|
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeDimensionOrFloat(value);
|
||||||
if(encodeResult!=null){
|
if(encodeResult!=null){
|
||||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||||
}else {
|
}else {
|
||||||
throw new EncodeException("Unknown value for type <integer>: '"+value+"'");
|
throw new EncodeException("Unknown value for type <integer>: '"+value+"'");
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.arsc.value.plurals.PluralsQuantity;
|
import com.reandroid.arsc.value.plurals.PluralsQuantity;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -28,20 +28,20 @@ class XMLValuesEncoderPlurals extends XMLValuesEncoderBag{
|
|||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
void encodeChildes(XMLElement parentElement, ResTableMapEntry resValueBag){
|
||||||
int count = parentElement.getChildesCount();
|
int count = parentElement.getChildesCount();
|
||||||
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
|
ResValueMapArray itemArray = resValueBag.getValue();
|
||||||
for(int i=0;i<count;i++){
|
for(int i=0;i<count;i++){
|
||||||
XMLElement child=parentElement.getChildAt(i);
|
XMLElement child=parentElement.getChildAt(i);
|
||||||
ResValueBagItem bagItem = itemArray.get(i);
|
ResValueMap bagItem = itemArray.get(i);
|
||||||
PluralsQuantity quantity = PluralsQuantity
|
PluralsQuantity quantity = PluralsQuantity
|
||||||
.value(child.getAttributeValue("quantity"));
|
.value(child.getAttributeValue("quantity"));
|
||||||
if(quantity==null){
|
if(quantity==null){
|
||||||
throw new EncodeException("Unknown plurals quantity: "
|
throw new EncodeException("Unknown plurals quantity: "
|
||||||
+child.toText());
|
+child.toText());
|
||||||
}
|
}
|
||||||
bagItem.setIdHigh((short) 0x0100);
|
bagItem.setNameHigh((short) 0x0100);
|
||||||
bagItem.setIdLow(quantity.getId());
|
bagItem.setNameLow(quantity.getId());
|
||||||
|
|
||||||
String valueText=child.getTextContent();
|
String valueText=child.getTextContent();
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
class XMLValuesEncoderString extends XMLValuesEncoder{
|
class XMLValuesEncoderString extends XMLValuesEncoder{
|
||||||
XMLValuesEncoderString(EncodeMaterials materials) {
|
XMLValuesEncoderString(EncodeMaterials materials) {
|
||||||
@ -24,15 +24,15 @@ import com.reandroid.arsc.value.EntryBlock;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
void encodeStringValue(Entry entry, String value){
|
||||||
entryBlock.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
|
entry.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeNullValue(EntryBlock entryBlock){
|
void encodeNullValue(Entry entry){
|
||||||
entryBlock.setValueAsString("");
|
entry.setValueAsString("");
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeBooleanValue(EntryBlock entryBlock, String value){
|
void encodeBooleanValue(Entry entry, String value){
|
||||||
entryBlock.setValueAsString(value);
|
entry.setValueAsString(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
|
||||||
import com.reandroid.arsc.value.ValueType;
|
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeValueType;
|
import com.reandroid.arsc.value.attribute.AttributeValueType;
|
||||||
import com.reandroid.xml.XMLElement;
|
import com.reandroid.xml.XMLElement;
|
||||||
@ -31,12 +28,12 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
|||||||
super(materials);
|
super(materials);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
void encodeChildes(XMLElement parentElement, ResTableMapEntry resValueBag){
|
||||||
int count = parentElement.getChildesCount();
|
int count = parentElement.getChildesCount();
|
||||||
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
|
ResValueMapArray itemArray = resValueBag.getValue();
|
||||||
for(int i=0;i<count;i++){
|
for(int i=0;i<count;i++){
|
||||||
XMLElement child=parentElement.getChildAt(i);
|
XMLElement child=parentElement.getChildAt(i);
|
||||||
ResValueBagItem item = itemArray.get(i);
|
ResValueMap item = itemArray.get(i);
|
||||||
String name=child.getAttributeValue("name");
|
String name=child.getAttributeValue("name");
|
||||||
int id=decodeUnknownAttributeHex(name);
|
int id=decodeUnknownAttributeHex(name);
|
||||||
if(id!=0){
|
if(id!=0){
|
||||||
@ -55,7 +52,7 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntryBlock attributeEntry=getMaterials()
|
Entry attributeEntry=getMaterials()
|
||||||
.getAttributeBlock(name);
|
.getAttributeBlock(name);
|
||||||
if(attributeEntry==null){
|
if(attributeEntry==null){
|
||||||
throw new EncodeException("Unknown attribute name: '"+child.toText()
|
throw new EncodeException("Unknown attribute name: '"+child.toText()
|
||||||
@ -74,11 +71,12 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
|||||||
}
|
}
|
||||||
return ValueDecoder.parseHex(name);
|
return ValueDecoder.parseHex(name);
|
||||||
}
|
}
|
||||||
private void encodeChild(XMLElement child, EntryBlock attributeEntry, ResValueBagItem bagItem){
|
private void encodeChild(XMLElement child, Entry attributeEntry, ResValueMap bagItem){
|
||||||
|
|
||||||
bagItem.setId(attributeEntry.getResourceId());
|
bagItem.setName(attributeEntry.getResourceId());
|
||||||
|
ResTableMapEntry tableEntry = (ResTableMapEntry) attributeEntry.getTableEntry();
|
||||||
AttributeBag attributeBag=AttributeBag
|
AttributeBag attributeBag=AttributeBag
|
||||||
.create((ResValueBag) attributeEntry.getResValue());
|
.create(tableEntry.getValue());
|
||||||
|
|
||||||
String valueText=child.getTextContent();
|
String valueText=child.getTextContent();
|
||||||
ValueDecoder.EncodeResult encodeEnumFlag =
|
ValueDecoder.EncodeResult encodeEnumFlag =
|
||||||
|
@ -17,10 +17,7 @@ package com.reandroid.arsc.array;
|
|||||||
|
|
||||||
import com.reandroid.arsc.item.IntegerArray;
|
import com.reandroid.arsc.item.IntegerArray;
|
||||||
import com.reandroid.arsc.item.IntegerItem;
|
import com.reandroid.arsc.item.IntegerItem;
|
||||||
import com.reandroid.arsc.value.BaseResValue;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
|
||||||
import com.reandroid.arsc.value.ResValueInt;
|
|
||||||
import com.reandroid.arsc.value.ValueType;
|
|
||||||
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;
|
||||||
@ -28,41 +25,41 @@ import com.reandroid.json.JSONObject;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
|
||||||
public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSONConvert<JSONArray> {
|
public class EntryArray extends OffsetBlockArray<Entry> implements JSONConvert<JSONArray> {
|
||||||
public EntryBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
public EntryArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
||||||
super(offsets, itemCount, itemStart);
|
super(offsets, itemCount, itemStart);
|
||||||
}
|
}
|
||||||
public boolean isEmpty(){
|
public boolean isEmpty(){
|
||||||
return !iterator(true).hasNext();
|
return !iterator(true).hasNext();
|
||||||
}
|
}
|
||||||
public void setEntry(short entryId, EntryBlock entryBlock){
|
public void setEntry(short entryId, Entry entry){
|
||||||
setItem(0xffff & entryId, entryBlock);
|
setItem(0xffff & entryId, entry);
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreate(short entryId){
|
public Entry getOrCreate(short entryId){
|
||||||
int id = 0xffff & entryId;
|
int id = 0xffff & entryId;
|
||||||
EntryBlock entryBlock=get(id);
|
Entry entry =get(id);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
int count=id+1;
|
int count=id+1;
|
||||||
ensureSize(count);
|
ensureSize(count);
|
||||||
refreshCount();
|
refreshCount();
|
||||||
return get(id);
|
return get(id);
|
||||||
}
|
}
|
||||||
public EntryBlock get(short entryId){
|
public Entry get(short entryId){
|
||||||
int index = 0xffff & entryId;
|
int index = 0xffff & entryId;
|
||||||
return super.get(index);
|
return super.get(index);
|
||||||
}
|
}
|
||||||
public EntryBlock getEntry(short entryId){
|
public Entry getEntry(short entryId){
|
||||||
return get(0xffff & entryId);
|
return get(0xffff & entryId);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public EntryBlock newInstance() {
|
public Entry newInstance() {
|
||||||
return new EntryBlock();
|
return new Entry();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public EntryBlock[] newInstance(int len) {
|
public Entry[] newInstance(int len) {
|
||||||
return new EntryBlock[len];
|
return new Entry[len];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,13 +67,13 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
|
|||||||
* Lets depreciate to warn developer
|
* Lets depreciate to warn developer
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public EntryBlock searchByEntryName(String entryName){
|
public Entry searchByEntryName(String entryName){
|
||||||
if(entryName==null){
|
if(entryName==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for(EntryBlock entryBlock:listItems()){
|
for(Entry entry:listItems()){
|
||||||
if(entryName.equals(entryBlock.getName())){
|
if(entryName.equals(entry.getName())){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -85,12 +82,12 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
|
|||||||
public JSONArray toJson() {
|
public JSONArray toJson() {
|
||||||
JSONArray jsonArray=new JSONArray();
|
JSONArray jsonArray=new JSONArray();
|
||||||
int index=0;
|
int index=0;
|
||||||
for(EntryBlock entryBlock:listItems()){
|
for(Entry entry :listItems()){
|
||||||
JSONObject childObject = entryBlock.toJson();
|
JSONObject childObject = entry.toJson();
|
||||||
if(childObject==null){
|
if(childObject==null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
childObject.put(NAME_id, entryBlock.getIndex());
|
childObject.put(NAME_id, entry.getIndex());
|
||||||
jsonArray.put(index, childObject);
|
jsonArray.put(index, childObject);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@ -108,20 +105,20 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
|
|||||||
}
|
}
|
||||||
int id=jsonObject.getInt(NAME_id);
|
int id=jsonObject.getInt(NAME_id);
|
||||||
ensureSize(id+1);
|
ensureSize(id+1);
|
||||||
EntryBlock entryBlock=get(id);
|
Entry entry =get(id);
|
||||||
entryBlock.fromJson(jsonObject);
|
entry.fromJson(jsonObject);
|
||||||
}
|
}
|
||||||
refreshCountAndStart();
|
refreshCountAndStart();
|
||||||
}
|
}
|
||||||
public void merge(EntryBlockArray entryBlockArray){
|
public void merge(EntryArray entryArray){
|
||||||
if(entryBlockArray==null||entryBlockArray==this||entryBlockArray.isEmpty()){
|
if(entryArray ==null|| entryArray ==this|| entryArray.isEmpty()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ensureSize(entryBlockArray.childesCount());
|
ensureSize(entryArray.childesCount());
|
||||||
Iterator<EntryBlock> itr=entryBlockArray.iterator(true);
|
Iterator<Entry> itr = entryArray.iterator(true);
|
||||||
while (itr.hasNext()){
|
while (itr.hasNext()){
|
||||||
EntryBlock comingBlock=itr.next();
|
Entry comingBlock = itr.next();
|
||||||
EntryBlock existingBlock=get(comingBlock.getIndex());
|
Entry existingBlock = get(comingBlock.getIndex());
|
||||||
existingBlock.merge(comingBlock);
|
existingBlock.merge(comingBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,33 +16,35 @@
|
|||||||
package com.reandroid.arsc.array;
|
package com.reandroid.arsc.array;
|
||||||
|
|
||||||
import com.reandroid.arsc.base.BlockArray;
|
import com.reandroid.arsc.base.BlockArray;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
|
|
||||||
public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements JSONConvert<JSONArray> {
|
public class ResValueMapArray extends BlockArray<ResValueMap> implements JSONConvert<JSONArray> {
|
||||||
public ResValueBagItemArray(){
|
public ResValueMapArray(){
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ResValueBagItem newInstance() {
|
public ResValueMap newInstance() {
|
||||||
return new ResValueBagItem();
|
return new ResValueMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResValueBagItem[] newInstance(int len) {
|
public ResValueMap[] newInstance(int len) {
|
||||||
return new ResValueBagItem[len];
|
return new ResValueMap[len];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRefreshed() {
|
protected void onRefreshed() {
|
||||||
|
}
|
||||||
|
public void onRemoved(){
|
||||||
|
for(ResValueMap resValueMap:listItems()){
|
||||||
|
resValueMap.onRemoved();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void clearChildes(){
|
public void clearChildes(){
|
||||||
for(ResValueBagItem bagItem:listItems()){
|
this.onRemoved();
|
||||||
bagItem.onRemoved();
|
|
||||||
}
|
|
||||||
super.clearChildes();
|
super.clearChildes();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@ -51,7 +53,7 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
|
|||||||
if(isNull()){
|
if(isNull()){
|
||||||
return jsonArray;
|
return jsonArray;
|
||||||
}
|
}
|
||||||
ResValueBagItem[] childes = getChildes();
|
ResValueMap[] childes = getChildes();
|
||||||
for(int i=0;i<childes.length;i++){
|
for(int i=0;i<childes.length;i++){
|
||||||
jsonArray.put(i, childes[i].toJson());
|
jsonArray.put(i, childes[i].toJson());
|
||||||
}
|
}
|
||||||
@ -69,7 +71,7 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
|
|||||||
get(i).fromJson(json.getJSONObject(i));
|
get(i).fromJson(json.getJSONObject(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void merge(ResValueBagItemArray bagItemArray){
|
public void merge(ResValueMapArray bagItemArray){
|
||||||
if(bagItemArray==null||bagItemArray==this){
|
if(bagItemArray==null||bagItemArray==this){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -77,8 +79,8 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
|
|||||||
int count=bagItemArray.childesCount();
|
int count=bagItemArray.childesCount();
|
||||||
ensureSize(count);
|
ensureSize(count);
|
||||||
for(int i=0;i<count;i++){
|
for(int i=0;i<count;i++){
|
||||||
ResValueBagItem coming=bagItemArray.get(i);
|
ResValueMap coming=bagItemArray.get(i);
|
||||||
ResValueBagItem exist=get(i);
|
ResValueMap exist=get(i);
|
||||||
exist.merge(coming);
|
exist.merge(coming);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,7 +18,7 @@ package com.reandroid.arsc.array;
|
|||||||
import com.reandroid.arsc.base.BlockArray;
|
import com.reandroid.arsc.base.BlockArray;
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
import com.reandroid.arsc.chunk.TypeBlock;
|
||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
@ -62,11 +62,11 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair>
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
public Entry getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
||||||
TypeBlock typeBlock=getOrCreateTypeBlock(typeId, qualifiers);
|
TypeBlock typeBlock=getOrCreateTypeBlock(typeId, qualifiers);
|
||||||
return typeBlock.getOrCreateEntry(entryId);
|
return typeBlock.getOrCreateEntry(entryId);
|
||||||
}
|
}
|
||||||
public EntryBlock getEntry(byte typeId, short entryId, String qualifiers){
|
public Entry getEntry(byte typeId, short entryId, String qualifiers){
|
||||||
TypeBlock typeBlock=getTypeBlock(typeId, qualifiers);
|
TypeBlock typeBlock=getTypeBlock(typeId, qualifiers);
|
||||||
if(typeBlock==null){
|
if(typeBlock==null){
|
||||||
return null;
|
return null;
|
||||||
|
@ -24,7 +24,7 @@ import com.reandroid.arsc.container.SpecTypePair;
|
|||||||
import com.reandroid.arsc.header.HeaderBlock;
|
import com.reandroid.arsc.header.HeaderBlock;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.item.TypeString;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
@ -58,7 +58,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
|||||||
trimNullBlocks();
|
trimNullBlocks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreateEntry(short entryId, String qualifiers){
|
public Entry getOrCreateEntry(short entryId, String qualifiers){
|
||||||
TypeBlock typeBlock=getOrCreate(qualifiers);
|
TypeBlock typeBlock=getOrCreate(qualifiers);
|
||||||
return typeBlock.getOrCreateEntry(entryId);
|
return typeBlock.getOrCreateEntry(entryId);
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public EntryBlock getEntry(short entryId, String qualifiers){
|
public Entry getEntry(short entryId, String qualifiers){
|
||||||
TypeBlock typeBlock=getTypeBlock(qualifiers);
|
TypeBlock typeBlock=getTypeBlock(qualifiers);
|
||||||
if(typeBlock==null){
|
if(typeBlock==null){
|
||||||
return null;
|
return null;
|
||||||
@ -243,7 +243,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
|||||||
public int getHighestEntryCount(){
|
public int getHighestEntryCount(){
|
||||||
int result=0;
|
int result=0;
|
||||||
for(TypeBlock typeBlock:getChildes()){
|
for(TypeBlock typeBlock:getChildes()){
|
||||||
int count=typeBlock.getEntryBlockArray().childesCount();
|
int count=typeBlock.getEntryArray().childesCount();
|
||||||
if(count>result){
|
if(count>result){
|
||||||
result=count;
|
result=count;
|
||||||
}
|
}
|
||||||
@ -303,7 +303,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
|||||||
* Lets depreciate to warn developer
|
* Lets depreciate to warn developer
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public EntryBlock searchByEntryName(String entryName){
|
public Entry searchByEntryName(String entryName){
|
||||||
if(entryName==null){
|
if(entryName==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,11 @@ package com.reandroid.arsc.chunk;
|
|||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.header.PackageHeader;
|
import com.reandroid.arsc.header.PackageHeader;
|
||||||
import com.reandroid.arsc.item.ReferenceItem;
|
|
||||||
import com.reandroid.arsc.list.OverlayableList;
|
import com.reandroid.arsc.list.OverlayableList;
|
||||||
import com.reandroid.arsc.list.StagedAliasList;
|
import com.reandroid.arsc.list.StagedAliasList;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.LibraryInfo;
|
import com.reandroid.arsc.value.LibraryInfo;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.arsc.value.StagedAliasEntry;
|
import com.reandroid.arsc.value.StagedAliasEntry;
|
||||||
@ -42,7 +40,9 @@ package com.reandroid.arsc.chunk;
|
|||||||
|
|
||||||
|
|
||||||
public class PackageBlock extends Chunk<PackageHeader>
|
public class PackageBlock extends Chunk<PackageHeader>
|
||||||
implements JSONConvert<JSONObject>, Comparable<PackageBlock> {
|
implements ParentChunk,
|
||||||
|
JSONConvert<JSONObject>,
|
||||||
|
Comparable<PackageBlock> {
|
||||||
|
|
||||||
private final TypeStringPool mTypeStringPool;
|
private final TypeStringPool mTypeStringPool;
|
||||||
private final SpecStringPool mSpecStringPool;
|
private final SpecStringPool mSpecStringPool;
|
||||||
@ -66,12 +66,12 @@ package com.reandroid.arsc.chunk;
|
|||||||
addChild(mSpecStringPool);
|
addChild(mSpecStringPool);
|
||||||
addChild(mBody);
|
addChild(mBody);
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreate(String qualifiers, String type, String name){
|
public Entry getOrCreate(String qualifiers, String type, String name){
|
||||||
ResConfig resConfig = new ResConfig();
|
ResConfig resConfig = new ResConfig();
|
||||||
resConfig.parseQualifiers(qualifiers);
|
resConfig.parseQualifiers(qualifiers);
|
||||||
return getOrCreate(resConfig, type, name);
|
return getOrCreate(resConfig, type, name);
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreate(ResConfig resConfig, String type, String name){
|
public Entry getOrCreate(ResConfig resConfig, String type, String name){
|
||||||
SpecTypePair specTypePair = getOrCreateSpecType(type);
|
SpecTypePair specTypePair = getOrCreateSpecType(type);
|
||||||
TypeBlock typeBlock = specTypePair.getOrCreateTypeBlock(resConfig);
|
TypeBlock typeBlock = specTypePair.getOrCreateTypeBlock(resConfig);
|
||||||
return typeBlock.getOrCreateEntry(name);
|
return typeBlock.getOrCreateEntry(name);
|
||||||
@ -158,6 +158,7 @@ package com.reandroid.arsc.chunk;
|
|||||||
public TypeStringPool getTypeStringPool(){
|
public TypeStringPool getTypeStringPool(){
|
||||||
return mTypeStringPool;
|
return mTypeStringPool;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public SpecStringPool getSpecStringPool(){
|
public SpecStringPool getSpecStringPool(){
|
||||||
return mSpecStringPool;
|
return mSpecStringPool;
|
||||||
}
|
}
|
||||||
@ -185,10 +186,10 @@ package com.reandroid.arsc.chunk;
|
|||||||
public Set<Integer> listResourceIds(){
|
public Set<Integer> listResourceIds(){
|
||||||
return mEntriesGroup.keySet();
|
return mEntriesGroup.keySet();
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
public Entry getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
||||||
return getSpecTypePairArray().getOrCreateEntry(typeId, entryId, qualifiers);
|
return getSpecTypePairArray().getOrCreateEntry(typeId, entryId, qualifiers);
|
||||||
}
|
}
|
||||||
public EntryBlock getEntry(byte typeId, short entryId, String qualifiers){
|
public Entry getEntry(byte typeId, short entryId, String qualifiers){
|
||||||
return getSpecTypePairArray().getEntry(typeId, entryId, qualifiers);
|
return getSpecTypePairArray().getEntry(typeId, entryId, qualifiers);
|
||||||
}
|
}
|
||||||
public TypeBlock getOrCreateTypeBlock(byte typeId, String qualifiers){
|
public TypeBlock getOrCreateTypeBlock(byte typeId, String qualifiers){
|
||||||
@ -223,48 +224,38 @@ package com.reandroid.arsc.chunk;
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public void updateEntry(EntryBlock entryBlock){
|
public void updateEntry(Entry entry){
|
||||||
if(entryBlock==null||entryBlock.isNull()){
|
if(entry ==null|| entry.isNull()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateEntryGroup(entryBlock);
|
updateEntryGroup(entry);
|
||||||
updateEntryTableReferences(entryBlock);
|
|
||||||
}
|
}
|
||||||
public void removeEntryGroup(EntryBlock entryBlock){
|
public void removeEntryGroup(Entry entry){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int id=entryBlock.getResourceId();
|
int id= entry.getResourceId();
|
||||||
EntryGroup group=getEntriesGroupMap().get(id);
|
EntryGroup group=getEntriesGroupMap().get(id);
|
||||||
if(group==null){
|
if(group==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
group.remove(entryBlock);
|
group.remove(entry);
|
||||||
if(group.size()==0){
|
if(group.size()==0){
|
||||||
getEntriesGroupMap().remove(id);
|
getEntriesGroupMap().remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void updateEntryTableReferences(EntryBlock entryBlock){
|
private void updateEntryGroup(Entry entry){
|
||||||
TableBlock tableBlock=getTableBlock();
|
int resId= entry.getResourceId();
|
||||||
if(tableBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<ReferenceItem> tableReferences=entryBlock.getTableStringReferences();
|
|
||||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
|
||||||
tableStringPool.addReferences(tableReferences);
|
|
||||||
}
|
|
||||||
private void updateEntryGroup(EntryBlock entryBlock){
|
|
||||||
int resId=entryBlock.getResourceId();
|
|
||||||
EntryGroup group=getEntriesGroupMap().get(resId);
|
EntryGroup group=getEntriesGroupMap().get(resId);
|
||||||
if(group==null){
|
if(group==null){
|
||||||
group=new EntryGroup(resId);
|
group=new EntryGroup(resId);
|
||||||
getEntriesGroupMap().put(resId, group);
|
getEntriesGroupMap().put(resId, group);
|
||||||
}
|
}
|
||||||
group.add(entryBlock);
|
group.add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<EntryBlock> listEntries(byte typeId, int entryId){
|
public List<Entry> listEntries(byte typeId, int entryId){
|
||||||
List<EntryBlock> results=new ArrayList<>();
|
List<Entry> results=new ArrayList<>();
|
||||||
for(SpecTypePair pair:listSpecTypePair(typeId)){
|
for(SpecTypePair pair:listSpecTypePair(typeId)){
|
||||||
results.addAll(pair.listEntries(entryId));
|
results.addAll(pair.listEntries(entryId));
|
||||||
}
|
}
|
||||||
@ -304,8 +295,8 @@ package com.reandroid.arsc.chunk;
|
|||||||
//getHeaderBlock().getTypeIdOffset().set(count-largest);
|
//getHeaderBlock().getTypeIdOffset().set(count-largest);
|
||||||
getHeaderBlock().getTypeIdOffsetItem().set(0);
|
getHeaderBlock().getTypeIdOffsetItem().set(0);
|
||||||
}
|
}
|
||||||
public void onEntryAdded(EntryBlock entryBlock){
|
public void onEntryAdded(Entry entry){
|
||||||
updateEntry(entryBlock);
|
updateEntry(entry);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onChunkLoaded() {
|
public void onChunkLoaded() {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.chunk;
|
package com.reandroid.arsc.chunk;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.EntryBlockArray;
|
import com.reandroid.arsc.array.EntryArray;
|
||||||
import com.reandroid.arsc.base.Block;
|
import com.reandroid.arsc.base.Block;
|
||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.arsc.header.TypeHeader;
|
import com.reandroid.arsc.header.TypeHeader;
|
||||||
@ -23,7 +23,7 @@ import com.reandroid.arsc.io.BlockLoad;
|
|||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
@ -38,14 +38,14 @@ import java.util.List;
|
|||||||
public class TypeBlock extends Chunk<TypeHeader>
|
public class TypeBlock extends Chunk<TypeHeader>
|
||||||
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
|
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
|
||||||
|
|
||||||
private final EntryBlockArray mEntryArray;
|
private final EntryArray mEntryArray;
|
||||||
private TypeString mTypeString;
|
private TypeString mTypeString;
|
||||||
public TypeBlock() {
|
public TypeBlock() {
|
||||||
super(new TypeHeader(), 2);
|
super(new TypeHeader(), 2);
|
||||||
TypeHeader header = getHeaderBlock();
|
TypeHeader header = getHeaderBlock();
|
||||||
|
|
||||||
IntegerArray entryOffsets = new IntegerArray();
|
IntegerArray entryOffsets = new IntegerArray();
|
||||||
this.mEntryArray = new EntryBlockArray(entryOffsets,
|
this.mEntryArray = new EntryArray(entryOffsets,
|
||||||
header.getCount(), header.getEntriesStart());
|
header.getCount(), header.getEntriesStart());
|
||||||
|
|
||||||
header.getFlags().setBlockLoad(this);
|
header.getFlags().setBlockLoad(this);
|
||||||
@ -122,7 +122,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
onSetEntryCount(count);
|
onSetEntryCount(count);
|
||||||
}
|
}
|
||||||
public boolean isEmpty(){
|
public boolean isEmpty(){
|
||||||
return getEntryBlockArray().isEmpty();
|
return getEntryArray().isEmpty();
|
||||||
}
|
}
|
||||||
public boolean isDefault(){
|
public boolean isDefault(){
|
||||||
return getResConfig().isDefault();
|
return getResConfig().isDefault();
|
||||||
@ -134,7 +134,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
getResConfig().parseQualifiers(qualifiers);
|
getResConfig().parseQualifiers(qualifiers);
|
||||||
}
|
}
|
||||||
public int countNonNullEntries(){
|
public int countNonNullEntries(){
|
||||||
return getEntryBlockArray().countNonNull();
|
return getEntryArray().countNonNull();
|
||||||
}
|
}
|
||||||
public SpecTypePair getParentSpecTypePair(){
|
public SpecTypePair getParentSpecTypePair(){
|
||||||
Block parent=getParent();
|
Block parent=getParent();
|
||||||
@ -148,29 +148,29 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
}
|
}
|
||||||
public void cleanEntries(){
|
public void cleanEntries(){
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
PackageBlock packageBlock=getPackageBlock();
|
||||||
List<EntryBlock> allEntries=listEntries(true);
|
List<Entry> allEntries=listEntries(true);
|
||||||
for(EntryBlock entryBlock:allEntries){
|
for(Entry entry :allEntries){
|
||||||
if(packageBlock!=null){
|
if(packageBlock!=null){
|
||||||
packageBlock.removeEntryGroup(entryBlock);
|
packageBlock.removeEntryGroup(entry);
|
||||||
}
|
}
|
||||||
entryBlock.setNull(true);
|
entry.setNull(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void removeEntry(EntryBlock entryBlock){
|
public void removeEntry(Entry entry){
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
PackageBlock packageBlock=getPackageBlock();
|
||||||
if(packageBlock!=null){
|
if(packageBlock!=null){
|
||||||
packageBlock.removeEntryGroup(entryBlock);
|
packageBlock.removeEntryGroup(entry);
|
||||||
}
|
}
|
||||||
entryBlock.setNull(true);
|
entry.setNull(true);
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreateEntry(String name){
|
public Entry getOrCreateEntry(String name){
|
||||||
for(EntryBlock entryBlock:getEntryBlockArray().listItems()){
|
for(Entry entry : getEntryArray().listItems()){
|
||||||
if(name.equals(entryBlock.getName())){
|
if(name.equals(entry.getName())){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpecTypePair specTypePair = getParentSpecTypePair();
|
SpecTypePair specTypePair = getParentSpecTypePair();
|
||||||
EntryBlock exist=specTypePair.getAnyEntry(name);
|
Entry exist=specTypePair.getAnyEntry(name);
|
||||||
int id;
|
int id;
|
||||||
if(exist!=null){
|
if(exist!=null){
|
||||||
id=exist.getIndex();
|
id=exist.getIndex();
|
||||||
@ -179,47 +179,47 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
}
|
}
|
||||||
SpecString specString = getPackageBlock()
|
SpecString specString = getPackageBlock()
|
||||||
.getSpecStringPool().getOrCreate(name);
|
.getSpecStringPool().getOrCreate(name);
|
||||||
EntryBlock entryBlock = getOrCreateEntry((short) id);
|
Entry entry = getOrCreateEntry((short) id);
|
||||||
if(entryBlock.isNull()){
|
if(entry.isNull()){
|
||||||
entryBlock.setValueAsRaw(ValueType.NULL, 0);
|
entry.setValueAsRaw(ValueType.NULL, 0);
|
||||||
}
|
}
|
||||||
entryBlock.setSpecReference(specString.getIndex());
|
entry.setSpecReference(specString.getIndex());
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreateEntry(short entryId){
|
public Entry getOrCreateEntry(short entryId){
|
||||||
return getEntryBlockArray().getOrCreate(entryId);
|
return getEntryArray().getOrCreate(entryId);
|
||||||
}
|
}
|
||||||
public EntryBlock getEntry(short entryId){
|
public Entry getEntry(short entryId){
|
||||||
return getEntryBlockArray().getEntry(entryId);
|
return getEntryArray().getEntry(entryId);
|
||||||
}
|
}
|
||||||
public ResConfig getResConfig(){
|
public ResConfig getResConfig(){
|
||||||
return getHeaderBlock().getConfig();
|
return getHeaderBlock().getConfig();
|
||||||
}
|
}
|
||||||
public EntryBlockArray getEntryBlockArray(){
|
public EntryArray getEntryArray(){
|
||||||
return mEntryArray;
|
return mEntryArray;
|
||||||
}
|
}
|
||||||
public List<EntryBlock> listEntries(){
|
public List<Entry> listEntries(){
|
||||||
return listEntries(false);
|
return listEntries(false);
|
||||||
}
|
}
|
||||||
public List<EntryBlock> listEntries(boolean skipNullBlock){
|
public List<Entry> listEntries(boolean skipNullBlock){
|
||||||
List<EntryBlock> results=new ArrayList<>();
|
List<Entry> results=new ArrayList<>();
|
||||||
Iterator<EntryBlock> itr = getEntryBlockArray().iterator(skipNullBlock);
|
Iterator<Entry> itr = getEntryArray().iterator(skipNullBlock);
|
||||||
while (itr.hasNext()){
|
while (itr.hasNext()){
|
||||||
EntryBlock block=itr.next();
|
Entry block=itr.next();
|
||||||
results.add(block);
|
results.add(block);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
public EntryBlock getEntryBlock(int entryId){
|
public Entry getEntry(int entryId){
|
||||||
return getEntryBlockArray().get(entryId);
|
return getEntryArray().get(entryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSetEntryCount(int count) {
|
private void onSetEntryCount(int count) {
|
||||||
getEntryBlockArray().setChildesCount(count);
|
getEntryArray().setChildesCount(count);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
getEntryBlockArray().refreshCountAndStart();
|
getEntryArray().refreshCountAndStart();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onPreRefreshRefresh(){
|
protected void onPreRefreshRefresh(){
|
||||||
@ -246,7 +246,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
jsonObject.put(NAME_id, getId());
|
jsonObject.put(NAME_id, getId());
|
||||||
jsonObject.put(NAME_name, getTypeName());
|
jsonObject.put(NAME_name, getTypeName());
|
||||||
jsonObject.put(NAME_config, getResConfig().toJson());
|
jsonObject.put(NAME_config, getResConfig().toJson());
|
||||||
jsonObject.put(NAME_entries, getEntryBlockArray().toJson());
|
jsonObject.put(NAME_entries, getEntryArray().toJson());
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@ -256,7 +256,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
if(name!=null){
|
if(name!=null){
|
||||||
setTypeName(name);
|
setTypeName(name);
|
||||||
}
|
}
|
||||||
getEntryBlockArray()
|
getEntryArray()
|
||||||
.fromJson(json.getJSONArray(NAME_entries));
|
.fromJson(json.getJSONArray(NAME_entries));
|
||||||
getResConfig()
|
getResConfig()
|
||||||
.fromJson(json.getJSONObject(NAME_config));
|
.fromJson(json.getJSONObject(NAME_config));
|
||||||
@ -270,7 +270,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
+getTypeId()+"!="+typeBlock.getTypeId());
|
+getTypeId()+"!="+typeBlock.getTypeId());
|
||||||
}
|
}
|
||||||
setTypeName(typeBlock.getTypeName());
|
setTypeName(typeBlock.getTypeName());
|
||||||
getEntryBlockArray().merge(typeBlock.getEntryBlockArray());
|
getEntryArray().merge(typeBlock.getEntryArray());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(TypeBlock typeBlock) {
|
public int compareTo(TypeBlock typeBlock) {
|
||||||
@ -286,8 +286,8 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
* Lets depreciate to warn developer
|
* Lets depreciate to warn developer
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public EntryBlock searchByEntryName(String entryName){
|
public Entry searchByEntryName(String entryName){
|
||||||
return getEntryBlockArray().searchByEntryName(entryName);
|
return getEntryArray().searchByEntryName(entryName);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
import com.reandroid.arsc.chunk.Chunk;
|
import com.reandroid.arsc.chunk.Chunk;
|
||||||
import com.reandroid.arsc.chunk.ChunkType;
|
import com.reandroid.arsc.chunk.ChunkType;
|
||||||
import com.reandroid.arsc.chunk.MainChunk;
|
import com.reandroid.arsc.chunk.MainChunk;
|
||||||
|
import com.reandroid.arsc.chunk.ParentChunk;
|
||||||
import com.reandroid.arsc.container.SingleBlockContainer;
|
import com.reandroid.arsc.container.SingleBlockContainer;
|
||||||
import com.reandroid.arsc.header.HeaderBlock;
|
import com.reandroid.arsc.header.HeaderBlock;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.pool.ResXmlStringPool;
|
import com.reandroid.arsc.pool.ResXmlStringPool;
|
||||||
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
@ -38,7 +40,7 @@
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ResXmlDocument extends Chunk<HeaderBlock>
|
public class ResXmlDocument extends Chunk<HeaderBlock>
|
||||||
implements MainChunk, JSONConvert<JSONObject> {
|
implements MainChunk, ParentChunk, JSONConvert<JSONObject> {
|
||||||
private final ResXmlStringPool mResXmlStringPool;
|
private final ResXmlStringPool mResXmlStringPool;
|
||||||
private final ResXmlIDMap mResXmlIDMap;
|
private final ResXmlIDMap mResXmlIDMap;
|
||||||
private ResXmlElement mResXmlElement;
|
private ResXmlElement mResXmlElement;
|
||||||
@ -166,6 +168,10 @@
|
|||||||
public ResXmlStringPool getStringPool(){
|
public ResXmlStringPool getStringPool(){
|
||||||
return mResXmlStringPool;
|
return mResXmlStringPool;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public StringPool<?> getSpecStringPool() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
public ResXmlIDMap getResXmlIDMap(){
|
public ResXmlIDMap getResXmlIDMap(){
|
||||||
return mResXmlIDMap;
|
return mResXmlIDMap;
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
package com.reandroid.arsc.container;
|
package com.reandroid.arsc.container;
|
||||||
|
|
||||||
import com.reandroid.arsc.base.BlockContainer;
|
import com.reandroid.arsc.base.BlockContainer;
|
||||||
import com.reandroid.arsc.value.BaseResValue;
|
import com.reandroid.arsc.value.ValueItem;
|
||||||
|
|
||||||
public class ResValueContainer extends BlockContainer<BaseResValue> {
|
public class ResValueContainer extends BlockContainer<ValueItem> {
|
||||||
private final BaseResValue[] mChildes;
|
private final ValueItem[] mChildes;
|
||||||
public ResValueContainer(){
|
public ResValueContainer(){
|
||||||
super();
|
super();
|
||||||
mChildes=new BaseResValue[1];
|
mChildes=new ValueItem[1];
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onRefreshed(){
|
protected void onRefreshed(){
|
||||||
@ -32,11 +32,11 @@ public class ResValueContainer extends BlockContainer<BaseResValue> {
|
|||||||
return mChildes.length;
|
return mChildes.length;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public BaseResValue[] getChildes() {
|
public ValueItem[] getChildes() {
|
||||||
return mChildes;
|
return mChildes;
|
||||||
}
|
}
|
||||||
public void setResValue(BaseResValue resValue){
|
public void setResValue(ValueItem resValue){
|
||||||
BaseResValue old=getResValue();
|
ValueItem old=getResValue();
|
||||||
if(old!=null){
|
if(old!=null){
|
||||||
old.setIndex(-1);
|
old.setIndex(-1);
|
||||||
old.setParent(null);
|
old.setParent(null);
|
||||||
@ -48,7 +48,7 @@ public class ResValueContainer extends BlockContainer<BaseResValue> {
|
|||||||
resValue.setIndex(0);
|
resValue.setIndex(0);
|
||||||
resValue.setParent(this);
|
resValue.setParent(this);
|
||||||
}
|
}
|
||||||
public BaseResValue getResValue(){
|
public ValueItem getResValue(){
|
||||||
if(mChildes.length==0){
|
if(mChildes.length==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import com.reandroid.arsc.chunk.TypeBlock;
|
|||||||
import com.reandroid.arsc.header.HeaderBlock;
|
import com.reandroid.arsc.header.HeaderBlock;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.item.TypeString;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
@ -53,11 +53,11 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
public SpecTypePair(){
|
public SpecTypePair(){
|
||||||
this(new SpecBlock(), new TypeBlockArray());
|
this(new SpecBlock(), new TypeBlockArray());
|
||||||
}
|
}
|
||||||
public EntryBlock getAnyEntry(String name){
|
public Entry getAnyEntry(String name){
|
||||||
for(TypeBlock typeBlock:listTypeBlocks()){
|
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||||
EntryBlock entryBlock=typeBlock.searchByEntryName(name);
|
Entry entry =typeBlock.searchByEntryName(name);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -74,10 +74,10 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
public int countTypeBlocks(){
|
public int countTypeBlocks(){
|
||||||
return getTypeBlockArray().childesCount();
|
return getTypeBlockArray().childesCount();
|
||||||
}
|
}
|
||||||
public EntryBlock getOrCreateEntry(short entryId, String qualifiers){
|
public Entry getOrCreateEntry(short entryId, String qualifiers){
|
||||||
return getTypeBlockArray().getOrCreateEntry(entryId, qualifiers);
|
return getTypeBlockArray().getOrCreateEntry(entryId, qualifiers);
|
||||||
}
|
}
|
||||||
public EntryBlock getEntry(short entryId, String qualifiers){
|
public Entry getEntry(short entryId, String qualifiers){
|
||||||
return getTypeBlockArray().getEntry(entryId, qualifiers);
|
return getTypeBlockArray().getEntry(entryId, qualifiers);
|
||||||
}
|
}
|
||||||
public TypeBlock getOrCreateTypeBlock(String qualifiers){
|
public TypeBlock getOrCreateTypeBlock(String qualifiers){
|
||||||
@ -115,7 +115,7 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
* Lets depreciate to warn developer
|
* Lets depreciate to warn developer
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public EntryBlock searchByEntryName(String entryName){
|
public Entry searchByEntryName(String entryName){
|
||||||
return getTypeBlockArray().searchByEntryName(entryName);
|
return getTypeBlockArray().searchByEntryName(entryName);
|
||||||
}
|
}
|
||||||
public SpecBlock getSpecBlock(){
|
public SpecBlock getSpecBlock(){
|
||||||
@ -134,16 +134,16 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public List<EntryBlock> listEntries(int entryId){
|
public List<Entry> listEntries(int entryId){
|
||||||
List<EntryBlock> results=new ArrayList<>();
|
List<Entry> results=new ArrayList<>();
|
||||||
Iterator<TypeBlock> itr = mTypeBlockArray.iterator(true);
|
Iterator<TypeBlock> itr = mTypeBlockArray.iterator(true);
|
||||||
while (itr.hasNext()){
|
while (itr.hasNext()){
|
||||||
TypeBlock typeBlock=itr.next();
|
TypeBlock typeBlock=itr.next();
|
||||||
EntryBlock entryBlock=typeBlock.getEntryBlock(entryId);
|
Entry entry = typeBlock.getEntry(entryId);
|
||||||
if(entryBlock==null||entryBlock.isNull()){
|
if(entry ==null|| entry.isNull()){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
results.add(entryBlock);
|
results.add(entry);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -242,14 +242,14 @@ import java.util.regex.Pattern;
|
|||||||
if(entryGroup==null){
|
if(entryGroup==null){
|
||||||
return String.format("@0x%08x", resourceId);
|
return String.format("@0x%08x", resourceId);
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock=entryGroup.pickOne();
|
Entry entry =entryGroup.pickOne();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return String.format("@0x%08x", resourceId);
|
return String.format("@0x%08x", resourceId);
|
||||||
}
|
}
|
||||||
String prefix=null;
|
String prefix=null;
|
||||||
if(currentPackage!=null){
|
if(currentPackage!=null){
|
||||||
String name=currentPackage.getName();
|
String name=currentPackage.getName();
|
||||||
String other=entryBlock.getPackageBlock().getName();
|
String other= entry.getPackageBlock().getName();
|
||||||
if(!name.equals(other)){
|
if(!name.equals(other)){
|
||||||
prefix=other+":";
|
prefix=other+":";
|
||||||
}
|
}
|
||||||
@ -300,34 +300,34 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
return decode(valueType, data);
|
return decode(valueType, data);
|
||||||
}
|
}
|
||||||
public static String decodeIntEntry(EntryStore store, EntryBlock entryBlock){
|
public static String decodeIntEntry(EntryStore store, Entry entry){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
BaseResValue baseResValue = entryBlock.getResValue();
|
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||||
if(!(baseResValue instanceof ResValueInt)){
|
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
ResValue resValue =(ResValue) tableEntry.getValue();
|
||||||
return decodeIntEntry(store, resValueInt);
|
return decodeIntEntry(store, resValue);
|
||||||
}
|
}
|
||||||
public static String decodeIntEntry(EntryStore store, ResValueInt resValueInt){
|
public static String decodeIntEntry(EntryStore store, ResValue resValue){
|
||||||
if(resValueInt==null){
|
if(resValue ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
EntryBlock parentEntry=resValueInt.getEntryBlock();
|
Entry parentEntry = resValue.getEntry();
|
||||||
if(parentEntry==null){
|
if(parentEntry==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ValueType valueType=resValueInt.getValueType();
|
ValueType valueType= resValue.getValueType();
|
||||||
int data=resValueInt.getData();
|
int data= resValue.getData();
|
||||||
return decodeIntEntry(store, parentEntry, valueType, data);
|
return decodeIntEntry(store, parentEntry, valueType, data);
|
||||||
}
|
}
|
||||||
public static String decodeIntEntry(EntryStore store, ResValueBagItem bagItem){
|
public static String decodeIntEntry(EntryStore store, ResValueMap bagItem){
|
||||||
if(bagItem==null){
|
if(bagItem==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
EntryBlock parentEntry=bagItem.getEntryBlock();
|
Entry parentEntry=bagItem.getEntry();
|
||||||
if(parentEntry==null){
|
if(parentEntry==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -335,7 +335,7 @@ import java.util.regex.Pattern;
|
|||||||
int data=bagItem.getData();
|
int data=bagItem.getData();
|
||||||
return decodeIntEntry(store, parentEntry, valueType, data);
|
return decodeIntEntry(store, parentEntry, valueType, data);
|
||||||
}
|
}
|
||||||
public static String decodeIntEntry(EntryStore store, EntryBlock parentEntry, ValueType valueType, int data){
|
public static String decodeIntEntry(EntryStore store, Entry parentEntry, ValueType valueType, int data){
|
||||||
if(valueType==ValueType.NULL){
|
if(valueType==ValueType.NULL){
|
||||||
return "@empty";
|
return "@empty";
|
||||||
}
|
}
|
||||||
@ -367,18 +367,18 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
return decode(valueType, data);
|
return decode(valueType, data);
|
||||||
}
|
}
|
||||||
public static String buildReferenceValue(EntryStore store, EntryBlock entryBlock){
|
public static String buildReferenceValue(EntryStore store, Entry entry){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
BaseResValue baseResValue = entryBlock.getResValue();
|
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||||
if(!(baseResValue instanceof ResValueInt)){
|
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
ResValue resValue =(ResValue) tableEntry.getValue();
|
||||||
int resourceId=resValueInt.getData();
|
int resourceId= resValue.getData();
|
||||||
ValueType valueType=resValueInt.getValueType();
|
ValueType valueType= resValue.getValueType();
|
||||||
return buildReferenceValue(store, entryBlock, valueType, resourceId);
|
return buildReferenceValue(store, entry, valueType, resourceId);
|
||||||
}
|
}
|
||||||
public static String decode(EntryStore entryStore, int currentPackageId, int nameResourceId, ValueType valueType, int rawVal){
|
public static String decode(EntryStore entryStore, int currentPackageId, int nameResourceId, ValueType valueType, int rawVal){
|
||||||
String currPackageName=getPackageName(entryStore, currentPackageId);
|
String currPackageName=getPackageName(entryStore, currentPackageId);
|
||||||
@ -446,17 +446,17 @@ import java.util.regex.Pattern;
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildReferenceValue(EntryStore store, EntryBlock entryBlock, ValueType valueType, int resourceId){
|
private static String buildReferenceValue(EntryStore store, Entry entry, ValueType valueType, int resourceId){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
EntryGroup value=searchEntryGroup(store, entryBlock, resourceId);
|
EntryGroup value=searchEntryGroup(store, entry, resourceId);
|
||||||
if(value==null){
|
if(value==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return buildReferenceValue(valueType, entryBlock, value);
|
return buildReferenceValue(valueType, entry, value);
|
||||||
}
|
}
|
||||||
private static String buildReferenceValue(ValueType valueType, EntryBlock entryBlock, EntryGroup value){
|
private static String buildReferenceValue(ValueType valueType, Entry entry, EntryGroup value){
|
||||||
char atOrQues;
|
char atOrQues;
|
||||||
if(valueType==ValueType.REFERENCE){
|
if(valueType==ValueType.REFERENCE){
|
||||||
atOrQues='@';
|
atOrQues='@';
|
||||||
@ -465,7 +465,7 @@ import java.util.regex.Pattern;
|
|||||||
}else {
|
}else {
|
||||||
atOrQues=0;
|
atOrQues=0;
|
||||||
}
|
}
|
||||||
String currentPackageName=getPackageName(entryBlock);
|
String currentPackageName=getPackageName(entry);
|
||||||
String referredPackageName=getPackageName(value);
|
String referredPackageName=getPackageName(value);
|
||||||
String typeName=value.getTypeName();
|
String typeName=value.getTypeName();
|
||||||
String name=value.getSpecName();
|
String name=value.getSpecName();
|
||||||
@ -524,18 +524,18 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
return getPackageName(entryGroup.pickOne());
|
return getPackageName(entryGroup.pickOne());
|
||||||
}
|
}
|
||||||
private static String getPackageName(EntryBlock entryBlock){
|
private static String getPackageName(Entry entry){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
PackageBlock packageBlock= entry.getPackageBlock();
|
||||||
if(packageBlock==null){
|
if(packageBlock==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return packageBlock.getName();
|
return packageBlock.getName();
|
||||||
}
|
}
|
||||||
private static EntryGroup searchEntryGroup(EntryStore store, EntryBlock entryBlock, int resourceId){
|
private static EntryGroup searchEntryGroup(EntryStore store, Entry entry, int resourceId){
|
||||||
EntryGroup entryGroup=searchEntryGroup(entryBlock, resourceId);
|
EntryGroup entryGroup=searchEntryGroup(entry, resourceId);
|
||||||
if(entryGroup!=null){
|
if(entryGroup!=null){
|
||||||
return entryGroup;
|
return entryGroup;
|
||||||
}
|
}
|
||||||
@ -544,11 +544,11 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
return store.getEntryGroup(resourceId);
|
return store.getEntryGroup(resourceId);
|
||||||
}
|
}
|
||||||
private static EntryGroup searchEntryGroup(EntryBlock entryBlock, int resourceId){
|
private static EntryGroup searchEntryGroup(Entry entry, int resourceId){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
PackageBlock packageBlock= entry.getPackageBlock();
|
||||||
if(packageBlock==null){
|
if(packageBlock==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -581,11 +581,11 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static String decodeIntEntryString(EntryBlock entryBlock, int data){
|
private static String decodeIntEntryString(Entry entry, int data){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
PackageBlock packageBlock= entry.getPackageBlock();
|
||||||
if(packageBlock==null){
|
if(packageBlock==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -719,9 +719,9 @@ import java.util.regex.Pattern;
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
private static String getResourceName(EntryStore store, EntryBlock entryBlock, int resourceId){
|
private static String getResourceName(EntryStore store, Entry entry, int resourceId){
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
EntryGroup group=searchEntryGroup(entryBlock, resourceId);
|
EntryGroup group=searchEntryGroup(entry, resourceId);
|
||||||
if(group!=null){
|
if(group!=null){
|
||||||
String name=group.getSpecName();
|
String name=group.getSpecName();
|
||||||
if(name!=null){
|
if(name!=null){
|
||||||
@ -748,58 +748,58 @@ import java.util.regex.Pattern;
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static AttributeBag getAttributeBag(EntryStore store, int resourceId){
|
private static AttributeBag getAttributeBag(EntryStore store, int resourceId){
|
||||||
ResValueBag resValueBag=getAttributeValueBag(store, resourceId);
|
ResTableMapEntry mapEntry=getAttributeValueBag(store, resourceId);
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return AttributeBag.create(resValueBag);
|
return AttributeBag.create(mapEntry.getValue());
|
||||||
}
|
}
|
||||||
private static ResValueBag getAttributeValueBag(EntryStore store, int resourceId){
|
private static ResTableMapEntry getAttributeValueBag(EntryStore store, int resourceId){
|
||||||
if(store==null){
|
if(store==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Collection<EntryGroup> foundGroups = store.getEntryGroups(resourceId);
|
Collection<EntryGroup> foundGroups = store.getEntryGroups(resourceId);
|
||||||
ResValueBag best=null;
|
ResTableMapEntry best=null;
|
||||||
for(EntryGroup group:foundGroups){
|
for(EntryGroup group:foundGroups){
|
||||||
ResValueBag valueBag= getAttributeValueBag(group);
|
ResTableMapEntry valueBag = getAttributeValueBag(group);
|
||||||
best=chooseBest(best, valueBag);
|
best=chooseBest(best, valueBag);
|
||||||
}
|
}
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
private static ResValueBag getAttributeValueBag(EntryGroup entryGroup){
|
private static ResTableMapEntry getAttributeValueBag(EntryGroup entryGroup){
|
||||||
if(entryGroup==null){
|
if(entryGroup==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueBag best=null;
|
ResTableMapEntry best=null;
|
||||||
Iterator<EntryBlock> iterator=entryGroup.iterator(true);
|
Iterator<Entry> iterator=entryGroup.iterator(true);
|
||||||
while (iterator.hasNext()){
|
while (iterator.hasNext()){
|
||||||
EntryBlock entryBlock=iterator.next();
|
Entry entry =iterator.next();
|
||||||
ResValueBag valueBag= getAttributeValueBag(entryBlock);
|
ResTableMapEntry valueBag = getAttributeValueBag(entry);
|
||||||
best=chooseBest(best, valueBag);
|
best=chooseBest(best, valueBag);
|
||||||
}
|
}
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
private static ResValueBag getAttributeValueBag(EntryBlock entryBlock){
|
private static ResTableMapEntry getAttributeValueBag(Entry entry){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
BaseResValue baseResValue = entryBlock.getResValue();
|
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||||
if(baseResValue instanceof ResValueBag){
|
if(tableEntry instanceof ResTableMapEntry){
|
||||||
return (ResValueBag) baseResValue;
|
return (ResTableMapEntry) tableEntry;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static ResValueBag chooseBest(ResValueBag valueBag1, ResValueBag valueBag2){
|
private static ResTableMapEntry chooseBest(ResTableMapEntry entry1, ResTableMapEntry entry2){
|
||||||
if(valueBag1==null){
|
if(entry1==null){
|
||||||
return valueBag2;
|
return entry2;
|
||||||
}
|
}
|
||||||
if(valueBag2==null){
|
if(entry2==null){
|
||||||
return valueBag1;
|
return entry1;
|
||||||
}
|
}
|
||||||
if(valueBag2.getCount()>valueBag1.getCount()){
|
if(entry2.getValue().childesCount()>entry1.getValue().childesCount()){
|
||||||
return valueBag2;
|
return entry2;
|
||||||
}
|
}
|
||||||
return valueBag1;
|
return entry1;
|
||||||
}
|
}
|
||||||
private static String toHexResourceId(int resourceId){
|
private static String toHexResourceId(int resourceId){
|
||||||
return String.format("0x%08x", resourceId);
|
return String.format("0x%08x", resourceId);
|
||||||
|
@ -21,11 +21,11 @@ import com.reandroid.arsc.chunk.TypeBlock;
|
|||||||
import com.reandroid.arsc.item.SpecString;
|
import com.reandroid.arsc.item.SpecString;
|
||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.item.TypeString;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class EntryGroup extends ItemGroup<EntryBlock> {
|
public class EntryGroup extends ItemGroup<Entry> {
|
||||||
private final int resourceId;
|
private final int resourceId;
|
||||||
public EntryGroup(int resId) {
|
public EntryGroup(int resId) {
|
||||||
super(create(), String.format("0x%08x", resId));
|
super(create(), String.format("0x%08x", resId));
|
||||||
@ -35,7 +35,7 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
|||||||
return resourceId;
|
return resourceId;
|
||||||
}
|
}
|
||||||
public boolean renameSpec(String name){
|
public boolean renameSpec(String name){
|
||||||
EntryBlock[] items=getItems();
|
Entry[] items=getItems();
|
||||||
if(items==null || name==null){
|
if(items==null || name==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -56,25 +56,25 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
|||||||
return (short) (getResourceId() & 0xffff);
|
return (short) (getResourceId() & 0xffff);
|
||||||
}
|
}
|
||||||
private boolean isAllSameSpec(){
|
private boolean isAllSameSpec(){
|
||||||
EntryBlock first=null;
|
Entry first=null;
|
||||||
for(EntryBlock entryBlock:listItems()){
|
for(Entry entry :listItems()){
|
||||||
if(first==null){
|
if(first==null){
|
||||||
first=entryBlock;
|
first= entry;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(first.getSpecReference()!=entryBlock.getSpecReference()){
|
if(first.getSpecReference()!= entry.getSpecReference()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public boolean renameSpec(int specReference){
|
public boolean renameSpec(int specReference){
|
||||||
EntryBlock[] items=getItems();
|
Entry[] items=getItems();
|
||||||
if(items==null){
|
if(items==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean renameOk=false;
|
boolean renameOk=false;
|
||||||
for(EntryBlock block:items){
|
for(Entry block:items){
|
||||||
if(block==null){
|
if(block==null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -86,45 +86,45 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
|||||||
}
|
}
|
||||||
return renameOk;
|
return renameOk;
|
||||||
}
|
}
|
||||||
public EntryBlock pickOne(){
|
public Entry pickOne(){
|
||||||
EntryBlock[] items=getItems();
|
Entry[] items=getItems();
|
||||||
if(items==null){
|
if(items==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
EntryBlock result = null;
|
Entry result = null;
|
||||||
for(EntryBlock entryBlock:items){
|
for(Entry entry :items){
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(result==null || result.isNull()){
|
if(result==null || result.isNull()){
|
||||||
result=entryBlock;
|
result= entry;
|
||||||
}else if(entryBlock.isDefault()){
|
}else if(entry.isDefault()){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public EntryBlock getDefault(){
|
public Entry getDefault(){
|
||||||
Iterator<EntryBlock> itr=iterator(true);
|
Iterator<Entry> itr=iterator(true);
|
||||||
while (itr.hasNext()){
|
while (itr.hasNext()){
|
||||||
EntryBlock entryBlock=itr.next();
|
Entry entry =itr.next();
|
||||||
if(entryBlock.isDefault()){
|
if(entry.isDefault()){
|
||||||
return entryBlock;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public TypeString getTypeString(){
|
public TypeString getTypeString(){
|
||||||
EntryBlock entryBlock=pickOne();
|
Entry entry =pickOne();
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock.getTypeString();
|
return entry.getTypeString();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public SpecString getSpecString(){
|
public SpecString getSpecString(){
|
||||||
EntryBlock entryBlock=pickOne();
|
Entry entry =pickOne();
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock.getSpecString();
|
return entry.getSpecString();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -143,11 +143,11 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
|||||||
return specString.get();
|
return specString.get();
|
||||||
}
|
}
|
||||||
private SpecStringPool getSpecStringPool(){
|
private SpecStringPool getSpecStringPool(){
|
||||||
EntryBlock entryBlock=get(0);
|
Entry entry =get(0);
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
TypeBlock typeBlock= entry.getTypeBlock();
|
||||||
if(typeBlock==null){
|
if(typeBlock==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -159,22 +159,22 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
EntryBlock entryBlock=pickOne();
|
Entry entry =pickOne();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return super.toString();
|
return super.toString();
|
||||||
}
|
}
|
||||||
return super.toString()+"{"+entryBlock.toString()+"}";
|
return super.toString()+"{"+ entry.toString()+"}";
|
||||||
}
|
}
|
||||||
private static BlockArrayCreator<EntryBlock> create(){
|
private static BlockArrayCreator<Entry> create(){
|
||||||
return new BlockArrayCreator<EntryBlock>(){
|
return new BlockArrayCreator<Entry>(){
|
||||||
@Override
|
@Override
|
||||||
public EntryBlock newInstance() {
|
public Entry newInstance() {
|
||||||
return new EntryBlock();
|
return new Entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntryBlock[] newInstance(int len) {
|
public Entry[] newInstance(int len) {
|
||||||
return new EntryBlock[len];
|
return new Entry[len];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import java.util.Objects;
|
|||||||
}
|
}
|
||||||
public List<T> listItems(){
|
public List<T> listItems(){
|
||||||
return new AbstractList<T>() {
|
return new AbstractList<T>() {
|
||||||
|
private final int mSize = ItemGroup.this.size();
|
||||||
@Override
|
@Override
|
||||||
public T get(int i) {
|
public T get(int i) {
|
||||||
return ItemGroup.this.get(i);
|
return ItemGroup.this.get(i);
|
||||||
@ -49,7 +50,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return ItemGroup.this.size();
|
return mSize;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -148,4 +148,21 @@ public abstract class BlockItem extends Block {
|
|||||||
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
||||||
bts[offset]= (byte) (val & 0xff);
|
bts[offset]= (byte) (val & 0xff);
|
||||||
}
|
}
|
||||||
|
protected static boolean getBit(byte[] bts, int byteOffset, int bitIndex){
|
||||||
|
return (((bts[byteOffset] & 0xff) >>bitIndex) & 0x1) == 1;
|
||||||
|
}
|
||||||
|
protected static void putBit(byte[] bts, int byteOffset, int bitIndex, boolean bit){
|
||||||
|
int val=bts[byteOffset] & 0xff;
|
||||||
|
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;
|
||||||
|
bts[byteOffset]=(byte) val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
38
src/main/java/com/reandroid/arsc/item/ReferenceBlock.java
Normal file
38
src/main/java/com/reandroid/arsc/item/ReferenceBlock.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.item;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
|
||||||
|
public class ReferenceBlock<T extends Block> implements ReferenceItem{
|
||||||
|
private final T block;
|
||||||
|
private final int offset;
|
||||||
|
public ReferenceBlock(T block, int offset){
|
||||||
|
this.block = block;
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
public T getBlock(){
|
||||||
|
return this.block;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void set(int val) {
|
||||||
|
BlockItem.putInteger(this.block.getBytes(), this.offset, val);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int get() {
|
||||||
|
return BlockItem.getInteger(this.block.getBytes(), this.offset);
|
||||||
|
}
|
||||||
|
}
|
@ -97,9 +97,6 @@ public class StringItem extends BlockItem implements JSONConvert<JSONObject> {
|
|||||||
if(str==null){
|
if(str==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(str.startsWith("*Plus taxes if applicable")){
|
|
||||||
String junk="";
|
|
||||||
}
|
|
||||||
StyleItem styleItem=getStyle();
|
StyleItem styleItem=getStyle();
|
||||||
if(styleItem==null){
|
if(styleItem==null){
|
||||||
return str;
|
return str;
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueReference;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
|
import com.reandroid.arsc.value.ValueItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -25,20 +26,20 @@ public class TableString extends StringItem {
|
|||||||
public TableString(boolean utf8) {
|
public TableString(boolean utf8) {
|
||||||
super(utf8);
|
super(utf8);
|
||||||
}
|
}
|
||||||
public List<EntryBlock> listReferencedEntries(boolean ignoreBagEntries){
|
public List<Entry> listReferencedEntries(boolean ignoreBagEntries){
|
||||||
List<EntryBlock> results=new ArrayList<>();
|
List<Entry> results=new ArrayList<>();
|
||||||
for(ReferenceItem ref:getReferencedList()){
|
for(ReferenceItem ref:getReferencedList()){
|
||||||
if(!(ref instanceof ResValueReference)){
|
if(!(ref instanceof ReferenceBlock)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock=((ResValueReference)ref).getEntryBlock();
|
ValueItem valueItem = (ValueItem) ((ReferenceBlock)ref).getBlock();
|
||||||
if(entryBlock==null){
|
if(valueItem ==null){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(ignoreBagEntries && entryBlock.isEntryTypeBag()){
|
if(ignoreBagEntries && (valueItem instanceof ResValueMap)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
results.add(entryBlock);
|
results.add(valueItem.getParentEntry());
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ import com.reandroid.arsc.io.BlockReader;
|
|||||||
import com.reandroid.arsc.item.ReferenceItem;
|
import com.reandroid.arsc.item.ReferenceItem;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -45,9 +45,9 @@ public class FrameworkTable extends TableBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int resolveResourceId(String typeName, String entryName){
|
public int resolveResourceId(String typeName, String entryName){
|
||||||
EntryBlock entryBlock=searchEntryBlock(typeName, entryName);
|
Entry entry = searchEntry(typeName, entryName);
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
return entryBlock.getResourceId();
|
return entry.getResourceId();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ public class FrameworkTable extends TableBlock {
|
|||||||
private boolean hasResourceGroupMap(){
|
private boolean hasResourceGroupMap(){
|
||||||
return mNameGroupMap!=null;
|
return mNameGroupMap!=null;
|
||||||
}
|
}
|
||||||
private EntryBlock searchEntryBlockFromMap(String typeName, String entryName){
|
private Entry searchEntryFromMap(String typeName, String entryName){
|
||||||
if(mNameGroupMap ==null){
|
if(mNameGroupMap ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -91,16 +91,16 @@ public class FrameworkTable extends TableBlock {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public EntryBlock searchEntryBlock(String typeName, String entryName){
|
public Entry searchEntry(String typeName, String entryName){
|
||||||
if(hasResourceGroupMap()){
|
if(hasResourceGroupMap()){
|
||||||
return searchEntryBlockFromMap(typeName, entryName);
|
return searchEntryFromMap(typeName, entryName);
|
||||||
}
|
}
|
||||||
return searchEntryBlockFromTable(typeName, entryName);
|
return searchEntryFromTable(typeName, entryName);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Since this is framework, we are sure of proper names.
|
* Since this is framework, we are sure of proper names.
|
||||||
*/
|
*/
|
||||||
public EntryBlock searchEntryBlockFromTable(String typeName, String entryName){
|
public Entry searchEntryFromTable(String typeName, String entryName){
|
||||||
for(PackageBlock packageBlock:listPackages()){
|
for(PackageBlock packageBlock:listPackages()){
|
||||||
SpecTypePair specTypePair = packageBlock.searchByTypeName(typeName);
|
SpecTypePair specTypePair = packageBlock.searchByTypeName(typeName);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
@ -166,8 +166,8 @@ public class FrameworkTable extends TableBlock {
|
|||||||
public void optimize(String frameworkName, String frameworkVersion){
|
public void optimize(String frameworkName, String frameworkVersion){
|
||||||
Map<Integer, EntryGroup> groupMap=scanAllEntryGroups();
|
Map<Integer, EntryGroup> groupMap=scanAllEntryGroups();
|
||||||
for(EntryGroup group:groupMap.values()){
|
for(EntryGroup group:groupMap.values()){
|
||||||
List<EntryBlock> entryBlockList=getEntriesToRemove(group);
|
List<Entry> entryList =getEntriesToRemove(group);
|
||||||
removeEntryBlocks(entryBlockList);
|
removeEntries(entryList);
|
||||||
}
|
}
|
||||||
for(PackageBlock pkg:listPackages()){
|
for(PackageBlock pkg:listPackages()){
|
||||||
clearNonDefaultConfigs(pkg);
|
clearNonDefaultConfigs(pkg);
|
||||||
@ -246,32 +246,32 @@ public class FrameworkTable extends TableBlock {
|
|||||||
}
|
}
|
||||||
zero.addReference(allRef);
|
zero.addReference(allRef);
|
||||||
}
|
}
|
||||||
private void removeEntryBlocks(List<EntryBlock> removeList){
|
private void removeEntries(List<Entry> removeList){
|
||||||
for(EntryBlock entryBlock:removeList){
|
for(Entry entry :removeList){
|
||||||
removeEntryBlock(entryBlock);
|
removeEntry(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void removeEntryBlock(EntryBlock entryBlock){
|
private void removeEntry(Entry entry){
|
||||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
TypeBlock typeBlock= entry.getTypeBlock();
|
||||||
if(typeBlock==null){
|
if(typeBlock==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
typeBlock.removeEntry(entryBlock);
|
typeBlock.removeEntry(entry);
|
||||||
|
|
||||||
}
|
}
|
||||||
private List<EntryBlock> getEntriesToRemove(EntryGroup group){
|
private List<Entry> getEntriesToRemove(EntryGroup group){
|
||||||
List<EntryBlock> results=new ArrayList<>();
|
List<Entry> results=new ArrayList<>();
|
||||||
EntryBlock mainEntry=group.pickOne();
|
Entry mainEntry=group.pickOne();
|
||||||
if(mainEntry==null){
|
if(mainEntry==null){
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
Iterator<EntryBlock> itr = group.iterator(true);
|
Iterator<Entry> itr = group.iterator(true);
|
||||||
while (itr.hasNext()){
|
while (itr.hasNext()){
|
||||||
EntryBlock entryBlock=itr.next();
|
Entry entry =itr.next();
|
||||||
if(entryBlock==mainEntry){
|
if(entry ==mainEntry){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
results.add(entryBlock);
|
results.add(entry);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.base.Block;
|
|
||||||
import com.reandroid.arsc.item.BlockItem;
|
|
||||||
import com.reandroid.arsc.item.ReferenceItem;
|
|
||||||
import com.reandroid.json.JSONConvert;
|
|
||||||
import com.reandroid.json.JSONObject;
|
|
||||||
|
|
||||||
public abstract class BaseResValue extends BlockItem implements JSONConvert<JSONObject> {
|
|
||||||
BaseResValue(int bytesLength){
|
|
||||||
super(bytesLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onRemoved(){
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntryBlock getEntryBlock(){
|
|
||||||
Block parent=getParent();
|
|
||||||
while(parent!=null){
|
|
||||||
if(parent instanceof EntryBlock){
|
|
||||||
return (EntryBlock)parent;
|
|
||||||
}
|
|
||||||
parent=parent.getParent();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean removeSpecReference(ReferenceItem ref){
|
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
|
||||||
if(entryBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return entryBlock.removeSpecReference(ref);
|
|
||||||
}
|
|
||||||
boolean removeTableReference(ReferenceItem ref){
|
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
|
||||||
if(entryBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return entryBlock.removeTableReference(ref);
|
|
||||||
}
|
|
||||||
void addSpecReference(ReferenceItem ref){
|
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
|
||||||
if(entryBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
entryBlock.addSpecReference(ref);
|
|
||||||
}
|
|
||||||
void addTableReference(ReferenceItem ref){
|
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
|
||||||
if(entryBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
entryBlock.addTableReference(ref);
|
|
||||||
}
|
|
||||||
void onDataLoaded() {
|
|
||||||
|
|
||||||
}
|
|
||||||
int getInt(int offset){
|
|
||||||
byte[] bts = getBytesInternal();
|
|
||||||
return bts[offset] & 0xff |
|
|
||||||
(bts[offset+1] & 0xff) << 8 |
|
|
||||||
(bts[offset+2] & 0xff) << 16 |
|
|
||||||
(bts[offset+3] & 0xff) << 24;
|
|
||||||
}
|
|
||||||
void setInt(int offset, int val){
|
|
||||||
if(val==getInt(offset)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
byte[] bts = getBytesInternal();
|
|
||||||
bts[offset+3]= (byte) (val >>> 24 & 0xff);
|
|
||||||
bts[offset+2]= (byte) (val >>> 16 & 0xff);
|
|
||||||
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
|
||||||
bts[offset]= (byte) (val & 0xff);
|
|
||||||
onBytesChanged();
|
|
||||||
}
|
|
||||||
void setShort(int offset, short val){
|
|
||||||
if(val==getShort(offset)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
byte[] bts = getBytesInternal();
|
|
||||||
bts[offset+1]= (byte) (val >>> 8 & 255);
|
|
||||||
bts[offset]= (byte) (val & 255);
|
|
||||||
onBytesChanged();
|
|
||||||
}
|
|
||||||
short getShort(int offset){
|
|
||||||
byte[] bts=getBytesInternal();
|
|
||||||
int i= bts[offset] & 0xff |
|
|
||||||
(bts[offset+1] & 0xff) << 8 ;
|
|
||||||
return (short)i;
|
|
||||||
}
|
|
||||||
void setByte(int offset, byte b){
|
|
||||||
byte[] bts=getBytesInternal();
|
|
||||||
if(b==bts[offset]){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bts[offset]=b;
|
|
||||||
onBytesChanged();
|
|
||||||
}
|
|
||||||
byte getByte(int offset){
|
|
||||||
return getBytesInternal()[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
static final String NAME_data = "data";
|
|
||||||
static final String NAME_value_type="value_type";
|
|
||||||
static final String NAME_id="id";
|
|
||||||
static final String NAME_parent="parent";
|
|
||||||
static final String NAME_items="items";
|
|
||||||
}
|
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
|
||||||
import com.reandroid.arsc.chunk.TableBlock;
|
|
||||||
import com.reandroid.arsc.item.ReferenceItem;
|
|
||||||
import com.reandroid.arsc.item.TableString;
|
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
|
||||||
|
|
||||||
public abstract class BaseResValueItem extends BaseResValue implements ResValueItem {
|
|
||||||
|
|
||||||
private ReferenceItem mReferenceItem;
|
|
||||||
BaseResValueItem(int bytesLength) {
|
|
||||||
super(bytesLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TableString getValueAsPoolString(){
|
|
||||||
return getTableString(getData());
|
|
||||||
}
|
|
||||||
String getString(int ref){
|
|
||||||
TableString tableString=getTableString(ref);
|
|
||||||
if(tableString==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return tableString.getHtml();
|
|
||||||
}
|
|
||||||
TableString getTableString(int ref){
|
|
||||||
TableStringPool stringPool=getTableStringPool();
|
|
||||||
if(stringPool==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return stringPool.get(ref);
|
|
||||||
}
|
|
||||||
TableStringPool getTableStringPool(){
|
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
|
||||||
if(entryBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
|
||||||
if(tableBlock!=null){
|
|
||||||
return tableBlock.getTableStringPool();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public ReferenceItem getTableStringReference(){
|
|
||||||
if(getValueType()!=ValueType.STRING || getEntryBlock()==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if(mReferenceItem==null){
|
|
||||||
mReferenceItem=new ResValueReference(this);
|
|
||||||
}
|
|
||||||
return mReferenceItem;
|
|
||||||
}
|
|
||||||
boolean hasTableReference(){
|
|
||||||
return mReferenceItem!=null;
|
|
||||||
}
|
|
||||||
boolean removeTableReference(){
|
|
||||||
ReferenceItem ref=mReferenceItem;
|
|
||||||
if(ref==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
|
||||||
if(entryBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mReferenceItem=null;
|
|
||||||
return entryBlock.removeTableReference(ref);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public ValueType getValueType(){
|
|
||||||
return ValueType.valueOf(getType());
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setValueType(ValueType valueType){
|
|
||||||
byte type=0;
|
|
||||||
if(valueType!=null){
|
|
||||||
type=valueType.getByte();
|
|
||||||
}
|
|
||||||
setType(type);
|
|
||||||
}
|
|
||||||
}
|
|
438
src/main/java/com/reandroid/arsc/value/Entry.java
Executable file
438
src/main/java/com/reandroid/arsc/value/Entry.java
Executable file
@ -0,0 +1,438 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
import com.reandroid.arsc.base.BlockCounter;
|
||||||
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
|
import com.reandroid.arsc.chunk.TypeBlock;
|
||||||
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.item.*;
|
||||||
|
import com.reandroid.json.JSONConvert;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class Entry extends Block implements JSONConvert<JSONObject> {
|
||||||
|
private TableEntry<?, ?> mTableEntry;
|
||||||
|
|
||||||
|
public Entry(){
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId(){
|
||||||
|
return getIndex();
|
||||||
|
}
|
||||||
|
public String getName(){
|
||||||
|
SpecString specString = getSpecString();
|
||||||
|
if(specString!=null){
|
||||||
|
return specString.get();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public String getTypeName(){
|
||||||
|
TypeBlock typeBlock = getTypeBlock();
|
||||||
|
if(typeBlock!=null){
|
||||||
|
return typeBlock.getTypeName();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public int getResourceId(){
|
||||||
|
PackageBlock packageBlock = getPackageBlock();
|
||||||
|
if(packageBlock==null){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TypeBlock typeBlock = getTypeBlock();
|
||||||
|
if(typeBlock==null){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (packageBlock.getId()<<24)
|
||||||
|
| (typeBlock.getId() << 16)
|
||||||
|
| getId();
|
||||||
|
}
|
||||||
|
public int getSpecReference(){
|
||||||
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
|
if(tableEntry == null){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return tableEntry.getHeader().getKey();
|
||||||
|
}
|
||||||
|
public TypeString getTypeString(){
|
||||||
|
TypeBlock typeBlock = getTypeBlock();
|
||||||
|
if(typeBlock!=null){
|
||||||
|
return typeBlock.getTypeString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public boolean isDefault(){
|
||||||
|
ResConfig resConfig = getResConfig();
|
||||||
|
if(resConfig!=null){
|
||||||
|
return resConfig.isDefault();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void setSpecReference(StringItem specReference){
|
||||||
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
|
if(tableEntry == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tableEntry.getHeader().setKey(specReference);
|
||||||
|
}
|
||||||
|
public void setSpecReference(int ref){
|
||||||
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
|
if(tableEntry == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tableEntry.getHeader().setKey(ref);
|
||||||
|
}
|
||||||
|
private Entry searchEntry(int resourceId){
|
||||||
|
if(resourceId==getResourceId()){
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
PackageBlock packageBlock= getPackageBlock();
|
||||||
|
if(packageBlock==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
TableBlock tableBlock = packageBlock.getTableBlock();
|
||||||
|
if(tableBlock==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
EntryGroup entryGroup = tableBlock.search(resourceId);
|
||||||
|
if(entryGroup!=null){
|
||||||
|
return entryGroup.pickOne();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public ResValue setValueAsRaw(ValueType valueType, int data){
|
||||||
|
TableEntry<?, ?> tableEntry = ensureTableEntry(false);
|
||||||
|
ResValue resValue = (ResValue) tableEntry.getValue();
|
||||||
|
resValue.setTypeAndData(valueType, data);
|
||||||
|
return resValue;
|
||||||
|
}
|
||||||
|
public ResValue setValueAsBoolean(boolean val){
|
||||||
|
int data = val?0xffffffff:0;
|
||||||
|
return setValueAsRaw(ValueType.INT_BOOLEAN, data);
|
||||||
|
}
|
||||||
|
public ResValue setValueAsReference(int resourceId){
|
||||||
|
return setValueAsRaw(ValueType.REFERENCE, resourceId);
|
||||||
|
}
|
||||||
|
public ResValue setValueAsString(String str){
|
||||||
|
TableEntry<?, ?> tableEntry = ensureTableEntry(false);
|
||||||
|
ResValue resValue = (ResValue) tableEntry.getValue();
|
||||||
|
resValue.setValueAsString(str);
|
||||||
|
return resValue;
|
||||||
|
}
|
||||||
|
public SpecString getSpecString(){
|
||||||
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
|
if(tableEntry == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PackageBlock packageBlock = getPackageBlock();
|
||||||
|
if(packageBlock == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return packageBlock.getSpecStringPool()
|
||||||
|
.get(tableEntry.getHeader().getKey());
|
||||||
|
}
|
||||||
|
public ResConfig getResConfig(){
|
||||||
|
TypeBlock typeBlock = getTypeBlock();
|
||||||
|
if(typeBlock!=null){
|
||||||
|
return typeBlock.getResConfig();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeBlock getTypeBlock(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof TypeBlock){
|
||||||
|
return (TypeBlock) parent;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private String getPackageName(){
|
||||||
|
PackageBlock packageBlock = getPackageBlock();
|
||||||
|
if(packageBlock!=null){
|
||||||
|
return packageBlock.getName();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public PackageBlock getPackageBlock(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof PackageBlock){
|
||||||
|
return (PackageBlock) parent;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private TableEntry<?, ?> ensureTableEntry(boolean is_complex){
|
||||||
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
|
if(tableEntry == null){
|
||||||
|
tableEntry = createTableEntry(is_complex);
|
||||||
|
setTableEntry(tableEntry);
|
||||||
|
return tableEntry;
|
||||||
|
}
|
||||||
|
if(is_complex){
|
||||||
|
if(tableEntry instanceof ResTableMapEntry){
|
||||||
|
return tableEntry;
|
||||||
|
}
|
||||||
|
tableEntry = createTableEntry(true);
|
||||||
|
setTableEntry(tableEntry);
|
||||||
|
return tableEntry;
|
||||||
|
}
|
||||||
|
tableEntry = createTableEntry(false);
|
||||||
|
setTableEntry(tableEntry);
|
||||||
|
return tableEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TableEntry<?, ?> getTableEntry(){
|
||||||
|
return mTableEntry;
|
||||||
|
}
|
||||||
|
public Header getHeader(){
|
||||||
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
|
if(tableEntry!=null){
|
||||||
|
return tableEntry.getHeader();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNull(){
|
||||||
|
return getTableEntry()==null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setNull(boolean is_null){
|
||||||
|
if(is_null){
|
||||||
|
setTableEntry(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public byte[] getBytes() {
|
||||||
|
if(isNull()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getTableEntry().getBytes();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int countBytes() {
|
||||||
|
if(isNull()){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return getTableEntry().countBytes();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onCountUpTo(BlockCounter counter) {
|
||||||
|
if(counter.FOUND){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(counter.END==this){
|
||||||
|
counter.FOUND=true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(isNull()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
counter.addCount(getTableEntry().countBytes());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected int onWriteBytes(OutputStream stream) throws IOException {
|
||||||
|
if(isNull()){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return getTableEntry().writeBytes(stream);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
|
TableEntry<?, ?> tableEntry = createTableEntry(reader);
|
||||||
|
setTableEntry(tableEntry);
|
||||||
|
tableEntry.readBytes(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isComplex(){
|
||||||
|
return getTableEntry() instanceof ResTableMapEntry;
|
||||||
|
}
|
||||||
|
public void setTableEntry(TableEntry<?, ?> tableEntry){
|
||||||
|
if(tableEntry==this.mTableEntry){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onTableEntryRemoved();
|
||||||
|
if(tableEntry==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tableEntry.setIndex(0);
|
||||||
|
tableEntry.setParent(this);
|
||||||
|
this.mTableEntry = tableEntry;
|
||||||
|
onTableEntryAdded();
|
||||||
|
}
|
||||||
|
private void onTableEntryAdded(){
|
||||||
|
PackageBlock packageBlock = getPackageBlock();
|
||||||
|
if(packageBlock!=null){
|
||||||
|
packageBlock.onEntryAdded(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void onTableEntryRemoved(){
|
||||||
|
TableEntry<?, ?> exist = this.mTableEntry;
|
||||||
|
if(exist == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PackageBlock packageBlock = getPackageBlock();
|
||||||
|
if(packageBlock!=null){
|
||||||
|
packageBlock.removeEntryGroup(this);
|
||||||
|
}
|
||||||
|
exist.onRemoved();
|
||||||
|
exist.setIndex(-1);
|
||||||
|
exist.setParent(null);
|
||||||
|
this.mTableEntry = null;
|
||||||
|
}
|
||||||
|
private TableEntry<?, ?> createTableEntry(BlockReader reader) throws IOException {
|
||||||
|
int startPosition = reader.getPosition();
|
||||||
|
reader.offset(2);
|
||||||
|
boolean is_complex = (0x0001 & reader.readShort()) == 0x0001;
|
||||||
|
reader.seek(startPosition);
|
||||||
|
return createTableEntry(is_complex);
|
||||||
|
}
|
||||||
|
private TableEntry<?, ?> createTableEntry(boolean is_complex) {
|
||||||
|
if(is_complex){
|
||||||
|
return new ResTableMapEntry();
|
||||||
|
}else {
|
||||||
|
return new ResTableEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
if(isNull()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getTableEntry().toJson();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
if(json==null){
|
||||||
|
setNull(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean is_complex = json.optBoolean(Header.NAME_is_complex, false);
|
||||||
|
TableEntry<?, ?> entry = createTableEntry(is_complex);
|
||||||
|
setTableEntry(entry);
|
||||||
|
entry.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void merge(Entry entry){
|
||||||
|
if(!shouldMerge(entry)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||||
|
TableEntry<?, ?> existEntry = ensureTableEntry(tableEntry instanceof ResTableMapEntry);
|
||||||
|
existEntry.merge(tableEntry);
|
||||||
|
}
|
||||||
|
private boolean shouldMerge(Entry coming){
|
||||||
|
if(coming == null || coming == this || coming.isNull()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(this.isNull()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return coming.getTableEntry().shouldMerge(coming.getTableEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String buildResourceName(int resourceId, char prefix, boolean includeType){
|
||||||
|
if(resourceId==0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Entry entry=searchEntry(resourceId);
|
||||||
|
return buildResourceName(entry, prefix, includeType);
|
||||||
|
}
|
||||||
|
public String buildResourceName(Entry entry, char prefix, boolean includeType){
|
||||||
|
if(entry==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String pkgName=entry.getPackageName();
|
||||||
|
if(getResourceId()==entry.getResourceId()){
|
||||||
|
pkgName=null;
|
||||||
|
}else if(pkgName!=null){
|
||||||
|
if(pkgName.equals(this.getPackageName())){
|
||||||
|
pkgName=null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String type=null;
|
||||||
|
if(includeType){
|
||||||
|
type=entry.getTypeName();
|
||||||
|
}
|
||||||
|
String name=entry.getName();
|
||||||
|
return buildResourceName(prefix, pkgName, type, name);
|
||||||
|
}
|
||||||
|
public String getResourceName(){
|
||||||
|
return buildResourceName('@',null, getTypeName(), getName());
|
||||||
|
}
|
||||||
|
public String getResourceName(char prefix){
|
||||||
|
return getResourceName(prefix, false, true);
|
||||||
|
}
|
||||||
|
public String getResourceName(char prefix, boolean includePackage, boolean includeType){
|
||||||
|
String pkg=includePackage?getPackageName():null;
|
||||||
|
String type=includeType?getTypeName():null;
|
||||||
|
return buildResourceName(prefix,pkg, type, getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append(String.format("0x%08x", getResourceId()));
|
||||||
|
builder.append(' ');
|
||||||
|
ResConfig resConfig = getResConfig();
|
||||||
|
if(resConfig!=null){
|
||||||
|
builder.append(resConfig);
|
||||||
|
builder.append(' ');
|
||||||
|
}
|
||||||
|
if(isNull()){
|
||||||
|
builder.append("NULL");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
builder.append('@');
|
||||||
|
builder.append(getTypeName());
|
||||||
|
builder.append('/');
|
||||||
|
builder.append(getName());
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildResourceName(char prefix, String packageName, String type, String name){
|
||||||
|
if(name==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StringBuilder builder=new StringBuilder();
|
||||||
|
if(prefix!=0){
|
||||||
|
builder.append(prefix);
|
||||||
|
}
|
||||||
|
if(packageName!=null){
|
||||||
|
builder.append(packageName);
|
||||||
|
builder.append(':');
|
||||||
|
}
|
||||||
|
if(type!=null){
|
||||||
|
builder.append(type);
|
||||||
|
builder.append('/');
|
||||||
|
}
|
||||||
|
builder.append(name);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -1,836 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.base.Block;
|
|
||||||
import com.reandroid.arsc.base.BlockCounter;
|
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
|
||||||
import com.reandroid.arsc.chunk.TableBlock;
|
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
|
||||||
import com.reandroid.arsc.item.*;
|
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
|
||||||
import com.reandroid.json.JSONConvert;
|
|
||||||
import com.reandroid.json.JSONObject;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
|
||||||
private ByteArray entryHeader;
|
|
||||||
private IntegerItem mSpecReference;
|
|
||||||
private BaseResValue mResValue;
|
|
||||||
private boolean mUnLocked;
|
|
||||||
public EntryBlock() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResValueInt setValueAsRaw(ValueType valueType, int rawValue){
|
|
||||||
ResValueInt resValueInt;
|
|
||||||
BaseResValue res = getResValue();
|
|
||||||
if(res instanceof ResValueInt){
|
|
||||||
resValueInt=(ResValueInt) res;
|
|
||||||
}else {
|
|
||||||
resValueInt=new ResValueInt();
|
|
||||||
setResValue(resValueInt);
|
|
||||||
}
|
|
||||||
resValueInt.setValueType(valueType);
|
|
||||||
resValueInt.setData(rawValue);
|
|
||||||
return resValueInt;
|
|
||||||
}
|
|
||||||
public ResValueInt setValueAsBoolean(boolean val){
|
|
||||||
ResValueInt resValueInt;
|
|
||||||
BaseResValue res = getResValue();
|
|
||||||
if(res instanceof ResValueInt){
|
|
||||||
resValueInt=(ResValueInt) res;
|
|
||||||
}else {
|
|
||||||
resValueInt=new ResValueInt();
|
|
||||||
setResValue(resValueInt);
|
|
||||||
}
|
|
||||||
resValueInt.setValueType(ValueType.INT_BOOLEAN);
|
|
||||||
resValueInt.setData(val?0xffffffff:0);
|
|
||||||
return resValueInt;
|
|
||||||
}
|
|
||||||
public ResValueInt setValueAsInteger(int val){
|
|
||||||
ResValueInt resValueInt;
|
|
||||||
BaseResValue res = getResValue();
|
|
||||||
if(res instanceof ResValueInt){
|
|
||||||
resValueInt=(ResValueInt) res;
|
|
||||||
}else {
|
|
||||||
resValueInt=new ResValueInt();
|
|
||||||
setResValue(resValueInt);
|
|
||||||
}
|
|
||||||
resValueInt.setValueType(ValueType.INT_DEC);
|
|
||||||
resValueInt.setData(val);
|
|
||||||
return resValueInt;
|
|
||||||
}
|
|
||||||
public ResValueInt setValueAsReference(int resId){
|
|
||||||
ResValueInt resValueInt;
|
|
||||||
BaseResValue res = getResValue();
|
|
||||||
if(res instanceof ResValueInt){
|
|
||||||
resValueInt=(ResValueInt) res;
|
|
||||||
}else {
|
|
||||||
resValueInt=new ResValueInt();
|
|
||||||
setResValue(resValueInt);
|
|
||||||
}
|
|
||||||
resValueInt.setValueType(ValueType.REFERENCE);
|
|
||||||
resValueInt.setData(resId);
|
|
||||||
return resValueInt;
|
|
||||||
}
|
|
||||||
public ResValueInt setValueAsString(String str){
|
|
||||||
TableStringPool stringPool=getTableStringPool();
|
|
||||||
if(stringPool==null){
|
|
||||||
throw new IllegalArgumentException("TableStringPool = null, EntryBlock not added to parent TableBlock");
|
|
||||||
}
|
|
||||||
TableString tableString = stringPool.getOrCreate(str);
|
|
||||||
ResValueInt resValueInt;
|
|
||||||
BaseResValue res = getResValue();
|
|
||||||
if(res instanceof ResValueInt){
|
|
||||||
resValueInt=(ResValueInt) res;
|
|
||||||
}else {
|
|
||||||
resValueInt=new ResValueInt();
|
|
||||||
setResValue(resValueInt);
|
|
||||||
}
|
|
||||||
resValueInt.setValueType(ValueType.STRING);
|
|
||||||
resValueInt.setData(tableString.getIndex());
|
|
||||||
return resValueInt;
|
|
||||||
}
|
|
||||||
public boolean getValueAsBoolean(){
|
|
||||||
int data = ((ResValueInt)getResValue()).getData();
|
|
||||||
return data!=0;
|
|
||||||
}
|
|
||||||
public String getValueAsString(){
|
|
||||||
TableString tableString= getValueAsTableString();
|
|
||||||
if(tableString==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return tableString.getHtml();
|
|
||||||
}
|
|
||||||
public TableString getValueAsTableString(){
|
|
||||||
TableStringPool stringPool = getTableStringPool();
|
|
||||||
if(stringPool==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
BaseResValue baseResValue = getResValue();
|
|
||||||
if(!(baseResValue instanceof ResValueInt)){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ResValueInt resValueInt = (ResValueInt)baseResValue;
|
|
||||||
return stringPool.get(resValueInt.getData());
|
|
||||||
}
|
|
||||||
private TableStringPool getTableStringPool(){
|
|
||||||
PackageBlock pkg=getPackageBlock();
|
|
||||||
if(pkg==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TableBlock table = pkg.getTableBlock();
|
|
||||||
if(table==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return table.getTableStringPool();
|
|
||||||
}
|
|
||||||
public boolean isDefault(){
|
|
||||||
TypeBlock typeBlock=getTypeBlock();
|
|
||||||
if(typeBlock!=null){
|
|
||||||
return typeBlock.isDefault();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public List<ReferenceItem> getTableStringReferences(){
|
|
||||||
if(isNull()){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
List<ReferenceItem> results=null;
|
|
||||||
BaseResValue resValue=getResValue();
|
|
||||||
if(resValue instanceof ResValueInt){
|
|
||||||
ResValueInt resValueInt=(ResValueInt)resValue;
|
|
||||||
ReferenceItem ref=resValueInt.getTableStringReference();
|
|
||||||
if(ref!=null){
|
|
||||||
results=new ArrayList<>();
|
|
||||||
results.add(ref);
|
|
||||||
}
|
|
||||||
}else if(resValue instanceof ResValueBag){
|
|
||||||
ResValueBag resValueBag=(ResValueBag)resValue;
|
|
||||||
results=resValueBag.getTableStringReferences();
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
boolean removeSpecReference(ReferenceItem ref){
|
|
||||||
if(ref==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
|
||||||
return specStringPool.removeReference(ref);
|
|
||||||
}
|
|
||||||
boolean removeTableReference(ReferenceItem ref){
|
|
||||||
if(ref==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
|
||||||
if(tableBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
|
||||||
return tableStringPool.removeReference(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addSpecReference(ReferenceItem ref){
|
|
||||||
if(ref==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
|
||||||
specStringPool.addReference(ref);
|
|
||||||
}
|
|
||||||
void addTableReference(ReferenceItem ref){
|
|
||||||
if(ref==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
|
||||||
if(tableBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
|
||||||
tableStringPool.addReference(ref);
|
|
||||||
}
|
|
||||||
private void removeTableReferences(){
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
|
||||||
if(tableBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
|
||||||
tableStringPool.removeReferences(getTableStringReferences());
|
|
||||||
}
|
|
||||||
private void removeSpecReferences(){
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
|
||||||
specStringPool.removeReference(getSpecReferenceBlock());
|
|
||||||
}
|
|
||||||
private void removeAllReferences(){
|
|
||||||
removeTableReferences();
|
|
||||||
removeSpecReferences();
|
|
||||||
}
|
|
||||||
private void setEntryTypeBag(boolean b){
|
|
||||||
entryHeader.putBit(OFFSET_FLAGS, 0, b);
|
|
||||||
refreshHeaderSize();
|
|
||||||
}
|
|
||||||
public boolean isEntryTypeBag(){
|
|
||||||
return entryHeader.getBit(OFFSET_FLAGS,0);
|
|
||||||
}
|
|
||||||
public void setPublic(boolean b){
|
|
||||||
entryHeader.putBit(OFFSET_FLAGS,1, b);
|
|
||||||
}
|
|
||||||
public boolean isPublic(){
|
|
||||||
return entryHeader.getBit(OFFSET_FLAGS,1);
|
|
||||||
}
|
|
||||||
public void setWeak(boolean b){
|
|
||||||
entryHeader.putBit(OFFSET_FLAGS, 2, b);
|
|
||||||
}
|
|
||||||
public boolean isWeak(){
|
|
||||||
return entryHeader.getBit(OFFSET_FLAGS,2);
|
|
||||||
}
|
|
||||||
private IntegerItem getSpecReferenceBlock(){
|
|
||||||
return mSpecReference;
|
|
||||||
}
|
|
||||||
public int getSpecReference(){
|
|
||||||
if(mSpecReference==null){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return mSpecReference.get();
|
|
||||||
}
|
|
||||||
public void setSpecReference(int ref){
|
|
||||||
boolean created = createNullSpecReference();
|
|
||||||
int old=mSpecReference.get();
|
|
||||||
if(ref==old){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mSpecReference.set(ref);
|
|
||||||
updateSpecRef(old, ref);
|
|
||||||
if(created){
|
|
||||||
updatePackage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void setSpecReference(SpecString specString){
|
|
||||||
removeSpecRef();
|
|
||||||
if(specString==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean created = createNullSpecReference();
|
|
||||||
mSpecReference.set(specString.getIndex());
|
|
||||||
if(created){
|
|
||||||
updatePackage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private boolean createNullSpecReference(){
|
|
||||||
if(mSpecReference==null){
|
|
||||||
mSpecReference = new IntegerItem();
|
|
||||||
mSpecReference.setNull(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public BaseResValue getResValue(){
|
|
||||||
return mResValue;
|
|
||||||
}
|
|
||||||
public void setResValue(BaseResValue resValue){
|
|
||||||
if(resValue==mResValue){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setResValueInternal(resValue);
|
|
||||||
if(resValue==null){
|
|
||||||
setNull(true);
|
|
||||||
}else {
|
|
||||||
setNull(false);
|
|
||||||
boolean is_bag=(resValue instanceof ResValueBag);
|
|
||||||
setEntryTypeBag(is_bag);
|
|
||||||
updatePackage();
|
|
||||||
updateSpecRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void setResValueInternal(BaseResValue resValue){
|
|
||||||
if(resValue==mResValue){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(resValue!=null){
|
|
||||||
resValue.setIndex(2);
|
|
||||||
resValue.setParent(this);
|
|
||||||
}
|
|
||||||
if(mResValue!=null){
|
|
||||||
mResValue.setIndex(-1);
|
|
||||||
mResValue.setParent(null);
|
|
||||||
mResValue.onRemoved();
|
|
||||||
}
|
|
||||||
if(resValue!=null){
|
|
||||||
setNull(false);
|
|
||||||
}
|
|
||||||
mResValue=resValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResConfig getResConfig(){
|
|
||||||
TypeBlock typeBlock=getTypeBlock();
|
|
||||||
if(typeBlock!=null){
|
|
||||||
return typeBlock.getResConfig();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public String getName(){
|
|
||||||
SpecString specString=getSpecString();
|
|
||||||
if(specString==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return specString.get();
|
|
||||||
}
|
|
||||||
public String getNameOrHex(){
|
|
||||||
String name = getName();
|
|
||||||
if(name==null){
|
|
||||||
name = String.format("@0x%08x", getResourceId());
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
private void setName(String name){
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
EntryGroup entryGroup = packageBlock.getEntryGroup(getResourceId());
|
|
||||||
if(entryGroup!=null){
|
|
||||||
entryGroup.renameSpec(name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool= packageBlock.getSpecStringPool();
|
|
||||||
SpecString specString=specStringPool.getOrCreate(name);
|
|
||||||
setSpecReference(specString.getIndex());
|
|
||||||
}
|
|
||||||
public String getTypeName(){
|
|
||||||
TypeString typeString=getTypeString();
|
|
||||||
if(typeString==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return typeString.get();
|
|
||||||
}
|
|
||||||
public String getPackageName(){
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return packageBlock.getName();
|
|
||||||
}
|
|
||||||
public SpecString getSpecString(){
|
|
||||||
if(mSpecReference==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
|
||||||
return specStringPool.get(getSpecReference());
|
|
||||||
}
|
|
||||||
public TypeString getTypeString(){
|
|
||||||
TypeBlock typeBlock=getTypeBlock();
|
|
||||||
if(typeBlock!=null){
|
|
||||||
return typeBlock.getTypeString();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public String buildResourceName(int resourceId, char prefix, boolean includeType){
|
|
||||||
if(resourceId==0){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
EntryBlock entryBlock=searchEntry(resourceId);
|
|
||||||
return buildResourceName(entryBlock, prefix, includeType);
|
|
||||||
}
|
|
||||||
private EntryBlock searchEntry(int resourceId){
|
|
||||||
if(resourceId==getResourceId()){
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TableBlock tableBlock= packageBlock.getTableBlock();
|
|
||||||
if(tableBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
EntryGroup entryGroup = tableBlock.search(resourceId);
|
|
||||||
if(entryGroup!=null){
|
|
||||||
return entryGroup.pickOne();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public String buildResourceName(EntryBlock entryBlock, char prefix, boolean includeType){
|
|
||||||
if(entryBlock==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String pkgName=entryBlock.getPackageName();
|
|
||||||
if(getResourceId()==entryBlock.getResourceId()){
|
|
||||||
pkgName=null;
|
|
||||||
}else if(pkgName!=null){
|
|
||||||
if(pkgName.equals(this.getPackageName())){
|
|
||||||
pkgName=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String type=null;
|
|
||||||
if(includeType){
|
|
||||||
type=entryBlock.getTypeName();
|
|
||||||
}
|
|
||||||
String name=entryBlock.getName();
|
|
||||||
return buildResourceName(prefix, pkgName, type, name);
|
|
||||||
}
|
|
||||||
public String getResourceName(){
|
|
||||||
return buildResourceName('@',null, getTypeName(), getName());
|
|
||||||
}
|
|
||||||
public String getResourceName(char prefix){
|
|
||||||
return getResourceName(prefix, false, true);
|
|
||||||
}
|
|
||||||
public String getResourceName(char prefix, boolean includePackage, boolean includeType){
|
|
||||||
String pkg=includePackage?getPackageName():null;
|
|
||||||
String type=includeType?getTypeName():null;
|
|
||||||
return buildResourceName(prefix,pkg, type, getName());
|
|
||||||
}
|
|
||||||
public int getResourceId(){
|
|
||||||
TypeBlock typeBlock=getTypeBlock();
|
|
||||||
if(typeBlock==null){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=typeBlock.getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int pkgId=packageBlock.getId();
|
|
||||||
int typeId=typeBlock.getId();
|
|
||||||
int entryId=getIndex();
|
|
||||||
return ((pkgId << 24) | (typeId << 16) | entryId);
|
|
||||||
}
|
|
||||||
public PackageBlock getPackageBlock(){
|
|
||||||
TypeBlock typeBlock=getTypeBlock();
|
|
||||||
if(typeBlock!=null){
|
|
||||||
return typeBlock.getPackageBlock();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
public TypeBlock getTypeBlock(){
|
|
||||||
Block parent=getParent();
|
|
||||||
while (parent!=null){
|
|
||||||
if(parent instanceof TypeBlock){
|
|
||||||
return (TypeBlock)parent;
|
|
||||||
}
|
|
||||||
parent=parent.getParent();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private void unlockEntry(){
|
|
||||||
if(mUnLocked){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mUnLocked = true;
|
|
||||||
entryHeader = new ByteArray(4);
|
|
||||||
if(mSpecReference==null){
|
|
||||||
this.mSpecReference = new IntegerItem();
|
|
||||||
}else if(mSpecReference.isNull()){
|
|
||||||
mSpecReference.setNull(false);
|
|
||||||
}
|
|
||||||
entryHeader.setIndex(0);
|
|
||||||
mSpecReference.setIndex(1);
|
|
||||||
entryHeader.setParent(this);
|
|
||||||
mSpecReference.setParent(this);
|
|
||||||
}
|
|
||||||
private void lockEntry(){
|
|
||||||
if(!mUnLocked){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
removeAllReferences();
|
|
||||||
mUnLocked = false;
|
|
||||||
entryHeader.setParent(null);
|
|
||||||
mSpecReference.setParent(null);
|
|
||||||
|
|
||||||
entryHeader.setIndex(-1);
|
|
||||||
mSpecReference.setIndex(-1);
|
|
||||||
removeResValue();
|
|
||||||
|
|
||||||
this.entryHeader = null;
|
|
||||||
this.mSpecReference =null;
|
|
||||||
}
|
|
||||||
private void removeResValue(){
|
|
||||||
if(mResValue!=null){
|
|
||||||
mResValue.setParent(null);
|
|
||||||
mResValue.setIndex(-1);
|
|
||||||
mResValue=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void refreshHeaderSize(){
|
|
||||||
short size;
|
|
||||||
if(isEntryTypeBag()){
|
|
||||||
size=HEADER_SIZE_BAG;
|
|
||||||
}else {
|
|
||||||
size=HEADER_SIZE_INT;
|
|
||||||
}
|
|
||||||
entryHeader.putShort(OFFSET_SIZE, size);
|
|
||||||
}
|
|
||||||
private void createResValue(){
|
|
||||||
if(getResValue()!=null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BaseResValue resValue;
|
|
||||||
if(isEntryTypeBag()){
|
|
||||||
resValue=new ResValueBag();
|
|
||||||
}else {
|
|
||||||
resValue=new ResValueInt();
|
|
||||||
}
|
|
||||||
setResValueInternal(resValue);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setNull(boolean is_null){
|
|
||||||
if(is_null){
|
|
||||||
lockEntry();
|
|
||||||
}else {
|
|
||||||
unlockEntry();
|
|
||||||
}
|
|
||||||
super.setNull(is_null);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean isNull(){
|
|
||||||
if(super.isNull() || !mUnLocked){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return mResValue==null;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public byte[] getBytes() {
|
|
||||||
if(isNull()){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
byte[] results=entryHeader.getBytes();
|
|
||||||
results=addBytes(results, mSpecReference.getBytes());
|
|
||||||
results=addBytes(results, mResValue.getBytes());
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int countBytes() {
|
|
||||||
if(isNull()){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
entryHeader -> 4 bytes
|
|
||||||
mSpecReference -> 4 bytes
|
|
||||||
-------
|
|
||||||
Total = 8 bytes, thus this value is always fixed no need to re-count
|
|
||||||
*/
|
|
||||||
return 8 + mResValue.countBytes();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onCountUpTo(BlockCounter counter) {
|
|
||||||
if(counter.FOUND){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(counter.END==this){
|
|
||||||
counter.FOUND=true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(isNull()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//counter.addCount(countBytes());
|
|
||||||
entryHeader.onCountUpTo(counter);
|
|
||||||
mSpecReference.onCountUpTo(counter);
|
|
||||||
mResValue.onCountUpTo(counter);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected int onWriteBytes(OutputStream stream) throws IOException {
|
|
||||||
if(isNull()){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int result=entryHeader.writeBytes(stream);
|
|
||||||
result+= mSpecReference.writeBytes(stream);
|
|
||||||
result+=mResValue.writeBytes(stream);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSpecRef(){
|
|
||||||
updateSpecRef(-1, getSpecReference());
|
|
||||||
}
|
|
||||||
private void updateSpecRef(int oldRef, int newNef){
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
|
||||||
SpecString specString=specStringPool.get(oldRef);
|
|
||||||
if(specString!=null){
|
|
||||||
specString.removeReference(getSpecReferenceBlock());
|
|
||||||
}
|
|
||||||
SpecString specStringNew=specStringPool.get(newNef);
|
|
||||||
if(specStringNew!=null){
|
|
||||||
specStringNew.addReference(getSpecReferenceBlock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void removeSpecRef(){
|
|
||||||
if(mSpecReference==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
|
||||||
SpecString specString=specStringPool.get(getSpecReference());
|
|
||||||
if(specString!=null){
|
|
||||||
specString.removeReference(getSpecReferenceBlock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void updatePackage(){
|
|
||||||
PackageBlock packageBlock=getPackageBlock();
|
|
||||||
if(packageBlock==null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
packageBlock.onEntryAdded(this);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onReadBytes(BlockReader reader) throws IOException{
|
|
||||||
setNull(false);
|
|
||||||
removeResValue();
|
|
||||||
entryHeader.readBytes(reader);
|
|
||||||
mSpecReference.readBytes(reader);
|
|
||||||
createResValue();
|
|
||||||
mResValue.readBytes(reader);
|
|
||||||
updatePackage();
|
|
||||||
updateSpecRef();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public JSONObject toJson() {
|
|
||||||
if(isNull()){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject jsonObject=new JSONObject();
|
|
||||||
jsonObject.put(NAME_entry_name, getSpecString().get());
|
|
||||||
if(isEntryTypeBag()){
|
|
||||||
jsonObject.put(NAME_is_bag, true);
|
|
||||||
}
|
|
||||||
if(isWeak()){
|
|
||||||
jsonObject.put(NAME_is_weak, true);
|
|
||||||
}
|
|
||||||
if(isPublic()){
|
|
||||||
jsonObject.put(NAME_is_shared, true);
|
|
||||||
}
|
|
||||||
jsonObject.put(NAME_value, getResValue().toJson());
|
|
||||||
return jsonObject;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void fromJson(JSONObject json) {
|
|
||||||
if(json==null){
|
|
||||||
setNull(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BaseResValue baseResValue;
|
|
||||||
if(json.optBoolean(NAME_is_bag, false)){
|
|
||||||
baseResValue=new ResValueBag();
|
|
||||||
}else {
|
|
||||||
baseResValue=new ResValueInt();
|
|
||||||
}
|
|
||||||
setResValue(baseResValue);
|
|
||||||
setPublic(json.optBoolean(NAME_is_shared, false));
|
|
||||||
setWeak(json.optBoolean(NAME_is_weak, false));
|
|
||||||
setName(json.getString(NAME_entry_name));
|
|
||||||
baseResValue.fromJson(json.getJSONObject(NAME_value));
|
|
||||||
mResValue.onDataLoaded();
|
|
||||||
}
|
|
||||||
public void merge(EntryBlock entryBlock){
|
|
||||||
if(!shouldMerge(entryBlock)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String name=entryBlock.getName();
|
|
||||||
if(name==null){
|
|
||||||
name="";
|
|
||||||
}
|
|
||||||
if(!entryBlock.isEntryTypeBag()){
|
|
||||||
ResValueInt comingValue = (ResValueInt) entryBlock.getResValue();
|
|
||||||
ResValueInt exist = getOrCreateResValueInt();
|
|
||||||
setResValue(exist);
|
|
||||||
exist.merge(comingValue);
|
|
||||||
}else {
|
|
||||||
ResValueBag comingValue = (ResValueBag) entryBlock.getResValue();
|
|
||||||
ResValueBag exist=getOrCreateResValueBag();
|
|
||||||
setResValue(exist);
|
|
||||||
exist.merge(comingValue);
|
|
||||||
}
|
|
||||||
SpecString spec = getPackageBlock()
|
|
||||||
.getSpecStringPool().getOrCreate(name);
|
|
||||||
setSpecReference(spec.getIndex());
|
|
||||||
setPublic(entryBlock.isPublic());
|
|
||||||
setWeak(entryBlock.isWeak());
|
|
||||||
}
|
|
||||||
private boolean shouldMerge(EntryBlock coming){
|
|
||||||
if(coming == null || coming == this || coming.isNull()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(this.isNull()){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
BaseResValue value = this.getResValue();
|
|
||||||
if(value instanceof ResValueInt){
|
|
||||||
ValueType valueType = ((ResValueInt)value).getValueType();
|
|
||||||
if(valueType==null || valueType==ValueType.NULL){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value = coming.getResValue();
|
|
||||||
if(value instanceof ResValueInt){
|
|
||||||
ValueType valueType = ((ResValueInt)value).getValueType();
|
|
||||||
return valueType!=null && valueType != ValueType.NULL;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
private ResValueBag getOrCreateResValueBag(){
|
|
||||||
if(mResValue instanceof ResValueBag){
|
|
||||||
return (ResValueBag) mResValue;
|
|
||||||
}
|
|
||||||
return new ResValueBag();
|
|
||||||
}
|
|
||||||
private ResValueInt getOrCreateResValueInt(){
|
|
||||||
if(mResValue instanceof ResValueInt){
|
|
||||||
return (ResValueInt) mResValue;
|
|
||||||
}
|
|
||||||
return new ResValueInt();
|
|
||||||
}
|
|
||||||
public static String buildResourceName(char prefix, String packageName, String type, String name){
|
|
||||||
if(name==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
StringBuilder builder=new StringBuilder();
|
|
||||||
if(prefix!=0){
|
|
||||||
builder.append(prefix);
|
|
||||||
}
|
|
||||||
if(packageName!=null){
|
|
||||||
builder.append(packageName);
|
|
||||||
builder.append(':');
|
|
||||||
}
|
|
||||||
if(type!=null){
|
|
||||||
builder.append(type);
|
|
||||||
builder.append('/');
|
|
||||||
}
|
|
||||||
builder.append(name);
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
StringBuilder builder=new StringBuilder();
|
|
||||||
builder.append(getClass().getSimpleName());
|
|
||||||
builder.append(": ");
|
|
||||||
ResConfig resConfig=getResConfig();
|
|
||||||
if(resConfig!=null){
|
|
||||||
builder.append(resConfig.toString());
|
|
||||||
builder.append(", ");
|
|
||||||
}
|
|
||||||
String name=getResourceName();
|
|
||||||
if(name==null){
|
|
||||||
name=getNameOrHex();
|
|
||||||
}else{
|
|
||||||
builder.append(" id=");
|
|
||||||
builder.append(String.format("0x%08x", getResourceId()));
|
|
||||||
}
|
|
||||||
builder.append('(');
|
|
||||||
builder.append(name);
|
|
||||||
builder.append(')');
|
|
||||||
if(isNull()){
|
|
||||||
builder.append(", null entry");
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
BaseResValue baseResValue=getResValue();
|
|
||||||
if(baseResValue instanceof ResValueInt){
|
|
||||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
|
||||||
builder.append(" '");
|
|
||||||
builder.append(resValueInt.toString());
|
|
||||||
builder.append(" '");
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int OFFSET_SIZE = 0;
|
|
||||||
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";
|
|
||||||
private static final String NAME_is_bag="is_bag";
|
|
||||||
private static final String NAME_is_shared="is_shared";
|
|
||||||
private static final String NAME_is_weak = "is_weak";
|
|
||||||
private static final String NAME_value="value";
|
|
||||||
|
|
||||||
}
|
|
56
src/main/java/com/reandroid/arsc/value/EntryHeader.java
Normal file
56
src/main/java/com/reandroid/arsc/value/EntryHeader.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
public class EntryHeader extends Header{
|
||||||
|
public EntryHeader(){
|
||||||
|
super(HEADER_SIZE_SCALAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
if(isNull()){
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
StringBuilder builder=new StringBuilder();
|
||||||
|
int byte_size = getSize();
|
||||||
|
int read_size = readSize();
|
||||||
|
if(byte_size!=8){
|
||||||
|
builder.append("size=").append(byte_size);
|
||||||
|
}
|
||||||
|
if(byte_size!=read_size){
|
||||||
|
builder.append(" readSize=").append(read_size);
|
||||||
|
}
|
||||||
|
if(isComplex()){
|
||||||
|
builder.append(" complex");
|
||||||
|
}
|
||||||
|
if(isPublic()){
|
||||||
|
builder.append(" public");
|
||||||
|
}
|
||||||
|
if(isWeak()){
|
||||||
|
builder.append(" weak");
|
||||||
|
}
|
||||||
|
String name = getName();
|
||||||
|
if(name!=null){
|
||||||
|
builder.append(" name=").append(name);
|
||||||
|
}else {
|
||||||
|
builder.append(" key=").append(getKey());
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final short HEADER_SIZE_SCALAR = 8;
|
||||||
|
}
|
107
src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java
Normal file
107
src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
public class EntryHeaderMap extends Header{
|
||||||
|
public EntryHeaderMap(){
|
||||||
|
super(HEADER_SIZE_COMPLEX);
|
||||||
|
setComplex(true);
|
||||||
|
}
|
||||||
|
public int getParentId(){
|
||||||
|
return getInteger(getBytesInternal(), OFFSET_PARENT_ID);
|
||||||
|
}
|
||||||
|
public void setParentId(int parentId){
|
||||||
|
putInteger(getBytesInternal(), OFFSET_PARENT_ID, parentId);
|
||||||
|
}
|
||||||
|
public int getValuesCount(){
|
||||||
|
return getInteger(getBytesInternal(), OFFSET_VALUE_COUNT);
|
||||||
|
}
|
||||||
|
public void setValuesCount(int valuesCount){
|
||||||
|
putInteger(getBytesInternal(), OFFSET_VALUE_COUNT, valuesCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void merge(Header header){
|
||||||
|
if(header == this || !(header instanceof EntryHeaderMap)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.merge(header);
|
||||||
|
EntryHeaderMap entryHeaderMap = (EntryHeaderMap) header;
|
||||||
|
setParentId(entryHeaderMap.getParentId());
|
||||||
|
setValuesCount(entryHeaderMap.getValuesCount());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void toJson(JSONObject jsonObject) {
|
||||||
|
super.toJson(jsonObject);
|
||||||
|
jsonObject.put(NAME_is_complex, true);
|
||||||
|
int parent_id = getParentId();
|
||||||
|
if(parent_id!=0){
|
||||||
|
jsonObject.put(NAME_parent_id, parent_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
super.fromJson(json);
|
||||||
|
setComplex(json.optBoolean(NAME_is_complex, true));
|
||||||
|
setParentId(json.optInt(NAME_parent_id));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
if(isNull()){
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
StringBuilder builder=new StringBuilder();
|
||||||
|
int byte_size = getSize();
|
||||||
|
int read_size = readSize();
|
||||||
|
if(byte_size!=16){
|
||||||
|
builder.append("size=").append(byte_size);
|
||||||
|
}
|
||||||
|
if(byte_size!=read_size){
|
||||||
|
builder.append(", readSize=").append(read_size);
|
||||||
|
}
|
||||||
|
if(isComplex()){
|
||||||
|
builder.append(" complex");
|
||||||
|
}
|
||||||
|
if(isPublic()){
|
||||||
|
builder.append(", public");
|
||||||
|
}
|
||||||
|
if(isWeak()){
|
||||||
|
builder.append(", weak");
|
||||||
|
}
|
||||||
|
String name = getName();
|
||||||
|
if(name!=null){
|
||||||
|
builder.append(", name=").append(name);
|
||||||
|
}else {
|
||||||
|
builder.append(", key=").append(getKey());
|
||||||
|
}
|
||||||
|
int parentId = getParentId();
|
||||||
|
if(parentId!=0){
|
||||||
|
builder.append(", parentId=");
|
||||||
|
builder.append(String.format("0x%08x", getParentId()));
|
||||||
|
}
|
||||||
|
builder.append(", count=").append(getValuesCount());
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final short HEADER_SIZE_COMPLEX = 16;
|
||||||
|
|
||||||
|
private static final int OFFSET_PARENT_ID = 8;
|
||||||
|
private static final int OFFSET_VALUE_COUNT = 12;
|
||||||
|
|
||||||
|
public static final String NAME_parent_id = "parent_id";
|
||||||
|
}
|
236
src/main/java/com/reandroid/arsc/value/Header.java
Normal file
236
src/main/java/com/reandroid/arsc/value/Header.java
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
import com.reandroid.arsc.chunk.ParentChunk;
|
||||||
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.item.*;
|
||||||
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
|
import com.reandroid.json.JSONConvert;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Header extends BlockItem implements JSONConvert<JSONObject> {
|
||||||
|
private ReferenceItem mStringReference;
|
||||||
|
public Header(int size){
|
||||||
|
super(size);
|
||||||
|
writeSize();
|
||||||
|
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, -1);
|
||||||
|
}
|
||||||
|
public void onRemoved(){
|
||||||
|
unLinkStringReference();
|
||||||
|
}
|
||||||
|
public String getName(){
|
||||||
|
StringItem stringItem = getNameString();
|
||||||
|
if(stringItem!=null){
|
||||||
|
return stringItem.get();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public boolean isComplex(){
|
||||||
|
return getBit(getBytesInternal(), OFFSET_FLAGS,0);
|
||||||
|
}
|
||||||
|
public void setComplex(boolean complex){
|
||||||
|
putBit(getBytesInternal(), OFFSET_FLAGS, 0, complex);
|
||||||
|
}
|
||||||
|
public void setPublic(boolean b){
|
||||||
|
putBit(getBytesInternal(), OFFSET_FLAGS,1, b);
|
||||||
|
}
|
||||||
|
public boolean isPublic(){
|
||||||
|
return getBit(getBytesInternal(), OFFSET_FLAGS,1);
|
||||||
|
}
|
||||||
|
public void setWeak(boolean b){
|
||||||
|
putBit(getBytesInternal(), OFFSET_FLAGS, 2, b);
|
||||||
|
}
|
||||||
|
public boolean isWeak(){
|
||||||
|
return getBit(getBytesInternal(), OFFSET_FLAGS,2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKey(){
|
||||||
|
return getInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE);
|
||||||
|
}
|
||||||
|
public void setKey(int key){
|
||||||
|
if(key == getKey()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unLinkStringReference();
|
||||||
|
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, key);
|
||||||
|
linkStringReference();
|
||||||
|
}
|
||||||
|
public void setKey(StringItem stringItem){
|
||||||
|
unLinkStringReference();
|
||||||
|
int key = -1;
|
||||||
|
if(stringItem!=null){
|
||||||
|
key=stringItem.getIndex();
|
||||||
|
}
|
||||||
|
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, key);
|
||||||
|
linkStringReference(stringItem);
|
||||||
|
}
|
||||||
|
public void setSize(int size){
|
||||||
|
super.setBytesLength(size, false);
|
||||||
|
writeSize();
|
||||||
|
}
|
||||||
|
public int getSize(){
|
||||||
|
return getBytesInternal().length;
|
||||||
|
}
|
||||||
|
int readSize(){
|
||||||
|
if(getSize()<2){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0xffff & getShort(getBytesInternal(), OFFSET_SIZE);
|
||||||
|
}
|
||||||
|
private void writeSize(){
|
||||||
|
int size = getSize();
|
||||||
|
if(size>1){
|
||||||
|
putShort(getBytesInternal(), OFFSET_SIZE, (short) size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void linkStringReference(){
|
||||||
|
linkStringReference(getNameString());
|
||||||
|
}
|
||||||
|
private void linkStringReference(StringItem stringItem){
|
||||||
|
unLinkStringReference();
|
||||||
|
if(stringItem==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReferenceItem stringReference = new ReferenceBlock<>(this, OFFSET_SPEC_REFERENCE);
|
||||||
|
mStringReference = stringReference;
|
||||||
|
stringItem.addReference(stringReference);
|
||||||
|
}
|
||||||
|
private void unLinkStringReference(){
|
||||||
|
ReferenceItem stringReference = mStringReference;
|
||||||
|
if(stringReference==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mStringReference = null;
|
||||||
|
StringItem stringItem = getNameString();
|
||||||
|
if(stringItem == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stringItem.removeReference(stringReference);
|
||||||
|
}
|
||||||
|
public StringItem getNameString(){
|
||||||
|
StringPool<?> specStringPool = getSpecStringPool();
|
||||||
|
if(specStringPool==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return specStringPool.get(getKey());
|
||||||
|
}
|
||||||
|
private StringPool<?> getSpecStringPool(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof ParentChunk){
|
||||||
|
return ((ParentChunk) parent).getSpecStringPool();
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
|
int size = reader.readUnsignedShort();
|
||||||
|
setBytesLength(size, false);
|
||||||
|
reader.readFully(getBytesInternal());
|
||||||
|
linkStringReference();
|
||||||
|
}
|
||||||
|
private void setName(String name){
|
||||||
|
if(name==null){
|
||||||
|
name = "";
|
||||||
|
}
|
||||||
|
StringPool<?> stringPool = getSpecStringPool();
|
||||||
|
if(stringPool==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StringItem stringItem = stringPool.getOrCreate(name);
|
||||||
|
setKey(stringItem.getIndex());
|
||||||
|
linkStringReference(stringItem);
|
||||||
|
}
|
||||||
|
public void merge(Header header){
|
||||||
|
if(header == null || header ==this){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setComplex(header.isComplex());
|
||||||
|
setWeak(header.isWeak());
|
||||||
|
setPublic(header.isPublic());
|
||||||
|
setName(header.getName());
|
||||||
|
}
|
||||||
|
public void toJson(JSONObject jsonObject) {
|
||||||
|
jsonObject.put(NAME_entry_name, getName());
|
||||||
|
if(isWeak()){
|
||||||
|
jsonObject.put(NAME_is_weak, true);
|
||||||
|
}
|
||||||
|
if(isPublic()){
|
||||||
|
jsonObject.put(NAME_is_public, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
toJson(jsonObject);
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
setWeak(json.optBoolean(NAME_is_weak, false));
|
||||||
|
setPublic(json.optBoolean(NAME_is_public, false));
|
||||||
|
setName(json.optString(NAME_entry_name));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
if(isNull()){
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
StringBuilder builder=new StringBuilder();
|
||||||
|
int byte_size = getSize();
|
||||||
|
int read_size = readSize();
|
||||||
|
if(byte_size!=8){
|
||||||
|
builder.append("size=").append(byte_size);
|
||||||
|
}
|
||||||
|
if(byte_size!=read_size){
|
||||||
|
builder.append(", readSize=").append(read_size);
|
||||||
|
}
|
||||||
|
if(isComplex()){
|
||||||
|
builder.append(", complex");
|
||||||
|
}
|
||||||
|
if(isPublic()){
|
||||||
|
builder.append(", public");
|
||||||
|
}
|
||||||
|
if(isWeak()){
|
||||||
|
builder.append(", weak");
|
||||||
|
}
|
||||||
|
String name = getName();
|
||||||
|
if(name!=null){
|
||||||
|
builder.append(", name=").append(name);
|
||||||
|
}else {
|
||||||
|
builder.append(", key=").append(getKey());
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int OFFSET_SIZE = 0;
|
||||||
|
private static final int OFFSET_FLAGS = 2;
|
||||||
|
private static final int OFFSET_SPEC_REFERENCE = 4;
|
||||||
|
|
||||||
|
|
||||||
|
public static final String NAME_is_complex = "is_complex";
|
||||||
|
public static final String NAME_is_public = "is_public";
|
||||||
|
public static final String NAME_is_weak = "is_weak";
|
||||||
|
|
||||||
|
public static final String NAME_entry_name = "entry_name";
|
||||||
|
}
|
66
src/main/java/com/reandroid/arsc/value/ResTableEntry.java
Normal file
66
src/main/java/com/reandroid/arsc/value/ResTableEntry.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
public class ResTableEntry extends TableEntry<EntryHeader, ResValue> {
|
||||||
|
public ResTableEntry() {
|
||||||
|
super(new EntryHeader(), new ResValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onRemoved(){
|
||||||
|
getHeader().onRemoved();
|
||||||
|
getValue().onRemoved();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
boolean shouldMerge(TableEntry<?, ?> tableEntry){
|
||||||
|
if(tableEntry == this || !(tableEntry instanceof ResTableEntry)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ResValue coming = ((ResTableEntry) tableEntry).getValue();
|
||||||
|
ValueType valueType = coming.getValueType();
|
||||||
|
if(valueType == null || valueType == ValueType.NULL){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
valueType = getValue().getValueType();
|
||||||
|
return valueType == null || valueType == ValueType.NULL;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void merge(TableEntry<?, ?> tableEntry){
|
||||||
|
if(tableEntry == this || !(tableEntry instanceof ResTableEntry)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getHeader().merge(tableEntry.getHeader());
|
||||||
|
getValue().merge((ValueItem) tableEntry.getValue());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
getHeader().toJson(jsonObject);
|
||||||
|
jsonObject.put(NAME_value, getValue().toJson());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
getHeader().fromJson(json);
|
||||||
|
JSONObject jsonObject = json.getJSONObject(NAME_value);
|
||||||
|
getValue().fromJson(jsonObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String NAME_value = "value";
|
||||||
|
}
|
114
src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java
Normal file
114
src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArray> {
|
||||||
|
public ResTableMapEntry(){
|
||||||
|
super(new EntryHeaderMap(), new ResValueMapArray());
|
||||||
|
}
|
||||||
|
public void refresh(){
|
||||||
|
getHeader().setValuesCount(getValue().childesCount());
|
||||||
|
}
|
||||||
|
public ResValueMap[] listResValueMap(){
|
||||||
|
return getValue().getChildes();
|
||||||
|
}
|
||||||
|
public int getParentId(){
|
||||||
|
return getHeader().getParentId();
|
||||||
|
}
|
||||||
|
public void setParentId(int parentId){
|
||||||
|
getHeader().setParentId(parentId);
|
||||||
|
}
|
||||||
|
public int getValuesCount(){
|
||||||
|
return getHeader().getValuesCount();
|
||||||
|
}
|
||||||
|
public void setValuesCount(int valuesCount){
|
||||||
|
getHeader().setValuesCount(valuesCount);
|
||||||
|
getValue().setChildesCount(valuesCount);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
void onHeaderLoaded(Header header){
|
||||||
|
getValue().setChildesCount(getValuesCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onRemoved(){
|
||||||
|
getHeader().onRemoved();
|
||||||
|
getValue().onRemoved();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
boolean shouldMerge(TableEntry<?, ?> tableEntry){
|
||||||
|
if(tableEntry == this || !(tableEntry instanceof ResTableMapEntry)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ResValueMapArray coming = ((ResTableMapEntry) tableEntry).getValue();
|
||||||
|
if(coming.childesCount() == 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return getValue().childesCount() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void merge(TableEntry<?, ?> tableEntry){
|
||||||
|
if(tableEntry==null || tableEntry==this){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResTableMapEntry coming = (ResTableMapEntry) tableEntry;
|
||||||
|
getHeader().merge(coming.getHeader());
|
||||||
|
getValue().merge(coming.getValue());
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
getHeader().toJson(jsonObject);
|
||||||
|
jsonObject.put(NAME_values, getValue().toJson());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
getHeader().fromJson(json);
|
||||||
|
getValue().fromJson(json.optJSONArray(NAME_values));
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append(getHeader());
|
||||||
|
ResValueMap[] valueMaps = listResValueMap();
|
||||||
|
int len = valueMaps.length;
|
||||||
|
int max = len;
|
||||||
|
if(max>4){
|
||||||
|
max = 4;
|
||||||
|
}
|
||||||
|
for(int i=0;i<max;i++){
|
||||||
|
builder.append("\n ");
|
||||||
|
builder.append(valueMaps[i]);
|
||||||
|
}
|
||||||
|
if(len>0){
|
||||||
|
if(max!=len){
|
||||||
|
builder.append("\n ...");
|
||||||
|
}
|
||||||
|
builder.append("\n ");
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String NAME_values = "values";
|
||||||
|
}
|
43
src/main/java/com/reandroid/arsc/value/ResValue.java
Executable file
43
src/main/java/com/reandroid/arsc/value/ResValue.java
Executable 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
|
||||||
|
public class ResValue extends ValueItem {
|
||||||
|
public ResValue() {
|
||||||
|
super(8);
|
||||||
|
}
|
||||||
|
public Entry getEntry(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof Entry){
|
||||||
|
return (Entry) parent;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getSizeOffset(){
|
||||||
|
return OFFSET_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final int OFFSET_SIZE = 0;
|
||||||
|
|
||||||
|
}
|
@ -1,188 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
|
||||||
import com.reandroid.arsc.base.Block;
|
|
||||||
import com.reandroid.arsc.base.BlockCounter;
|
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
|
||||||
import com.reandroid.arsc.item.IntegerItem;
|
|
||||||
import com.reandroid.arsc.item.ReferenceItem;
|
|
||||||
import com.reandroid.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class ResValueBag extends BaseResValue {
|
|
||||||
|
|
||||||
private final IntegerItem mParentId;
|
|
||||||
private final IntegerItem mCount;
|
|
||||||
private final ResValueBagItemArray mResValueBagItemArray;
|
|
||||||
public ResValueBag(){
|
|
||||||
super(0);
|
|
||||||
mParentId =new IntegerItem();
|
|
||||||
mCount=new IntegerItem();
|
|
||||||
mResValueBagItemArray=new ResValueBagItemArray();
|
|
||||||
|
|
||||||
mParentId.setParent(this);
|
|
||||||
mParentId.setIndex(0);
|
|
||||||
mCount.setParent(this);
|
|
||||||
mCount.setIndex(1);
|
|
||||||
mResValueBagItemArray.setParent(this);
|
|
||||||
mResValueBagItemArray.setIndex(2);
|
|
||||||
}
|
|
||||||
public ResValueBagItem[] getBagItems(){
|
|
||||||
return getResValueBagItemArray().getChildes();
|
|
||||||
}
|
|
||||||
public List<ReferenceItem> getTableStringReferences(){
|
|
||||||
List<ReferenceItem> results=null;
|
|
||||||
for(ResValueBagItem bagItem:getResValueBagItemArray().listItems()){
|
|
||||||
ReferenceItem ref=bagItem.getTableStringReference();
|
|
||||||
if(ref==null){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(results==null){
|
|
||||||
results=new ArrayList<>();
|
|
||||||
}
|
|
||||||
results.add(ref);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
public ResValueBagItemArray getResValueBagItemArray(){
|
|
||||||
return mResValueBagItemArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getParentId(){
|
|
||||||
return mParentId.get();
|
|
||||||
}
|
|
||||||
public void setParentId(int id){
|
|
||||||
mParentId.set(id);
|
|
||||||
}
|
|
||||||
public int getCount(){
|
|
||||||
return mCount.get();
|
|
||||||
}
|
|
||||||
public void setCount(int count){
|
|
||||||
if(count<0){
|
|
||||||
count=0;
|
|
||||||
}
|
|
||||||
mCount.set(count);
|
|
||||||
mResValueBagItemArray.setChildesCount(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getBytes() {
|
|
||||||
byte[] results = mParentId.getBytes();
|
|
||||||
results=addBytes(results, mCount.getBytes());
|
|
||||||
results=addBytes(results, mResValueBagItemArray.getBytes());
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int countBytes() {
|
|
||||||
int result;
|
|
||||||
result = mParentId.countBytes();
|
|
||||||
result+=mCount.countBytes();
|
|
||||||
result+=mResValueBagItemArray.countBytes();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onCountUpTo(BlockCounter counter) {
|
|
||||||
if(countSubChildes(counter, mParentId)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(countSubChildes(counter, mCount)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
countSubChildes(counter, mResValueBagItemArray);
|
|
||||||
}
|
|
||||||
private boolean countSubChildes(BlockCounter counter, Block child){
|
|
||||||
if(counter.FOUND){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(counter.END==child){
|
|
||||||
counter.FOUND=true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int c=child.countBytes();
|
|
||||||
counter.addCount(c);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshCount(){
|
|
||||||
mCount.set(getResValueBagItemArray().childesCount());
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected int onWriteBytes(OutputStream writer) throws IOException {
|
|
||||||
if(isNull()){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int result;
|
|
||||||
result=mParentId.writeBytes(writer);
|
|
||||||
result+=mCount.writeBytes(writer);
|
|
||||||
result+=mResValueBagItemArray.writeBytes(writer);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onReadBytes(BlockReader reader) throws IOException{
|
|
||||||
mResValueBagItemArray.clearChildes();
|
|
||||||
mParentId.readBytes(reader);
|
|
||||||
mCount.readBytes(reader);
|
|
||||||
mResValueBagItemArray.setChildesCount(mCount.get());
|
|
||||||
mResValueBagItemArray.readBytes(reader);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
void onDataLoaded() {
|
|
||||||
for(ResValueBagItem item: mResValueBagItemArray.listItems()){
|
|
||||||
item.refreshTableReference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public JSONObject toJson() {
|
|
||||||
if(isNull()){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject jsonObject=new JSONObject();
|
|
||||||
jsonObject.put(NAME_parent, getParentId());
|
|
||||||
jsonObject.put(NAME_items, getResValueBagItemArray().toJson());
|
|
||||||
return jsonObject;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void fromJson(JSONObject json) {
|
|
||||||
setParentId(json.getInt(NAME_parent));
|
|
||||||
getResValueBagItemArray().fromJson(json.getJSONArray(NAME_items));
|
|
||||||
refreshCount();
|
|
||||||
}
|
|
||||||
public void merge(ResValueBag resValueBag){
|
|
||||||
if(resValueBag==null || resValueBag==this || resValueBag.getCount()==0){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setParentId(resValueBag.getParentId());
|
|
||||||
getResValueBagItemArray().merge(resValueBag.getResValueBagItemArray());
|
|
||||||
refreshCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
StringBuilder builder=new StringBuilder();
|
|
||||||
builder.append(getClass().getSimpleName());
|
|
||||||
builder.append(": parent=");
|
|
||||||
builder.append(String.format("0x%08x", getParentId()));
|
|
||||||
builder.append(", count=");
|
|
||||||
builder.append(getCount());
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,259 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.base.Block;
|
|
||||||
import com.reandroid.arsc.item.ReferenceItem;
|
|
||||||
import com.reandroid.arsc.item.TableString;
|
|
||||||
import com.reandroid.json.JSONObject;
|
|
||||||
|
|
||||||
public class ResValueBagItem extends BaseResValueItem{
|
|
||||||
|
|
||||||
public ResValueBagItem() {
|
|
||||||
super(BYTES_COUNT);
|
|
||||||
setHeaderSize(BYTES_SIZE);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onRemoved(){
|
|
||||||
removeTableReference();
|
|
||||||
}
|
|
||||||
public String getValueAsString(){
|
|
||||||
return getTableString(getData()).getHtml();
|
|
||||||
}
|
|
||||||
public void setValueAsString(String str){
|
|
||||||
this.setValueType(ValueType.STRING);
|
|
||||||
TableString tableString=getTableStringPool().getOrCreate(str);
|
|
||||||
setData(tableString.getIndex());
|
|
||||||
}
|
|
||||||
public boolean getValueAsBoolean(){
|
|
||||||
return getData()!=0;
|
|
||||||
}
|
|
||||||
public void setValueAsBoolean(boolean val){
|
|
||||||
this.setValueType(ValueType.INT_BOOLEAN);
|
|
||||||
int data=val?0xffffffff:0;
|
|
||||||
setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResValueBag getParentBag(){
|
|
||||||
Block parent=getParent();
|
|
||||||
while(parent!=null){
|
|
||||||
if(parent instanceof ResValueBag){
|
|
||||||
return (ResValueBag) parent;
|
|
||||||
}
|
|
||||||
parent=parent.getParent();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setHeaderSize(short size) {
|
|
||||||
setShort(OFFSET_SIZE, size);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public short getHeaderSize() {
|
|
||||||
return getShort(OFFSET_SIZE);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setReserved(byte reserved) {
|
|
||||||
setByte(OFFSET_RESERVED, reserved);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public byte getReserved() {
|
|
||||||
return getByte(OFFSET_RESERVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id){
|
|
||||||
setInt(OFFSET_ID, id);
|
|
||||||
}
|
|
||||||
public int getId(){
|
|
||||||
return getInt(OFFSET_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypeAndData(ValueType valueType, int data){
|
|
||||||
this.setValueType(valueType);
|
|
||||||
setData(data);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setType(byte type){
|
|
||||||
byte old=getType();
|
|
||||||
if(type==old){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
removeTableReference();
|
|
||||||
setByte(OFFSET_TYPE, type);
|
|
||||||
if(type==ValueType.STRING.getByte()){
|
|
||||||
ReferenceItem ref=getTableStringReference();
|
|
||||||
removeTableReference(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public byte getType(){
|
|
||||||
return getByte(OFFSET_TYPE);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int getData(){
|
|
||||||
return getInt(OFFSET_DATA);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setData(int data){
|
|
||||||
int old=getData();
|
|
||||||
if(data==old){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
beforeDataValueChanged();
|
|
||||||
setInt(OFFSET_DATA, data);
|
|
||||||
afterDataValueChanged();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onSetReference(int data){
|
|
||||||
setInt(OFFSET_DATA, data);
|
|
||||||
}
|
|
||||||
private void beforeDataValueChanged(){
|
|
||||||
if(getValueType()==ValueType.STRING){
|
|
||||||
removeTableReference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void afterDataValueChanged(){
|
|
||||||
refreshTableReference();
|
|
||||||
}
|
|
||||||
void refreshTableReference(){
|
|
||||||
if(getValueType()==ValueType.STRING){
|
|
||||||
if(!hasTableReference()){
|
|
||||||
addTableReference(getTableStringReference());
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
removeTableReference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public short getIdHigh(){
|
|
||||||
return getShort(OFFSET_ID+2);
|
|
||||||
}
|
|
||||||
public short getIdLow(){
|
|
||||||
return getShort(OFFSET_ID);
|
|
||||||
}
|
|
||||||
public void setIdHigh(short val){
|
|
||||||
setShort(OFFSET_ID+2, val);
|
|
||||||
}
|
|
||||||
public void setIdLow(short val){
|
|
||||||
setShort(OFFSET_ID, val);
|
|
||||||
}
|
|
||||||
public short getDataHigh(){
|
|
||||||
return getShort(OFFSET_DATA+2);
|
|
||||||
}
|
|
||||||
public short getDataLow(){
|
|
||||||
return getShort(OFFSET_DATA);
|
|
||||||
}
|
|
||||||
public void setDataHigh(short val){
|
|
||||||
if(val==getDataHigh()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
beforeDataValueChanged();
|
|
||||||
setShort(OFFSET_DATA+2, val);
|
|
||||||
afterDataValueChanged();
|
|
||||||
}
|
|
||||||
public void setDataLow(short val){
|
|
||||||
if(val==getDataLow()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
beforeDataValueChanged();
|
|
||||||
setShort(OFFSET_DATA, val);
|
|
||||||
afterDataValueChanged();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public JSONObject toJson() {
|
|
||||||
if(isNull()){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject jsonObject=new JSONObject();
|
|
||||||
ValueType valueType=getValueType();
|
|
||||||
jsonObject.put(NAME_value_type, valueType.name());
|
|
||||||
jsonObject.put(NAME_id, getId());
|
|
||||||
if(valueType==ValueType.STRING){
|
|
||||||
jsonObject.put(NAME_data, getValueAsString());
|
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
|
||||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
|
||||||
}else {
|
|
||||||
jsonObject.put(NAME_data, getData());
|
|
||||||
}
|
|
||||||
return jsonObject;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void fromJson(JSONObject json) {
|
|
||||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
|
||||||
this.setValueType(valueType);
|
|
||||||
setId(json.getInt(NAME_id));
|
|
||||||
if(valueType==ValueType.STRING){
|
|
||||||
setValueAsString(json.optString(NAME_data, ""));
|
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
|
||||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
|
||||||
}else {
|
|
||||||
setData(json.getInt(NAME_data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void merge(ResValueBagItem bagItem){
|
|
||||||
if(bagItem==null||bagItem==this){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setId(bagItem.getId());
|
|
||||||
ValueType valueType=bagItem.getValueType();
|
|
||||||
if(valueType==ValueType.STRING){
|
|
||||||
setValueAsString(bagItem.getValueAsString());
|
|
||||||
}else {
|
|
||||||
this.setValueType(valueType);
|
|
||||||
setData(bagItem.getData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
StringBuilder builder=new StringBuilder();
|
|
||||||
builder.append(getClass().getSimpleName());
|
|
||||||
builder.append(" type=");
|
|
||||||
ValueType vt=getValueType();
|
|
||||||
if(vt!=null){
|
|
||||||
builder.append(vt.name());
|
|
||||||
}else {
|
|
||||||
builder.append("Unknown");
|
|
||||||
}
|
|
||||||
builder.append(" size=").append(getHeaderSize());
|
|
||||||
builder.append(" bytes=").append(countBytes());
|
|
||||||
builder.append('(');
|
|
||||||
builder.append(String.format("0x%02x", getType()));
|
|
||||||
builder.append(") id=");
|
|
||||||
builder.append(String.format("0x%08x", getId()));
|
|
||||||
builder.append(", data=");
|
|
||||||
builder.append(String.format("0x%08x", getData()));
|
|
||||||
if(vt==ValueType.STRING){
|
|
||||||
TableString ts=getTableString(getData());
|
|
||||||
if(ts==null){
|
|
||||||
builder.append(" Null table string");
|
|
||||||
}else {
|
|
||||||
builder.append(" \"").append(ts.getHtml()).append("\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
private static final int OFFSET_ID=0;
|
|
||||||
private static final int OFFSET_SIZE=4;
|
|
||||||
private static final int OFFSET_RESERVED=6;
|
|
||||||
private static final int OFFSET_TYPE=7;
|
|
||||||
private static final int OFFSET_DATA=8;
|
|
||||||
|
|
||||||
private static final int BYTES_COUNT=12;
|
|
||||||
|
|
||||||
private static final short BYTES_SIZE=0x08;
|
|
||||||
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
|
||||||
import com.reandroid.arsc.item.TableString;
|
|
||||||
import com.reandroid.json.JSONObject;
|
|
||||||
|
|
||||||
public class ResValueInt extends BaseResValueItem {
|
|
||||||
public ResValueInt() {
|
|
||||||
super(BYTES_COUNT);
|
|
||||||
setHeaderSize(BYTES_SIZE);
|
|
||||||
}
|
|
||||||
protected void onRemoved(){
|
|
||||||
removeTableReference();
|
|
||||||
}
|
|
||||||
public String getValueAsString(){
|
|
||||||
return getString(getData());
|
|
||||||
}
|
|
||||||
public void setValueAsString(String str){
|
|
||||||
setValueType(ValueType.STRING);
|
|
||||||
TableString tableString=getTableStringPool().getOrCreate(str);
|
|
||||||
setData(tableString.getIndex());
|
|
||||||
}
|
|
||||||
public void setValueAsBoolean(boolean val){
|
|
||||||
setValueType(ValueType.INT_BOOLEAN);
|
|
||||||
int data=val?0xffffffff:0;
|
|
||||||
setData(data);
|
|
||||||
}
|
|
||||||
public boolean getValueAsBoolean(){
|
|
||||||
return getData()!=0;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
void onDataLoaded() {
|
|
||||||
if(getValueType()==ValueType.STRING){
|
|
||||||
if(!hasTableReference()){
|
|
||||||
addTableReference(getTableStringReference());
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
removeTableReference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setHeaderSize(short size) {
|
|
||||||
setShort(OFFSET_SIZE, size);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public short getHeaderSize() {
|
|
||||||
return getShort(OFFSET_SIZE);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setReserved(byte reserved) {
|
|
||||||
setByte(OFFSET_RESERVED, reserved);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public byte getReserved() {
|
|
||||||
return getByte(OFFSET_RESERVED);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setType(byte type){
|
|
||||||
byte old=getType();
|
|
||||||
if(type==old){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
removeTableReference();
|
|
||||||
setByte(OFFSET_TYPE, type);
|
|
||||||
if(type==ValueType.STRING.getByte()){
|
|
||||||
addTableReference(getTableStringReference());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public byte getType(){
|
|
||||||
return getByte(OFFSET_TYPE);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int getData(){
|
|
||||||
return getInt(OFFSET_DATA);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setData(int data){
|
|
||||||
int old=getData();
|
|
||||||
if(data==old){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
removeTableReference();
|
|
||||||
setInt(OFFSET_DATA, data);
|
|
||||||
if(getValueType()==ValueType.STRING){
|
|
||||||
addTableReference(getTableStringReference());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onSetReference(int data){
|
|
||||||
setInt(OFFSET_DATA, data);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public JSONObject toJson() {
|
|
||||||
if(isNull()){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONObject jsonObject=new JSONObject();
|
|
||||||
ValueType valueType=getValueType();
|
|
||||||
jsonObject.put(NAME_value_type, valueType.name());
|
|
||||||
if(valueType==ValueType.STRING){
|
|
||||||
jsonObject.put(NAME_data, getValueAsString());
|
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
|
||||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
|
||||||
}else {
|
|
||||||
jsonObject.put(NAME_data, getData());
|
|
||||||
}
|
|
||||||
return jsonObject;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void fromJson(JSONObject json) {
|
|
||||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
|
||||||
if(valueType==ValueType.STRING){
|
|
||||||
setValueAsString(json.optString(NAME_data, ""));
|
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
|
||||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
|
||||||
}else {
|
|
||||||
setValueType(valueType);
|
|
||||||
setData(json.getInt(NAME_data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void merge(ResValueInt resValueInt){
|
|
||||||
if(resValueInt==null||resValueInt==this){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ValueType valueType=resValueInt.getValueType();
|
|
||||||
if(valueType==ValueType.STRING){
|
|
||||||
setValueAsString(resValueInt.getValueAsString());
|
|
||||||
}else {
|
|
||||||
setValueType(valueType);
|
|
||||||
setData(resValueInt.getData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
StringBuilder builder=new StringBuilder();
|
|
||||||
builder.append(getClass().getSimpleName());
|
|
||||||
builder.append(" type=");
|
|
||||||
ValueType vt=getValueType();
|
|
||||||
if(vt!=null){
|
|
||||||
builder.append(vt.name());
|
|
||||||
}else {
|
|
||||||
builder.append("Unknown");
|
|
||||||
}
|
|
||||||
String data=null;
|
|
||||||
if(vt==ValueType.STRING){
|
|
||||||
data=getString(getData());
|
|
||||||
}else{
|
|
||||||
data= ValueDecoder.decode(vt, getData());
|
|
||||||
}
|
|
||||||
if(data==null){
|
|
||||||
data=String.format("0x%08x", getData());
|
|
||||||
}
|
|
||||||
builder.append('(');
|
|
||||||
builder.append(String.format("0x%02x", getType()));
|
|
||||||
builder.append("), data=");
|
|
||||||
builder.append(data);
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int OFFSET_SIZE=0;
|
|
||||||
private static final int OFFSET_RESERVED=2;
|
|
||||||
private static final int OFFSET_TYPE=3;
|
|
||||||
private static final int OFFSET_DATA=4;
|
|
||||||
|
|
||||||
private static final int BYTES_COUNT=8;
|
|
||||||
private static final short BYTES_SIZE=0x08;
|
|
||||||
|
|
||||||
}
|
|
115
src/main/java/com/reandroid/arsc/value/ResValueMap.java
Executable file
115
src/main/java/com/reandroid/arsc/value/ResValueMap.java
Executable file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
public class ResValueMap extends ValueItem{
|
||||||
|
|
||||||
|
public ResValueMap() {
|
||||||
|
super(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry getEntry(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof Entry){
|
||||||
|
return (Entry) parent;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResTableMapEntry getParentMapEntry(){
|
||||||
|
Block parent=getParent();
|
||||||
|
while(parent!=null){
|
||||||
|
if(parent instanceof ResTableMapEntry){
|
||||||
|
return (ResTableMapEntry) parent;
|
||||||
|
}
|
||||||
|
parent=parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getName(){
|
||||||
|
return getInteger(getBytesInternal(), OFFSET_NAME);
|
||||||
|
}
|
||||||
|
public void setName(int name){
|
||||||
|
putInteger(getBytesInternal(), OFFSET_NAME, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getSizeOffset(){
|
||||||
|
return OFFSET_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject jsonObject = super.toJson();
|
||||||
|
if(jsonObject==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
jsonObject.put(NAME_name, getName());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
super.fromJson(json);
|
||||||
|
setName(json.getInt(NAME_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "name="+String.format("0x%08x", getName())
|
||||||
|
+", "+super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int OFFSET_NAME = 0;
|
||||||
|
private static final int OFFSET_SIZE = 4;
|
||||||
|
|
||||||
|
public static final String NAME_name = "name";
|
||||||
|
|
||||||
|
public void setNameHigh(short val){
|
||||||
|
int name = getName() & 0xffff;
|
||||||
|
name = ((val & 0xffff) <<16 ) | name;
|
||||||
|
setName(name);
|
||||||
|
}
|
||||||
|
public void setNameLow(short val){
|
||||||
|
int name = getName() & 0xffff0000;
|
||||||
|
name = (val & 0xffff) | name;
|
||||||
|
setName(name);
|
||||||
|
}
|
||||||
|
public void setDataHigh(short val){
|
||||||
|
int data = getData() & 0xffff;
|
||||||
|
data = ((val & 0xffff) <<16 ) | data;
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
public void setDataLow(short val){
|
||||||
|
int data = getData() & 0xffff0000;
|
||||||
|
data = (val & 0xffff) | data;
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
public void merge(ResValueMap resValueMap){
|
||||||
|
if(resValueMap==null||resValueMap==this){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.merge(resValueMap);
|
||||||
|
setName(resValueMap.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.arsc.value;
|
|
||||||
|
|
||||||
import com.reandroid.arsc.item.ReferenceItem;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class ResValueReference implements ReferenceItem {
|
|
||||||
private final BaseResValueItem resValueItem;
|
|
||||||
public ResValueReference(BaseResValueItem resValueItem){
|
|
||||||
this.resValueItem=resValueItem;
|
|
||||||
}
|
|
||||||
public EntryBlock getEntryBlock(){
|
|
||||||
return resValueItem.getEntryBlock();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void set(int val) {
|
|
||||||
resValueItem.onSetReference(val);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int get() {
|
|
||||||
return resValueItem.getData();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
ResValueReference that = (ResValueReference) o;
|
|
||||||
return Objects.equals(resValueItem, that.resValueItem);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(resValueItem);
|
|
||||||
}
|
|
||||||
}
|
|
116
src/main/java/com/reandroid/arsc/value/TableEntry.java
Normal file
116
src/main/java/com/reandroid/arsc/value/TableEntry.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
import com.reandroid.arsc.base.BlockCounter;
|
||||||
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.json.JSONConvert;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public abstract class TableEntry<HEADER extends Header, VALUE extends Block> extends Block implements
|
||||||
|
JSONConvert<JSONObject> {
|
||||||
|
private final HEADER header;
|
||||||
|
private final VALUE resValue;
|
||||||
|
|
||||||
|
TableEntry(HEADER header, VALUE resValue){
|
||||||
|
super();
|
||||||
|
this.header = header;
|
||||||
|
this.resValue = resValue;
|
||||||
|
|
||||||
|
this.header.setParent(this);
|
||||||
|
this.header.setIndex(0);
|
||||||
|
this.resValue.setParent(this);
|
||||||
|
this.resValue.setIndex(1);
|
||||||
|
}
|
||||||
|
public Entry getParentEntry(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof Entry){
|
||||||
|
return (Entry) parent;
|
||||||
|
}
|
||||||
|
parent=parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public void refresh(){
|
||||||
|
}
|
||||||
|
public final HEADER getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
public VALUE getValue(){
|
||||||
|
return resValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBytes() {
|
||||||
|
byte[] results = getHeader().getBytes();
|
||||||
|
results = addBytes(results, getValue().getBytes());
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int countBytes() {
|
||||||
|
int result = getHeader().countBytes();
|
||||||
|
result += getValue().countBytes();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onCountUpTo(BlockCounter counter) {
|
||||||
|
if(counter.FOUND){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(counter.END==this){
|
||||||
|
counter.FOUND=true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getHeader().onCountUpTo(counter);
|
||||||
|
getValue().onCountUpTo(counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
|
Header header = getHeader();
|
||||||
|
header.readBytes(reader);
|
||||||
|
onHeaderLoaded(header);
|
||||||
|
getValue().readBytes(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int onWriteBytes(OutputStream stream) throws IOException {
|
||||||
|
int result;
|
||||||
|
result = getHeader().writeBytes(stream);
|
||||||
|
result += getValue().writeBytes(stream);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onHeaderLoaded(Header header){
|
||||||
|
}
|
||||||
|
abstract void onRemoved();
|
||||||
|
abstract boolean shouldMerge(TableEntry<?, ?> tableEntry);
|
||||||
|
|
||||||
|
public abstract void merge(TableEntry<?, ?> tableEntry);
|
||||||
|
@Override
|
||||||
|
public abstract JSONObject toJson();
|
||||||
|
@Override
|
||||||
|
public abstract void fromJson(JSONObject json);
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return getHeader()+", value={"+getValue()+"}";
|
||||||
|
}
|
||||||
|
}
|
295
src/main/java/com/reandroid/arsc/value/ValueItem.java
Executable file
295
src/main/java/com/reandroid/arsc/value/ValueItem.java
Executable file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* 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.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.base.Block;
|
||||||
|
import com.reandroid.arsc.chunk.MainChunk;
|
||||||
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.item.BlockItem;
|
||||||
|
import com.reandroid.arsc.item.ReferenceBlock;
|
||||||
|
import com.reandroid.arsc.item.ReferenceItem;
|
||||||
|
import com.reandroid.arsc.item.StringItem;
|
||||||
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
|
import com.reandroid.json.JSONConvert;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public abstract class ValueItem extends BlockItem implements Value,
|
||||||
|
JSONConvert<JSONObject>{
|
||||||
|
private ReferenceItem mStringReference;
|
||||||
|
public ValueItem(int bytesLength) {
|
||||||
|
super(bytesLength);
|
||||||
|
writeSize();
|
||||||
|
}
|
||||||
|
public void onRemoved(){
|
||||||
|
unLinkStringReference();
|
||||||
|
}
|
||||||
|
public Entry getParentEntry(){
|
||||||
|
Block parent=getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof Entry){
|
||||||
|
return (Entry) parent;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public void refresh(){
|
||||||
|
writeSize();
|
||||||
|
}
|
||||||
|
public ReferenceItem getTableStringReference(){
|
||||||
|
return mStringReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract int getSizeOffset();
|
||||||
|
|
||||||
|
byte getRes0(){
|
||||||
|
return getBytesInternal()[getSizeOffset()+OFFSET_RES0];
|
||||||
|
}
|
||||||
|
public byte getType(){
|
||||||
|
return getBytesInternal()[getSizeOffset()+OFFSET_TYPE];
|
||||||
|
}
|
||||||
|
public void setType(byte type){
|
||||||
|
if(type == getType()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] bts = getBytesInternal();
|
||||||
|
int offset = getSizeOffset()+OFFSET_TYPE;
|
||||||
|
byte old = bts[offset];
|
||||||
|
bts[offset] = type;
|
||||||
|
onTypeChanged(old, type);
|
||||||
|
}
|
||||||
|
public int getSize(){
|
||||||
|
return 0xffff & getShort(getBytesInternal(), getSizeOffset()+OFFSET_SIZE);
|
||||||
|
}
|
||||||
|
public void setSize(int size){
|
||||||
|
size = getSizeOffset() + size;
|
||||||
|
setBytesLength(size, false);
|
||||||
|
writeSize();
|
||||||
|
}
|
||||||
|
private void writeSize(){
|
||||||
|
int offset = getSizeOffset();
|
||||||
|
int size = countBytes() - offset;
|
||||||
|
putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size);
|
||||||
|
}
|
||||||
|
private void onDataLoaded(){
|
||||||
|
if(getValueType() == ValueType.STRING){
|
||||||
|
linkStringReference();
|
||||||
|
}else {
|
||||||
|
unLinkStringReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public ValueType getValueType(){
|
||||||
|
return ValueType.valueOf(getType());
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setValueType(ValueType valueType){
|
||||||
|
byte type = 0;
|
||||||
|
if(valueType!=null){
|
||||||
|
type = valueType.getByte();
|
||||||
|
}
|
||||||
|
setType(type);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getData(){
|
||||||
|
return getInteger(getBytesInternal(), getSizeOffset()+OFFSET_DATA);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setData(int data){
|
||||||
|
byte[] bts = getBytesInternal();
|
||||||
|
int old = getInteger(bts, getSizeOffset()+OFFSET_DATA);
|
||||||
|
if(old == data){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unLinkStringReference();
|
||||||
|
putInteger(bts, getSizeOffset()+OFFSET_DATA, data);
|
||||||
|
if(ValueType.STRING==getValueType()){
|
||||||
|
linkStringReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public StringItem getDataAsPoolString(){
|
||||||
|
StringPool<?> stringPool = getStringPool();
|
||||||
|
if(stringPool == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return stringPool.get(getData());
|
||||||
|
}
|
||||||
|
private void onTypeChanged(byte old, byte type){
|
||||||
|
byte typeString = ValueType.STRING.getByte();
|
||||||
|
if(old == typeString){
|
||||||
|
unLinkStringReference();
|
||||||
|
}else if(type == typeString){
|
||||||
|
linkStringReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void linkStringReference(){
|
||||||
|
StringItem tableString = getDataAsPoolString();
|
||||||
|
if(tableString==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ReferenceItem stringReference = mStringReference;
|
||||||
|
if(stringReference!=null){
|
||||||
|
unLinkStringReference();
|
||||||
|
}
|
||||||
|
stringReference = new ReferenceBlock<>(this, getSizeOffset()+OFFSET_DATA);
|
||||||
|
mStringReference = stringReference;
|
||||||
|
tableString.addReference(stringReference);
|
||||||
|
}
|
||||||
|
private void unLinkStringReference(){
|
||||||
|
ReferenceItem stringReference = mStringReference;
|
||||||
|
if(stringReference==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mStringReference = null;
|
||||||
|
StringPool<?> stringPool = getStringPool();
|
||||||
|
if(stringPool == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stringPool.removeReference(stringReference);
|
||||||
|
}
|
||||||
|
private StringPool<?> getStringPool(){
|
||||||
|
Block parent = getParent();
|
||||||
|
while (parent!=null){
|
||||||
|
if(parent instanceof MainChunk){
|
||||||
|
return ((MainChunk) parent).getStringPool();
|
||||||
|
}
|
||||||
|
parent=parent.getParent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
|
initializeBytes(reader);
|
||||||
|
super.onReadBytes(reader);
|
||||||
|
onDataLoaded();
|
||||||
|
}
|
||||||
|
private void initializeBytes(BlockReader reader) throws IOException {
|
||||||
|
int position = reader.getPosition();
|
||||||
|
int offset = getSizeOffset();
|
||||||
|
reader.offset(offset);
|
||||||
|
int size = reader.readUnsignedShort();
|
||||||
|
reader.seek(position);
|
||||||
|
setBytesLength(offset + size, false);
|
||||||
|
}
|
||||||
|
public String getValueAsString(){
|
||||||
|
StringItem stringItem = getDataAsPoolString();
|
||||||
|
if(stringItem!=null){
|
||||||
|
return stringItem.getHtml();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public void setValueAsString(String str){
|
||||||
|
StringItem stringItem = getStringPool().getOrCreate(str);
|
||||||
|
setData(stringItem.getIndex());
|
||||||
|
setValueType(ValueType.STRING);
|
||||||
|
}
|
||||||
|
public boolean getValueAsBoolean(){
|
||||||
|
return getData()!=0;
|
||||||
|
}
|
||||||
|
public void setValueAsBoolean(boolean val){
|
||||||
|
setValueType(ValueType.INT_BOOLEAN);
|
||||||
|
int data=val?0xffffffff:0;
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
public void setTypeAndData(ValueType valueType, int data){
|
||||||
|
setData(data);
|
||||||
|
setValueType(valueType);
|
||||||
|
}
|
||||||
|
public void merge(ValueItem valueItem){
|
||||||
|
if(valueItem == null || valueItem==this){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setSize(valueItem.getSize());
|
||||||
|
ValueType coming = valueItem.getValueType();
|
||||||
|
if(coming == ValueType.STRING){
|
||||||
|
setValueAsString(valueItem.getValueAsString());
|
||||||
|
}else {
|
||||||
|
setTypeAndData(coming, valueItem.getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public JSONObject toJson() {
|
||||||
|
if(isNull()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
ValueType valueType = getValueType();
|
||||||
|
jsonObject.put(NAME_value_type, valueType.name());
|
||||||
|
if(valueType==ValueType.STRING){
|
||||||
|
jsonObject.put(NAME_data, getValueAsString());
|
||||||
|
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||||
|
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||||
|
}else {
|
||||||
|
jsonObject.put(NAME_data, getData());
|
||||||
|
}
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void fromJson(JSONObject json) {
|
||||||
|
ValueType valueType = ValueType.fromName(json.getString(NAME_value_type));
|
||||||
|
if(valueType==ValueType.STRING){
|
||||||
|
setValueAsString(json.optString(NAME_data, ""));
|
||||||
|
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||||
|
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||||
|
}else {
|
||||||
|
setValueType(valueType);
|
||||||
|
setData(json.getInt(NAME_data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
int size = getSize();
|
||||||
|
if(size!=8){
|
||||||
|
builder.append("size=").append(getSize());
|
||||||
|
builder.append(", ");
|
||||||
|
}
|
||||||
|
builder.append("type=");
|
||||||
|
ValueType valueType=getValueType();
|
||||||
|
if(valueType!=null){
|
||||||
|
builder.append(valueType);
|
||||||
|
}else {
|
||||||
|
builder.append(String.format("0x%02x", (0xff & getType())));
|
||||||
|
}
|
||||||
|
builder.append(", data=");
|
||||||
|
int data = getData();
|
||||||
|
if(valueType==ValueType.STRING){
|
||||||
|
StringItem tableString = getDataAsPoolString();
|
||||||
|
if(tableString!=null){
|
||||||
|
builder.append(tableString.getHtml());
|
||||||
|
}else {
|
||||||
|
builder.append(String.format("0x%08x", data));
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
builder.append(String.format("0x%08x", data));
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int OFFSET_SIZE = 0;
|
||||||
|
private static final int OFFSET_RES0 = 2;
|
||||||
|
private static final int OFFSET_TYPE = 3;
|
||||||
|
private static final int OFFSET_DATA = 4;
|
||||||
|
|
||||||
|
|
||||||
|
static final String NAME_data = "data";
|
||||||
|
static final String NAME_value_type = "value_type";
|
||||||
|
}
|
@ -15,9 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.array;
|
package com.reandroid.arsc.value.array;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
|
|
||||||
public class ArrayBag {
|
public class ArrayBag {
|
||||||
private final ArrayBagItem[] mBagItems;
|
private final ArrayBagItem[] mBagItems;
|
||||||
@ -28,18 +28,18 @@ public class ArrayBag {
|
|||||||
return mBagItems;
|
return mBagItems;
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryBlock.getName();
|
return entry.getName();
|
||||||
}
|
}
|
||||||
public String getTypeName(){
|
public String getTypeName(){
|
||||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryBlock.getTypeName();
|
return entry.getTypeName();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -63,39 +63,38 @@ public class ArrayBag {
|
|||||||
|
|
||||||
/** The result of this is not always 100% accurate,
|
/** The result of this is not always 100% accurate,
|
||||||
* in addition to this use your methods to cross check like type-name == "array"**/
|
* in addition to this use your methods to cross check like type-name == "array"**/
|
||||||
public static boolean isArray(ResValueBag resValueBag){
|
public static boolean isArray(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock = resValueBag.getEntryBlock();
|
if(mapEntry.getParentId()!=0){
|
||||||
if(entryBlock==null){
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(resValueBag.getParentId()!=0){
|
ArrayBagItem[] arrayBagItems = ArrayBagItem.create(mapEntry.listResValueMap());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ArrayBagItem[] arrayBagItems = ArrayBagItem.create(resValueBag.getBagItems());
|
|
||||||
if(arrayBagItems==null || arrayBagItems.length==0){
|
if(arrayBagItems==null || arrayBagItems.length==0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(int i=0;i< arrayBagItems.length; i++){
|
for(int i=0;i< arrayBagItems.length; i++){
|
||||||
ArrayBagItem arrayBagItem = arrayBagItems[i];
|
ArrayBagItem arrayBagItem = arrayBagItems[i];
|
||||||
ResValueBagItem resValueBagItem = arrayBagItem.getBagItem();
|
ResValueMap resValueMap = arrayBagItem.getBagItem();
|
||||||
if(resValueBagItem.getIdHigh()!=0x0100){
|
int name = resValueMap.getName();
|
||||||
|
int high = (name >> 16) & 0xffff;
|
||||||
|
if(high!=0x0100){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(resValueBagItem.getIdLow() != (i+1)){
|
int low = name & 0xffff;
|
||||||
|
if(low != (i+1)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayBag create(ResValueBag resValueBag){
|
public static ArrayBag create(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ArrayBagItem[] bagItems=ArrayBagItem.create(resValueBag.getBagItems());
|
ArrayBagItem[] bagItems=ArrayBagItem.create(mapEntry.listResValueMap());
|
||||||
if(bagItems==null){
|
if(bagItems==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -19,19 +19,19 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ArrayBagItem {
|
public class ArrayBagItem {
|
||||||
private final ResValueBagItem mBagItem;
|
private final ResValueMap mBagItem;
|
||||||
public ArrayBagItem(ResValueBagItem bagItem){
|
public ArrayBagItem(ResValueMap bagItem){
|
||||||
this.mBagItem=bagItem;
|
this.mBagItem=bagItem;
|
||||||
}
|
}
|
||||||
public ResValueBagItem getBagItem() {
|
public ResValueMap getBagItem() {
|
||||||
return mBagItem;
|
return mBagItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,11 +39,11 @@ import java.util.List;
|
|||||||
return getBagItem().getValueType();
|
return getBagItem().getValueType();
|
||||||
}
|
}
|
||||||
private TableStringPool getStringPool(){
|
private TableStringPool getStringPool(){
|
||||||
EntryBlock entryBlock=getBagItem().getEntryBlock();
|
Entry entry =getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PackageBlock pkg = entryBlock.getPackageBlock();
|
PackageBlock pkg = entry.getPackageBlock();
|
||||||
if(pkg==null){
|
if(pkg==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -88,17 +88,17 @@ import java.util.List;
|
|||||||
builder.append("</item>");
|
builder.append("</item>");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
public static ArrayBagItem[] create(ResValueBagItem[] resValueBagItems){
|
public static ArrayBagItem[] create(ResValueMap[] resValueMaps){
|
||||||
if(resValueBagItems==null){
|
if(resValueMaps ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int len=resValueBagItems.length;
|
int len= resValueMaps.length;
|
||||||
if(len==0){
|
if(len==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<ArrayBagItem> results=new ArrayList<>();
|
List<ArrayBagItem> results=new ArrayList<>();
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
ArrayBagItem item=create(resValueBagItems[i]);
|
ArrayBagItem item=create(resValueMaps[i]);
|
||||||
if(item==null){
|
if(item==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -106,11 +106,11 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
return results.toArray(new ArrayBagItem[0]);
|
return results.toArray(new ArrayBagItem[0]);
|
||||||
}
|
}
|
||||||
public static ArrayBagItem create(ResValueBagItem resValueBagItem){
|
public static ArrayBagItem create(ResValueMap resValueMap){
|
||||||
if(resValueBagItem==null){
|
if(resValueMap ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ArrayBagItem item=new ArrayBagItem(resValueBagItem);
|
ArrayBagItem item=new ArrayBagItem(resValueMap);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.attribute;
|
package com.reandroid.arsc.value.attribute;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
|
|
||||||
@ -220,9 +221,9 @@ public class AttributeBag {
|
|||||||
AttributeBagItem[] bagItems= getBagItems();
|
AttributeBagItem[] bagItems= getBagItems();
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
AttributeBagItem format=getFormat();
|
AttributeBagItem format=getFormat();
|
||||||
EntryBlock entryBlock=format.getBagItem().getEntryBlock();
|
Entry entry =format.getBagItem().getEntry();
|
||||||
if(entryBlock!=null){
|
if(entry !=null){
|
||||||
builder.append(entryBlock.getSpecString());
|
builder.append(entry.getSpecString());
|
||||||
}
|
}
|
||||||
int len=bagItems.length;
|
int len=bagItems.length;
|
||||||
builder.append(", childes=").append(len);
|
builder.append(", childes=").append(len);
|
||||||
@ -234,21 +235,21 @@ public class AttributeBag {
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AttributeBag create(ResValueBag resValueBag){
|
public static AttributeBag create(ResValueMapArray resValueMapArray){
|
||||||
if(resValueBag==null){
|
if(resValueMapArray==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueBag.getBagItems());
|
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueMapArray.getChildes());
|
||||||
if(bagItems==null){
|
if(bagItems==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new AttributeBag(bagItems);
|
return new AttributeBag(bagItems);
|
||||||
}
|
}
|
||||||
public static boolean isAttribute(ResValueBag resValueBag){
|
public static boolean isAttribute(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueBag.getBagItems());
|
AttributeBagItem[] bagItems=AttributeBagItem.create(mapEntry.listResValueMap());
|
||||||
return bagItems!=null;
|
return bagItems!=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,14 @@ package com.reandroid.arsc.value.attribute;
|
|||||||
|
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
|
|
||||||
|
|
||||||
public class AttributeBagItem {
|
public class AttributeBagItem {
|
||||||
private final ResValueBagItem mBagItem;
|
private final ResValueMap mBagItem;
|
||||||
public AttributeBagItem(ResValueBagItem bagItem){
|
public AttributeBagItem(ResValueMap bagItem){
|
||||||
this.mBagItem=bagItem;
|
this.mBagItem=bagItem;
|
||||||
}
|
}
|
||||||
public int getData(){
|
public int getData(){
|
||||||
@ -36,7 +36,7 @@ public class AttributeBagItem {
|
|||||||
public String getNameOrHex(EntryStore entryStore){
|
public String getNameOrHex(EntryStore entryStore){
|
||||||
String name=getName(entryStore);
|
String name=getName(entryStore);
|
||||||
if(name==null){
|
if(name==null){
|
||||||
name=String.format("@0x%08x", getBagItem().getId());
|
name=String.format("@0x%08x", getBagItem().getName());
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -47,9 +47,9 @@ public class AttributeBagItem {
|
|||||||
if(isType()){
|
if(isType()){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
int id=item.getId();
|
int id=item.getName();
|
||||||
EntryBlock parentEntry=item.getEntryBlock();
|
Entry parentEntry=item.getEntry();
|
||||||
if(parentEntry!=null){
|
if(parentEntry!=null){
|
||||||
PackageBlock packageBlock=parentEntry.getPackageBlock();
|
PackageBlock packageBlock=parentEntry.getPackageBlock();
|
||||||
if(packageBlock!=null){
|
if(packageBlock!=null){
|
||||||
@ -70,26 +70,27 @@ public class AttributeBagItem {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public ResValueBagItem getBagItem() {
|
public ResValueMap getBagItem() {
|
||||||
return mBagItem;
|
return mBagItem;
|
||||||
}
|
}
|
||||||
public AttributeItemType getItemType(){
|
public AttributeItemType getItemType(){
|
||||||
if(!isType()){
|
if(!isType()){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
return AttributeItemType.valueOf(item.getIdLow());
|
int low = item.getName() & 0xffff;
|
||||||
|
return AttributeItemType.valueOf((short) low);
|
||||||
}
|
}
|
||||||
public boolean isType(){
|
public boolean isType(){
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
return item.getIdHigh()==0x0100;
|
return ((item.getName()>>16) & 0xffff)==0x0100;
|
||||||
}
|
}
|
||||||
public boolean contains(AttributeValueType valueType){
|
public boolean contains(AttributeValueType valueType){
|
||||||
if(valueType == null || getItemType()!=AttributeItemType.FORMAT){
|
if(valueType == null || getItemType()!=AttributeItemType.FORMAT){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int value = 0xff & valueType.getByte();
|
int value = 0xff & valueType.getByte();
|
||||||
int dataLow = 0xffff & getBagItem().getDataLow();
|
int dataLow = 0xffff & getBagItem().getData();
|
||||||
return (dataLow & value) == value;
|
return (dataLow & value) == value;
|
||||||
}
|
}
|
||||||
public boolean isEqualType(AttributeValueType valueType){
|
public boolean isEqualType(AttributeValueType valueType){
|
||||||
@ -97,7 +98,7 @@ public class AttributeBagItem {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int value = 0xff & valueType.getByte();
|
int value = 0xff & valueType.getByte();
|
||||||
int dataLow = 0xffff & getBagItem().getDataLow();
|
int dataLow = 0xffff & getBagItem().getData();
|
||||||
return (dataLow == value);
|
return (dataLow == value);
|
||||||
}
|
}
|
||||||
public AttributeValueType[] getValueTypes(){
|
public AttributeValueType[] getValueTypes(){
|
||||||
@ -105,8 +106,8 @@ public class AttributeBagItem {
|
|||||||
if(type!=AttributeItemType.FORMAT){
|
if(type!=AttributeItemType.FORMAT){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
short low=item.getDataLow();
|
short low = (short) (item.getData() & 0xffff);
|
||||||
return AttributeValueType.valuesOf(low);
|
return AttributeValueType.valuesOf(low);
|
||||||
}
|
}
|
||||||
public Integer getBound(){
|
public Integer getBound(){
|
||||||
@ -114,7 +115,7 @@ public class AttributeBagItem {
|
|||||||
if(type==null || type==AttributeItemType.FORMAT){
|
if(type==null || type==AttributeItemType.FORMAT){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
return item.getData();
|
return item.getData();
|
||||||
}
|
}
|
||||||
public boolean isEnum(){
|
public boolean isEnum(){
|
||||||
@ -122,16 +123,18 @@ public class AttributeBagItem {
|
|||||||
if(type!=AttributeItemType.FORMAT){
|
if(type!=AttributeItemType.FORMAT){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
return item.getDataHigh()==AttributeBag.TYPE_ENUM;
|
int high = (item.getData() >> 16) & 0xffff;
|
||||||
|
return high==AttributeBag.TYPE_ENUM;
|
||||||
}
|
}
|
||||||
public boolean isFlag(){
|
public boolean isFlag(){
|
||||||
AttributeItemType type=getItemType();
|
AttributeItemType type=getItemType();
|
||||||
if(type!=AttributeItemType.FORMAT){
|
if(type!=AttributeItemType.FORMAT){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
return item.getDataHigh()==AttributeBag.TYPE_FLAG;
|
int high = (item.getData() >> 16) & 0xffff;
|
||||||
|
return high==AttributeBag.TYPE_FLAG;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
@ -157,7 +160,7 @@ public class AttributeBagItem {
|
|||||||
builder.append(bound);
|
builder.append(bound);
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
builder.append(getNameOrHex());
|
builder.append(getNameOrHex());
|
||||||
builder.append("=").append(String.format("0x%x", item.getData()));
|
builder.append("=").append(String.format("0x%x", item.getData()));
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
@ -190,15 +193,15 @@ public class AttributeBagItem {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public static AttributeBagItem[] create(ResValueBagItem[] resValueBagItems){
|
public static AttributeBagItem[] create(ResValueMap[] resValueMaps){
|
||||||
if(resValueBagItems==null){
|
if(resValueMaps ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
AttributeBagItem format=null;
|
AttributeBagItem format=null;
|
||||||
int len=resValueBagItems.length;
|
int len= resValueMaps.length;
|
||||||
AttributeBagItem[] bagItems=new AttributeBagItem[len];
|
AttributeBagItem[] bagItems=new AttributeBagItem[len];
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
AttributeBagItem item=new AttributeBagItem(resValueBagItems[i]);
|
AttributeBagItem item=new AttributeBagItem(resValueMaps[i]);
|
||||||
bagItems[i]=item;
|
bagItems[i]=item;
|
||||||
if(format==null){
|
if(format==null){
|
||||||
if(AttributeItemType.FORMAT==item.getItemType()){
|
if(AttributeItemType.FORMAT==item.getItemType()){
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.plurals;
|
package com.reandroid.arsc.value.plurals;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
|
|
||||||
public class PluralsBag {
|
public class PluralsBag {
|
||||||
private final PluralsBagItem[] mBagItems;
|
private final PluralsBagItem[] mBagItems;
|
||||||
private PluralsBag(PluralsBagItem[] bagItems){
|
private PluralsBag(PluralsBagItem[] bagItems){
|
||||||
this.mBagItems=bagItems;
|
this.mBagItems=bagItems;
|
||||||
@ -27,18 +27,18 @@ public class PluralsBag {
|
|||||||
return mBagItems;
|
return mBagItems;
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryBlock.getName();
|
return entry.getName();
|
||||||
}
|
}
|
||||||
public String getTypeName(){
|
public String getTypeName(){
|
||||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryBlock.getTypeName();
|
return entry.getTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -63,22 +63,18 @@ public class PluralsBag {
|
|||||||
|
|
||||||
/** The result of this is not always 100% accurate,
|
/** The result of this is not always 100% accurate,
|
||||||
* in addition to this use your methods to cross check like type-name == "plurals"**/
|
* in addition to this use your methods to cross check like type-name == "plurals"**/
|
||||||
public static boolean isPlurals(ResValueBag resValueBag){
|
public static boolean isPlurals(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock = resValueBag.getEntryBlock();
|
return PluralsBagItem.create(mapEntry.listResValueMap()) != null;
|
||||||
if(entryBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return PluralsBagItem.create(resValueBag.getBagItems()) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluralsBag create(ResValueBag resValueBag){
|
public static PluralsBag create(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PluralsBagItem[] bagItems=PluralsBagItem.create(resValueBag.getBagItems());
|
PluralsBagItem[] bagItems=PluralsBagItem.create(mapEntry.listResValueMap());
|
||||||
if(bagItems==null){
|
if(bagItems==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -29,26 +29,27 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class PluralsBagItem {
|
public class PluralsBagItem {
|
||||||
private final ResValueBagItem mBagItem;
|
private final ResValueMap mBagItem;
|
||||||
private PluralsBagItem(ResValueBagItem bagItem){
|
private PluralsBagItem(ResValueMap bagItem){
|
||||||
this.mBagItem=bagItem;
|
this.mBagItem=bagItem;
|
||||||
}
|
}
|
||||||
public ResValueBagItem getBagItem() {
|
public ResValueMap getBagItem() {
|
||||||
return mBagItem;
|
return mBagItem;
|
||||||
}
|
}
|
||||||
public PluralsQuantity getQuantity(){
|
public PluralsQuantity getQuantity(){
|
||||||
ResValueBagItem item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
return PluralsQuantity.valueOf(item.getIdLow());
|
int low = item.getName() & 0xffff;
|
||||||
|
return PluralsQuantity.valueOf((short) low);
|
||||||
}
|
}
|
||||||
public ValueType getValueType(){
|
public ValueType getValueType(){
|
||||||
return getBagItem().getValueType();
|
return getBagItem().getValueType();
|
||||||
}
|
}
|
||||||
private TableStringPool getStringPool(){
|
private TableStringPool getStringPool(){
|
||||||
EntryBlock entryBlock=getBagItem().getEntryBlock();
|
Entry entry =getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PackageBlock pkg = entryBlock.getPackageBlock();
|
PackageBlock pkg = entry.getPackageBlock();
|
||||||
if(pkg==null){
|
if(pkg==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -96,22 +97,23 @@ public class PluralsBagItem {
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluralsBagItem[] create(ResValueBagItem[] resValueBagItems){
|
public static PluralsBagItem[] create(ResValueMap[] resValueMaps){
|
||||||
if(resValueBagItems==null){
|
if(resValueMaps ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int len=resValueBagItems.length;
|
int len= resValueMaps.length;
|
||||||
if(len==0){
|
if(len==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Set<PluralsQuantity> duplicates=new HashSet<>();
|
Set<PluralsQuantity> duplicates=new HashSet<>();
|
||||||
List<PluralsBagItem> results=new ArrayList<>();
|
List<PluralsBagItem> results=new ArrayList<>();
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
ResValueBagItem resValueBagItem = resValueBagItems[i];
|
ResValueMap resValueMap = resValueMaps[i];
|
||||||
if(resValueBagItem.getIdHigh() != 0x0100){
|
int high = (resValueMap.getName() >> 16) & 0xffff;
|
||||||
|
if(high != 0x0100){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PluralsBagItem item=create(resValueBagItem);
|
PluralsBagItem item=create(resValueMap);
|
||||||
if(item==null){
|
if(item==null){
|
||||||
// If it reaches here type name is obfuscated
|
// If it reaches here type name is obfuscated
|
||||||
return null;
|
return null;
|
||||||
@ -125,8 +127,8 @@ public class PluralsBagItem {
|
|||||||
}
|
}
|
||||||
return results.toArray(new PluralsBagItem[0]);
|
return results.toArray(new PluralsBagItem[0]);
|
||||||
}
|
}
|
||||||
public static PluralsBagItem create(ResValueBagItem resValueBagItem){
|
public static PluralsBagItem create(ResValueMap resValueMap){
|
||||||
PluralsBagItem item=new PluralsBagItem(resValueBagItem);
|
PluralsBagItem item=new PluralsBagItem(resValueMap);
|
||||||
if(item.getQuantity()==null){
|
if(item.getQuantity()==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,8 @@
|
|||||||
package com.reandroid.arsc.value.style;
|
package com.reandroid.arsc.value.style;
|
||||||
|
|
||||||
import com.reandroid.arsc.item.SpecString;
|
import com.reandroid.arsc.item.SpecString;
|
||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ResValueBag;
|
|
||||||
|
|
||||||
public class StyleBag {
|
public class StyleBag {
|
||||||
private final StyleBagItem[] mBagItems;
|
private final StyleBagItem[] mBagItems;
|
||||||
@ -29,11 +28,11 @@ public class StyleBag {
|
|||||||
return mBagItems;
|
return mBagItems;
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
Entry entry = getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SpecString spec = entryBlock.getSpecString();
|
SpecString spec = entry.getSpecString();
|
||||||
if(spec==null){
|
if(spec==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -44,39 +43,35 @@ public class StyleBag {
|
|||||||
if(id==0){
|
if(id==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
Entry entry = getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryBlock.buildResourceName(id, '@', true);
|
return entry.buildResourceName(id, '@', true);
|
||||||
}
|
}
|
||||||
public int getParentId(){
|
public int getParentId(){
|
||||||
ResValueBag resValueBag=getBagItems()[0].getBagItem().getParentBag();
|
ResTableMapEntry mapEntry = getBagItems()[0].getBagItem().getParentMapEntry();
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return resValueBag.getParentId();
|
return mapEntry.getParentId();
|
||||||
}
|
}
|
||||||
public int getResourceId(){
|
public int getResourceId(){
|
||||||
EntryBlock entryBlock=getEntryBlock();
|
Entry entry = getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return entryBlock.getResourceId();
|
return entry.getResourceId();
|
||||||
}
|
}
|
||||||
public String getTypeName(){
|
public String getTypeName(){
|
||||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TypeString typeString = entryBlock.getTypeString();
|
return entry.getTypeName();
|
||||||
if(typeString==null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return typeString.get();
|
|
||||||
}
|
}
|
||||||
private EntryBlock getEntryBlock(){
|
private Entry getEntry(){
|
||||||
return getBagItems()[0].getBagItem().getEntryBlock();
|
return getBagItems()[0].getBagItem().getEntry();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -107,22 +102,18 @@ public class StyleBag {
|
|||||||
|
|
||||||
/** The result of this is not always 100% accurate,
|
/** The result of this is not always 100% accurate,
|
||||||
* in addition to this use your methods to cross check like type-name == "plurals"**/
|
* in addition to this use your methods to cross check like type-name == "plurals"**/
|
||||||
public static boolean isStyle(ResValueBag resValueBag){
|
public static boolean isStyle(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock = resValueBag.getEntryBlock();
|
return StyleBag.create(mapEntry) != null;
|
||||||
if(entryBlock==null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return StyleBag.create(resValueBag) != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StyleBag create(ResValueBag resValueBag){
|
public static StyleBag create(ResTableMapEntry mapEntry){
|
||||||
if(resValueBag==null){
|
if(mapEntry==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StyleBagItem[] bagItems=StyleBagItem.create(resValueBag.getBagItems());
|
StyleBagItem[] bagItems=StyleBagItem.create(mapEntry.getValue().getChildes());
|
||||||
if(bagItems==null){
|
if(bagItems==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,24 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.style;
|
package com.reandroid.arsc.value.style;
|
||||||
|
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueBagItem;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class StyleBagItem {
|
public class StyleBagItem {
|
||||||
private final ResValueBagItem mBagItem;
|
private final ResValueMap mBagItem;
|
||||||
public StyleBagItem(ResValueBagItem bagItem){
|
public StyleBagItem(ResValueMap bagItem){
|
||||||
this.mBagItem=bagItem;
|
this.mBagItem=bagItem;
|
||||||
}
|
}
|
||||||
public ResValueBagItem getBagItem() {
|
public ResValueMap getBagItem() {
|
||||||
return mBagItem;
|
return mBagItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName(){
|
public String getName(){
|
||||||
EntryBlock block=getBagItem().getEntryBlock();
|
Entry block=getBagItem().getEntry();
|
||||||
if(block==null){
|
if(block==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ public class StyleBagItem {
|
|||||||
return block.buildResourceName(getNameId(), prefix, false);
|
return block.buildResourceName(getNameId(), prefix, false);
|
||||||
}
|
}
|
||||||
public int getNameId(){
|
public int getNameId(){
|
||||||
return getBagItem().getId();
|
return getBagItem().getName();
|
||||||
}
|
}
|
||||||
public boolean hasStringValue(){
|
public boolean hasStringValue(){
|
||||||
return getValueType()== ValueType.STRING;
|
return getValueType()== ValueType.STRING;
|
||||||
@ -56,8 +56,8 @@ public class StyleBagItem {
|
|||||||
if(valueType!=ValueType.REFERENCE && valueType!=ValueType.ATTRIBUTE){
|
if(valueType!=ValueType.REFERENCE && valueType!=ValueType.ATTRIBUTE){
|
||||||
throw new IllegalArgumentException("Not REF ValueType="+valueType);
|
throw new IllegalArgumentException("Not REF ValueType="+valueType);
|
||||||
}
|
}
|
||||||
EntryBlock entryBlock=getBagItem().getEntryBlock();
|
Entry entry =getBagItem().getEntry();
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
char prefix='@';
|
char prefix='@';
|
||||||
@ -67,7 +67,7 @@ public class StyleBagItem {
|
|||||||
includeType=false;
|
includeType=false;
|
||||||
}
|
}
|
||||||
int id=getValue();
|
int id=getValue();
|
||||||
return entryBlock.buildResourceName(id, prefix, includeType);
|
return entry.buildResourceName(id, prefix, includeType);
|
||||||
}
|
}
|
||||||
public String getStringValue(){
|
public String getStringValue(){
|
||||||
return mBagItem.getValueAsString();
|
return mBagItem.getValueAsString();
|
||||||
@ -102,17 +102,17 @@ public class StyleBagItem {
|
|||||||
builder.append("</item>");
|
builder.append("</item>");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
public static StyleBagItem[] create(ResValueBagItem[] resValueBagItems){
|
public static StyleBagItem[] create(ResValueMap[] resValueMaps){
|
||||||
if(resValueBagItems==null){
|
if(resValueMaps ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int len=resValueBagItems.length;
|
int len= resValueMaps.length;
|
||||||
if(len==0){
|
if(len==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<StyleBagItem> results=new ArrayList<>();
|
List<StyleBagItem> results=new ArrayList<>();
|
||||||
for(int i=0;i<len;i++){
|
for(int i=0;i<len;i++){
|
||||||
StyleBagItem item=create(resValueBagItems[i]);
|
StyleBagItem item=create(resValueMaps[i]);
|
||||||
if(item==null){
|
if(item==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -120,10 +120,10 @@ public class StyleBagItem {
|
|||||||
}
|
}
|
||||||
return results.toArray(new StyleBagItem[0]);
|
return results.toArray(new StyleBagItem[0]);
|
||||||
}
|
}
|
||||||
public static StyleBagItem create(ResValueBagItem resValueBagItem){
|
public static StyleBagItem create(ResValueMap resValueMap){
|
||||||
if(resValueBagItem==null){
|
if(resValueMap ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new StyleBagItem(resValueBagItem);
|
return new StyleBagItem(resValueMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.value.EntryBlock;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.StagedAliasEntry;
|
import com.reandroid.arsc.value.StagedAliasEntry;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -31,13 +31,13 @@ public class TableEntryStore implements EntryStore{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getEntryName(int resourceId){
|
public String getEntryName(int resourceId){
|
||||||
EntryBlock entryBlock=getEntryBlock(resourceId);
|
Entry entry = getEntry(resourceId);
|
||||||
if(entryBlock==null){
|
if(entry ==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryBlock.getName();
|
return entry.getName();
|
||||||
}
|
}
|
||||||
public EntryBlock getEntryBlock(int resourceId){
|
public Entry getEntry(int resourceId){
|
||||||
if(resourceId==0){
|
if(resourceId==0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user