From 7430b40c5438a1dfaa1cc44c784834107f1148a7 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Mon, 13 Feb 2023 11:38:58 -0500 Subject: [PATCH] rename classes --- .../java/com/reandroid/apk/ApkModule.java | 8 +- .../reandroid/apk/ApkModuleXmlDecoder.java | 54 +- src/main/java/com/reandroid/apk/ResFile.java | 65 +- .../com/reandroid/apk/StringPoolBuilder.java | 6 +- .../reandroid/apk/xmldecoder/BagDecoder.java | 6 +- .../apk/xmldecoder/XMLArrayDecoder.java | 31 +- .../apk/xmldecoder/XMLAttrDecoder.java | 10 +- .../apk/xmldecoder/XMLBagDecoder.java | 13 +- .../apk/xmldecoder/XMLCommonBagDecoder.java | 26 +- .../apk/xmldecoder/XMLPluralsDecoder.java | 37 +- .../apk/xmlencoder/EncodeMaterials.java | 92 +- .../apk/xmlencoder/FilePathEncoder.java | 8 +- .../apk/xmlencoder/XMLFileEncoder.java | 24 +- .../apk/xmlencoder/XMLValuesEncoder.java | 45 +- .../apk/xmlencoder/XMLValuesEncoderArray.java | 16 +- .../apk/xmlencoder/XMLValuesEncoderAttr.java | 38 +- .../apk/xmlencoder/XMLValuesEncoderBag.java | 19 +- .../apk/xmlencoder/XMLValuesEncoderColor.java | 8 +- .../xmlencoder/XMLValuesEncoderCommon.java | 12 +- .../apk/xmlencoder/XMLValuesEncoderDimen.java | 8 +- .../apk/xmlencoder/XMLValuesEncoderId.java | 26 +- .../xmlencoder/XMLValuesEncoderInteger.java | 10 +- .../xmlencoder/XMLValuesEncoderPlurals.java | 16 +- .../xmlencoder/XMLValuesEncoderString.java | 14 +- .../apk/xmlencoder/XMLValuesEncoderStyle.java | 22 +- .../{EntryBlockArray.java => EntryArray.java} | 63 +- ...agItemArray.java => ResValueMapArray.java} | 32 +- .../arsc/array/SpecTypePairArray.java | 6 +- .../reandroid/arsc/array/TypeBlockArray.java | 10 +- .../reandroid/arsc/chunk/PackageBlock.java | 55 +- .../com/reandroid/arsc/chunk/TypeBlock.java | 84 +- .../arsc/chunk/xml/ResXmlDocument.java | 8 +- .../arsc/container/ResValueContainer.java | 16 +- .../arsc/container/SpecTypePair.java | 26 +- .../reandroid/arsc/decoder/ValueDecoder.java | 138 +-- .../com/reandroid/arsc/group/EntryGroup.java | 80 +- .../com/reandroid/arsc/group/ItemGroup.java | 3 +- .../com/reandroid/arsc/item/BlockItem.java | 17 + .../reandroid/arsc/item/ReferenceBlock.java | 38 + .../com/reandroid/arsc/item/StringItem.java | 3 - .../com/reandroid/arsc/item/TableString.java | 19 +- .../reandroid/arsc/util/FrameworkTable.java | 48 +- .../reandroid/arsc/value/BaseResValue.java | 123 --- .../arsc/value/BaseResValueItem.java | 99 --- .../java/com/reandroid/arsc/value/Entry.java | 438 +++++++++ .../com/reandroid/arsc/value/EntryBlock.java | 836 ------------------ .../com/reandroid/arsc/value/EntryHeader.java | 56 ++ .../reandroid/arsc/value/EntryHeaderMap.java | 107 +++ .../java/com/reandroid/arsc/value/Header.java | 236 +++++ .../reandroid/arsc/value/ResTableEntry.java | 66 ++ .../arsc/value/ResTableMapEntry.java | 114 +++ .../com/reandroid/arsc/value/ResValue.java | 43 + .../com/reandroid/arsc/value/ResValueBag.java | 188 ---- .../reandroid/arsc/value/ResValueBagItem.java | 259 ------ .../com/reandroid/arsc/value/ResValueInt.java | 184 ---- .../com/reandroid/arsc/value/ResValueMap.java | 115 +++ .../arsc/value/ResValueReference.java | 49 - .../com/reandroid/arsc/value/TableEntry.java | 116 +++ .../com/reandroid/arsc/value/ValueItem.java | 295 ++++++ .../reandroid/arsc/value/array/ArrayBag.java | 45 +- .../arsc/value/array/ArrayBagItem.java | 30 +- .../arsc/value/attribute/AttributeBag.java | 23 +- .../value/attribute/AttributeBagItem.java | 57 +- .../arsc/value/plurals/PluralsBag.java | 34 +- .../arsc/value/plurals/PluralsBagItem.java | 38 +- .../reandroid/arsc/value/style/StyleBag.java | 59 +- .../arsc/value/style/StyleBagItem.java | 34 +- .../com/reandroid/common/TableEntryStore.java | 10 +- 68 files changed, 2407 insertions(+), 2507 deletions(-) rename src/main/java/com/reandroid/arsc/array/{EntryBlockArray.java => EntryArray.java} (60%) rename src/main/java/com/reandroid/arsc/array/{ResValueBagItemArray.java => ResValueMapArray.java} (73%) create mode 100644 src/main/java/com/reandroid/arsc/item/ReferenceBlock.java delete mode 100755 src/main/java/com/reandroid/arsc/value/BaseResValue.java delete mode 100755 src/main/java/com/reandroid/arsc/value/BaseResValueItem.java create mode 100755 src/main/java/com/reandroid/arsc/value/Entry.java delete mode 100755 src/main/java/com/reandroid/arsc/value/EntryBlock.java create mode 100644 src/main/java/com/reandroid/arsc/value/EntryHeader.java create mode 100644 src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java create mode 100644 src/main/java/com/reandroid/arsc/value/Header.java create mode 100644 src/main/java/com/reandroid/arsc/value/ResTableEntry.java create mode 100644 src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java create mode 100755 src/main/java/com/reandroid/arsc/value/ResValue.java delete mode 100755 src/main/java/com/reandroid/arsc/value/ResValueBag.java delete mode 100755 src/main/java/com/reandroid/arsc/value/ResValueBagItem.java delete mode 100755 src/main/java/com/reandroid/arsc/value/ResValueInt.java create mode 100755 src/main/java/com/reandroid/arsc/value/ResValueMap.java delete mode 100644 src/main/java/com/reandroid/arsc/value/ResValueReference.java create mode 100644 src/main/java/com/reandroid/arsc/value/TableEntry.java create mode 100755 src/main/java/com/reandroid/arsc/value/ValueItem.java diff --git a/src/main/java/com/reandroid/apk/ApkModule.java b/src/main/java/com/reandroid/apk/ApkModule.java index ec23341..ec18e40 100644 --- a/src/main/java/com/reandroid/apk/ApkModule.java +++ b/src/main/java/com/reandroid/apk/ApkModule.java @@ -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 entryBlockList = tableString.listReferencedEntries(true); - if(entryBlockList.size()==0){ + List entryList = tableString.listReferencedEntries(true); + if(entryList.size()==0){ continue; } - ResFile resFile=new ResFile(inputSource, entryBlockList); + ResFile resFile=new ResFile(inputSource, entryList); results.add(resFile); } } diff --git a/src/main/java/com/reandroid/apk/ApkModuleXmlDecoder.java b/src/main/java/com/reandroid/apk/ApkModuleXmlDecoder.java index 670a554..4915da3 100644 --- a/src/main/java/com/reandroid/apk/ApkModuleXmlDecoder.java +++ b/src/main/java/com/reandroid/apk/ApkModuleXmlDecoder.java @@ -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 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 resConfigSet=decodedEntries.get(entryBlock.getResourceId()); + private boolean containsDecodedEntry(Entry entry){ + Set 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; diff --git a/src/main/java/com/reandroid/apk/ResFile.java b/src/main/java/com/reandroid/apk/ResFile.java index 2d8109f..ae4b05f 100644 --- a/src/main/java/com/reandroid/apk/ResFile.java +++ b/src/main/java/com/reandroid/apk/ResFile.java @@ -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 entryBlockList; + private final List 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 entryBlockList){ + private Entry mSelectedEntry; + public ResFile(InputSource inputSource, List entryList){ this.inputSource=inputSource; - this.entryBlockList=entryBlockList; + this.entryList = entryList; } - public List getEntryBlockList(){ - return entryBlockList; + public List 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 entryList = entryBlockList; + private Entry selectOne(){ + List 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); diff --git a/src/main/java/com/reandroid/apk/StringPoolBuilder.java b/src/main/java/com/reandroid/apk/StringPoolBuilder.java index 02f124a..651eb5d 100644 --- a/src/main/java/com/reandroid/apk/StringPoolBuilder.java +++ b/src/main/java/com/reandroid/apk/StringPoolBuilder.java @@ -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))){ diff --git a/src/main/java/com/reandroid/apk/xmldecoder/BagDecoder.java b/src/main/java/com/reandroid/apk/xmldecoder/BagDecoder.java index 7de9a2e..1fd583b 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/BagDecoder.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/BagDecoder.java @@ -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); } diff --git a/src/main/java/com/reandroid/apk/xmldecoder/XMLArrayDecoder.java b/src/main/java/com/reandroid/apk/xmldecoder/XMLArrayDecoder.java index 8a32971..0e53313 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/XMLArrayDecoder.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/XMLArrayDecoder.java @@ -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 valueTypes = new HashSet<>(); for(int i=0;i> 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; } diff --git a/src/main/java/com/reandroid/apk/xmldecoder/XMLAttrDecoder.java b/src/main/java/com/reandroid/apk/xmldecoder/XMLAttrDecoder.java index a7e8b9e..146a6fc 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/XMLAttrDecoder.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/XMLAttrDecoder.java @@ -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){ diff --git a/src/main/java/com/reandroid/apk/xmldecoder/XMLBagDecoder.java b/src/main/java/com/reandroid/apk/xmldecoder/XMLBagDecoder.java index db4a205..c639ebf 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/XMLBagDecoder.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/XMLBagDecoder.java @@ -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; } } diff --git a/src/main/java/com/reandroid/apk/xmldecoder/XMLCommonBagDecoder.java b/src/main/java/com/reandroid/apk/xmldecoder/XMLCommonBagDecoder.java index 6769a2f..874104a 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/XMLCommonBagDecoder.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/XMLCommonBagDecoder.java @@ -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; } } diff --git a/src/main/java/com/reandroid/apk/xmldecoder/XMLPluralsDecoder.java b/src/main/java/com/reandroid/apk/xmldecoder/XMLPluralsDecoder.java index c71a61c..f6326bc 100644 --- a/src/main/java/com/reandroid/apk/xmldecoder/XMLPluralsDecoder.java +++ b/src/main/java/com/reandroid/apk/xmldecoder/XMLPluralsDecoder.java @@ -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> 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; } diff --git a/src/main/java/com/reandroid/apk/xmlencoder/EncodeMaterials.java b/src/main/java/com/reandroid/apk/xmlencoder/EncodeMaterials.java index f65f970..e13152d 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/EncodeMaterials.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/EncodeMaterials.java @@ -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 mFrameworkPackageNames; - private final ResNameMap mLocalResNameMap = new ResNameMap<>(); + private final ResNameMap 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 localMap = mLocalResNameMap; + private void loadLocalEntryMap(String type){ + ResNameMap 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; } } } diff --git a/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java b/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java index 41cb2a5..10cefb4 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/FilePathEncoder.java @@ -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; diff --git a/src/main/java/com/reandroid/apk/xmlencoder/XMLFileEncoder.java b/src/main/java/com/reandroid/apk/xmlencoder/XMLFileEncoder.java index 97a0a2c..a0bb3f5 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/XMLFileEncoder.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/XMLFileEncoder.java @@ -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; } diff --git a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java index 9a051ef..8897452 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoder.java @@ -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: '"+value+"'"); } diff --git a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderPlurals.java b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderPlurals.java index 16cf800..e09f7a2 100644 --- a/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderPlurals.java +++ b/src/main/java/com/reandroid/apk/xmlencoder/XMLValuesEncoderPlurals.java @@ -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 implements JSONConvert { - public EntryBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){ +public class EntryArray extends OffsetBlockArray implements JSONConvert { + 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 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 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 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 itr=entryBlockArray.iterator(true); + ensureSize(entryArray.childesCount()); + Iterator 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); } } diff --git a/src/main/java/com/reandroid/arsc/array/ResValueBagItemArray.java b/src/main/java/com/reandroid/arsc/array/ResValueMapArray.java similarity index 73% rename from src/main/java/com/reandroid/arsc/array/ResValueBagItemArray.java rename to src/main/java/com/reandroid/arsc/array/ResValueMapArray.java index b98e6cd..36bf132 100755 --- a/src/main/java/com/reandroid/arsc/array/ResValueBagItemArray.java +++ b/src/main/java/com/reandroid/arsc/array/ResValueMapArray.java @@ -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 implements JSONConvert { - public ResValueBagItemArray(){ +public class ResValueMapArray extends BlockArray implements JSONConvert { + 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 implements if(isNull()){ return jsonArray; } - ResValueBagItem[] childes = getChildes(); + ResValueMap[] childes = getChildes(); for(int i=0;i 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 implements int count=bagItemArray.childesCount(); ensureSize(count); for(int i=0;i } 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; diff --git a/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java b/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java index bbbcd62..7593747 100755 --- a/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java +++ b/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java @@ -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 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 } 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 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 * Lets depreciate to warn developer */ @Deprecated - public EntryBlock searchByEntryName(String entryName){ + public Entry searchByEntryName(String entryName){ if(entryName==null){ return null; } diff --git a/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java b/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java index d10dbb4..9d8511e 100755 --- a/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/PackageBlock.java @@ -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 - implements JSONConvert, Comparable { + implements ParentChunk, + JSONConvert, + Comparable { 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 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 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 listEntries(byte typeId, int entryId){ - List results=new ArrayList<>(); + public List listEntries(byte typeId, int entryId){ + List 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() { diff --git a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java index efac077..8aa5906 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java @@ -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 implements BlockLoad, JSONConvert, Comparable { - 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 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 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 } public void cleanEntries(){ PackageBlock packageBlock=getPackageBlock(); - List allEntries=listEntries(true); - for(EntryBlock entryBlock:allEntries){ + List 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 } 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 listEntries(){ + public List listEntries(){ return listEntries(false); } - public List listEntries(boolean skipNullBlock){ - List results=new ArrayList<>(); - Iterator itr = getEntryBlockArray().iterator(skipNullBlock); + public List listEntries(boolean skipNullBlock){ + List results=new ArrayList<>(); + Iterator 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 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 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 +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 * 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 { diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java index cd703c3..b7c7836 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlDocument.java @@ -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 - implements MainChunk, JSONConvert { + implements MainChunk, ParentChunk, JSONConvert { 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; } diff --git a/src/main/java/com/reandroid/arsc/container/ResValueContainer.java b/src/main/java/com/reandroid/arsc/container/ResValueContainer.java index e0216b6..a9b4a97 100755 --- a/src/main/java/com/reandroid/arsc/container/ResValueContainer.java +++ b/src/main/java/com/reandroid/arsc/container/ResValueContainer.java @@ -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 { - private final BaseResValue[] mChildes; +public class ResValueContainer extends BlockContainer { + 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 { 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 { resValue.setIndex(0); resValue.setParent(this); } - public BaseResValue getResValue(){ + public ValueItem getResValue(){ if(mChildes.length==0){ return null; } diff --git a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java index 16efda5..d4e706a 100755 --- a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java +++ b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java @@ -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 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 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 * 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 } return null; } - public List listEntries(int entryId){ - List results=new ArrayList<>(); + public List listEntries(int entryId){ + List results=new ArrayList<>(); Iterator 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; } diff --git a/src/main/java/com/reandroid/arsc/decoder/ValueDecoder.java b/src/main/java/com/reandroid/arsc/decoder/ValueDecoder.java index 36fe845..f73f734 100755 --- a/src/main/java/com/reandroid/arsc/decoder/ValueDecoder.java +++ b/src/main/java/com/reandroid/arsc/decoder/ValueDecoder.java @@ -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 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 iterator=entryGroup.iterator(true); + ResTableMapEntry best=null; + Iterator 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); diff --git a/src/main/java/com/reandroid/arsc/group/EntryGroup.java b/src/main/java/com/reandroid/arsc/group/EntryGroup.java index b114379..fe6a801 100755 --- a/src/main/java/com/reandroid/arsc/group/EntryGroup.java +++ b/src/main/java/com/reandroid/arsc/group/EntryGroup.java @@ -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 { +public class EntryGroup extends ItemGroup { private final int resourceId; public EntryGroup(int resId) { super(create(), String.format("0x%08x", resId)); @@ -35,7 +35,7 @@ public class EntryGroup extends ItemGroup { 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 { 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 { } 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 itr=iterator(true); + public Entry getDefault(){ + Iterator 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 { 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 { } @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 create(){ - return new BlockArrayCreator(){ + private static BlockArrayCreator create(){ + return new BlockArrayCreator(){ @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]; } }; } diff --git a/src/main/java/com/reandroid/arsc/group/ItemGroup.java b/src/main/java/com/reandroid/arsc/group/ItemGroup.java index 8fd4da2..eab4fa9 100755 --- a/src/main/java/com/reandroid/arsc/group/ItemGroup.java +++ b/src/main/java/com/reandroid/arsc/group/ItemGroup.java @@ -42,6 +42,7 @@ import java.util.Objects; } public List listItems(){ return new AbstractList() { + 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; } }; } diff --git a/src/main/java/com/reandroid/arsc/item/BlockItem.java b/src/main/java/com/reandroid/arsc/item/BlockItem.java index ad3392c..6008c4e 100755 --- a/src/main/java/com/reandroid/arsc/item/BlockItem.java +++ b/src/main/java/com/reandroid/arsc/item/BlockItem.java @@ -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) & val; + val=left|right; + bts[byteOffset]=(byte) val; + } } diff --git a/src/main/java/com/reandroid/arsc/item/ReferenceBlock.java b/src/main/java/com/reandroid/arsc/item/ReferenceBlock.java new file mode 100644 index 0000000..2e31858 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/item/ReferenceBlock.java @@ -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 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); + } +} diff --git a/src/main/java/com/reandroid/arsc/item/StringItem.java b/src/main/java/com/reandroid/arsc/item/StringItem.java index 35d2897..e5d6222 100755 --- a/src/main/java/com/reandroid/arsc/item/StringItem.java +++ b/src/main/java/com/reandroid/arsc/item/StringItem.java @@ -97,9 +97,6 @@ public class StringItem extends BlockItem implements JSONConvert { if(str==null){ return null; } - if(str.startsWith("*Plus taxes if applicable")){ - String junk=""; - } StyleItem styleItem=getStyle(); if(styleItem==null){ return str; diff --git a/src/main/java/com/reandroid/arsc/item/TableString.java b/src/main/java/com/reandroid/arsc/item/TableString.java index c2e80b4..077a709 100755 --- a/src/main/java/com/reandroid/arsc/item/TableString.java +++ b/src/main/java/com/reandroid/arsc/item/TableString.java @@ -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 listReferencedEntries(boolean ignoreBagEntries){ - List results=new ArrayList<>(); + public List listReferencedEntries(boolean ignoreBagEntries){ + List 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; } diff --git a/src/main/java/com/reandroid/arsc/util/FrameworkTable.java b/src/main/java/com/reandroid/arsc/util/FrameworkTable.java index 79981ec..d897920 100755 --- a/src/main/java/com/reandroid/arsc/util/FrameworkTable.java +++ b/src/main/java/com/reandroid/arsc/util/FrameworkTable.java @@ -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 groupMap=scanAllEntryGroups(); for(EntryGroup group:groupMap.values()){ - List entryBlockList=getEntriesToRemove(group); - removeEntryBlocks(entryBlockList); + List 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 removeList){ - for(EntryBlock entryBlock:removeList){ - removeEntryBlock(entryBlock); + private void removeEntries(List 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 getEntriesToRemove(EntryGroup group){ - List results=new ArrayList<>(); - EntryBlock mainEntry=group.pickOne(); + private List getEntriesToRemove(EntryGroup group){ + List results=new ArrayList<>(); + Entry mainEntry=group.pickOne(); if(mainEntry==null){ return results; } - Iterator itr = group.iterator(true); + Iterator 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; } diff --git a/src/main/java/com/reandroid/arsc/value/BaseResValue.java b/src/main/java/com/reandroid/arsc/value/BaseResValue.java deleted file mode 100755 index b1db9e3..0000000 --- a/src/main/java/com/reandroid/arsc/value/BaseResValue.java +++ /dev/null @@ -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 { - 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"; -} diff --git a/src/main/java/com/reandroid/arsc/value/BaseResValueItem.java b/src/main/java/com/reandroid/arsc/value/BaseResValueItem.java deleted file mode 100755 index 914d1b3..0000000 --- a/src/main/java/com/reandroid/arsc/value/BaseResValueItem.java +++ /dev/null @@ -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); - } -} diff --git a/src/main/java/com/reandroid/arsc/value/Entry.java b/src/main/java/com/reandroid/arsc/value/Entry.java new file mode 100755 index 0000000..9d741d1 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/Entry.java @@ -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 { + 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(); + } + } diff --git a/src/main/java/com/reandroid/arsc/value/EntryBlock.java b/src/main/java/com/reandroid/arsc/value/EntryBlock.java deleted file mode 100755 index 7364510..0000000 --- a/src/main/java/com/reandroid/arsc/value/EntryBlock.java +++ /dev/null @@ -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 { - 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 getTableStringReferences(){ - if(isNull()){ - return null; - } - List 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"; - -} diff --git a/src/main/java/com/reandroid/arsc/value/EntryHeader.java b/src/main/java/com/reandroid/arsc/value/EntryHeader.java new file mode 100644 index 0000000..0dbc068 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/EntryHeader.java @@ -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; +} diff --git a/src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java b/src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java new file mode 100644 index 0000000..f2ea76d --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java @@ -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"; +} diff --git a/src/main/java/com/reandroid/arsc/value/Header.java b/src/main/java/com/reandroid/arsc/value/Header.java new file mode 100644 index 0000000..bcc1f7f --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/Header.java @@ -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 { + 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"; +} diff --git a/src/main/java/com/reandroid/arsc/value/ResTableEntry.java b/src/main/java/com/reandroid/arsc/value/ResTableEntry.java new file mode 100644 index 0000000..f72678b --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/ResTableEntry.java @@ -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 { + 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"; +} diff --git a/src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java b/src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java new file mode 100644 index 0000000..74f636a --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java @@ -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 { + 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;i0){ + if(max!=len){ + builder.append("\n ..."); + } + builder.append("\n "); + } + return builder.toString(); + } + + public static final String NAME_values = "values"; +} diff --git a/src/main/java/com/reandroid/arsc/value/ResValue.java b/src/main/java/com/reandroid/arsc/value/ResValue.java new file mode 100755 index 0000000..047397e --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/ResValue.java @@ -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; + +} diff --git a/src/main/java/com/reandroid/arsc/value/ResValueBag.java b/src/main/java/com/reandroid/arsc/value/ResValueBag.java deleted file mode 100755 index 5d72da8..0000000 --- a/src/main/java/com/reandroid/arsc/value/ResValueBag.java +++ /dev/null @@ -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 getTableStringReferences(){ - List 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(); - } - -} diff --git a/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java b/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java deleted file mode 100755 index 0e0bcdb..0000000 --- a/src/main/java/com/reandroid/arsc/value/ResValueBagItem.java +++ /dev/null @@ -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; - -} diff --git a/src/main/java/com/reandroid/arsc/value/ResValueInt.java b/src/main/java/com/reandroid/arsc/value/ResValueInt.java deleted file mode 100755 index 0925d64..0000000 --- a/src/main/java/com/reandroid/arsc/value/ResValueInt.java +++ /dev/null @@ -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; - -} diff --git a/src/main/java/com/reandroid/arsc/value/ResValueMap.java b/src/main/java/com/reandroid/arsc/value/ResValueMap.java new file mode 100755 index 0000000..62e0c8c --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/ResValueMap.java @@ -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()); + } + +} diff --git a/src/main/java/com/reandroid/arsc/value/ResValueReference.java b/src/main/java/com/reandroid/arsc/value/ResValueReference.java deleted file mode 100644 index bf8376d..0000000 --- a/src/main/java/com/reandroid/arsc/value/ResValueReference.java +++ /dev/null @@ -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); - } -} diff --git a/src/main/java/com/reandroid/arsc/value/TableEntry.java b/src/main/java/com/reandroid/arsc/value/TableEntry.java new file mode 100644 index 0000000..8ecb21f --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/TableEntry.java @@ -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
extends Block implements + JSONConvert { + 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()+"}"; + } +} diff --git a/src/main/java/com/reandroid/arsc/value/ValueItem.java b/src/main/java/com/reandroid/arsc/value/ValueItem.java new file mode 100755 index 0000000..bffe3d9 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/value/ValueItem.java @@ -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{ + 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"; + } diff --git a/src/main/java/com/reandroid/arsc/value/array/ArrayBag.java b/src/main/java/com/reandroid/arsc/value/array/ArrayBag.java index 4fd6fff..108a0cb 100644 --- a/src/main/java/com/reandroid/arsc/value/array/ArrayBag.java +++ b/src/main/java/com/reandroid/arsc/value/array/ArrayBag.java @@ -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; } diff --git a/src/main/java/com/reandroid/arsc/value/array/ArrayBagItem.java b/src/main/java/com/reandroid/arsc/value/array/ArrayBagItem.java index 3c7697c..4a91758 100644 --- a/src/main/java/com/reandroid/arsc/value/array/ArrayBagItem.java +++ b/src/main/java/com/reandroid/arsc/value/array/ArrayBagItem.java @@ -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(""); 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 results=new ArrayList<>(); for(int i=0;i>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 duplicates=new HashSet<>(); List results=new ArrayList<>(); for(int i=0;i> 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; } diff --git a/src/main/java/com/reandroid/arsc/value/style/StyleBag.java b/src/main/java/com/reandroid/arsc/value/style/StyleBag.java index b0ad88e..1c7e627 100644 --- a/src/main/java/com/reandroid/arsc/value/style/StyleBag.java +++ b/src/main/java/com/reandroid/arsc/value/style/StyleBag.java @@ -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; } diff --git a/src/main/java/com/reandroid/arsc/value/style/StyleBagItem.java b/src/main/java/com/reandroid/arsc/value/style/StyleBagItem.java index 999adbc..1348e0c 100644 --- a/src/main/java/com/reandroid/arsc/value/style/StyleBagItem.java +++ b/src/main/java/com/reandroid/arsc/value/style/StyleBagItem.java @@ -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(""); 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 results=new ArrayList<>(); for(int i=0;i