rename classes

This commit is contained in:
REAndroid 2023-02-13 11:38:58 -05:00
parent 3f7dc3bf9f
commit 7430b40c54
68 changed files with 2407 additions and 2507 deletions

View File

@ -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);
} }
} }

View File

@ -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;

View File

@ -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);

View File

@ -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))){

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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){

View File

@ -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;
} }
} }

View File

@ -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;
} }
} }

View File

@ -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;
} }

View File

@ -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;
} }
} }
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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() {

View File

@ -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();

View File

@ -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);
} }

View File

@ -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());

View File

@ -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);
} }
} }
} }

View File

@ -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));
} }
} }

View File

@ -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);
} }

View File

@ -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);
} }
} }

View File

@ -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+"'");
} }

View File

@ -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();

View File

@ -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);
} }
} }

View File

@ -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 =

View File

@ -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);
} }
} }

View File

@ -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);
} }
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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() {

View File

@ -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 {

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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);

View File

@ -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];
} }
}; };
} }

View File

@ -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;
} }
}; };
} }

View File

@ -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;
}
} }

View 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);
}
}

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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";
}

View File

@ -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);
}
}

View 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();
}
}

View File

@ -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";
}

View 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;
}

View 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";
}

View 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";
}

View 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";
}

View 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";
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2022 github.com/REAndroid
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reandroid.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;
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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;
}

View 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());
}
}

View File

@ -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);
}
}

View 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()+"}";
}
}

View 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";
}

View File

@ -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;
} }

View File

@ -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;
} }
} }

View File

@ -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;
} }

View File

@ -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()){

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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);
} }
} }

View File

@ -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;
} }