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.item.TableString;
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.IOException;
@ -180,11 +180,11 @@ public class ApkModule {
continue;
}
for(TableString tableString:groupTableString.listItems()){
List<EntryBlock> entryBlockList = tableString.listReferencedEntries(true);
if(entryBlockList.size()==0){
List<Entry> entryList = tableString.listReferencedEntries(true);
if(entryList.size()==0){
continue;
}
ResFile resFile=new ResFile(inputSource, entryBlockList);
ResFile resFile=new ResFile(inputSource, entryList);
results.add(resFile);
}
}

View File

@ -107,8 +107,8 @@ import java.util.*;
}
private void decodeResRaw(File outDir, ResFile resFile)
throws IOException {
EntryBlock entryBlock=resFile.pickOne();
PackageBlock packageBlock=entryBlock.getPackageBlock();
Entry entry =resFile.pickOne();
PackageBlock packageBlock= entry.getPackageBlock();
File pkgDir=new File(outDir, getPackageDirName(packageBlock));
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)
throws IOException, XMLException{
EntryBlock entryBlock=resFile.pickOne();
PackageBlock packageBlock=entryBlock.getPackageBlock();
Entry entry =resFile.pickOne();
PackageBlock packageBlock= entry.getPackageBlock();
ResXmlDocument resXmlDocument =new ResXmlDocument();
resXmlDocument.readBytes(resFile.getInputSource().openStream());
@ -181,24 +181,24 @@ import java.util.*;
xmlDocument.save(file, true);
addDecodedPath(AndroidManifestBlock.FILE_NAME);
}
private void addDecodedEntry(EntryBlock entryBlock){
if(entryBlock.isNull()){
private void addDecodedEntry(Entry entry){
if(entry.isNull()){
return;
}
int resourceId=entryBlock.getResourceId();
int resourceId= entry.getResourceId();
Set<ResConfig> resConfigSet=decodedEntries.get(resourceId);
if(resConfigSet==null){
resConfigSet=new HashSet<>();
decodedEntries.put(resourceId, resConfigSet);
}
resConfigSet.add(entryBlock.getResConfig());
resConfigSet.add(entry.getResConfig());
}
private boolean containsDecodedEntry(EntryBlock entryBlock){
Set<ResConfig> resConfigSet=decodedEntries.get(entryBlock.getResourceId());
private boolean containsDecodedEntry(Entry entry){
Set<ResConfig> resConfigSet=decodedEntries.get(entry.getResourceId());
if(resConfigSet==null){
return false;
}
return resConfigSet.contains(entryBlock.getResConfig());
return resConfigSet.contains(entry.getResConfig());
}
private void decodeValues(EntryStore entryStore, File outDir, TableBlock tableBlock) throws IOException {
for(PackageBlock packageBlock:tableBlock.listPackages()){
@ -221,11 +221,11 @@ import java.util.*;
private void decodeValues(EntryStore entryStore, File outDir, TypeBlock typeBlock) throws IOException {
XMLDocument xmlDocument = new XMLDocument("resources");
XMLElement docElement = xmlDocument.getDocumentElement();
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
if(containsDecodedEntry(entryBlock)){
for(Entry entry :typeBlock.listEntries(true)){
if(containsDecodedEntry(entry)){
continue;
}
docElement.addChild(decodeValue(entryStore, entryBlock));
docElement.addChild(decodeValue(entryStore, entry));
}
if(docElement.getChildesCount()==0){
return;
@ -240,28 +240,28 @@ import java.util.*;
file=new File(file, type+".xml");
xmlDocument.save(file, false);
}
private XMLElement decodeValue(EntryStore entryStore, EntryBlock entryBlock){
XMLElement element=new XMLElement(entryBlock.getTypeName());
int resourceId=entryBlock.getResourceId();
XMLAttribute attribute=new XMLAttribute("name", entryBlock.getName());
private XMLElement decodeValue(EntryStore entryStore, Entry entry){
XMLElement element=new XMLElement(entry.getTypeName());
int resourceId= entry.getResourceId();
XMLAttribute attribute=new XMLAttribute("name", entry.getName());
element.addAttribute(attribute);
attribute.setNameId(resourceId);
element.setResourceId(resourceId);
if(!entryBlock.isEntryTypeBag()){
ResValueInt resValueInt=(ResValueInt) entryBlock.getResValue();
if(resValueInt.getValueType()== ValueType.STRING){
if(!entry.isComplex()){
ResValue resValue =(ResValue) entry.getTableEntry().getValue();
if(resValue.getValueType()== ValueType.STRING){
XmlHelper.setTextContent(element,
resValueInt.getValueAsPoolString());
resValue.getDataAsPoolString());
}else {
String value = ValueDecoder.decodeEntryValue(entryStore,
entryBlock.getPackageBlock(),
resValueInt.getValueType(),
resValueInt.getData());
entry.getPackageBlock(),
resValue.getValueType(),
resValue.getData());
element.setTextContent(value);
}
}else {
ResValueBag resValueBag=(ResValueBag) entryBlock.getResValue();
xmlBagDecoder.decode(resValueBag, element);
ResTableMapEntry mapEntry = (ResTableMapEntry) entry.getTableEntry();
xmlBagDecoder.decode(mapEntry, 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.arsc.chunk.TypeBlock;
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.*;
import com.reandroid.json.JSONObject;
import java.io.File;
@ -28,23 +28,23 @@ import java.io.InputStream;
import java.util.List;
public class ResFile {
private final List<EntryBlock> entryBlockList;
private final List<Entry> entryList;
private final InputSource inputSource;
private boolean mBinXml;
private boolean mBinXmlChecked;
private String mFileExtension;
private boolean mFileExtensionChecked;
private EntryBlock mSelectedEntryBlock;
public ResFile(InputSource inputSource, List<EntryBlock> entryBlockList){
private Entry mSelectedEntry;
public ResFile(InputSource inputSource, List<Entry> entryList){
this.inputSource=inputSource;
this.entryBlockList=entryBlockList;
this.entryList = entryList;
}
public List<EntryBlock> getEntryBlockList(){
return entryBlockList;
public List<Entry> getEntryList(){
return entryList;
}
public String validateTypeDirectoryName(){
EntryBlock entryBlock=pickOne();
if(entryBlock==null){
Entry entry =pickOne();
if(entry ==null){
return null;
}
String path=getFilePath();
@ -61,34 +61,34 @@ public class ResFile {
i++;
name=path.substring(i);
}
TypeBlock typeBlock=entryBlock.getTypeBlock();
TypeBlock typeBlock= entry.getTypeBlock();
String typeName=typeBlock.getTypeName()+typeBlock.getResConfig().getQualifiers();
return root+typeName+"/"+name;
}
public EntryBlock pickOne(){
if(mSelectedEntryBlock==null){
mSelectedEntryBlock=selectOne();
public Entry pickOne(){
if(mSelectedEntry ==null){
mSelectedEntry =selectOne();
}
return mSelectedEntryBlock;
return mSelectedEntry;
}
private EntryBlock selectOne(){
List<EntryBlock> entryList = entryBlockList;
private Entry selectOne(){
List<Entry> entryList = this.entryList;
if(entryList.size()==0){
return null;
}
for(EntryBlock entryBlock:entryList){
if(!entryBlock.isNull() && entryBlock.isDefault()){
return entryBlock;
for(Entry entry :entryList){
if(!entry.isNull() && entry.isDefault()){
return entry;
}
}
for(EntryBlock entryBlock:entryList){
if(!entryBlock.isNull()){
return entryBlock;
for(Entry entry :entryList){
if(!entry.isNull()){
return entry;
}
}
for(EntryBlock entryBlock:entryList){
if(entryBlock.isDefault()){
return entryBlock;
for(Entry entry :entryList){
if(entry.isDefault()){
return entry;
}
}
return entryList.get(0);
@ -98,8 +98,13 @@ public class ResFile {
}
public void setFilePath(String filePath){
getInputSource().setAlias(filePath);
for(EntryBlock entryBlock:entryBlockList){
entryBlock.getValueAsTableString().set(filePath);
for(Entry entry : entryList){
TableEntry<?, ?> tableEntry = entry.getTableEntry();
if(!(tableEntry instanceof ResTableEntry)){
continue;
}
ResValue resValue = ((ResTableEntry) tableEntry).getValue();
resValue.setValueAsString(filePath);
}
}
public InputSource getInputSource() {
@ -143,13 +148,13 @@ public class ResFile {
return new File(dir, path);
}
public String buildPath(){
EntryBlock entryBlock=pickOne();
TypeBlock typeBlock=entryBlock.getTypeBlock();
Entry entry =pickOne();
TypeBlock typeBlock= entry.getTypeBlock();
StringBuilder builder=new StringBuilder();
builder.append(typeBlock.getTypeName());
builder.append(typeBlock.getQualifiers());
builder.append('/');
builder.append(entryBlock.getName());
builder.append(entry.getName());
String ext=getFileExtension();
if(ext!=null){
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.pool.SpecStringPool;
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.json.JSONArray;
import com.reandroid.json.JSONException;
@ -90,8 +90,8 @@ public class StringPoolBuilder {
return mSpecNameMap.get(pkgId);
}
private void scan(JSONObject jsonObject){
if(jsonObject.has(EntryBlock.NAME_entry_name)){
addSpecName(jsonObject.optString(EntryBlock.NAME_entry_name));
if(jsonObject.has(Header.NAME_entry_name)){
addSpecName(jsonObject.optString(Header.NAME_entry_name));
}
if(jsonObject.has(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;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
@ -27,6 +27,6 @@ abstract class BagDecoder {
EntryStore getEntryStore(){
return entryStore;
}
public abstract void decode(ResValueBag resValueBag, XMLElement parentElement);
public abstract boolean canDecode(ResValueBag resValueBag);
public abstract void decode(ResTableMapEntry mapEntry, XMLElement parentElement);
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.XmlHelper;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
@ -33,16 +33,16 @@ import java.util.Set;
}
@Override
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
ResValueBagItem[] bagItems = resValueBag.getBagItems();
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
ResValueMap[] bagItems = mapEntry.listResValueMap();
EntryStore entryStore=getEntryStore();
Set<ValueType> valueTypes = new HashSet<>();
for(int i=0;i<bagItems.length;i++){
ResValueBagItem bagItem = bagItems[i];
ResValueMap bagItem = bagItems[i];
ValueType valueType = bagItem.getValueType();
XMLElement child = new XMLElement("item");
if(valueType == ValueType.STRING){
XmlHelper.setTextContent(child, bagItem.getValueAsPoolString());
XmlHelper.setTextContent(child, bagItem.getDataAsPoolString());
}else {
String value = ValueDecoder.decodeIntEntry(entryStore, bagItem);
child.setTextContent(value);
@ -57,25 +57,28 @@ import java.util.Set;
}
}
@Override
public boolean canDecode(ResValueBag resValueBag) {
return isResBagArrayValue(resValueBag);
public boolean canDecode(ResTableMapEntry mapEntry) {
return isArrayValue(mapEntry);
}
public static boolean isResBagArrayValue(ResValueBag resValueBag){
int parentId=resValueBag.getParentId();
public static boolean isArrayValue(ResTableMapEntry mapEntry){
int parentId=mapEntry.getParentId();
if(parentId!=0){
return false;
}
ResValueBagItem[] bagItems = resValueBag.getBagItems();
ResValueMap[] bagItems = mapEntry.listResValueMap();
if(bagItems==null||bagItems.length==0){
return false;
}
int len=bagItems.length;
for(int i=0;i<len;i++){
ResValueBagItem item=bagItems[i];
if(item.getIdHigh()!=0x0100 && item.getIdHigh()!=0x0200){
ResValueMap item=bagItems[i];
int name = item.getName();
int high = (name >> 16) & 0xffff;
if(high!=0x0100 && high!=0x0200){
return false;
}
int id=item.getIdLow()-1;
int low = name & 0xffff;
int id = low - 1;
if(id!=i){
return false;
}

View File

@ -15,7 +15,7 @@
*/
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.AttributeBagItem;
import com.reandroid.common.EntryStore;
@ -26,8 +26,8 @@ class XMLAttrDecoder extends BagDecoder{
super(entryStore);
}
@Override
public void decode(ResValueBag resValueBag, XMLElement parentElement){
AttributeBag attributeBag=AttributeBag.create(resValueBag);
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement){
AttributeBag attributeBag=AttributeBag.create(mapEntry.getValue());
decodeParentAttributes(parentElement, attributeBag);
boolean is_flag=attributeBag.isFlag();
@ -55,8 +55,8 @@ class XMLAttrDecoder extends BagDecoder{
}
}
@Override
public boolean canDecode(ResValueBag resValueBag) {
return AttributeBag.isAttribute(resValueBag);
public boolean canDecode(ResTableMapEntry mapEntry) {
return AttributeBag.isAttribute(mapEntry);
}
private void decodeParentAttributes(XMLElement element, AttributeBag attributeBag){

View File

@ -15,7 +15,8 @@
*/
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.xml.XMLElement;
@ -34,13 +35,13 @@ public class XMLBagDecoder {
this.decoderList.add(new XMLArrayDecoder(entryStore));
this.commonBagDecoder = new XMLCommonBagDecoder(entryStore);
}
public void decode(ResValueBag resValueBag, XMLElement parentElement){
BagDecoder bagDecoder=getFor(resValueBag);
bagDecoder.decode(resValueBag, parentElement);
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement){
BagDecoder bagDecoder=getFor(mapEntry);
bagDecoder.decode(mapEntry, parentElement);
}
private BagDecoder getFor(ResValueBag resValueBag){
private BagDecoder getFor(ResTableMapEntry mapEntry){
for(BagDecoder bagDecoder:decoderList){
if(bagDecoder.canDecode(resValueBag)){
if(bagDecoder.canDecode(mapEntry)){
return bagDecoder;
}
}

View File

@ -18,8 +18,8 @@ package com.reandroid.apk.xmldecoder;
import com.reandroid.apk.XmlHelper;
import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
@ -30,12 +30,12 @@ class XMLCommonBagDecoder extends BagDecoder{
}
@Override
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
PackageBlock currentPackage=resValueBag
.getEntryBlock().getPackageBlock();
PackageBlock currentPackage= mapEntry
.getParentEntry().getPackageBlock();
int parentId = resValueBag.getParentId();
int parentId = mapEntry.getParentId();
String parent;
if(parentId!=0){
parent = ValueDecoder.decodeEntryValue(getEntryStore(),
@ -47,20 +47,20 @@ class XMLCommonBagDecoder extends BagDecoder{
parentElement.setAttribute("parent", parent);
}
int currentPackageId=currentPackage.getId();
ResValueBagItem[] bagItems = resValueBag.getBagItems();
ResValueMap[] bagItems = mapEntry.listResValueMap();
EntryStore entryStore = getEntryStore();
for(int i=0;i< bagItems.length;i++){
ResValueBagItem item=bagItems[i];
int resourceId=item.getId();
ResValueMap item=bagItems[i];
int resourceId=item.getName();
XMLElement child=new XMLElement("item");
String name = ValueDecoder.decodeAttributeName(
entryStore, currentPackage, item.getId());
entryStore, currentPackage, item.getName());
child.setAttribute("name", name);
ValueType valueType = item.getValueType();
if(valueType == ValueType.STRING){
XmlHelper.setTextContent(child, item.getValueAsPoolString());
XmlHelper.setTextContent(child, item.getDataAsPoolString());
}else {
String value = ValueDecoder.decode(entryStore, currentPackageId,
resourceId, item.getValueType(), item.getData());
@ -70,7 +70,7 @@ class XMLCommonBagDecoder extends BagDecoder{
}
}
@Override
public boolean canDecode(ResValueBag resValueBag) {
return resValueBag!=null;
public boolean canDecode(ResTableMapEntry mapEntry) {
return mapEntry !=null;
}
}

View File

@ -17,10 +17,7 @@ package com.reandroid.apk.xmldecoder;
import com.reandroid.apk.XmlHelper;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.BaseResValue;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.*;
import com.reandroid.arsc.value.plurals.PluralsQuantity;
import com.reandroid.common.EntryStore;
import com.reandroid.xml.XMLElement;
@ -30,19 +27,19 @@ class XMLPluralsDecoder extends BagDecoder{
super(entryStore);
}
@Override
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
ResValueBagItem[] bagItems = resValueBag.getBagItems();
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
ResValueMap[] bagItems = mapEntry.listResValueMap();
int len=bagItems.length;
EntryStore entryStore=getEntryStore();
for(int i=0;i<len;i++){
ResValueBagItem item = bagItems[i];
PluralsQuantity quantity = PluralsQuantity.valueOf(item.getIdLow());
ResValueMap item = bagItems[i];
int low = item.getName() & 0xffff;
PluralsQuantity quantity = PluralsQuantity.valueOf((short) low);
XMLElement child=new XMLElement("item");
child.setAttribute("quantity", quantity.toString());
if(item.getValueType() == ValueType.STRING){
XmlHelper.setTextContent(child, item.getValueAsPoolString());
XmlHelper.setTextContent(child, item.getDataAsPoolString());
}else {
String value = ValueDecoder.decodeIntEntry(entryStore, item);
child.setTextContent(value);
@ -53,27 +50,29 @@ class XMLPluralsDecoder extends BagDecoder{
}
@Override
public boolean canDecode(ResValueBag resValueBag) {
return isResBagPluralsValue(resValueBag);
public boolean canDecode(ResTableMapEntry mapEntry) {
return isResBagPluralsValue(mapEntry);
}
public static boolean isResBagPluralsValue(BaseResValue baseResValue){
ResValueBag resValueBag=(ResValueBag)baseResValue;
int parentId=resValueBag.getParentId();
public static boolean isResBagPluralsValue(ResTableMapEntry valueItem){
int parentId=valueItem.getParentId();
if(parentId!=0){
return false;
}
ResValueBagItem[] bagItems = resValueBag.getBagItems();
ResValueMap[] bagItems = valueItem.listResValueMap();
if(bagItems==null||bagItems.length==0){
return false;
}
int len=bagItems.length;
for(int i=0;i<len;i++){
ResValueBagItem item=bagItems[i];
if(item.getIdHigh()!=0x0100){
ResValueMap item=bagItems[i];
int name = item.getName();
int high = (name >> 16) & 0xffff;
if(high!=0x0100){
return false;
}
PluralsQuantity pq=PluralsQuantity.valueOf(item.getIdLow());
int low = name & 0xffff;
PluralsQuantity pq=PluralsQuantity.valueOf((short) low);
if(pq==null){
return false;
}

View File

@ -26,7 +26,7 @@
import com.reandroid.arsc.item.SpecString;
import com.reandroid.arsc.util.FrameworkTable;
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.ResourceResolver;
@ -41,7 +41,7 @@
private APKLogger apkLogger;
private boolean mForceCreateNamespaces = true;
private Set<String> mFrameworkPackageNames;
private final ResNameMap<EntryBlock> mLocalResNameMap = new ResNameMap<>();
private final ResNameMap<Entry> mLocalResNameMap = new ResNameMap<>();
public EncodeMaterials(){
}
public SpecString getSpecString(String name){
@ -49,7 +49,7 @@
.get(name)
.get(0);
}
public EntryBlock getAttributeBlock(String refString){
public Entry getAttributeBlock(String refString){
String packageName = null;
String type = "attr";
String name = refString;
@ -62,7 +62,7 @@
|| packageName.equals(getCurrentPackageName())
|| !isFrameworkPackageName(packageName)){
return getLocalEntryBlock(type, name);
return getLocalEntry(type, name);
}
return getFrameworkEntry(type, name);
}
@ -105,9 +105,9 @@
", name="+name);
}
public int resolveFrameworkResourceId(String packageName, String type, String name){
EntryBlock entryBlock = getFrameworkEntry(packageName, type, name);
if(entryBlock!=null){
return entryBlock.getResourceId();
Entry entry = getFrameworkEntry(packageName, type, name);
if(entry !=null){
return entry.getResourceId();
}
throw new EncodeException("Framework entry not found: " +
"package="+packageName+
@ -115,9 +115,9 @@
", name="+name);
}
public int resolveFrameworkResourceId(int packageId, String type, String name){
EntryBlock entryBlock = getFrameworkEntry(packageId, type, name);
if(entryBlock!=null){
return entryBlock.getResourceId();
Entry entry = getFrameworkEntry(packageId, type, name);
if(entry !=null){
return entry.getResourceId();
}
throw new EncodeException("Framework entry not found: " +
"packageId="+String.format("0x%02x", packageId)+
@ -141,23 +141,23 @@
}
return null;
}
public EntryBlock getLocalEntryBlock(String type, String name){
EntryBlock entryBlock=mLocalResNameMap.get(type, name);
if(entryBlock!=null){
return entryBlock;
public Entry getLocalEntry(String type, String name){
Entry entry =mLocalResNameMap.get(type, name);
if(entry !=null){
return entry;
}
loadLocalEntryBlockMap(type);
entryBlock=mLocalResNameMap.get(type, name);
if(entryBlock!=null){
return entryBlock;
loadLocalEntryMap(type);
entry =mLocalResNameMap.get(type, name);
if(entry !=null){
return entry;
}
entryBlock= searchLocalEntryBlock(type, name);
if(entryBlock!=null){
mLocalResNameMap.add(type, name, entryBlock);
entry = searchLocalEntry(type, name);
if(entry !=null){
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()){
if(type.equals(entryGroup.getTypeName()) &&
name.equals(entryGroup.getSpecName())){
@ -167,9 +167,9 @@
SpecTypePair specTypePair=currentPackage.searchByTypeName(type);
if(specTypePair!=null){
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
if(name.equals(entryBlock.getName())){
return entryBlock;
for(Entry entry :typeBlock.listEntries(true)){
if(name.equals(entry.getName())){
return entry;
}
}
break;
@ -182,9 +182,9 @@
specTypePair=packageBlock.searchByTypeName(type);
if(specTypePair!=null){
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
if(name.equals(entryBlock.getName())){
return entryBlock;
for(Entry entry :typeBlock.listEntries(true)){
if(name.equals(entry.getName())){
return entry;
}
}
break;
@ -193,25 +193,25 @@
}
return null;
}
private void loadLocalEntryBlockMap(String type){
ResNameMap<EntryBlock> localMap = mLocalResNameMap;
private void loadLocalEntryMap(String type){
ResNameMap<Entry> localMap = mLocalResNameMap;
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
SpecTypePair specTypePair=packageBlock.searchByTypeName(type);
if(specTypePair!=null){
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
localMap.add(entryBlock.getTypeName(),
entryBlock.getName(), entryBlock);
for(Entry entry :typeBlock.listEntries(true)){
localMap.add(entry.getTypeName(),
entry.getName(), entry);
}
}
}
}
}
public EntryBlock getFrameworkEntry(String type, String name){
public Entry getFrameworkEntry(String type, String name){
for(FrameworkTable table:frameworkTables){
EntryBlock entryBlock = table.searchEntryBlock(type, name);
if(entryBlock!=null){
return entryBlock;
Entry entry = table.searchEntry(type, name);
if(entry !=null){
return entry;
}
}
return null;
@ -232,26 +232,26 @@
mFrameworkPackageNames=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(PackageBlock packageBlock:table.listPackages()){
if(packageName.equals(packageBlock.getName())){
EntryBlock entryBlock = table.searchEntryBlock(type, name);
if(entryBlock!=null){
return entryBlock;
Entry entry = table.searchEntry(type, name);
if(entry !=null){
return entry;
}
}
}
}
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(PackageBlock packageBlock:table.listPackages()){
if(packageId==packageBlock.getId()){
EntryBlock entryBlock = table.searchEntryBlock(type, name);
if(entryBlock!=null){
return entryBlock;
Entry entry = table.searchEntry(type, name);
if(entry !=null){
return entry;
}
}
}

View File

@ -22,7 +22,7 @@ package com.reandroid.apk.xmlencoder;
import com.reandroid.apk.UncompressedFiles;
import com.reandroid.arsc.chunk.PackageBlock;
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.XMLSource;
@ -71,12 +71,12 @@ package com.reandroid.apk.xmlencoder;
String name = EncodeUtil.getEntryNameFromResFile(resFile);
int resourceId=materials.resolveLocalResourceId(type, name);
EntryBlock entryBlock=typeBlock
Entry entry =typeBlock
.getOrCreateEntry((short) (0xffff & resourceId));
String path=EncodeUtil.getEntryPathFromResFile(resFile);
entryBlock.setValueAsString(path);
entryBlock.setSpecReference(materials.getSpecString(name));
entry.setValueAsString(path);
entry.setSpecReference(materials.getSpecString(name));
InputSource inputSource=createInputSource(path, resFile);
addInputSource(inputSource);
return inputSource;

View File

@ -15,10 +15,10 @@
*/
package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.array.ResValueMapArray;
import com.reandroid.arsc.chunk.xml.*;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.attribute.AttributeBag;
import com.reandroid.arsc.value.attribute.AttributeValueType;
@ -105,11 +105,11 @@ public class XMLFileEncoder {
}
String name=attribute.getNameWoPrefix();
int resourceId=decodeUnknownAttributeHex(name);
EntryBlock entryBlock=null;
Entry entry =null;
if(resourceId==0){
entryBlock=getAttributeBlock(attribute);
if(entryBlock!=null){
resourceId=entryBlock.getResourceId();
entry =getAttributeBlock(attribute);
if(entry !=null){
resourceId= entry.getResourceId();
}
}
ResXmlAttribute xmlAttribute =
@ -139,9 +139,9 @@ public class XMLFileEncoder {
xmlAttribute.setData(materials.resolveReference(valueText));
continue;
}
if(entryBlock!=null){
if(entry !=null){
AttributeBag attributeBag=AttributeBag
.create((ResValueBag) entryBlock.getResValue());
.create((ResValueMapArray) entry.getTableEntry().getValue());
ValueDecoder.EncodeResult encodeResult =
attributeBag.encodeEnumOrFlagValue(valueText);
@ -205,9 +205,9 @@ public class XMLFileEncoder {
idBuilder.add(id, name);
return;
}
EntryBlock entryBlock = getAttributeBlock(attribute);
if(entryBlock!=null){
idBuilder.add(entryBlock.getResourceId(), entryBlock.getName());
Entry entry = getAttributeBlock(attribute);
if(entry !=null){
idBuilder.add(entry.getResourceId(), entry.getName());
}
}
private int decodeUnknownAttributeHex(String name){
@ -220,7 +220,7 @@ public class XMLFileEncoder {
}
return ValueDecoder.parseHex(name);
}
private EntryBlock getAttributeBlock(XMLAttribute attribute){
private Entry getAttributeBlock(XMLAttribute attribute){
if(attribute instanceof SchemaAttr){
return null;
}

View File

@ -21,7 +21,7 @@ import com.reandroid.arsc.container.SpecTypePair;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.item.SpecString;
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.xml.XMLDocument;
import com.reandroid.xml.XMLElement;
@ -37,7 +37,7 @@ class XMLValuesEncoder {
int count = documentElement.getChildesCount();
typeBlock.getEntryBlockArray().ensureSize(count);
typeBlock.getEntryArray().ensureSize(count);
for(int i=0;i<count;i++){
XMLElement element = documentElement.getChildAt(i);
@ -48,45 +48,46 @@ class XMLValuesEncoder {
String name = element.getAttributeValue("name");
int resourceId = getMaterials()
.resolveLocalResourceId(typeBlock.getTypeName(), name);
EntryBlock entryBlock = typeBlock
Entry entry = typeBlock
.getOrCreateEntry((short) (0xffff & resourceId));
encodeValue(entryBlock, element);
encodeValue(entry, element);
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);
encodeValue(entryBlock, value);
encodeValue(entry, value);
}
void encodeValue(EntryBlock entryBlock, String value){
void encodeValue(Entry entry, String value){
if(EncodeUtil.isEmpty(value)){
encodeNullValue(entryBlock);
encodeNullValue(entry);
}else if(isLiteralEmpty(value)){
encodeLiteralEmptyValue(entryBlock, value);
encodeLiteralEmptyValue(entry, value);
}else if(isBoolean(value)){
encodeBooleanValue(entryBlock, value);
encodeBooleanValue(entry, value);
}else if(ValueDecoder.isReference(value)){
encodeReferenceValue(entryBlock, value);
encodeReferenceValue(entry, value);
}else {
encodeStringValue(entryBlock, value);
encodeStringValue(entry, value);
}
}
void encodeNullValue(EntryBlock entryBlock){
void encodeNullValue(Entry entry){
// Nothing to do
}
void encodeLiteralEmptyValue(EntryBlock entryBlock, String value){
entryBlock.setValueAsRaw(ValueType.NULL, 0);
void encodeLiteralEmptyValue(Entry entry, String value){
entry.setValueAsRaw(ValueType.NULL, 0);
}
void encodeBooleanValue(EntryBlock entryBlock, String value){
entryBlock.setValueAsBoolean("true".equals(value.toLowerCase()));
void encodeBooleanValue(Entry entry, String value){
entry.setValueAsBoolean("true".equals(value.toLowerCase()));
}
void encodeReferenceValue(EntryBlock entryBlock, String value){
void encodeReferenceValue(Entry entry, String 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){
@ -98,7 +99,7 @@ class XMLValuesEncoder {
int highest = specTypePair.getHighestEntryCount();
TypeBlock typeBlock = specTypePair
.getOrCreateTypeBlock(qualifiers);
typeBlock.getEntryBlockArray().ensureSize(highest);
typeBlock.getEntryArray().ensureSize(highest);
return typeBlock;
}
EncodeMaterials getMaterials() {

View File

@ -16,10 +16,10 @@
package com.reandroid.apk.xmlencoder;
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.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.xml.XMLElement;
@ -28,7 +28,7 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
super(materials);
}
@Override
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
void encodeChildes(XMLElement parentElement, ResTableMapEntry mapEntry){
int count = parentElement.getChildesCount();
String tagName = parentElement.getTagName();
boolean force_string = false;
@ -38,12 +38,12 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
}else if(ApkUtil.TAG_INTEGER_ARRAY.equals(tagName)){
force_integer = true;
}
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
ResValueMapArray itemArray = mapEntry.getValue();
for(int i=0;i<count;i++){
XMLElement child=parentElement.getChildAt(i);
ResValueBagItem bagItem = itemArray.get(i);
bagItem.setIdHigh((short) 0x0100);
bagItem.setIdLow((short) (i+1));
ResValueMap bagItem = itemArray.get(i);
bagItem.setNameHigh((short) 0x0100);
bagItem.setNameLow((short) (i+1));
String valueText=child.getTextContent();

View File

@ -15,10 +15,10 @@
*/
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.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.attribute.AttributeBag;
import com.reandroid.arsc.value.attribute.AttributeItemType;
@ -39,21 +39,21 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
return count;
}
@Override
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
encodeAttributes(parentElement, resValueBag);
encodeEnumOrFlag(parentElement, resValueBag);
void encodeChildes(XMLElement parentElement, ResTableMapEntry mapEntry){
encodeAttributes(parentElement, mapEntry);
encodeEnumOrFlag(parentElement, mapEntry);
// TODO: re-check if this is necessary
resValueBag.getEntryBlock().setPublic(true);
mapEntry.getHeader().setPublic(true);
}
private void encodeAttributes(XMLElement parentElement, ResValueBag resValueBag){
ResValueBagItemArray bagItemArray = resValueBag.getResValueBagItemArray();
private void encodeAttributes(XMLElement parentElement, ResTableMapEntry mapEntry){
ResValueMapArray mapArray = mapEntry.getValue();
int bagIndex=0;
ResValueBagItem formatItem = bagItemArray.get(bagIndex);
ResValueMap formatItem = mapArray.get(bagIndex);
formatItem.setIdHigh((short) 0x0100);
formatItem.setIdLow(AttributeItemType.FORMAT.getValue());
formatItem.setNameHigh((short) 0x0100);
formatItem.setNameLow(AttributeItemType.FORMAT.getValue());
formatItem.setValueType(ValueType.INT_DEC);
formatItem.setDataHigh(getChildTypes(parentElement));
@ -75,15 +75,15 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
throw new EncodeException("Unknown attribute: '"+name
+"', on attribute: "+attribute.toString());
}
ResValueBagItem bagItem = bagItemArray.get(bagIndex);
bagItem.setIdHigh((short) 0x0100);
bagItem.setIdLow(itemType.getValue());
ResValueMap bagItem = mapArray.get(bagIndex);
bagItem.setNameHigh((short) 0x0100);
bagItem.setNameLow(itemType.getValue());
bagItem.setValueType(ValueType.INT_DEC);
bagItem.setData(ValueDecoder.parseInteger(attribute.getValue()));
bagIndex++;
}
}
private void encodeEnumOrFlag(XMLElement element, ResValueBag resValueBag){
private void encodeEnumOrFlag(XMLElement element, ResTableMapEntry mapEntry){
int count=element.getChildesCount();
if(count==0){
return;
@ -94,7 +94,7 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
}
EncodeMaterials materials = getMaterials();
ResValueBagItemArray bagItemArray = resValueBag.getResValueBagItemArray();
ResValueMapArray mapArray = mapEntry.getValue();
for(int i=0;i<count;i++){
XMLElement child=element.getChildAt(i);
@ -113,8 +113,8 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
throw new EncodeException("Unknown value for element '"+child.toText()+"'");
}
ResValueBagItem bagItem = bagItemArray.get(i+offset);
bagItem.setId(resourceId);
ResValueMap bagItem = mapArray.get(i+offset);
bagItem.setName(resourceId);
bagItem.setValueType(encodeResult.valueType);
bagItem.setData(encodeResult.value);
}

View File

@ -15,8 +15,8 @@
*/
package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.xml.XMLElement;
class XMLValuesEncoderBag extends XMLValuesEncoder{
@ -24,18 +24,19 @@ class XMLValuesEncoderBag extends XMLValuesEncoder{
super(materials);
}
@Override
void encodeValue(EntryBlock entryBlock, XMLElement element){
ResValueBag resValueBag=new ResValueBag();
entryBlock.setResValue(resValueBag);
void encodeValue(Entry entry, XMLElement element){
ResTableMapEntry tableMapEntry = new ResTableMapEntry();
entry.setTableEntry(tableMapEntry);
String parent=element.getAttributeValue("parent");
if(!EncodeUtil.isEmpty(parent)){
int parentId=getMaterials().resolveReference(parent);
resValueBag.setParentId(parentId);
tableMapEntry.getHeader().setParentId(parentId);
}
resValueBag.setCount(getChildesCount(element));
encodeChildes(element, resValueBag);
tableMapEntry.getValue().setChildesCount(getChildesCount(element));
encodeChildes(element, tableMapEntry);
tableMapEntry.refresh();
}
void encodeChildes(XMLElement element, ResValueBag resValueBag){
void encodeChildes(XMLElement element, ResTableMapEntry mapEntry){
throw new EncodeException("Unimplemented bag type encoder: "
+element.getTagName());

View File

@ -16,21 +16,21 @@
package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.Entry;
class XMLValuesEncoderColor extends XMLValuesEncoder{
XMLValuesEncoderColor(EncodeMaterials materials) {
super(materials);
}
@Override
void encodeStringValue(EntryBlock entryBlock, String value){
void encodeStringValue(Entry entry, String value){
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeColor(value);
if(encodeResult!=null){
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
}else {
// If reaches here the value might be
// 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;
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) {
super(materials);
}
@Override
void encodeStringValue(EntryBlock entryBlock, String value){
void encodeStringValue(Entry entry, String value){
if(ValueDecoder.isReference(value)){
entryBlock.setValueAsReference(getMaterials().resolveReference(value));
entry.setValueAsReference(getMaterials().resolveReference(value));
}else {
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeGuessAny(value);
if(encodeResult!=null){
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
}else {
entryBlock.setValueAsString(ValueDecoder
entry.setValueAsString(ValueDecoder
.unEscapeSpecialCharacter(value));
}
}

View File

@ -16,21 +16,21 @@
package com.reandroid.apk.xmlencoder;
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) {
super(materials);
}
@Override
void encodeStringValue(EntryBlock entryBlock, String value){
void encodeStringValue(Entry entry, String value){
ValueDecoder.EncodeResult encodeResult =
ValueDecoder.encodeDimensionOrFloat(value);
if(encodeResult==null){
encodeResult=ValueDecoder.encodeHexOrInt(value);
}
if(encodeResult!=null){
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
}else {
throw new EncodeException("Unknown dimen value: "+value);
}

View File

@ -15,29 +15,31 @@
*/
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) {
super(materials);
}
@Override
void encodeStringValue(EntryBlock entryBlock, String value){
void encodeStringValue(Entry entry, String value){
throw new EncodeException("Unexpected value for id: "+value);
}
@Override
void encodeNullValue(EntryBlock entryBlock){
entryBlock.setValueAsString("");
setVisibility(entryBlock);
void encodeNullValue(Entry entry){
entry.setValueAsString("");
setVisibility(entry);
}
@Override
void encodeBooleanValue(EntryBlock entryBlock, String value){
super.encodeBooleanValue(entryBlock, value);
setVisibility(entryBlock);
void encodeBooleanValue(Entry entry, String value){
super.encodeBooleanValue(entry, value);
setVisibility(entry);
}
private void setVisibility(EntryBlock entryBlock){
entryBlock.setWeak(true);
entryBlock.setPublic(true);
private void setVisibility(Entry entry){
Header header = entry.getHeader();
header.setWeak(true);
header.setPublic(true);
}
}

View File

@ -16,7 +16,7 @@
package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ValueType;
class XMLValuesEncoderInteger extends XMLValuesEncoder{
@ -24,16 +24,16 @@ class XMLValuesEncoderInteger extends XMLValuesEncoder{
super(materials);
}
@Override
void encodeStringValue(EntryBlock entryBlock, String value){
void encodeStringValue(Entry entry, String value){
value=value.trim();
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)){
entryBlock.setValueAsRaw(ValueType.INT_HEX, ValueDecoder.parseHex(value));
entry.setValueAsRaw(ValueType.INT_HEX, ValueDecoder.parseHex(value));
}else {
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeDimensionOrFloat(value);
if(encodeResult!=null){
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
}else {
throw new EncodeException("Unknown value for type <integer>: '"+value+"'");
}

View File

@ -15,10 +15,10 @@
*/
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.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.plurals.PluralsQuantity;
import com.reandroid.xml.XMLElement;
@ -28,20 +28,20 @@ class XMLValuesEncoderPlurals extends XMLValuesEncoderBag{
super(materials);
}
@Override
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
void encodeChildes(XMLElement parentElement, ResTableMapEntry resValueBag){
int count = parentElement.getChildesCount();
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
ResValueMapArray itemArray = resValueBag.getValue();
for(int i=0;i<count;i++){
XMLElement child=parentElement.getChildAt(i);
ResValueBagItem bagItem = itemArray.get(i);
ResValueMap bagItem = itemArray.get(i);
PluralsQuantity quantity = PluralsQuantity
.value(child.getAttributeValue("quantity"));
if(quantity==null){
throw new EncodeException("Unknown plurals quantity: "
+child.toText());
}
bagItem.setIdHigh((short) 0x0100);
bagItem.setIdLow(quantity.getId());
bagItem.setNameHigh((short) 0x0100);
bagItem.setNameLow(quantity.getId());
String valueText=child.getTextContent();

View File

@ -16,7 +16,7 @@
package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.Entry;
class XMLValuesEncoderString extends XMLValuesEncoder{
XMLValuesEncoderString(EncodeMaterials materials) {
@ -24,15 +24,15 @@ import com.reandroid.arsc.value.EntryBlock;
}
@Override
void encodeStringValue(EntryBlock entryBlock, String value){
entryBlock.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
void encodeStringValue(Entry entry, String value){
entry.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
}
@Override
void encodeNullValue(EntryBlock entryBlock){
entryBlock.setValueAsString("");
void encodeNullValue(Entry entry){
entry.setValueAsString("");
}
@Override
void encodeBooleanValue(EntryBlock entryBlock, String value){
entryBlock.setValueAsString(value);
void encodeBooleanValue(Entry entry, String value){
entry.setValueAsString(value);
}
}

View File

@ -15,12 +15,9 @@
*/
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.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.*;
import com.reandroid.arsc.value.attribute.AttributeBag;
import com.reandroid.arsc.value.attribute.AttributeValueType;
import com.reandroid.xml.XMLElement;
@ -31,12 +28,12 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
super(materials);
}
@Override
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
void encodeChildes(XMLElement parentElement, ResTableMapEntry resValueBag){
int count = parentElement.getChildesCount();
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
ResValueMapArray itemArray = resValueBag.getValue();
for(int i=0;i<count;i++){
XMLElement child=parentElement.getChildAt(i);
ResValueBagItem item = itemArray.get(i);
ResValueMap item = itemArray.get(i);
String name=child.getAttributeValue("name");
int id=decodeUnknownAttributeHex(name);
if(id!=0){
@ -55,7 +52,7 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
continue;
}
EntryBlock attributeEntry=getMaterials()
Entry attributeEntry=getMaterials()
.getAttributeBlock(name);
if(attributeEntry==null){
throw new EncodeException("Unknown attribute name: '"+child.toText()
@ -74,11 +71,12 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
}
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
.create((ResValueBag) attributeEntry.getResValue());
.create(tableEntry.getValue());
String valueText=child.getTextContent();
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.IntegerItem;
import com.reandroid.arsc.value.BaseResValue;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueInt;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.arsc.value.Entry;
import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONArray;
import com.reandroid.json.JSONObject;
@ -28,41 +25,41 @@ import com.reandroid.json.JSONObject;
import java.util.Iterator;
public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSONConvert<JSONArray> {
public EntryBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
public class EntryArray extends OffsetBlockArray<Entry> implements JSONConvert<JSONArray> {
public EntryArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
super(offsets, itemCount, itemStart);
}
public boolean isEmpty(){
return !iterator(true).hasNext();
}
public void setEntry(short entryId, EntryBlock entryBlock){
setItem(0xffff & entryId, entryBlock);
public void setEntry(short entryId, Entry entry){
setItem(0xffff & entryId, entry);
}
public EntryBlock getOrCreate(short entryId){
public Entry getOrCreate(short entryId){
int id = 0xffff & entryId;
EntryBlock entryBlock=get(id);
if(entryBlock!=null){
return entryBlock;
Entry entry =get(id);
if(entry !=null){
return entry;
}
int count=id+1;
ensureSize(count);
refreshCount();
return get(id);
}
public EntryBlock get(short entryId){
public Entry get(short entryId){
int index = 0xffff & entryId;
return super.get(index);
}
public EntryBlock getEntry(short entryId){
public Entry getEntry(short entryId){
return get(0xffff & entryId);
}
@Override
public EntryBlock newInstance() {
return new EntryBlock();
public Entry newInstance() {
return new Entry();
}
@Override
public EntryBlock[] newInstance(int len) {
return new EntryBlock[len];
public Entry[] newInstance(int len) {
return new Entry[len];
}
/**
@ -70,13 +67,13 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
* Lets depreciate to warn developer
*/
@Deprecated
public EntryBlock searchByEntryName(String entryName){
public Entry searchByEntryName(String entryName){
if(entryName==null){
return null;
}
for(EntryBlock entryBlock:listItems()){
if(entryName.equals(entryBlock.getName())){
return entryBlock;
for(Entry entry:listItems()){
if(entryName.equals(entry.getName())){
return entry;
}
}
return null;
@ -85,12 +82,12 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
public JSONArray toJson() {
JSONArray jsonArray=new JSONArray();
int index=0;
for(EntryBlock entryBlock:listItems()){
JSONObject childObject = entryBlock.toJson();
for(Entry entry :listItems()){
JSONObject childObject = entry.toJson();
if(childObject==null){
continue;
}
childObject.put(NAME_id, entryBlock.getIndex());
childObject.put(NAME_id, entry.getIndex());
jsonArray.put(index, childObject);
index++;
}
@ -108,20 +105,20 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
}
int id=jsonObject.getInt(NAME_id);
ensureSize(id+1);
EntryBlock entryBlock=get(id);
entryBlock.fromJson(jsonObject);
Entry entry =get(id);
entry.fromJson(jsonObject);
}
refreshCountAndStart();
}
public void merge(EntryBlockArray entryBlockArray){
if(entryBlockArray==null||entryBlockArray==this||entryBlockArray.isEmpty()){
public void merge(EntryArray entryArray){
if(entryArray ==null|| entryArray ==this|| entryArray.isEmpty()){
return;
}
ensureSize(entryBlockArray.childesCount());
Iterator<EntryBlock> itr=entryBlockArray.iterator(true);
ensureSize(entryArray.childesCount());
Iterator<Entry> itr = entryArray.iterator(true);
while (itr.hasNext()){
EntryBlock comingBlock=itr.next();
EntryBlock existingBlock=get(comingBlock.getIndex());
Entry comingBlock = itr.next();
Entry existingBlock = get(comingBlock.getIndex());
existingBlock.merge(comingBlock);
}
}

View File

@ -16,33 +16,35 @@
package com.reandroid.arsc.array;
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.JSONArray;
public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements JSONConvert<JSONArray> {
public ResValueBagItemArray(){
public class ResValueMapArray extends BlockArray<ResValueMap> implements JSONConvert<JSONArray> {
public ResValueMapArray(){
super();
}
@Override
public ResValueBagItem newInstance() {
return new ResValueBagItem();
public ResValueMap newInstance() {
return new ResValueMap();
}
@Override
public ResValueBagItem[] newInstance(int len) {
return new ResValueBagItem[len];
public ResValueMap[] newInstance(int len) {
return new ResValueMap[len];
}
@Override
protected void onRefreshed() {
}
public void onRemoved(){
for(ResValueMap resValueMap:listItems()){
resValueMap.onRemoved();
}
}
@Override
public void clearChildes(){
for(ResValueBagItem bagItem:listItems()){
bagItem.onRemoved();
}
this.onRemoved();
super.clearChildes();
}
@Override
@ -51,7 +53,7 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
if(isNull()){
return jsonArray;
}
ResValueBagItem[] childes = getChildes();
ResValueMap[] childes = getChildes();
for(int i=0;i<childes.length;i++){
jsonArray.put(i, childes[i].toJson());
}
@ -69,7 +71,7 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
get(i).fromJson(json.getJSONObject(i));
}
}
public void merge(ResValueBagItemArray bagItemArray){
public void merge(ResValueMapArray bagItemArray){
if(bagItemArray==null||bagItemArray==this){
return;
}
@ -77,8 +79,8 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
int count=bagItemArray.childesCount();
ensureSize(count);
for(int i=0;i<count;i++){
ResValueBagItem coming=bagItemArray.get(i);
ResValueBagItem exist=get(i);
ResValueMap coming=bagItemArray.get(i);
ResValueMap exist=get(i);
exist.merge(coming);
}
}

View File

@ -18,7 +18,7 @@ package com.reandroid.arsc.array;
import com.reandroid.arsc.base.BlockArray;
import com.reandroid.arsc.chunk.TypeBlock;
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.json.JSONConvert;
import com.reandroid.json.JSONArray;
@ -62,11 +62,11 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair>
}
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);
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);
if(typeBlock==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.io.BlockReader;
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.json.JSONConvert;
import com.reandroid.json.JSONArray;
@ -58,7 +58,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
trimNullBlocks();
}
}
public EntryBlock getOrCreateEntry(short entryId, String qualifiers){
public Entry getOrCreateEntry(short entryId, String qualifiers){
TypeBlock typeBlock=getOrCreate(qualifiers);
return typeBlock.getOrCreateEntry(entryId);
}
@ -70,7 +70,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
}
return true;
}
public EntryBlock getEntry(short entryId, String qualifiers){
public Entry getEntry(short entryId, String qualifiers){
TypeBlock typeBlock=getTypeBlock(qualifiers);
if(typeBlock==null){
return null;
@ -243,7 +243,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
public int getHighestEntryCount(){
int result=0;
for(TypeBlock typeBlock:getChildes()){
int count=typeBlock.getEntryBlockArray().childesCount();
int count=typeBlock.getEntryArray().childesCount();
if(count>result){
result=count;
}
@ -303,7 +303,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
* Lets depreciate to warn developer
*/
@Deprecated
public EntryBlock searchByEntryName(String entryName){
public Entry searchByEntryName(String entryName){
if(entryName==null){
return null;
}

View File

@ -24,13 +24,11 @@ package com.reandroid.arsc.chunk;
import com.reandroid.arsc.container.SpecTypePair;
import com.reandroid.arsc.group.EntryGroup;
import com.reandroid.arsc.header.PackageHeader;
import com.reandroid.arsc.item.ReferenceItem;
import com.reandroid.arsc.list.OverlayableList;
import com.reandroid.arsc.list.StagedAliasList;
import com.reandroid.arsc.pool.SpecStringPool;
import com.reandroid.arsc.pool.TableStringPool;
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.ResConfig;
import com.reandroid.arsc.value.StagedAliasEntry;
@ -42,7 +40,9 @@ package com.reandroid.arsc.chunk;
public class PackageBlock extends Chunk<PackageHeader>
implements JSONConvert<JSONObject>, Comparable<PackageBlock> {
implements ParentChunk,
JSONConvert<JSONObject>,
Comparable<PackageBlock> {
private final TypeStringPool mTypeStringPool;
private final SpecStringPool mSpecStringPool;
@ -66,12 +66,12 @@ package com.reandroid.arsc.chunk;
addChild(mSpecStringPool);
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.parseQualifiers(qualifiers);
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);
TypeBlock typeBlock = specTypePair.getOrCreateTypeBlock(resConfig);
return typeBlock.getOrCreateEntry(name);
@ -158,6 +158,7 @@ package com.reandroid.arsc.chunk;
public TypeStringPool getTypeStringPool(){
return mTypeStringPool;
}
@Override
public SpecStringPool getSpecStringPool(){
return mSpecStringPool;
}
@ -185,10 +186,10 @@ package com.reandroid.arsc.chunk;
public Set<Integer> listResourceIds(){
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);
}
public EntryBlock getEntry(byte typeId, short entryId, String qualifiers){
public Entry getEntry(byte typeId, short entryId, String qualifiers){
return getSpecTypePairArray().getEntry(typeId, entryId, qualifiers);
}
public TypeBlock getOrCreateTypeBlock(byte typeId, String qualifiers){
@ -223,48 +224,38 @@ package com.reandroid.arsc.chunk;
}
return null;
}
public void updateEntry(EntryBlock entryBlock){
if(entryBlock==null||entryBlock.isNull()){
public void updateEntry(Entry entry){
if(entry ==null|| entry.isNull()){
return;
}
updateEntryGroup(entryBlock);
updateEntryTableReferences(entryBlock);
updateEntryGroup(entry);
}
public void removeEntryGroup(EntryBlock entryBlock){
if(entryBlock==null){
public void removeEntryGroup(Entry entry){
if(entry ==null){
return;
}
int id=entryBlock.getResourceId();
int id= entry.getResourceId();
EntryGroup group=getEntriesGroupMap().get(id);
if(group==null){
return;
}
group.remove(entryBlock);
group.remove(entry);
if(group.size()==0){
getEntriesGroupMap().remove(id);
}
}
private void updateEntryTableReferences(EntryBlock entryBlock){
TableBlock tableBlock=getTableBlock();
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();
private void updateEntryGroup(Entry entry){
int resId= entry.getResourceId();
EntryGroup group=getEntriesGroupMap().get(resId);
if(group==null){
group=new EntryGroup(resId);
getEntriesGroupMap().put(resId, group);
}
group.add(entryBlock);
group.add(entry);
}
public List<EntryBlock> listEntries(byte typeId, int entryId){
List<EntryBlock> results=new ArrayList<>();
public List<Entry> listEntries(byte typeId, int entryId){
List<Entry> results=new ArrayList<>();
for(SpecTypePair pair:listSpecTypePair(typeId)){
results.addAll(pair.listEntries(entryId));
}
@ -304,8 +295,8 @@ package com.reandroid.arsc.chunk;
//getHeaderBlock().getTypeIdOffset().set(count-largest);
getHeaderBlock().getTypeIdOffsetItem().set(0);
}
public void onEntryAdded(EntryBlock entryBlock){
updateEntry(entryBlock);
public void onEntryAdded(Entry entry){
updateEntry(entry);
}
@Override
public void onChunkLoaded() {

View File

@ -15,7 +15,7 @@
*/
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.container.SpecTypePair;
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.item.*;
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.ValueType;
import com.reandroid.json.JSONConvert;
@ -38,14 +38,14 @@ import java.util.List;
public class TypeBlock extends Chunk<TypeHeader>
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
private final EntryBlockArray mEntryArray;
private final EntryArray mEntryArray;
private TypeString mTypeString;
public TypeBlock() {
super(new TypeHeader(), 2);
TypeHeader header = getHeaderBlock();
IntegerArray entryOffsets = new IntegerArray();
this.mEntryArray = new EntryBlockArray(entryOffsets,
this.mEntryArray = new EntryArray(entryOffsets,
header.getCount(), header.getEntriesStart());
header.getFlags().setBlockLoad(this);
@ -122,7 +122,7 @@ public class TypeBlock extends Chunk<TypeHeader>
onSetEntryCount(count);
}
public boolean isEmpty(){
return getEntryBlockArray().isEmpty();
return getEntryArray().isEmpty();
}
public boolean isDefault(){
return getResConfig().isDefault();
@ -134,7 +134,7 @@ public class TypeBlock extends Chunk<TypeHeader>
getResConfig().parseQualifiers(qualifiers);
}
public int countNonNullEntries(){
return getEntryBlockArray().countNonNull();
return getEntryArray().countNonNull();
}
public SpecTypePair getParentSpecTypePair(){
Block parent=getParent();
@ -148,29 +148,29 @@ public class TypeBlock extends Chunk<TypeHeader>
}
public void cleanEntries(){
PackageBlock packageBlock=getPackageBlock();
List<EntryBlock> allEntries=listEntries(true);
for(EntryBlock entryBlock:allEntries){
List<Entry> allEntries=listEntries(true);
for(Entry entry :allEntries){
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();
if(packageBlock!=null){
packageBlock.removeEntryGroup(entryBlock);
packageBlock.removeEntryGroup(entry);
}
entryBlock.setNull(true);
entry.setNull(true);
}
public EntryBlock getOrCreateEntry(String name){
for(EntryBlock entryBlock:getEntryBlockArray().listItems()){
if(name.equals(entryBlock.getName())){
return entryBlock;
public Entry getOrCreateEntry(String name){
for(Entry entry : getEntryArray().listItems()){
if(name.equals(entry.getName())){
return entry;
}
}
SpecTypePair specTypePair = getParentSpecTypePair();
EntryBlock exist=specTypePair.getAnyEntry(name);
Entry exist=specTypePair.getAnyEntry(name);
int id;
if(exist!=null){
id=exist.getIndex();
@ -179,47 +179,47 @@ public class TypeBlock extends Chunk<TypeHeader>
}
SpecString specString = getPackageBlock()
.getSpecStringPool().getOrCreate(name);
EntryBlock entryBlock = getOrCreateEntry((short) id);
if(entryBlock.isNull()){
entryBlock.setValueAsRaw(ValueType.NULL, 0);
Entry entry = getOrCreateEntry((short) id);
if(entry.isNull()){
entry.setValueAsRaw(ValueType.NULL, 0);
}
entryBlock.setSpecReference(specString.getIndex());
return entryBlock;
entry.setSpecReference(specString.getIndex());
return entry;
}
public EntryBlock getOrCreateEntry(short entryId){
return getEntryBlockArray().getOrCreate(entryId);
public Entry getOrCreateEntry(short entryId){
return getEntryArray().getOrCreate(entryId);
}
public EntryBlock getEntry(short entryId){
return getEntryBlockArray().getEntry(entryId);
public Entry getEntry(short entryId){
return getEntryArray().getEntry(entryId);
}
public ResConfig getResConfig(){
return getHeaderBlock().getConfig();
}
public EntryBlockArray getEntryBlockArray(){
public EntryArray getEntryArray(){
return mEntryArray;
}
public List<EntryBlock> listEntries(){
public List<Entry> listEntries(){
return listEntries(false);
}
public List<EntryBlock> listEntries(boolean skipNullBlock){
List<EntryBlock> results=new ArrayList<>();
Iterator<EntryBlock> itr = getEntryBlockArray().iterator(skipNullBlock);
public List<Entry> listEntries(boolean skipNullBlock){
List<Entry> results=new ArrayList<>();
Iterator<Entry> itr = getEntryArray().iterator(skipNullBlock);
while (itr.hasNext()){
EntryBlock block=itr.next();
Entry block=itr.next();
results.add(block);
}
return results;
}
public EntryBlock getEntryBlock(int entryId){
return getEntryBlockArray().get(entryId);
public Entry getEntry(int entryId){
return getEntryArray().get(entryId);
}
private void onSetEntryCount(int count) {
getEntryBlockArray().setChildesCount(count);
getEntryArray().setChildesCount(count);
}
@Override
protected void onChunkRefreshed() {
getEntryBlockArray().refreshCountAndStart();
getEntryArray().refreshCountAndStart();
}
@Override
protected void onPreRefreshRefresh(){
@ -246,7 +246,7 @@ public class TypeBlock extends Chunk<TypeHeader>
jsonObject.put(NAME_id, getId());
jsonObject.put(NAME_name, getTypeName());
jsonObject.put(NAME_config, getResConfig().toJson());
jsonObject.put(NAME_entries, getEntryBlockArray().toJson());
jsonObject.put(NAME_entries, getEntryArray().toJson());
return jsonObject;
}
@Override
@ -256,7 +256,7 @@ public class TypeBlock extends Chunk<TypeHeader>
if(name!=null){
setTypeName(name);
}
getEntryBlockArray()
getEntryArray()
.fromJson(json.getJSONArray(NAME_entries));
getResConfig()
.fromJson(json.getJSONObject(NAME_config));
@ -270,7 +270,7 @@ public class TypeBlock extends Chunk<TypeHeader>
+getTypeId()+"!="+typeBlock.getTypeId());
}
setTypeName(typeBlock.getTypeName());
getEntryBlockArray().merge(typeBlock.getEntryBlockArray());
getEntryArray().merge(typeBlock.getEntryArray());
}
@Override
public int compareTo(TypeBlock typeBlock) {
@ -286,8 +286,8 @@ public class TypeBlock extends Chunk<TypeHeader>
* Lets depreciate to warn developer
*/
@Deprecated
public EntryBlock searchByEntryName(String entryName){
return getEntryBlockArray().searchByEntryName(entryName);
public Entry searchByEntryName(String entryName){
return getEntryArray().searchByEntryName(entryName);
}
@Override
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.ChunkType;
import com.reandroid.arsc.chunk.MainChunk;
import com.reandroid.arsc.chunk.ParentChunk;
import com.reandroid.arsc.container.SingleBlockContainer;
import com.reandroid.arsc.header.HeaderBlock;
import com.reandroid.arsc.io.BlockReader;
import com.reandroid.arsc.pool.ResXmlStringPool;
import com.reandroid.arsc.pool.StringPool;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.common.EntryStore;
import com.reandroid.json.JSONArray;
@ -38,7 +40,7 @@
import java.util.Set;
public class ResXmlDocument extends Chunk<HeaderBlock>
implements MainChunk, JSONConvert<JSONObject> {
implements MainChunk, ParentChunk, JSONConvert<JSONObject> {
private final ResXmlStringPool mResXmlStringPool;
private final ResXmlIDMap mResXmlIDMap;
private ResXmlElement mResXmlElement;
@ -166,6 +168,10 @@
public ResXmlStringPool getStringPool(){
return mResXmlStringPool;
}
@Override
public StringPool<?> getSpecStringPool() {
return null;
}
public ResXmlIDMap getResXmlIDMap(){
return mResXmlIDMap;
}

View File

@ -16,13 +16,13 @@
package com.reandroid.arsc.container;
import com.reandroid.arsc.base.BlockContainer;
import com.reandroid.arsc.value.BaseResValue;
import com.reandroid.arsc.value.ValueItem;
public class ResValueContainer extends BlockContainer<BaseResValue> {
private final BaseResValue[] mChildes;
public class ResValueContainer extends BlockContainer<ValueItem> {
private final ValueItem[] mChildes;
public ResValueContainer(){
super();
mChildes=new BaseResValue[1];
mChildes=new ValueItem[1];
}
@Override
protected void onRefreshed(){
@ -32,11 +32,11 @@ public class ResValueContainer extends BlockContainer<BaseResValue> {
return mChildes.length;
}
@Override
public BaseResValue[] getChildes() {
public ValueItem[] getChildes() {
return mChildes;
}
public void setResValue(BaseResValue resValue){
BaseResValue old=getResValue();
public void setResValue(ValueItem resValue){
ValueItem old=getResValue();
if(old!=null){
old.setIndex(-1);
old.setParent(null);
@ -48,7 +48,7 @@ public class ResValueContainer extends BlockContainer<BaseResValue> {
resValue.setIndex(0);
resValue.setParent(this);
}
public BaseResValue getResValue(){
public ValueItem getResValue(){
if(mChildes.length==0){
return null;
}

View File

@ -25,7 +25,7 @@ import com.reandroid.arsc.chunk.TypeBlock;
import com.reandroid.arsc.header.HeaderBlock;
import com.reandroid.arsc.io.BlockReader;
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.json.JSONConvert;
import com.reandroid.json.JSONObject;
@ -53,11 +53,11 @@ public class SpecTypePair extends BlockContainer<Block>
public SpecTypePair(){
this(new SpecBlock(), new TypeBlockArray());
}
public EntryBlock getAnyEntry(String name){
public Entry getAnyEntry(String name){
for(TypeBlock typeBlock:listTypeBlocks()){
EntryBlock entryBlock=typeBlock.searchByEntryName(name);
if(entryBlock!=null){
return entryBlock;
Entry entry =typeBlock.searchByEntryName(name);
if(entry !=null){
return entry;
}
}
return null;
@ -74,10 +74,10 @@ public class SpecTypePair extends BlockContainer<Block>
public int countTypeBlocks(){
return getTypeBlockArray().childesCount();
}
public EntryBlock getOrCreateEntry(short entryId, String qualifiers){
public Entry getOrCreateEntry(short entryId, String 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);
}
public TypeBlock getOrCreateTypeBlock(String qualifiers){
@ -115,7 +115,7 @@ public class SpecTypePair extends BlockContainer<Block>
* Lets depreciate to warn developer
*/
@Deprecated
public EntryBlock searchByEntryName(String entryName){
public Entry searchByEntryName(String entryName){
return getTypeBlockArray().searchByEntryName(entryName);
}
public SpecBlock getSpecBlock(){
@ -134,16 +134,16 @@ public class SpecTypePair extends BlockContainer<Block>
}
return null;
}
public List<EntryBlock> listEntries(int entryId){
List<EntryBlock> results=new ArrayList<>();
public List<Entry> listEntries(int entryId){
List<Entry> results=new ArrayList<>();
Iterator<TypeBlock> itr = mTypeBlockArray.iterator(true);
while (itr.hasNext()){
TypeBlock typeBlock=itr.next();
EntryBlock entryBlock=typeBlock.getEntryBlock(entryId);
if(entryBlock==null||entryBlock.isNull()){
Entry entry = typeBlock.getEntry(entryId);
if(entry ==null|| entry.isNull()){
continue;
}
results.add(entryBlock);
results.add(entry);
}
return results;
}

View File

@ -242,14 +242,14 @@ import java.util.regex.Pattern;
if(entryGroup==null){
return String.format("@0x%08x", resourceId);
}
EntryBlock entryBlock=entryGroup.pickOne();
if(entryBlock==null){
Entry entry =entryGroup.pickOne();
if(entry ==null){
return String.format("@0x%08x", resourceId);
}
String prefix=null;
if(currentPackage!=null){
String name=currentPackage.getName();
String other=entryBlock.getPackageBlock().getName();
String other= entry.getPackageBlock().getName();
if(!name.equals(other)){
prefix=other+":";
}
@ -300,34 +300,34 @@ import java.util.regex.Pattern;
}
return decode(valueType, data);
}
public static String decodeIntEntry(EntryStore store, EntryBlock entryBlock){
if(entryBlock==null){
public static String decodeIntEntry(EntryStore store, Entry entry){
if(entry ==null){
return null;
}
BaseResValue baseResValue = entryBlock.getResValue();
if(!(baseResValue instanceof ResValueInt)){
TableEntry<?, ?> tableEntry = entry.getTableEntry();
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
return null;
}
ResValueInt resValueInt=(ResValueInt)baseResValue;
return decodeIntEntry(store, resValueInt);
ResValue resValue =(ResValue) tableEntry.getValue();
return decodeIntEntry(store, resValue);
}
public static String decodeIntEntry(EntryStore store, ResValueInt resValueInt){
if(resValueInt==null){
public static String decodeIntEntry(EntryStore store, ResValue resValue){
if(resValue ==null){
return null;
}
EntryBlock parentEntry=resValueInt.getEntryBlock();
Entry parentEntry = resValue.getEntry();
if(parentEntry==null){
return null;
}
ValueType valueType=resValueInt.getValueType();
int data=resValueInt.getData();
ValueType valueType= resValue.getValueType();
int data= resValue.getData();
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){
return null;
}
EntryBlock parentEntry=bagItem.getEntryBlock();
Entry parentEntry=bagItem.getEntry();
if(parentEntry==null){
return null;
}
@ -335,7 +335,7 @@ import java.util.regex.Pattern;
int data=bagItem.getData();
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){
return "@empty";
}
@ -367,18 +367,18 @@ import java.util.regex.Pattern;
}
return decode(valueType, data);
}
public static String buildReferenceValue(EntryStore store, EntryBlock entryBlock){
if(entryBlock==null){
public static String buildReferenceValue(EntryStore store, Entry entry){
if(entry ==null){
return null;
}
BaseResValue baseResValue = entryBlock.getResValue();
if(!(baseResValue instanceof ResValueInt)){
TableEntry<?, ?> tableEntry = entry.getTableEntry();
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
return null;
}
ResValueInt resValueInt=(ResValueInt)baseResValue;
int resourceId=resValueInt.getData();
ValueType valueType=resValueInt.getValueType();
return buildReferenceValue(store, entryBlock, valueType, resourceId);
ResValue resValue =(ResValue) tableEntry.getValue();
int resourceId= resValue.getData();
ValueType valueType= resValue.getValueType();
return buildReferenceValue(store, entry, valueType, resourceId);
}
public static String decode(EntryStore entryStore, int currentPackageId, int nameResourceId, ValueType valueType, int rawVal){
String currPackageName=getPackageName(entryStore, currentPackageId);
@ -446,17 +446,17 @@ import java.util.regex.Pattern;
return builder.toString();
}
private static String buildReferenceValue(EntryStore store, EntryBlock entryBlock, ValueType valueType, int resourceId){
if(entryBlock==null){
private static String buildReferenceValue(EntryStore store, Entry entry, ValueType valueType, int resourceId){
if(entry ==null){
return null;
}
EntryGroup value=searchEntryGroup(store, entryBlock, resourceId);
EntryGroup value=searchEntryGroup(store, entry, resourceId);
if(value==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;
if(valueType==ValueType.REFERENCE){
atOrQues='@';
@ -465,7 +465,7 @@ import java.util.regex.Pattern;
}else {
atOrQues=0;
}
String currentPackageName=getPackageName(entryBlock);
String currentPackageName=getPackageName(entry);
String referredPackageName=getPackageName(value);
String typeName=value.getTypeName();
String name=value.getSpecName();
@ -524,18 +524,18 @@ import java.util.regex.Pattern;
}
return getPackageName(entryGroup.pickOne());
}
private static String getPackageName(EntryBlock entryBlock){
if(entryBlock==null){
private static String getPackageName(Entry entry){
if(entry ==null){
return null;
}
PackageBlock packageBlock=entryBlock.getPackageBlock();
PackageBlock packageBlock= entry.getPackageBlock();
if(packageBlock==null){
return null;
}
return packageBlock.getName();
}
private static EntryGroup searchEntryGroup(EntryStore store, EntryBlock entryBlock, int resourceId){
EntryGroup entryGroup=searchEntryGroup(entryBlock, resourceId);
private static EntryGroup searchEntryGroup(EntryStore store, Entry entry, int resourceId){
EntryGroup entryGroup=searchEntryGroup(entry, resourceId);
if(entryGroup!=null){
return entryGroup;
}
@ -544,11 +544,11 @@ import java.util.regex.Pattern;
}
return store.getEntryGroup(resourceId);
}
private static EntryGroup searchEntryGroup(EntryBlock entryBlock, int resourceId){
if(entryBlock==null){
private static EntryGroup searchEntryGroup(Entry entry, int resourceId){
if(entry ==null){
return null;
}
PackageBlock packageBlock=entryBlock.getPackageBlock();
PackageBlock packageBlock= entry.getPackageBlock();
if(packageBlock==null){
return null;
}
@ -581,11 +581,11 @@ import java.util.regex.Pattern;
}
return null;
}
private static String decodeIntEntryString(EntryBlock entryBlock, int data){
if(entryBlock==null){
private static String decodeIntEntryString(Entry entry, int data){
if(entry ==null){
return null;
}
PackageBlock packageBlock=entryBlock.getPackageBlock();
PackageBlock packageBlock= entry.getPackageBlock();
if(packageBlock==null){
return null;
}
@ -719,9 +719,9 @@ import java.util.regex.Pattern;
}
return 0;
}
private static String getResourceName(EntryStore store, EntryBlock entryBlock, int resourceId){
if(entryBlock!=null){
EntryGroup group=searchEntryGroup(entryBlock, resourceId);
private static String getResourceName(EntryStore store, Entry entry, int resourceId){
if(entry !=null){
EntryGroup group=searchEntryGroup(entry, resourceId);
if(group!=null){
String name=group.getSpecName();
if(name!=null){
@ -748,58 +748,58 @@ import java.util.regex.Pattern;
return null;
}
private static AttributeBag getAttributeBag(EntryStore store, int resourceId){
ResValueBag resValueBag=getAttributeValueBag(store, resourceId);
if(resValueBag==null){
ResTableMapEntry mapEntry=getAttributeValueBag(store, resourceId);
if(mapEntry==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){
return null;
}
Collection<EntryGroup> foundGroups = store.getEntryGroups(resourceId);
ResValueBag best=null;
ResTableMapEntry best=null;
for(EntryGroup group:foundGroups){
ResValueBag valueBag= getAttributeValueBag(group);
ResTableMapEntry valueBag = getAttributeValueBag(group);
best=chooseBest(best, valueBag);
}
return best;
}
private static ResValueBag getAttributeValueBag(EntryGroup entryGroup){
private static ResTableMapEntry getAttributeValueBag(EntryGroup entryGroup){
if(entryGroup==null){
return null;
}
ResValueBag best=null;
Iterator<EntryBlock> iterator=entryGroup.iterator(true);
ResTableMapEntry best=null;
Iterator<Entry> iterator=entryGroup.iterator(true);
while (iterator.hasNext()){
EntryBlock entryBlock=iterator.next();
ResValueBag valueBag= getAttributeValueBag(entryBlock);
Entry entry =iterator.next();
ResTableMapEntry valueBag = getAttributeValueBag(entry);
best=chooseBest(best, valueBag);
}
return best;
}
private static ResValueBag getAttributeValueBag(EntryBlock entryBlock){
if(entryBlock==null){
private static ResTableMapEntry getAttributeValueBag(Entry entry){
if(entry ==null){
return null;
}
BaseResValue baseResValue = entryBlock.getResValue();
if(baseResValue instanceof ResValueBag){
return (ResValueBag) baseResValue;
TableEntry<?, ?> tableEntry = entry.getTableEntry();
if(tableEntry instanceof ResTableMapEntry){
return (ResTableMapEntry) tableEntry;
}
return null;
}
private static ResValueBag chooseBest(ResValueBag valueBag1, ResValueBag valueBag2){
if(valueBag1==null){
return valueBag2;
private static ResTableMapEntry chooseBest(ResTableMapEntry entry1, ResTableMapEntry entry2){
if(entry1==null){
return entry2;
}
if(valueBag2==null){
return valueBag1;
if(entry2==null){
return entry1;
}
if(valueBag2.getCount()>valueBag1.getCount()){
return valueBag2;
if(entry2.getValue().childesCount()>entry1.getValue().childesCount()){
return entry2;
}
return valueBag1;
return entry1;
}
private static String toHexResourceId(int 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.TypeString;
import com.reandroid.arsc.pool.SpecStringPool;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.Entry;
import java.util.Iterator;
public class EntryGroup extends ItemGroup<EntryBlock> {
public class EntryGroup extends ItemGroup<Entry> {
private final int resourceId;
public EntryGroup(int resId) {
super(create(), String.format("0x%08x", resId));
@ -35,7 +35,7 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
return resourceId;
}
public boolean renameSpec(String name){
EntryBlock[] items=getItems();
Entry[] items=getItems();
if(items==null || name==null){
return false;
}
@ -56,25 +56,25 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
return (short) (getResourceId() & 0xffff);
}
private boolean isAllSameSpec(){
EntryBlock first=null;
for(EntryBlock entryBlock:listItems()){
Entry first=null;
for(Entry entry :listItems()){
if(first==null){
first=entryBlock;
first= entry;
continue;
}
if(first.getSpecReference()!=entryBlock.getSpecReference()){
if(first.getSpecReference()!= entry.getSpecReference()){
return false;
}
}
return true;
}
public boolean renameSpec(int specReference){
EntryBlock[] items=getItems();
Entry[] items=getItems();
if(items==null){
return false;
}
boolean renameOk=false;
for(EntryBlock block:items){
for(Entry block:items){
if(block==null){
continue;
}
@ -86,45 +86,45 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
}
return renameOk;
}
public EntryBlock pickOne(){
EntryBlock[] items=getItems();
public Entry pickOne(){
Entry[] items=getItems();
if(items==null){
return null;
}
EntryBlock result = null;
for(EntryBlock entryBlock:items){
if(entryBlock==null){
Entry result = null;
for(Entry entry :items){
if(entry ==null){
continue;
}
if(result==null || result.isNull()){
result=entryBlock;
}else if(entryBlock.isDefault()){
return entryBlock;
result= entry;
}else if(entry.isDefault()){
return entry;
}
}
return result;
}
public EntryBlock getDefault(){
Iterator<EntryBlock> itr=iterator(true);
public Entry getDefault(){
Iterator<Entry> itr=iterator(true);
while (itr.hasNext()){
EntryBlock entryBlock=itr.next();
if(entryBlock.isDefault()){
return entryBlock;
Entry entry =itr.next();
if(entry.isDefault()){
return entry;
}
}
return null;
}
public TypeString getTypeString(){
EntryBlock entryBlock=pickOne();
if(entryBlock!=null){
return entryBlock.getTypeString();
Entry entry =pickOne();
if(entry !=null){
return entry.getTypeString();
}
return null;
}
public SpecString getSpecString(){
EntryBlock entryBlock=pickOne();
if(entryBlock!=null){
return entryBlock.getSpecString();
Entry entry =pickOne();
if(entry !=null){
return entry.getSpecString();
}
return null;
}
@ -143,11 +143,11 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
return specString.get();
}
private SpecStringPool getSpecStringPool(){
EntryBlock entryBlock=get(0);
if(entryBlock==null){
Entry entry =get(0);
if(entry ==null){
return null;
}
TypeBlock typeBlock=entryBlock.getTypeBlock();
TypeBlock typeBlock= entry.getTypeBlock();
if(typeBlock==null){
return null;
}
@ -159,22 +159,22 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
}
@Override
public String toString(){
EntryBlock entryBlock=pickOne();
if(entryBlock==null){
Entry entry =pickOne();
if(entry ==null){
return super.toString();
}
return super.toString()+"{"+entryBlock.toString()+"}";
return super.toString()+"{"+ entry.toString()+"}";
}
private static BlockArrayCreator<EntryBlock> create(){
return new BlockArrayCreator<EntryBlock>(){
private static BlockArrayCreator<Entry> create(){
return new BlockArrayCreator<Entry>(){
@Override
public EntryBlock newInstance() {
return new EntryBlock();
public Entry newInstance() {
return new Entry();
}
@Override
public EntryBlock[] newInstance(int len) {
return new EntryBlock[len];
public Entry[] newInstance(int len) {
return new Entry[len];
}
};
}

View File

@ -42,6 +42,7 @@ import java.util.Objects;
}
public List<T> listItems(){
return new AbstractList<T>() {
private final int mSize = ItemGroup.this.size();
@Override
public T get(int i) {
return ItemGroup.this.get(i);
@ -49,7 +50,7 @@ import java.util.Objects;
@Override
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]= (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){
return null;
}
if(str.startsWith("*Plus taxes if applicable")){
String junk="";
}
StyleItem styleItem=getStyle();
if(styleItem==null){
return str;

View File

@ -15,8 +15,9 @@
*/
package com.reandroid.arsc.item;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueReference;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueItem;
import java.util.ArrayList;
import java.util.List;
@ -25,20 +26,20 @@ public class TableString extends StringItem {
public TableString(boolean utf8) {
super(utf8);
}
public List<EntryBlock> listReferencedEntries(boolean ignoreBagEntries){
List<EntryBlock> results=new ArrayList<>();
public List<Entry> listReferencedEntries(boolean ignoreBagEntries){
List<Entry> results=new ArrayList<>();
for(ReferenceItem ref:getReferencedList()){
if(!(ref instanceof ResValueReference)){
if(!(ref instanceof ReferenceBlock)){
continue;
}
EntryBlock entryBlock=((ResValueReference)ref).getEntryBlock();
if(entryBlock==null){
ValueItem valueItem = (ValueItem) ((ReferenceBlock)ref).getBlock();
if(valueItem ==null){
continue;
}
if(ignoreBagEntries && entryBlock.isEntryTypeBag()){
if(ignoreBagEntries && (valueItem instanceof ResValueMap)){
continue;
}
results.add(entryBlock);
results.add(valueItem.getParentEntry());
}
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.TableString;
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 java.io.*;
@ -45,9 +45,9 @@ public class FrameworkTable extends TableBlock {
}
public int resolveResourceId(String typeName, String entryName){
EntryBlock entryBlock=searchEntryBlock(typeName, entryName);
if(entryBlock!=null){
return entryBlock.getResourceId();
Entry entry = searchEntry(typeName, entryName);
if(entry !=null){
return entry.getResourceId();
}
return 0;
}
@ -81,7 +81,7 @@ public class FrameworkTable extends TableBlock {
private boolean hasResourceGroupMap(){
return mNameGroupMap!=null;
}
private EntryBlock searchEntryBlockFromMap(String typeName, String entryName){
private Entry searchEntryFromMap(String typeName, String entryName){
if(mNameGroupMap ==null){
return null;
}
@ -91,16 +91,16 @@ public class FrameworkTable extends TableBlock {
}
return null;
}
public EntryBlock searchEntryBlock(String typeName, String entryName){
public Entry searchEntry(String typeName, String entryName){
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.
*/
public EntryBlock searchEntryBlockFromTable(String typeName, String entryName){
public Entry searchEntryFromTable(String typeName, String entryName){
for(PackageBlock packageBlock:listPackages()){
SpecTypePair specTypePair = packageBlock.searchByTypeName(typeName);
if(specTypePair!=null){
@ -166,8 +166,8 @@ public class FrameworkTable extends TableBlock {
public void optimize(String frameworkName, String frameworkVersion){
Map<Integer, EntryGroup> groupMap=scanAllEntryGroups();
for(EntryGroup group:groupMap.values()){
List<EntryBlock> entryBlockList=getEntriesToRemove(group);
removeEntryBlocks(entryBlockList);
List<Entry> entryList =getEntriesToRemove(group);
removeEntries(entryList);
}
for(PackageBlock pkg:listPackages()){
clearNonDefaultConfigs(pkg);
@ -246,32 +246,32 @@ public class FrameworkTable extends TableBlock {
}
zero.addReference(allRef);
}
private void removeEntryBlocks(List<EntryBlock> removeList){
for(EntryBlock entryBlock:removeList){
removeEntryBlock(entryBlock);
private void removeEntries(List<Entry> removeList){
for(Entry entry :removeList){
removeEntry(entry);
}
}
private void removeEntryBlock(EntryBlock entryBlock){
TypeBlock typeBlock=entryBlock.getTypeBlock();
private void removeEntry(Entry entry){
TypeBlock typeBlock= entry.getTypeBlock();
if(typeBlock==null){
return;
}
typeBlock.removeEntry(entryBlock);
typeBlock.removeEntry(entry);
}
private List<EntryBlock> getEntriesToRemove(EntryGroup group){
List<EntryBlock> results=new ArrayList<>();
EntryBlock mainEntry=group.pickOne();
private List<Entry> getEntriesToRemove(EntryGroup group){
List<Entry> results=new ArrayList<>();
Entry mainEntry=group.pickOne();
if(mainEntry==null){
return results;
}
Iterator<EntryBlock> itr = group.iterator(true);
Iterator<Entry> itr = group.iterator(true);
while (itr.hasNext()){
EntryBlock entryBlock=itr.next();
if(entryBlock==mainEntry){
Entry entry =itr.next();
if(entry ==mainEntry){
continue;
}
results.add(entryBlock);
results.add(entry);
}
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;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ResValueMap;
public class ArrayBag {
private final ArrayBagItem[] mBagItems;
@ -28,18 +28,18 @@ public class ArrayBag {
return mBagItems;
}
public String getName(){
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItems()[0].getBagItem().getEntry();
if(entry ==null){
return null;
}
return entryBlock.getName();
return entry.getName();
}
public String getTypeName(){
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItems()[0].getBagItem().getEntry();
if(entry ==null){
return null;
}
return entryBlock.getTypeName();
return entry.getTypeName();
}
@Override
public String toString() {
@ -63,39 +63,38 @@ public class ArrayBag {
/** The result of this is not always 100% accurate,
* in addition to this use your methods to cross check like type-name == "array"**/
public static boolean isArray(ResValueBag resValueBag){
if(resValueBag==null){
public static boolean isArray(ResTableMapEntry mapEntry){
if(mapEntry==null){
return false;
}
EntryBlock entryBlock = resValueBag.getEntryBlock();
if(entryBlock==null){
if(mapEntry.getParentId()!=0){
return false;
}
if(resValueBag.getParentId()!=0){
return false;
}
ArrayBagItem[] arrayBagItems = ArrayBagItem.create(resValueBag.getBagItems());
ArrayBagItem[] arrayBagItems = ArrayBagItem.create(mapEntry.listResValueMap());
if(arrayBagItems==null || arrayBagItems.length==0){
return false;
}
for(int i=0;i< arrayBagItems.length; i++){
ArrayBagItem arrayBagItem = arrayBagItems[i];
ResValueBagItem resValueBagItem = arrayBagItem.getBagItem();
if(resValueBagItem.getIdHigh()!=0x0100){
ResValueMap resValueMap = arrayBagItem.getBagItem();
int name = resValueMap.getName();
int high = (name >> 16) & 0xffff;
if(high!=0x0100){
return false;
}
if(resValueBagItem.getIdLow() != (i+1)){
int low = name & 0xffff;
if(low != (i+1)){
return false;
}
}
return true;
}
public static ArrayBag create(ResValueBag resValueBag){
if(resValueBag==null){
public static ArrayBag create(ResTableMapEntry mapEntry){
if(mapEntry==null){
return null;
}
ArrayBagItem[] bagItems=ArrayBagItem.create(resValueBag.getBagItems());
ArrayBagItem[] bagItems=ArrayBagItem.create(mapEntry.listResValueMap());
if(bagItems==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.item.TableString;
import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import java.util.ArrayList;
import java.util.List;
public class ArrayBagItem {
private final ResValueBagItem mBagItem;
public ArrayBagItem(ResValueBagItem bagItem){
private final ResValueMap mBagItem;
public ArrayBagItem(ResValueMap bagItem){
this.mBagItem=bagItem;
}
public ResValueBagItem getBagItem() {
public ResValueMap getBagItem() {
return mBagItem;
}
@ -39,11 +39,11 @@ import java.util.List;
return getBagItem().getValueType();
}
private TableStringPool getStringPool(){
EntryBlock entryBlock=getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItem().getEntry();
if(entry ==null){
return null;
}
PackageBlock pkg = entryBlock.getPackageBlock();
PackageBlock pkg = entry.getPackageBlock();
if(pkg==null){
return null;
}
@ -88,17 +88,17 @@ import java.util.List;
builder.append("</item>");
return builder.toString();
}
public static ArrayBagItem[] create(ResValueBagItem[] resValueBagItems){
if(resValueBagItems==null){
public static ArrayBagItem[] create(ResValueMap[] resValueMaps){
if(resValueMaps ==null){
return null;
}
int len=resValueBagItems.length;
int len= resValueMaps.length;
if(len==0){
return null;
}
List<ArrayBagItem> results=new ArrayList<>();
for(int i=0;i<len;i++){
ArrayBagItem item=create(resValueBagItems[i]);
ArrayBagItem item=create(resValueMaps[i]);
if(item==null){
return null;
}
@ -106,11 +106,11 @@ import java.util.List;
}
return results.toArray(new ArrayBagItem[0]);
}
public static ArrayBagItem create(ResValueBagItem resValueBagItem){
if(resValueBagItem==null){
public static ArrayBagItem create(ResValueMap resValueMap){
if(resValueMap ==null){
return null;
}
ArrayBagItem item=new ArrayBagItem(resValueBagItem);
ArrayBagItem item=new ArrayBagItem(resValueMap);
return item;
}
}

View File

@ -15,9 +15,10 @@
*/
package com.reandroid.arsc.value.attribute;
import com.reandroid.arsc.array.ResValueMapArray;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
import com.reandroid.arsc.value.ValueType;
import com.reandroid.common.EntryStore;
@ -220,9 +221,9 @@ public class AttributeBag {
AttributeBagItem[] bagItems= getBagItems();
StringBuilder builder=new StringBuilder();
AttributeBagItem format=getFormat();
EntryBlock entryBlock=format.getBagItem().getEntryBlock();
if(entryBlock!=null){
builder.append(entryBlock.getSpecString());
Entry entry =format.getBagItem().getEntry();
if(entry !=null){
builder.append(entry.getSpecString());
}
int len=bagItems.length;
builder.append(", childes=").append(len);
@ -234,21 +235,21 @@ public class AttributeBag {
return builder.toString();
}
public static AttributeBag create(ResValueBag resValueBag){
if(resValueBag==null){
public static AttributeBag create(ResValueMapArray resValueMapArray){
if(resValueMapArray==null){
return null;
}
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueBag.getBagItems());
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueMapArray.getChildes());
if(bagItems==null){
return null;
}
return new AttributeBag(bagItems);
}
public static boolean isAttribute(ResValueBag resValueBag){
if(resValueBag==null){
public static boolean isAttribute(ResTableMapEntry mapEntry){
if(mapEntry==null){
return false;
}
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueBag.getBagItems());
AttributeBagItem[] bagItems=AttributeBagItem.create(mapEntry.listResValueMap());
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.group.EntryGroup;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.common.EntryStore;
public class AttributeBagItem {
private final ResValueBagItem mBagItem;
public AttributeBagItem(ResValueBagItem bagItem){
private final ResValueMap mBagItem;
public AttributeBagItem(ResValueMap bagItem){
this.mBagItem=bagItem;
}
public int getData(){
@ -36,7 +36,7 @@ public class AttributeBagItem {
public String getNameOrHex(EntryStore entryStore){
String name=getName(entryStore);
if(name==null){
name=String.format("@0x%08x", getBagItem().getId());
name=String.format("@0x%08x", getBagItem().getName());
}
return name;
}
@ -47,9 +47,9 @@ public class AttributeBagItem {
if(isType()){
return null;
}
ResValueBagItem item=getBagItem();
int id=item.getId();
EntryBlock parentEntry=item.getEntryBlock();
ResValueMap item=getBagItem();
int id=item.getName();
Entry parentEntry=item.getEntry();
if(parentEntry!=null){
PackageBlock packageBlock=parentEntry.getPackageBlock();
if(packageBlock!=null){
@ -70,26 +70,27 @@ public class AttributeBagItem {
}
return null;
}
public ResValueBagItem getBagItem() {
public ResValueMap getBagItem() {
return mBagItem;
}
public AttributeItemType getItemType(){
if(!isType()){
return null;
}
ResValueBagItem item=getBagItem();
return AttributeItemType.valueOf(item.getIdLow());
ResValueMap item=getBagItem();
int low = item.getName() & 0xffff;
return AttributeItemType.valueOf((short) low);
}
public boolean isType(){
ResValueBagItem item=getBagItem();
return item.getIdHigh()==0x0100;
ResValueMap item=getBagItem();
return ((item.getName()>>16) & 0xffff)==0x0100;
}
public boolean contains(AttributeValueType valueType){
if(valueType == null || getItemType()!=AttributeItemType.FORMAT){
return false;
}
int value = 0xff & valueType.getByte();
int dataLow = 0xffff & getBagItem().getDataLow();
int dataLow = 0xffff & getBagItem().getData();
return (dataLow & value) == value;
}
public boolean isEqualType(AttributeValueType valueType){
@ -97,7 +98,7 @@ public class AttributeBagItem {
return false;
}
int value = 0xff & valueType.getByte();
int dataLow = 0xffff & getBagItem().getDataLow();
int dataLow = 0xffff & getBagItem().getData();
return (dataLow == value);
}
public AttributeValueType[] getValueTypes(){
@ -105,8 +106,8 @@ public class AttributeBagItem {
if(type!=AttributeItemType.FORMAT){
return null;
}
ResValueBagItem item=getBagItem();
short low=item.getDataLow();
ResValueMap item=getBagItem();
short low = (short) (item.getData() & 0xffff);
return AttributeValueType.valuesOf(low);
}
public Integer getBound(){
@ -114,7 +115,7 @@ public class AttributeBagItem {
if(type==null || type==AttributeItemType.FORMAT){
return null;
}
ResValueBagItem item=getBagItem();
ResValueMap item=getBagItem();
return item.getData();
}
public boolean isEnum(){
@ -122,16 +123,18 @@ public class AttributeBagItem {
if(type!=AttributeItemType.FORMAT){
return false;
}
ResValueBagItem item=getBagItem();
return item.getDataHigh()==AttributeBag.TYPE_ENUM;
ResValueMap item=getBagItem();
int high = (item.getData() >> 16) & 0xffff;
return high==AttributeBag.TYPE_ENUM;
}
public boolean isFlag(){
AttributeItemType type=getItemType();
if(type!=AttributeItemType.FORMAT){
return false;
}
ResValueBagItem item=getBagItem();
return item.getDataHigh()==AttributeBag.TYPE_FLAG;
ResValueMap item=getBagItem();
int high = (item.getData() >> 16) & 0xffff;
return high==AttributeBag.TYPE_FLAG;
}
@Override
public String toString(){
@ -157,7 +160,7 @@ public class AttributeBagItem {
builder.append(bound);
return builder.toString();
}
ResValueBagItem item=getBagItem();
ResValueMap item=getBagItem();
builder.append(getNameOrHex());
builder.append("=").append(String.format("0x%x", item.getData()));
return builder.toString();
@ -190,15 +193,15 @@ public class AttributeBagItem {
}
return null;
}
public static AttributeBagItem[] create(ResValueBagItem[] resValueBagItems){
if(resValueBagItems==null){
public static AttributeBagItem[] create(ResValueMap[] resValueMaps){
if(resValueMaps ==null){
return null;
}
AttributeBagItem format=null;
int len=resValueBagItems.length;
int len= resValueMaps.length;
AttributeBagItem[] bagItems=new AttributeBagItem[len];
for(int i=0;i<len;i++){
AttributeBagItem item=new AttributeBagItem(resValueBagItems[i]);
AttributeBagItem item=new AttributeBagItem(resValueMaps[i]);
bagItems[i]=item;
if(format==null){
if(AttributeItemType.FORMAT==item.getItemType()){

View File

@ -15,10 +15,10 @@
*/
package com.reandroid.arsc.value.plurals;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
public class PluralsBag {
public class PluralsBag {
private final PluralsBagItem[] mBagItems;
private PluralsBag(PluralsBagItem[] bagItems){
this.mBagItems=bagItems;
@ -27,18 +27,18 @@ public class PluralsBag {
return mBagItems;
}
public String getName(){
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItems()[0].getBagItem().getEntry();
if(entry ==null){
return null;
}
return entryBlock.getName();
return entry.getName();
}
public String getTypeName(){
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItems()[0].getBagItem().getEntry();
if(entry ==null){
return null;
}
return entryBlock.getTypeName();
return entry.getTypeName();
}
@Override
@ -63,22 +63,18 @@ public class PluralsBag {
/** The result of this is not always 100% accurate,
* in addition to this use your methods to cross check like type-name == "plurals"**/
public static boolean isPlurals(ResValueBag resValueBag){
if(resValueBag==null){
public static boolean isPlurals(ResTableMapEntry mapEntry){
if(mapEntry==null){
return false;
}
EntryBlock entryBlock = resValueBag.getEntryBlock();
if(entryBlock==null){
return false;
}
return PluralsBagItem.create(resValueBag.getBagItems()) != null;
return PluralsBagItem.create(mapEntry.listResValueMap()) != null;
}
public static PluralsBag create(ResValueBag resValueBag){
if(resValueBag==null){
public static PluralsBag create(ResTableMapEntry mapEntry){
if(mapEntry==null){
return null;
}
PluralsBagItem[] bagItems=PluralsBagItem.create(resValueBag.getBagItems());
PluralsBagItem[] bagItems=PluralsBagItem.create(mapEntry.listResValueMap());
if(bagItems==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.item.TableString;
import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import java.util.ArrayList;
@ -29,26 +29,27 @@ import java.util.List;
import java.util.Set;
public class PluralsBagItem {
private final ResValueBagItem mBagItem;
private PluralsBagItem(ResValueBagItem bagItem){
private final ResValueMap mBagItem;
private PluralsBagItem(ResValueMap bagItem){
this.mBagItem=bagItem;
}
public ResValueBagItem getBagItem() {
public ResValueMap getBagItem() {
return mBagItem;
}
public PluralsQuantity getQuantity(){
ResValueBagItem item=getBagItem();
return PluralsQuantity.valueOf(item.getIdLow());
ResValueMap item=getBagItem();
int low = item.getName() & 0xffff;
return PluralsQuantity.valueOf((short) low);
}
public ValueType getValueType(){
return getBagItem().getValueType();
}
private TableStringPool getStringPool(){
EntryBlock entryBlock=getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItem().getEntry();
if(entry ==null){
return null;
}
PackageBlock pkg = entryBlock.getPackageBlock();
PackageBlock pkg = entry.getPackageBlock();
if(pkg==null){
return null;
}
@ -96,22 +97,23 @@ public class PluralsBagItem {
return builder.toString();
}
public static PluralsBagItem[] create(ResValueBagItem[] resValueBagItems){
if(resValueBagItems==null){
public static PluralsBagItem[] create(ResValueMap[] resValueMaps){
if(resValueMaps ==null){
return null;
}
int len=resValueBagItems.length;
int len= resValueMaps.length;
if(len==0){
return null;
}
Set<PluralsQuantity> duplicates=new HashSet<>();
List<PluralsBagItem> results=new ArrayList<>();
for(int i=0;i<len;i++){
ResValueBagItem resValueBagItem = resValueBagItems[i];
if(resValueBagItem.getIdHigh() != 0x0100){
ResValueMap resValueMap = resValueMaps[i];
int high = (resValueMap.getName() >> 16) & 0xffff;
if(high != 0x0100){
return null;
}
PluralsBagItem item=create(resValueBagItem);
PluralsBagItem item=create(resValueMap);
if(item==null){
// If it reaches here type name is obfuscated
return null;
@ -125,8 +127,8 @@ public class PluralsBagItem {
}
return results.toArray(new PluralsBagItem[0]);
}
public static PluralsBagItem create(ResValueBagItem resValueBagItem){
PluralsBagItem item=new PluralsBagItem(resValueBagItem);
public static PluralsBagItem create(ResValueMap resValueMap){
PluralsBagItem item=new PluralsBagItem(resValueMap);
if(item.getQuantity()==null){
return null;
}

View File

@ -16,9 +16,8 @@
package com.reandroid.arsc.value.style;
import com.reandroid.arsc.item.SpecString;
import com.reandroid.arsc.item.TypeString;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBag;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResTableMapEntry;
public class StyleBag {
private final StyleBagItem[] mBagItems;
@ -29,11 +28,11 @@ public class StyleBag {
return mBagItems;
}
public String getName(){
EntryBlock entryBlock=getEntryBlock();
if(entryBlock==null){
Entry entry = getEntry();
if(entry ==null){
return null;
}
SpecString spec = entryBlock.getSpecString();
SpecString spec = entry.getSpecString();
if(spec==null){
return null;
}
@ -44,39 +43,35 @@ public class StyleBag {
if(id==0){
return null;
}
EntryBlock entryBlock=getEntryBlock();
if(entryBlock==null){
Entry entry = getEntry();
if(entry ==null){
return null;
}
return entryBlock.buildResourceName(id, '@', true);
return entry.buildResourceName(id, '@', true);
}
public int getParentId(){
ResValueBag resValueBag=getBagItems()[0].getBagItem().getParentBag();
if(resValueBag==null){
ResTableMapEntry mapEntry = getBagItems()[0].getBagItem().getParentMapEntry();
if(mapEntry==null){
return 0;
}
return resValueBag.getParentId();
return mapEntry.getParentId();
}
public int getResourceId(){
EntryBlock entryBlock=getEntryBlock();
if(entryBlock==null){
Entry entry = getEntry();
if(entry ==null){
return 0;
}
return entryBlock.getResourceId();
return entry.getResourceId();
}
public String getTypeName(){
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItems()[0].getBagItem().getEntry();
if(entry ==null){
return null;
}
TypeString typeString = entryBlock.getTypeString();
if(typeString==null){
return null;
}
return typeString.get();
return entry.getTypeName();
}
private EntryBlock getEntryBlock(){
return getBagItems()[0].getBagItem().getEntryBlock();
private Entry getEntry(){
return getBagItems()[0].getBagItem().getEntry();
}
@Override
public String toString() {
@ -107,22 +102,18 @@ public class StyleBag {
/** The result of this is not always 100% accurate,
* in addition to this use your methods to cross check like type-name == "plurals"**/
public static boolean isStyle(ResValueBag resValueBag){
if(resValueBag==null){
public static boolean isStyle(ResTableMapEntry mapEntry){
if(mapEntry==null){
return false;
}
EntryBlock entryBlock = resValueBag.getEntryBlock();
if(entryBlock==null){
return false;
}
return StyleBag.create(resValueBag) != null;
return StyleBag.create(mapEntry) != null;
}
public static StyleBag create(ResValueBag resValueBag){
if(resValueBag==null){
public static StyleBag create(ResTableMapEntry mapEntry){
if(mapEntry==null){
return null;
}
StyleBagItem[] bagItems=StyleBagItem.create(resValueBag.getBagItems());
StyleBagItem[] bagItems=StyleBagItem.create(mapEntry.getValue().getChildes());
if(bagItems==null){
return null;
}

View File

@ -15,24 +15,24 @@
*/
package com.reandroid.arsc.value.style;
import com.reandroid.arsc.value.EntryBlock;
import com.reandroid.arsc.value.ResValueBagItem;
import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.value.ValueType;
import java.util.ArrayList;
import java.util.List;
public class StyleBagItem {
private final ResValueBagItem mBagItem;
public StyleBagItem(ResValueBagItem bagItem){
private final ResValueMap mBagItem;
public StyleBagItem(ResValueMap bagItem){
this.mBagItem=bagItem;
}
public ResValueBagItem getBagItem() {
public ResValueMap getBagItem() {
return mBagItem;
}
public String getName(){
EntryBlock block=getBagItem().getEntryBlock();
Entry block=getBagItem().getEntry();
if(block==null){
return null;
}
@ -40,7 +40,7 @@ public class StyleBagItem {
return block.buildResourceName(getNameId(), prefix, false);
}
public int getNameId(){
return getBagItem().getId();
return getBagItem().getName();
}
public boolean hasStringValue(){
return getValueType()== ValueType.STRING;
@ -56,8 +56,8 @@ public class StyleBagItem {
if(valueType!=ValueType.REFERENCE && valueType!=ValueType.ATTRIBUTE){
throw new IllegalArgumentException("Not REF ValueType="+valueType);
}
EntryBlock entryBlock=getBagItem().getEntryBlock();
if(entryBlock==null){
Entry entry =getBagItem().getEntry();
if(entry ==null){
return null;
}
char prefix='@';
@ -67,7 +67,7 @@ public class StyleBagItem {
includeType=false;
}
int id=getValue();
return entryBlock.buildResourceName(id, prefix, includeType);
return entry.buildResourceName(id, prefix, includeType);
}
public String getStringValue(){
return mBagItem.getValueAsString();
@ -102,17 +102,17 @@ public class StyleBagItem {
builder.append("</item>");
return builder.toString();
}
public static StyleBagItem[] create(ResValueBagItem[] resValueBagItems){
if(resValueBagItems==null){
public static StyleBagItem[] create(ResValueMap[] resValueMaps){
if(resValueMaps ==null){
return null;
}
int len=resValueBagItems.length;
int len= resValueMaps.length;
if(len==0){
return null;
}
List<StyleBagItem> results=new ArrayList<>();
for(int i=0;i<len;i++){
StyleBagItem item=create(resValueBagItems[i]);
StyleBagItem item=create(resValueMaps[i]);
if(item==null){
return null;
}
@ -120,10 +120,10 @@ public class StyleBagItem {
}
return results.toArray(new StyleBagItem[0]);
}
public static StyleBagItem create(ResValueBagItem resValueBagItem){
if(resValueBagItem==null){
public static StyleBagItem create(ResValueMap resValueMap){
if(resValueMap ==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.group.EntryGroup;
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 java.util.*;
@ -31,13 +31,13 @@ public class TableEntryStore implements EntryStore{
}
public String getEntryName(int resourceId){
EntryBlock entryBlock=getEntryBlock(resourceId);
if(entryBlock==null){
Entry entry = getEntry(resourceId);
if(entry ==null){
return null;
}
return entryBlock.getName();
return entry.getName();
}
public EntryBlock getEntryBlock(int resourceId){
public Entry getEntry(int resourceId){
if(resourceId==0){
return null;
}