mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 14:24:25 +02:00
rename classes
This commit is contained in:
parent
3f7dc3bf9f
commit
7430b40c54
@ -24,7 +24,7 @@ import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||
import com.reandroid.arsc.group.StringGroup;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -180,11 +180,11 @@ public class ApkModule {
|
||||
continue;
|
||||
}
|
||||
for(TableString tableString:groupTableString.listItems()){
|
||||
List<EntryBlock> entryBlockList = tableString.listReferencedEntries(true);
|
||||
if(entryBlockList.size()==0){
|
||||
List<Entry> entryList = tableString.listReferencedEntries(true);
|
||||
if(entryList.size()==0){
|
||||
continue;
|
||||
}
|
||||
ResFile resFile=new ResFile(inputSource, entryBlockList);
|
||||
ResFile resFile=new ResFile(inputSource, entryList);
|
||||
results.add(resFile);
|
||||
}
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ import java.util.*;
|
||||
}
|
||||
private void decodeResRaw(File outDir, ResFile resFile)
|
||||
throws IOException {
|
||||
EntryBlock entryBlock=resFile.pickOne();
|
||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
||||
Entry entry =resFile.pickOne();
|
||||
PackageBlock packageBlock= entry.getPackageBlock();
|
||||
|
||||
File pkgDir=new File(outDir, getPackageDirName(packageBlock));
|
||||
File resDir=new File(pkgDir, ApkUtil.RES_DIR_NAME);
|
||||
@ -128,8 +128,8 @@ import java.util.*;
|
||||
}
|
||||
private void decodeResXml(EntryStore entryStore, File outDir, ResFile resFile)
|
||||
throws IOException, XMLException{
|
||||
EntryBlock entryBlock=resFile.pickOne();
|
||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
||||
Entry entry =resFile.pickOne();
|
||||
PackageBlock packageBlock= entry.getPackageBlock();
|
||||
ResXmlDocument resXmlDocument =new ResXmlDocument();
|
||||
resXmlDocument.readBytes(resFile.getInputSource().openStream());
|
||||
|
||||
@ -181,24 +181,24 @@ import java.util.*;
|
||||
xmlDocument.save(file, true);
|
||||
addDecodedPath(AndroidManifestBlock.FILE_NAME);
|
||||
}
|
||||
private void addDecodedEntry(EntryBlock entryBlock){
|
||||
if(entryBlock.isNull()){
|
||||
private void addDecodedEntry(Entry entry){
|
||||
if(entry.isNull()){
|
||||
return;
|
||||
}
|
||||
int resourceId=entryBlock.getResourceId();
|
||||
int resourceId= entry.getResourceId();
|
||||
Set<ResConfig> resConfigSet=decodedEntries.get(resourceId);
|
||||
if(resConfigSet==null){
|
||||
resConfigSet=new HashSet<>();
|
||||
decodedEntries.put(resourceId, resConfigSet);
|
||||
}
|
||||
resConfigSet.add(entryBlock.getResConfig());
|
||||
resConfigSet.add(entry.getResConfig());
|
||||
}
|
||||
private boolean containsDecodedEntry(EntryBlock entryBlock){
|
||||
Set<ResConfig> resConfigSet=decodedEntries.get(entryBlock.getResourceId());
|
||||
private boolean containsDecodedEntry(Entry entry){
|
||||
Set<ResConfig> resConfigSet=decodedEntries.get(entry.getResourceId());
|
||||
if(resConfigSet==null){
|
||||
return false;
|
||||
}
|
||||
return resConfigSet.contains(entryBlock.getResConfig());
|
||||
return resConfigSet.contains(entry.getResConfig());
|
||||
}
|
||||
private void decodeValues(EntryStore entryStore, File outDir, TableBlock tableBlock) throws IOException {
|
||||
for(PackageBlock packageBlock:tableBlock.listPackages()){
|
||||
@ -221,11 +221,11 @@ import java.util.*;
|
||||
private void decodeValues(EntryStore entryStore, File outDir, TypeBlock typeBlock) throws IOException {
|
||||
XMLDocument xmlDocument = new XMLDocument("resources");
|
||||
XMLElement docElement = xmlDocument.getDocumentElement();
|
||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
||||
if(containsDecodedEntry(entryBlock)){
|
||||
for(Entry entry :typeBlock.listEntries(true)){
|
||||
if(containsDecodedEntry(entry)){
|
||||
continue;
|
||||
}
|
||||
docElement.addChild(decodeValue(entryStore, entryBlock));
|
||||
docElement.addChild(decodeValue(entryStore, entry));
|
||||
}
|
||||
if(docElement.getChildesCount()==0){
|
||||
return;
|
||||
@ -240,28 +240,28 @@ import java.util.*;
|
||||
file=new File(file, type+".xml");
|
||||
xmlDocument.save(file, false);
|
||||
}
|
||||
private XMLElement decodeValue(EntryStore entryStore, EntryBlock entryBlock){
|
||||
XMLElement element=new XMLElement(entryBlock.getTypeName());
|
||||
int resourceId=entryBlock.getResourceId();
|
||||
XMLAttribute attribute=new XMLAttribute("name", entryBlock.getName());
|
||||
private XMLElement decodeValue(EntryStore entryStore, Entry entry){
|
||||
XMLElement element=new XMLElement(entry.getTypeName());
|
||||
int resourceId= entry.getResourceId();
|
||||
XMLAttribute attribute=new XMLAttribute("name", entry.getName());
|
||||
element.addAttribute(attribute);
|
||||
attribute.setNameId(resourceId);
|
||||
element.setResourceId(resourceId);
|
||||
if(!entryBlock.isEntryTypeBag()){
|
||||
ResValueInt resValueInt=(ResValueInt) entryBlock.getResValue();
|
||||
if(resValueInt.getValueType()== ValueType.STRING){
|
||||
if(!entry.isComplex()){
|
||||
ResValue resValue =(ResValue) entry.getTableEntry().getValue();
|
||||
if(resValue.getValueType()== ValueType.STRING){
|
||||
XmlHelper.setTextContent(element,
|
||||
resValueInt.getValueAsPoolString());
|
||||
resValue.getDataAsPoolString());
|
||||
}else {
|
||||
String value = ValueDecoder.decodeEntryValue(entryStore,
|
||||
entryBlock.getPackageBlock(),
|
||||
resValueInt.getValueType(),
|
||||
resValueInt.getData());
|
||||
entry.getPackageBlock(),
|
||||
resValue.getValueType(),
|
||||
resValue.getData());
|
||||
element.setTextContent(value);
|
||||
}
|
||||
}else {
|
||||
ResValueBag resValueBag=(ResValueBag) entryBlock.getResValue();
|
||||
xmlBagDecoder.decode(resValueBag, element);
|
||||
ResTableMapEntry mapEntry = (ResTableMapEntry) entry.getTableEntry();
|
||||
xmlBagDecoder.decode(mapEntry, element);
|
||||
return element;
|
||||
}
|
||||
return element;
|
||||
|
@ -19,7 +19,7 @@ import com.reandroid.archive.InputSource;
|
||||
import com.reandroid.apk.xmlencoder.XMLEncodeSource;
|
||||
import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.*;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
@ -28,23 +28,23 @@ import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class ResFile {
|
||||
private final List<EntryBlock> entryBlockList;
|
||||
private final List<Entry> entryList;
|
||||
private final InputSource inputSource;
|
||||
private boolean mBinXml;
|
||||
private boolean mBinXmlChecked;
|
||||
private String mFileExtension;
|
||||
private boolean mFileExtensionChecked;
|
||||
private EntryBlock mSelectedEntryBlock;
|
||||
public ResFile(InputSource inputSource, List<EntryBlock> entryBlockList){
|
||||
private Entry mSelectedEntry;
|
||||
public ResFile(InputSource inputSource, List<Entry> entryList){
|
||||
this.inputSource=inputSource;
|
||||
this.entryBlockList=entryBlockList;
|
||||
this.entryList = entryList;
|
||||
}
|
||||
public List<EntryBlock> getEntryBlockList(){
|
||||
return entryBlockList;
|
||||
public List<Entry> getEntryList(){
|
||||
return entryList;
|
||||
}
|
||||
public String validateTypeDirectoryName(){
|
||||
EntryBlock entryBlock=pickOne();
|
||||
if(entryBlock==null){
|
||||
Entry entry =pickOne();
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
String path=getFilePath();
|
||||
@ -61,34 +61,34 @@ public class ResFile {
|
||||
i++;
|
||||
name=path.substring(i);
|
||||
}
|
||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
||||
TypeBlock typeBlock= entry.getTypeBlock();
|
||||
String typeName=typeBlock.getTypeName()+typeBlock.getResConfig().getQualifiers();
|
||||
return root+typeName+"/"+name;
|
||||
}
|
||||
public EntryBlock pickOne(){
|
||||
if(mSelectedEntryBlock==null){
|
||||
mSelectedEntryBlock=selectOne();
|
||||
public Entry pickOne(){
|
||||
if(mSelectedEntry ==null){
|
||||
mSelectedEntry =selectOne();
|
||||
}
|
||||
return mSelectedEntryBlock;
|
||||
return mSelectedEntry;
|
||||
}
|
||||
private EntryBlock selectOne(){
|
||||
List<EntryBlock> entryList = entryBlockList;
|
||||
private Entry selectOne(){
|
||||
List<Entry> entryList = this.entryList;
|
||||
if(entryList.size()==0){
|
||||
return null;
|
||||
}
|
||||
for(EntryBlock entryBlock:entryList){
|
||||
if(!entryBlock.isNull() && entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
for(Entry entry :entryList){
|
||||
if(!entry.isNull() && entry.isDefault()){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
for(EntryBlock entryBlock:entryList){
|
||||
if(!entryBlock.isNull()){
|
||||
return entryBlock;
|
||||
for(Entry entry :entryList){
|
||||
if(!entry.isNull()){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
for(EntryBlock entryBlock:entryList){
|
||||
if(entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
for(Entry entry :entryList){
|
||||
if(entry.isDefault()){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return entryList.get(0);
|
||||
@ -98,8 +98,13 @@ public class ResFile {
|
||||
}
|
||||
public void setFilePath(String filePath){
|
||||
getInputSource().setAlias(filePath);
|
||||
for(EntryBlock entryBlock:entryBlockList){
|
||||
entryBlock.getValueAsTableString().set(filePath);
|
||||
for(Entry entry : entryList){
|
||||
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||
if(!(tableEntry instanceof ResTableEntry)){
|
||||
continue;
|
||||
}
|
||||
ResValue resValue = ((ResTableEntry) tableEntry).getValue();
|
||||
resValue.setValueAsString(filePath);
|
||||
}
|
||||
}
|
||||
public InputSource getInputSource() {
|
||||
@ -143,13 +148,13 @@ public class ResFile {
|
||||
return new File(dir, path);
|
||||
}
|
||||
public String buildPath(){
|
||||
EntryBlock entryBlock=pickOne();
|
||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
||||
Entry entry =pickOne();
|
||||
TypeBlock typeBlock= entry.getTypeBlock();
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(typeBlock.getTypeName());
|
||||
builder.append(typeBlock.getQualifiers());
|
||||
builder.append('/');
|
||||
builder.append(entryBlock.getName());
|
||||
builder.append(entry.getName());
|
||||
String ext=getFileExtension();
|
||||
if(ext!=null){
|
||||
builder.append(ext);
|
||||
|
@ -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))){
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ package com.reandroid.apk.xmldecoder;
|
||||
import com.reandroid.apk.ApkUtil;
|
||||
import com.reandroid.apk.XmlHelper;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.common.EntryStore;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
@ -33,16 +33,16 @@ import java.util.Set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
|
||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
||||
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
|
||||
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||
EntryStore entryStore=getEntryStore();
|
||||
Set<ValueType> valueTypes = new HashSet<>();
|
||||
for(int i=0;i<bagItems.length;i++){
|
||||
ResValueBagItem bagItem = bagItems[i];
|
||||
ResValueMap bagItem = bagItems[i];
|
||||
ValueType valueType = bagItem.getValueType();
|
||||
XMLElement child = new XMLElement("item");
|
||||
if(valueType == ValueType.STRING){
|
||||
XmlHelper.setTextContent(child, bagItem.getValueAsPoolString());
|
||||
XmlHelper.setTextContent(child, bagItem.getDataAsPoolString());
|
||||
}else {
|
||||
String value = ValueDecoder.decodeIntEntry(entryStore, bagItem);
|
||||
child.setTextContent(value);
|
||||
@ -57,25 +57,28 @@ import java.util.Set;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean canDecode(ResValueBag resValueBag) {
|
||||
return isResBagArrayValue(resValueBag);
|
||||
public boolean canDecode(ResTableMapEntry mapEntry) {
|
||||
return isArrayValue(mapEntry);
|
||||
}
|
||||
public static boolean isResBagArrayValue(ResValueBag resValueBag){
|
||||
int parentId=resValueBag.getParentId();
|
||||
public static boolean isArrayValue(ResTableMapEntry mapEntry){
|
||||
int parentId=mapEntry.getParentId();
|
||||
if(parentId!=0){
|
||||
return false;
|
||||
}
|
||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
||||
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||
if(bagItems==null||bagItems.length==0){
|
||||
return false;
|
||||
}
|
||||
int len=bagItems.length;
|
||||
for(int i=0;i<len;i++){
|
||||
ResValueBagItem item=bagItems[i];
|
||||
if(item.getIdHigh()!=0x0100 && item.getIdHigh()!=0x0200){
|
||||
ResValueMap item=bagItems[i];
|
||||
int name = item.getName();
|
||||
int high = (name >> 16) & 0xffff;
|
||||
if(high!=0x0100 && high!=0x0200){
|
||||
return false;
|
||||
}
|
||||
int id=item.getIdLow()-1;
|
||||
int low = name & 0xffff;
|
||||
int id = low - 1;
|
||||
if(id!=i){
|
||||
return false;
|
||||
}
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,7 @@ package com.reandroid.apk.xmldecoder;
|
||||
|
||||
import com.reandroid.apk.XmlHelper;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.BaseResValue;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.arsc.value.*;
|
||||
import com.reandroid.arsc.value.plurals.PluralsQuantity;
|
||||
import com.reandroid.common.EntryStore;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
@ -30,19 +27,19 @@ class XMLPluralsDecoder extends BagDecoder{
|
||||
super(entryStore);
|
||||
}
|
||||
@Override
|
||||
public void decode(ResValueBag resValueBag, XMLElement parentElement) {
|
||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
||||
public void decode(ResTableMapEntry mapEntry, XMLElement parentElement) {
|
||||
ResValueMap[] bagItems = mapEntry.listResValueMap();
|
||||
int len=bagItems.length;
|
||||
EntryStore entryStore=getEntryStore();
|
||||
for(int i=0;i<len;i++){
|
||||
ResValueBagItem item = bagItems[i];
|
||||
|
||||
PluralsQuantity quantity = PluralsQuantity.valueOf(item.getIdLow());
|
||||
ResValueMap item = bagItems[i];
|
||||
int low = item.getName() & 0xffff;
|
||||
PluralsQuantity quantity = PluralsQuantity.valueOf((short) low);
|
||||
XMLElement child=new XMLElement("item");
|
||||
child.setAttribute("quantity", quantity.toString());
|
||||
|
||||
if(item.getValueType() == ValueType.STRING){
|
||||
XmlHelper.setTextContent(child, item.getValueAsPoolString());
|
||||
XmlHelper.setTextContent(child, item.getDataAsPoolString());
|
||||
}else {
|
||||
String value = ValueDecoder.decodeIntEntry(entryStore, item);
|
||||
child.setTextContent(value);
|
||||
@ -53,27 +50,29 @@ class XMLPluralsDecoder extends BagDecoder{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDecode(ResValueBag resValueBag) {
|
||||
return isResBagPluralsValue(resValueBag);
|
||||
public boolean canDecode(ResTableMapEntry mapEntry) {
|
||||
return isResBagPluralsValue(mapEntry);
|
||||
}
|
||||
|
||||
public static boolean isResBagPluralsValue(BaseResValue baseResValue){
|
||||
ResValueBag resValueBag=(ResValueBag)baseResValue;
|
||||
int parentId=resValueBag.getParentId();
|
||||
public static boolean isResBagPluralsValue(ResTableMapEntry valueItem){
|
||||
int parentId=valueItem.getParentId();
|
||||
if(parentId!=0){
|
||||
return false;
|
||||
}
|
||||
ResValueBagItem[] bagItems = resValueBag.getBagItems();
|
||||
ResValueMap[] bagItems = valueItem.listResValueMap();
|
||||
if(bagItems==null||bagItems.length==0){
|
||||
return false;
|
||||
}
|
||||
int len=bagItems.length;
|
||||
for(int i=0;i<len;i++){
|
||||
ResValueBagItem item=bagItems[i];
|
||||
if(item.getIdHigh()!=0x0100){
|
||||
ResValueMap item=bagItems[i];
|
||||
int name = item.getName();
|
||||
int high = (name >> 16) & 0xffff;
|
||||
if(high!=0x0100){
|
||||
return false;
|
||||
}
|
||||
PluralsQuantity pq=PluralsQuantity.valueOf(item.getIdLow());
|
||||
int low = name & 0xffff;
|
||||
PluralsQuantity pq=PluralsQuantity.valueOf((short) low);
|
||||
if(pq==null){
|
||||
return false;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
import com.reandroid.arsc.item.SpecString;
|
||||
import com.reandroid.arsc.util.FrameworkTable;
|
||||
import com.reandroid.arsc.util.ResNameMap;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.common.Frameworks;
|
||||
import com.reandroid.common.ResourceResolver;
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
private APKLogger apkLogger;
|
||||
private boolean mForceCreateNamespaces = true;
|
||||
private Set<String> mFrameworkPackageNames;
|
||||
private final ResNameMap<EntryBlock> mLocalResNameMap = new ResNameMap<>();
|
||||
private final ResNameMap<Entry> mLocalResNameMap = new ResNameMap<>();
|
||||
public EncodeMaterials(){
|
||||
}
|
||||
public SpecString getSpecString(String name){
|
||||
@ -49,7 +49,7 @@
|
||||
.get(name)
|
||||
.get(0);
|
||||
}
|
||||
public EntryBlock getAttributeBlock(String refString){
|
||||
public Entry getAttributeBlock(String refString){
|
||||
String packageName = null;
|
||||
String type = "attr";
|
||||
String name = refString;
|
||||
@ -62,7 +62,7 @@
|
||||
|| packageName.equals(getCurrentPackageName())
|
||||
|| !isFrameworkPackageName(packageName)){
|
||||
|
||||
return getLocalEntryBlock(type, name);
|
||||
return getLocalEntry(type, name);
|
||||
}
|
||||
return getFrameworkEntry(type, name);
|
||||
}
|
||||
@ -105,9 +105,9 @@
|
||||
", name="+name);
|
||||
}
|
||||
public int resolveFrameworkResourceId(String packageName, String type, String name){
|
||||
EntryBlock entryBlock = getFrameworkEntry(packageName, type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock.getResourceId();
|
||||
Entry entry = getFrameworkEntry(packageName, type, name);
|
||||
if(entry !=null){
|
||||
return entry.getResourceId();
|
||||
}
|
||||
throw new EncodeException("Framework entry not found: " +
|
||||
"package="+packageName+
|
||||
@ -115,9 +115,9 @@
|
||||
", name="+name);
|
||||
}
|
||||
public int resolveFrameworkResourceId(int packageId, String type, String name){
|
||||
EntryBlock entryBlock = getFrameworkEntry(packageId, type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock.getResourceId();
|
||||
Entry entry = getFrameworkEntry(packageId, type, name);
|
||||
if(entry !=null){
|
||||
return entry.getResourceId();
|
||||
}
|
||||
throw new EncodeException("Framework entry not found: " +
|
||||
"packageId="+String.format("0x%02x", packageId)+
|
||||
@ -141,23 +141,23 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public EntryBlock getLocalEntryBlock(String type, String name){
|
||||
EntryBlock entryBlock=mLocalResNameMap.get(type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
public Entry getLocalEntry(String type, String name){
|
||||
Entry entry =mLocalResNameMap.get(type, name);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
loadLocalEntryBlockMap(type);
|
||||
entryBlock=mLocalResNameMap.get(type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
loadLocalEntryMap(type);
|
||||
entry =mLocalResNameMap.get(type, name);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
entryBlock= searchLocalEntryBlock(type, name);
|
||||
if(entryBlock!=null){
|
||||
mLocalResNameMap.add(type, name, entryBlock);
|
||||
entry = searchLocalEntry(type, name);
|
||||
if(entry !=null){
|
||||
mLocalResNameMap.add(type, name, entry);
|
||||
}
|
||||
return entryBlock;
|
||||
return entry;
|
||||
}
|
||||
private EntryBlock searchLocalEntryBlock(String type, String name){
|
||||
private Entry searchLocalEntry(String type, String name){
|
||||
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
||||
if(type.equals(entryGroup.getTypeName()) &&
|
||||
name.equals(entryGroup.getSpecName())){
|
||||
@ -167,9 +167,9 @@
|
||||
SpecTypePair specTypePair=currentPackage.searchByTypeName(type);
|
||||
if(specTypePair!=null){
|
||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
||||
if(name.equals(entryBlock.getName())){
|
||||
return entryBlock;
|
||||
for(Entry entry :typeBlock.listEntries(true)){
|
||||
if(name.equals(entry.getName())){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -182,9 +182,9 @@
|
||||
specTypePair=packageBlock.searchByTypeName(type);
|
||||
if(specTypePair!=null){
|
||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
||||
if(name.equals(entryBlock.getName())){
|
||||
return entryBlock;
|
||||
for(Entry entry :typeBlock.listEntries(true)){
|
||||
if(name.equals(entry.getName())){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -193,25 +193,25 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void loadLocalEntryBlockMap(String type){
|
||||
ResNameMap<EntryBlock> localMap = mLocalResNameMap;
|
||||
private void loadLocalEntryMap(String type){
|
||||
ResNameMap<Entry> localMap = mLocalResNameMap;
|
||||
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
||||
SpecTypePair specTypePair=packageBlock.searchByTypeName(type);
|
||||
if(specTypePair!=null){
|
||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||
for(EntryBlock entryBlock:typeBlock.listEntries(true)){
|
||||
localMap.add(entryBlock.getTypeName(),
|
||||
entryBlock.getName(), entryBlock);
|
||||
for(Entry entry :typeBlock.listEntries(true)){
|
||||
localMap.add(entry.getTypeName(),
|
||||
entry.getName(), entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public EntryBlock getFrameworkEntry(String type, String name){
|
||||
public Entry getFrameworkEntry(String type, String name){
|
||||
for(FrameworkTable table:frameworkTables){
|
||||
EntryBlock entryBlock = table.searchEntryBlock(type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
Entry entry = table.searchEntry(type, name);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -232,26 +232,26 @@
|
||||
mFrameworkPackageNames=results;
|
||||
return results;
|
||||
}
|
||||
public EntryBlock getFrameworkEntry(String packageName, String type, String name){
|
||||
public Entry getFrameworkEntry(String packageName, String type, String name){
|
||||
for(FrameworkTable table:frameworkTables){
|
||||
for(PackageBlock packageBlock:table.listPackages()){
|
||||
if(packageName.equals(packageBlock.getName())){
|
||||
EntryBlock entryBlock = table.searchEntryBlock(type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
Entry entry = table.searchEntry(type, name);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public EntryBlock getFrameworkEntry(int packageId, String type, String name){
|
||||
public Entry getFrameworkEntry(int packageId, String type, String name){
|
||||
for(FrameworkTable table:frameworkTables){
|
||||
for(PackageBlock packageBlock:table.listPackages()){
|
||||
if(packageId==packageBlock.getId()){
|
||||
EntryBlock entryBlock = table.searchEntryBlock(type, name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
Entry entry = table.searchEntry(type, name);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import com.reandroid.arsc.container.SpecTypePair;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.item.SpecString;
|
||||
import com.reandroid.arsc.pool.TypeStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.xml.XMLDocument;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
@ -37,7 +37,7 @@ class XMLValuesEncoder {
|
||||
|
||||
int count = documentElement.getChildesCount();
|
||||
|
||||
typeBlock.getEntryBlockArray().ensureSize(count);
|
||||
typeBlock.getEntryArray().ensureSize(count);
|
||||
|
||||
for(int i=0;i<count;i++){
|
||||
XMLElement element = documentElement.getChildAt(i);
|
||||
@ -48,45 +48,46 @@ class XMLValuesEncoder {
|
||||
String name = element.getAttributeValue("name");
|
||||
int resourceId = getMaterials()
|
||||
.resolveLocalResourceId(typeBlock.getTypeName(), name);
|
||||
EntryBlock entryBlock = typeBlock
|
||||
Entry entry = typeBlock
|
||||
.getOrCreateEntry((short) (0xffff & resourceId));
|
||||
|
||||
encodeValue(entryBlock, element);
|
||||
encodeValue(entry, element);
|
||||
|
||||
SpecString specString = getMaterials().getSpecString(name);
|
||||
entryBlock.setSpecReference(specString);
|
||||
entry.setSpecReference(specString);
|
||||
entry.getPackageBlock().onEntryAdded(entry);
|
||||
}
|
||||
void encodeValue(EntryBlock entryBlock, XMLElement element){
|
||||
void encodeValue(Entry entry, XMLElement element){
|
||||
String value = getValue(element);
|
||||
encodeValue(entryBlock, value);
|
||||
encodeValue(entry, value);
|
||||
}
|
||||
void encodeValue(EntryBlock entryBlock, String value){
|
||||
void encodeValue(Entry entry, String value){
|
||||
if(EncodeUtil.isEmpty(value)){
|
||||
encodeNullValue(entryBlock);
|
||||
encodeNullValue(entry);
|
||||
}else if(isLiteralEmpty(value)){
|
||||
encodeLiteralEmptyValue(entryBlock, value);
|
||||
encodeLiteralEmptyValue(entry, value);
|
||||
}else if(isBoolean(value)){
|
||||
encodeBooleanValue(entryBlock, value);
|
||||
encodeBooleanValue(entry, value);
|
||||
}else if(ValueDecoder.isReference(value)){
|
||||
encodeReferenceValue(entryBlock, value);
|
||||
encodeReferenceValue(entry, value);
|
||||
}else {
|
||||
encodeStringValue(entryBlock, value);
|
||||
encodeStringValue(entry, value);
|
||||
}
|
||||
}
|
||||
void encodeNullValue(EntryBlock entryBlock){
|
||||
void encodeNullValue(Entry entry){
|
||||
// Nothing to do
|
||||
}
|
||||
void encodeLiteralEmptyValue(EntryBlock entryBlock, String value){
|
||||
entryBlock.setValueAsRaw(ValueType.NULL, 0);
|
||||
void encodeLiteralEmptyValue(Entry entry, String value){
|
||||
entry.setValueAsRaw(ValueType.NULL, 0);
|
||||
}
|
||||
void encodeBooleanValue(EntryBlock entryBlock, String value){
|
||||
entryBlock.setValueAsBoolean("true".equals(value.toLowerCase()));
|
||||
void encodeBooleanValue(Entry entry, String value){
|
||||
entry.setValueAsBoolean("true".equals(value.toLowerCase()));
|
||||
}
|
||||
void encodeReferenceValue(EntryBlock entryBlock, String value){
|
||||
void encodeReferenceValue(Entry entry, String value){
|
||||
int resourceId = getMaterials().resolveReference(value);
|
||||
entryBlock.setValueAsReference(resourceId);
|
||||
entry.setValueAsReference(resourceId);
|
||||
}
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
|
||||
}
|
||||
private TypeBlock getTypeBlock(String type, String qualifiers){
|
||||
@ -98,7 +99,7 @@ class XMLValuesEncoder {
|
||||
int highest = specTypePair.getHighestEntryCount();
|
||||
TypeBlock typeBlock = specTypePair
|
||||
.getOrCreateTypeBlock(qualifiers);
|
||||
typeBlock.getEntryBlockArray().ensureSize(highest);
|
||||
typeBlock.getEntryArray().ensureSize(highest);
|
||||
return typeBlock;
|
||||
}
|
||||
EncodeMaterials getMaterials() {
|
||||
|
@ -16,10 +16,10 @@
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.apk.ApkUtil;
|
||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
||||
import com.reandroid.arsc.array.ResValueMapArray;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
|
||||
@ -28,7 +28,7 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
||||
void encodeChildes(XMLElement parentElement, ResTableMapEntry mapEntry){
|
||||
int count = parentElement.getChildesCount();
|
||||
String tagName = parentElement.getTagName();
|
||||
boolean force_string = false;
|
||||
@ -38,12 +38,12 @@ class XMLValuesEncoderArray extends XMLValuesEncoderBag{
|
||||
}else if(ApkUtil.TAG_INTEGER_ARRAY.equals(tagName)){
|
||||
force_integer = true;
|
||||
}
|
||||
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
|
||||
ResValueMapArray itemArray = mapEntry.getValue();
|
||||
for(int i=0;i<count;i++){
|
||||
XMLElement child=parentElement.getChildAt(i);
|
||||
ResValueBagItem bagItem = itemArray.get(i);
|
||||
bagItem.setIdHigh((short) 0x0100);
|
||||
bagItem.setIdLow((short) (i+1));
|
||||
ResValueMap bagItem = itemArray.get(i);
|
||||
bagItem.setNameHigh((short) 0x0100);
|
||||
bagItem.setNameLow((short) (i+1));
|
||||
|
||||
String valueText=child.getTextContent();
|
||||
|
||||
|
@ -15,10 +15,10 @@
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
||||
import com.reandroid.arsc.array.ResValueMapArray;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||
import com.reandroid.arsc.value.attribute.AttributeItemType;
|
||||
@ -39,21 +39,21 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
||||
return count;
|
||||
}
|
||||
@Override
|
||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
||||
encodeAttributes(parentElement, resValueBag);
|
||||
encodeEnumOrFlag(parentElement, resValueBag);
|
||||
void encodeChildes(XMLElement parentElement, ResTableMapEntry mapEntry){
|
||||
encodeAttributes(parentElement, mapEntry);
|
||||
encodeEnumOrFlag(parentElement, mapEntry);
|
||||
// TODO: re-check if this is necessary
|
||||
resValueBag.getEntryBlock().setPublic(true);
|
||||
mapEntry.getHeader().setPublic(true);
|
||||
}
|
||||
private void encodeAttributes(XMLElement parentElement, ResValueBag resValueBag){
|
||||
ResValueBagItemArray bagItemArray = resValueBag.getResValueBagItemArray();
|
||||
private void encodeAttributes(XMLElement parentElement, ResTableMapEntry mapEntry){
|
||||
ResValueMapArray mapArray = mapEntry.getValue();
|
||||
|
||||
int bagIndex=0;
|
||||
|
||||
ResValueBagItem formatItem = bagItemArray.get(bagIndex);
|
||||
ResValueMap formatItem = mapArray.get(bagIndex);
|
||||
|
||||
formatItem.setIdHigh((short) 0x0100);
|
||||
formatItem.setIdLow(AttributeItemType.FORMAT.getValue());
|
||||
formatItem.setNameHigh((short) 0x0100);
|
||||
formatItem.setNameLow(AttributeItemType.FORMAT.getValue());
|
||||
formatItem.setValueType(ValueType.INT_DEC);
|
||||
formatItem.setDataHigh(getChildTypes(parentElement));
|
||||
|
||||
@ -75,15 +75,15 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
||||
throw new EncodeException("Unknown attribute: '"+name
|
||||
+"', on attribute: "+attribute.toString());
|
||||
}
|
||||
ResValueBagItem bagItem = bagItemArray.get(bagIndex);
|
||||
bagItem.setIdHigh((short) 0x0100);
|
||||
bagItem.setIdLow(itemType.getValue());
|
||||
ResValueMap bagItem = mapArray.get(bagIndex);
|
||||
bagItem.setNameHigh((short) 0x0100);
|
||||
bagItem.setNameLow(itemType.getValue());
|
||||
bagItem.setValueType(ValueType.INT_DEC);
|
||||
bagItem.setData(ValueDecoder.parseInteger(attribute.getValue()));
|
||||
bagIndex++;
|
||||
}
|
||||
}
|
||||
private void encodeEnumOrFlag(XMLElement element, ResValueBag resValueBag){
|
||||
private void encodeEnumOrFlag(XMLElement element, ResTableMapEntry mapEntry){
|
||||
int count=element.getChildesCount();
|
||||
if(count==0){
|
||||
return;
|
||||
@ -94,7 +94,7 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
||||
}
|
||||
|
||||
EncodeMaterials materials = getMaterials();
|
||||
ResValueBagItemArray bagItemArray = resValueBag.getResValueBagItemArray();
|
||||
ResValueMapArray mapArray = mapEntry.getValue();
|
||||
|
||||
for(int i=0;i<count;i++){
|
||||
XMLElement child=element.getChildAt(i);
|
||||
@ -113,8 +113,8 @@ class XMLValuesEncoderAttr extends XMLValuesEncoderBag{
|
||||
throw new EncodeException("Unknown value for element '"+child.toText()+"'");
|
||||
}
|
||||
|
||||
ResValueBagItem bagItem = bagItemArray.get(i+offset);
|
||||
bagItem.setId(resourceId);
|
||||
ResValueMap bagItem = mapArray.get(i+offset);
|
||||
bagItem.setName(resourceId);
|
||||
bagItem.setValueType(encodeResult.valueType);
|
||||
bagItem.setData(encodeResult.value);
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
|
||||
class XMLValuesEncoderBag extends XMLValuesEncoder{
|
||||
@ -24,18 +24,19 @@ class XMLValuesEncoderBag extends XMLValuesEncoder{
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeValue(EntryBlock entryBlock, XMLElement element){
|
||||
ResValueBag resValueBag=new ResValueBag();
|
||||
entryBlock.setResValue(resValueBag);
|
||||
void encodeValue(Entry entry, XMLElement element){
|
||||
ResTableMapEntry tableMapEntry = new ResTableMapEntry();
|
||||
entry.setTableEntry(tableMapEntry);
|
||||
String parent=element.getAttributeValue("parent");
|
||||
if(!EncodeUtil.isEmpty(parent)){
|
||||
int parentId=getMaterials().resolveReference(parent);
|
||||
resValueBag.setParentId(parentId);
|
||||
tableMapEntry.getHeader().setParentId(parentId);
|
||||
}
|
||||
resValueBag.setCount(getChildesCount(element));
|
||||
encodeChildes(element, resValueBag);
|
||||
tableMapEntry.getValue().setChildesCount(getChildesCount(element));
|
||||
encodeChildes(element, tableMapEntry);
|
||||
tableMapEntry.refresh();
|
||||
}
|
||||
void encodeChildes(XMLElement element, ResValueBag resValueBag){
|
||||
void encodeChildes(XMLElement element, ResTableMapEntry mapEntry){
|
||||
throw new EncodeException("Unimplemented bag type encoder: "
|
||||
+element.getTagName());
|
||||
|
||||
|
@ -16,21 +16,21 @@
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
class XMLValuesEncoderColor extends XMLValuesEncoder{
|
||||
XMLValuesEncoderColor(EncodeMaterials materials) {
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeColor(value);
|
||||
if(encodeResult!=null){
|
||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
}else {
|
||||
// If reaches here the value might be
|
||||
// file path e.g. res/color/something.xml
|
||||
entryBlock.setValueAsString(value);
|
||||
entry.setValueAsString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,22 +16,22 @@
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
class XMLValuesEncoderCommon extends XMLValuesEncoder{
|
||||
XMLValuesEncoderCommon(EncodeMaterials materials) {
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
if(ValueDecoder.isReference(value)){
|
||||
entryBlock.setValueAsReference(getMaterials().resolveReference(value));
|
||||
entry.setValueAsReference(getMaterials().resolveReference(value));
|
||||
}else {
|
||||
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeGuessAny(value);
|
||||
if(encodeResult!=null){
|
||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
}else {
|
||||
entryBlock.setValueAsString(ValueDecoder
|
||||
entry.setValueAsString(ValueDecoder
|
||||
.unEscapeSpecialCharacter(value));
|
||||
}
|
||||
}
|
||||
|
@ -16,21 +16,21 @@
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
class XMLValuesEncoderDimen extends XMLValuesEncoder{
|
||||
XMLValuesEncoderDimen(EncodeMaterials materials) {
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
ValueDecoder.EncodeResult encodeResult =
|
||||
ValueDecoder.encodeDimensionOrFloat(value);
|
||||
if(encodeResult==null){
|
||||
encodeResult=ValueDecoder.encodeHexOrInt(value);
|
||||
}
|
||||
if(encodeResult!=null){
|
||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
}else {
|
||||
throw new EncodeException("Unknown dimen value: "+value);
|
||||
}
|
||||
|
@ -15,7 +15,8 @@
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Header;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
class XMLValuesEncoderId extends XMLValuesEncoder{
|
||||
public XMLValuesEncoderId(EncodeMaterials materials) {
|
||||
@ -23,21 +24,22 @@ class XMLValuesEncoderId extends XMLValuesEncoder{
|
||||
}
|
||||
|
||||
@Override
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
throw new EncodeException("Unexpected value for id: "+value);
|
||||
}
|
||||
@Override
|
||||
void encodeNullValue(EntryBlock entryBlock){
|
||||
entryBlock.setValueAsString("");
|
||||
setVisibility(entryBlock);
|
||||
void encodeNullValue(Entry entry){
|
||||
entry.setValueAsString("");
|
||||
setVisibility(entry);
|
||||
}
|
||||
@Override
|
||||
void encodeBooleanValue(EntryBlock entryBlock, String value){
|
||||
super.encodeBooleanValue(entryBlock, value);
|
||||
setVisibility(entryBlock);
|
||||
void encodeBooleanValue(Entry entry, String value){
|
||||
super.encodeBooleanValue(entry, value);
|
||||
setVisibility(entry);
|
||||
}
|
||||
private void setVisibility(EntryBlock entryBlock){
|
||||
entryBlock.setWeak(true);
|
||||
entryBlock.setPublic(true);
|
||||
private void setVisibility(Entry entry){
|
||||
Header header = entry.getHeader();
|
||||
header.setWeak(true);
|
||||
header.setPublic(true);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
|
||||
class XMLValuesEncoderInteger extends XMLValuesEncoder{
|
||||
@ -24,16 +24,16 @@ class XMLValuesEncoderInteger extends XMLValuesEncoder{
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
value=value.trim();
|
||||
if(ValueDecoder.isInteger(value)){
|
||||
entryBlock.setValueAsRaw(ValueType.INT_DEC, ValueDecoder.parseInteger(value));
|
||||
entry.setValueAsRaw(ValueType.INT_DEC, ValueDecoder.parseInteger(value));
|
||||
}else if(ValueDecoder.isHex(value)){
|
||||
entryBlock.setValueAsRaw(ValueType.INT_HEX, ValueDecoder.parseHex(value));
|
||||
entry.setValueAsRaw(ValueType.INT_HEX, ValueDecoder.parseHex(value));
|
||||
}else {
|
||||
ValueDecoder.EncodeResult encodeResult=ValueDecoder.encodeDimensionOrFloat(value);
|
||||
if(encodeResult!=null){
|
||||
entryBlock.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
entry.setValueAsRaw(encodeResult.valueType, encodeResult.value);
|
||||
}else {
|
||||
throw new EncodeException("Unknown value for type <integer>: '"+value+"'");
|
||||
}
|
||||
|
@ -15,10 +15,10 @@
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
||||
import com.reandroid.arsc.array.ResValueMapArray;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.arsc.value.plurals.PluralsQuantity;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
@ -28,20 +28,20 @@ class XMLValuesEncoderPlurals extends XMLValuesEncoderBag{
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
||||
void encodeChildes(XMLElement parentElement, ResTableMapEntry resValueBag){
|
||||
int count = parentElement.getChildesCount();
|
||||
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
|
||||
ResValueMapArray itemArray = resValueBag.getValue();
|
||||
for(int i=0;i<count;i++){
|
||||
XMLElement child=parentElement.getChildAt(i);
|
||||
ResValueBagItem bagItem = itemArray.get(i);
|
||||
ResValueMap bagItem = itemArray.get(i);
|
||||
PluralsQuantity quantity = PluralsQuantity
|
||||
.value(child.getAttributeValue("quantity"));
|
||||
if(quantity==null){
|
||||
throw new EncodeException("Unknown plurals quantity: "
|
||||
+child.toText());
|
||||
}
|
||||
bagItem.setIdHigh((short) 0x0100);
|
||||
bagItem.setIdLow(quantity.getId());
|
||||
bagItem.setNameHigh((short) 0x0100);
|
||||
bagItem.setNameLow(quantity.getId());
|
||||
|
||||
String valueText=child.getTextContent();
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
class XMLValuesEncoderString extends XMLValuesEncoder{
|
||||
XMLValuesEncoderString(EncodeMaterials materials) {
|
||||
@ -24,15 +24,15 @@ import com.reandroid.arsc.value.EntryBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
void encodeStringValue(EntryBlock entryBlock, String value){
|
||||
entryBlock.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
|
||||
void encodeStringValue(Entry entry, String value){
|
||||
entry.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
|
||||
}
|
||||
@Override
|
||||
void encodeNullValue(EntryBlock entryBlock){
|
||||
entryBlock.setValueAsString("");
|
||||
void encodeNullValue(Entry entry){
|
||||
entry.setValueAsString("");
|
||||
}
|
||||
@Override
|
||||
void encodeBooleanValue(EntryBlock entryBlock, String value){
|
||||
entryBlock.setValueAsString(value);
|
||||
void encodeBooleanValue(Entry entry, String value){
|
||||
entry.setValueAsString(value);
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,9 @@
|
||||
*/
|
||||
package com.reandroid.apk.xmlencoder;
|
||||
|
||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
||||
import com.reandroid.arsc.array.ResValueMapArray;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.arsc.value.*;
|
||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||
import com.reandroid.arsc.value.attribute.AttributeValueType;
|
||||
import com.reandroid.xml.XMLElement;
|
||||
@ -31,12 +28,12 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
||||
super(materials);
|
||||
}
|
||||
@Override
|
||||
void encodeChildes(XMLElement parentElement, ResValueBag resValueBag){
|
||||
void encodeChildes(XMLElement parentElement, ResTableMapEntry resValueBag){
|
||||
int count = parentElement.getChildesCount();
|
||||
ResValueBagItemArray itemArray = resValueBag.getResValueBagItemArray();
|
||||
ResValueMapArray itemArray = resValueBag.getValue();
|
||||
for(int i=0;i<count;i++){
|
||||
XMLElement child=parentElement.getChildAt(i);
|
||||
ResValueBagItem item = itemArray.get(i);
|
||||
ResValueMap item = itemArray.get(i);
|
||||
String name=child.getAttributeValue("name");
|
||||
int id=decodeUnknownAttributeHex(name);
|
||||
if(id!=0){
|
||||
@ -55,7 +52,7 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
||||
continue;
|
||||
}
|
||||
|
||||
EntryBlock attributeEntry=getMaterials()
|
||||
Entry attributeEntry=getMaterials()
|
||||
.getAttributeBlock(name);
|
||||
if(attributeEntry==null){
|
||||
throw new EncodeException("Unknown attribute name: '"+child.toText()
|
||||
@ -74,11 +71,12 @@ class XMLValuesEncoderStyle extends XMLValuesEncoderBag{
|
||||
}
|
||||
return ValueDecoder.parseHex(name);
|
||||
}
|
||||
private void encodeChild(XMLElement child, EntryBlock attributeEntry, ResValueBagItem bagItem){
|
||||
private void encodeChild(XMLElement child, Entry attributeEntry, ResValueMap bagItem){
|
||||
|
||||
bagItem.setId(attributeEntry.getResourceId());
|
||||
bagItem.setName(attributeEntry.getResourceId());
|
||||
ResTableMapEntry tableEntry = (ResTableMapEntry) attributeEntry.getTableEntry();
|
||||
AttributeBag attributeBag=AttributeBag
|
||||
.create((ResValueBag) attributeEntry.getResValue());
|
||||
.create(tableEntry.getValue());
|
||||
|
||||
String valueText=child.getTextContent();
|
||||
ValueDecoder.EncodeResult encodeEnumFlag =
|
||||
|
@ -17,10 +17,7 @@ package com.reandroid.arsc.array;
|
||||
|
||||
import com.reandroid.arsc.item.IntegerArray;
|
||||
import com.reandroid.arsc.item.IntegerItem;
|
||||
import com.reandroid.arsc.value.BaseResValue;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueInt;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONArray;
|
||||
import com.reandroid.json.JSONObject;
|
||||
@ -28,41 +25,41 @@ import com.reandroid.json.JSONObject;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSONConvert<JSONArray> {
|
||||
public EntryBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
||||
public class EntryArray extends OffsetBlockArray<Entry> implements JSONConvert<JSONArray> {
|
||||
public EntryArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
||||
super(offsets, itemCount, itemStart);
|
||||
}
|
||||
public boolean isEmpty(){
|
||||
return !iterator(true).hasNext();
|
||||
}
|
||||
public void setEntry(short entryId, EntryBlock entryBlock){
|
||||
setItem(0xffff & entryId, entryBlock);
|
||||
public void setEntry(short entryId, Entry entry){
|
||||
setItem(0xffff & entryId, entry);
|
||||
}
|
||||
public EntryBlock getOrCreate(short entryId){
|
||||
public Entry getOrCreate(short entryId){
|
||||
int id = 0xffff & entryId;
|
||||
EntryBlock entryBlock=get(id);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
Entry entry =get(id);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
int count=id+1;
|
||||
ensureSize(count);
|
||||
refreshCount();
|
||||
return get(id);
|
||||
}
|
||||
public EntryBlock get(short entryId){
|
||||
public Entry get(short entryId){
|
||||
int index = 0xffff & entryId;
|
||||
return super.get(index);
|
||||
}
|
||||
public EntryBlock getEntry(short entryId){
|
||||
public Entry getEntry(short entryId){
|
||||
return get(0xffff & entryId);
|
||||
}
|
||||
@Override
|
||||
public EntryBlock newInstance() {
|
||||
return new EntryBlock();
|
||||
public Entry newInstance() {
|
||||
return new Entry();
|
||||
}
|
||||
@Override
|
||||
public EntryBlock[] newInstance(int len) {
|
||||
return new EntryBlock[len];
|
||||
public Entry[] newInstance(int len) {
|
||||
return new Entry[len];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,13 +67,13 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
|
||||
* Lets depreciate to warn developer
|
||||
*/
|
||||
@Deprecated
|
||||
public EntryBlock searchByEntryName(String entryName){
|
||||
public Entry searchByEntryName(String entryName){
|
||||
if(entryName==null){
|
||||
return null;
|
||||
}
|
||||
for(EntryBlock entryBlock:listItems()){
|
||||
if(entryName.equals(entryBlock.getName())){
|
||||
return entryBlock;
|
||||
for(Entry entry:listItems()){
|
||||
if(entryName.equals(entry.getName())){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -85,12 +82,12 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
|
||||
public JSONArray toJson() {
|
||||
JSONArray jsonArray=new JSONArray();
|
||||
int index=0;
|
||||
for(EntryBlock entryBlock:listItems()){
|
||||
JSONObject childObject = entryBlock.toJson();
|
||||
for(Entry entry :listItems()){
|
||||
JSONObject childObject = entry.toJson();
|
||||
if(childObject==null){
|
||||
continue;
|
||||
}
|
||||
childObject.put(NAME_id, entryBlock.getIndex());
|
||||
childObject.put(NAME_id, entry.getIndex());
|
||||
jsonArray.put(index, childObject);
|
||||
index++;
|
||||
}
|
||||
@ -108,20 +105,20 @@ public class EntryBlockArray extends OffsetBlockArray<EntryBlock> implements JSO
|
||||
}
|
||||
int id=jsonObject.getInt(NAME_id);
|
||||
ensureSize(id+1);
|
||||
EntryBlock entryBlock=get(id);
|
||||
entryBlock.fromJson(jsonObject);
|
||||
Entry entry =get(id);
|
||||
entry.fromJson(jsonObject);
|
||||
}
|
||||
refreshCountAndStart();
|
||||
}
|
||||
public void merge(EntryBlockArray entryBlockArray){
|
||||
if(entryBlockArray==null||entryBlockArray==this||entryBlockArray.isEmpty()){
|
||||
public void merge(EntryArray entryArray){
|
||||
if(entryArray ==null|| entryArray ==this|| entryArray.isEmpty()){
|
||||
return;
|
||||
}
|
||||
ensureSize(entryBlockArray.childesCount());
|
||||
Iterator<EntryBlock> itr=entryBlockArray.iterator(true);
|
||||
ensureSize(entryArray.childesCount());
|
||||
Iterator<Entry> itr = entryArray.iterator(true);
|
||||
while (itr.hasNext()){
|
||||
EntryBlock comingBlock=itr.next();
|
||||
EntryBlock existingBlock=get(comingBlock.getIndex());
|
||||
Entry comingBlock = itr.next();
|
||||
Entry existingBlock = get(comingBlock.getIndex());
|
||||
existingBlock.merge(comingBlock);
|
||||
}
|
||||
}
|
@ -16,33 +16,35 @@
|
||||
package com.reandroid.arsc.array;
|
||||
|
||||
import com.reandroid.arsc.base.BlockArray;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONArray;
|
||||
|
||||
public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements JSONConvert<JSONArray> {
|
||||
public ResValueBagItemArray(){
|
||||
public class ResValueMapArray extends BlockArray<ResValueMap> implements JSONConvert<JSONArray> {
|
||||
public ResValueMapArray(){
|
||||
super();
|
||||
}
|
||||
@Override
|
||||
public ResValueBagItem newInstance() {
|
||||
return new ResValueBagItem();
|
||||
public ResValueMap newInstance() {
|
||||
return new ResValueMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResValueBagItem[] newInstance(int len) {
|
||||
return new ResValueBagItem[len];
|
||||
public ResValueMap[] newInstance(int len) {
|
||||
return new ResValueMap[len];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRefreshed() {
|
||||
|
||||
}
|
||||
public void onRemoved(){
|
||||
for(ResValueMap resValueMap:listItems()){
|
||||
resValueMap.onRemoved();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void clearChildes(){
|
||||
for(ResValueBagItem bagItem:listItems()){
|
||||
bagItem.onRemoved();
|
||||
}
|
||||
this.onRemoved();
|
||||
super.clearChildes();
|
||||
}
|
||||
@Override
|
||||
@ -51,7 +53,7 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
|
||||
if(isNull()){
|
||||
return jsonArray;
|
||||
}
|
||||
ResValueBagItem[] childes = getChildes();
|
||||
ResValueMap[] childes = getChildes();
|
||||
for(int i=0;i<childes.length;i++){
|
||||
jsonArray.put(i, childes[i].toJson());
|
||||
}
|
||||
@ -69,7 +71,7 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
|
||||
get(i).fromJson(json.getJSONObject(i));
|
||||
}
|
||||
}
|
||||
public void merge(ResValueBagItemArray bagItemArray){
|
||||
public void merge(ResValueMapArray bagItemArray){
|
||||
if(bagItemArray==null||bagItemArray==this){
|
||||
return;
|
||||
}
|
||||
@ -77,8 +79,8 @@ public class ResValueBagItemArray extends BlockArray<ResValueBagItem> implements
|
||||
int count=bagItemArray.childesCount();
|
||||
ensureSize(count);
|
||||
for(int i=0;i<count;i++){
|
||||
ResValueBagItem coming=bagItemArray.get(i);
|
||||
ResValueBagItem exist=get(i);
|
||||
ResValueMap coming=bagItemArray.get(i);
|
||||
ResValueMap exist=get(i);
|
||||
exist.merge(coming);
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ package com.reandroid.arsc.array;
|
||||
import com.reandroid.arsc.base.BlockArray;
|
||||
import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.container.SpecTypePair;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResConfig;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONArray;
|
||||
@ -62,11 +62,11 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair>
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public EntryBlock getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
||||
public Entry getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
||||
TypeBlock typeBlock=getOrCreateTypeBlock(typeId, qualifiers);
|
||||
return typeBlock.getOrCreateEntry(entryId);
|
||||
}
|
||||
public EntryBlock getEntry(byte typeId, short entryId, String qualifiers){
|
||||
public Entry getEntry(byte typeId, short entryId, String qualifiers){
|
||||
TypeBlock typeBlock=getTypeBlock(typeId, qualifiers);
|
||||
if(typeBlock==null){
|
||||
return null;
|
||||
|
@ -24,7 +24,7 @@ import com.reandroid.arsc.container.SpecTypePair;
|
||||
import com.reandroid.arsc.header.HeaderBlock;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.TypeString;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResConfig;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONArray;
|
||||
@ -58,7 +58,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
||||
trimNullBlocks();
|
||||
}
|
||||
}
|
||||
public EntryBlock getOrCreateEntry(short entryId, String qualifiers){
|
||||
public Entry getOrCreateEntry(short entryId, String qualifiers){
|
||||
TypeBlock typeBlock=getOrCreate(qualifiers);
|
||||
return typeBlock.getOrCreateEntry(entryId);
|
||||
}
|
||||
@ -70,7 +70,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public EntryBlock getEntry(short entryId, String qualifiers){
|
||||
public Entry getEntry(short entryId, String qualifiers){
|
||||
TypeBlock typeBlock=getTypeBlock(qualifiers);
|
||||
if(typeBlock==null){
|
||||
return null;
|
||||
@ -243,7 +243,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
||||
public int getHighestEntryCount(){
|
||||
int result=0;
|
||||
for(TypeBlock typeBlock:getChildes()){
|
||||
int count=typeBlock.getEntryBlockArray().childesCount();
|
||||
int count=typeBlock.getEntryArray().childesCount();
|
||||
if(count>result){
|
||||
result=count;
|
||||
}
|
||||
@ -303,7 +303,7 @@ public class TypeBlockArray extends BlockArray<TypeBlock>
|
||||
* Lets depreciate to warn developer
|
||||
*/
|
||||
@Deprecated
|
||||
public EntryBlock searchByEntryName(String entryName){
|
||||
public Entry searchByEntryName(String entryName){
|
||||
if(entryName==null){
|
||||
return null;
|
||||
}
|
||||
|
@ -24,13 +24,11 @@ package com.reandroid.arsc.chunk;
|
||||
import com.reandroid.arsc.container.SpecTypePair;
|
||||
import com.reandroid.arsc.group.EntryGroup;
|
||||
import com.reandroid.arsc.header.PackageHeader;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.arsc.list.OverlayableList;
|
||||
import com.reandroid.arsc.list.StagedAliasList;
|
||||
import com.reandroid.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
import com.reandroid.arsc.pool.TypeStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.LibraryInfo;
|
||||
import com.reandroid.arsc.value.ResConfig;
|
||||
import com.reandroid.arsc.value.StagedAliasEntry;
|
||||
@ -42,7 +40,9 @@ package com.reandroid.arsc.chunk;
|
||||
|
||||
|
||||
public class PackageBlock extends Chunk<PackageHeader>
|
||||
implements JSONConvert<JSONObject>, Comparable<PackageBlock> {
|
||||
implements ParentChunk,
|
||||
JSONConvert<JSONObject>,
|
||||
Comparable<PackageBlock> {
|
||||
|
||||
private final TypeStringPool mTypeStringPool;
|
||||
private final SpecStringPool mSpecStringPool;
|
||||
@ -66,12 +66,12 @@ package com.reandroid.arsc.chunk;
|
||||
addChild(mSpecStringPool);
|
||||
addChild(mBody);
|
||||
}
|
||||
public EntryBlock getOrCreate(String qualifiers, String type, String name){
|
||||
public Entry getOrCreate(String qualifiers, String type, String name){
|
||||
ResConfig resConfig = new ResConfig();
|
||||
resConfig.parseQualifiers(qualifiers);
|
||||
return getOrCreate(resConfig, type, name);
|
||||
}
|
||||
public EntryBlock getOrCreate(ResConfig resConfig, String type, String name){
|
||||
public Entry getOrCreate(ResConfig resConfig, String type, String name){
|
||||
SpecTypePair specTypePair = getOrCreateSpecType(type);
|
||||
TypeBlock typeBlock = specTypePair.getOrCreateTypeBlock(resConfig);
|
||||
return typeBlock.getOrCreateEntry(name);
|
||||
@ -158,6 +158,7 @@ package com.reandroid.arsc.chunk;
|
||||
public TypeStringPool getTypeStringPool(){
|
||||
return mTypeStringPool;
|
||||
}
|
||||
@Override
|
||||
public SpecStringPool getSpecStringPool(){
|
||||
return mSpecStringPool;
|
||||
}
|
||||
@ -185,10 +186,10 @@ package com.reandroid.arsc.chunk;
|
||||
public Set<Integer> listResourceIds(){
|
||||
return mEntriesGroup.keySet();
|
||||
}
|
||||
public EntryBlock getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
||||
public Entry getOrCreateEntry(byte typeId, short entryId, String qualifiers){
|
||||
return getSpecTypePairArray().getOrCreateEntry(typeId, entryId, qualifiers);
|
||||
}
|
||||
public EntryBlock getEntry(byte typeId, short entryId, String qualifiers){
|
||||
public Entry getEntry(byte typeId, short entryId, String qualifiers){
|
||||
return getSpecTypePairArray().getEntry(typeId, entryId, qualifiers);
|
||||
}
|
||||
public TypeBlock getOrCreateTypeBlock(byte typeId, String qualifiers){
|
||||
@ -223,48 +224,38 @@ package com.reandroid.arsc.chunk;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void updateEntry(EntryBlock entryBlock){
|
||||
if(entryBlock==null||entryBlock.isNull()){
|
||||
public void updateEntry(Entry entry){
|
||||
if(entry ==null|| entry.isNull()){
|
||||
return;
|
||||
}
|
||||
updateEntryGroup(entryBlock);
|
||||
updateEntryTableReferences(entryBlock);
|
||||
updateEntryGroup(entry);
|
||||
}
|
||||
public void removeEntryGroup(EntryBlock entryBlock){
|
||||
if(entryBlock==null){
|
||||
public void removeEntryGroup(Entry entry){
|
||||
if(entry ==null){
|
||||
return;
|
||||
}
|
||||
int id=entryBlock.getResourceId();
|
||||
int id= entry.getResourceId();
|
||||
EntryGroup group=getEntriesGroupMap().get(id);
|
||||
if(group==null){
|
||||
return;
|
||||
}
|
||||
group.remove(entryBlock);
|
||||
group.remove(entry);
|
||||
if(group.size()==0){
|
||||
getEntriesGroupMap().remove(id);
|
||||
}
|
||||
}
|
||||
private void updateEntryTableReferences(EntryBlock entryBlock){
|
||||
TableBlock tableBlock=getTableBlock();
|
||||
if(tableBlock==null){
|
||||
return;
|
||||
}
|
||||
List<ReferenceItem> tableReferences=entryBlock.getTableStringReferences();
|
||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
||||
tableStringPool.addReferences(tableReferences);
|
||||
}
|
||||
private void updateEntryGroup(EntryBlock entryBlock){
|
||||
int resId=entryBlock.getResourceId();
|
||||
private void updateEntryGroup(Entry entry){
|
||||
int resId= entry.getResourceId();
|
||||
EntryGroup group=getEntriesGroupMap().get(resId);
|
||||
if(group==null){
|
||||
group=new EntryGroup(resId);
|
||||
getEntriesGroupMap().put(resId, group);
|
||||
}
|
||||
group.add(entryBlock);
|
||||
group.add(entry);
|
||||
}
|
||||
|
||||
public List<EntryBlock> listEntries(byte typeId, int entryId){
|
||||
List<EntryBlock> results=new ArrayList<>();
|
||||
public List<Entry> listEntries(byte typeId, int entryId){
|
||||
List<Entry> results=new ArrayList<>();
|
||||
for(SpecTypePair pair:listSpecTypePair(typeId)){
|
||||
results.addAll(pair.listEntries(entryId));
|
||||
}
|
||||
@ -304,8 +295,8 @@ package com.reandroid.arsc.chunk;
|
||||
//getHeaderBlock().getTypeIdOffset().set(count-largest);
|
||||
getHeaderBlock().getTypeIdOffsetItem().set(0);
|
||||
}
|
||||
public void onEntryAdded(EntryBlock entryBlock){
|
||||
updateEntry(entryBlock);
|
||||
public void onEntryAdded(Entry entry){
|
||||
updateEntry(entry);
|
||||
}
|
||||
@Override
|
||||
public void onChunkLoaded() {
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.reandroid.arsc.chunk;
|
||||
|
||||
import com.reandroid.arsc.array.EntryBlockArray;
|
||||
import com.reandroid.arsc.array.EntryArray;
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.container.SpecTypePair;
|
||||
import com.reandroid.arsc.header.TypeHeader;
|
||||
@ -23,7 +23,7 @@ import com.reandroid.arsc.io.BlockLoad;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.*;
|
||||
import com.reandroid.arsc.pool.TypeStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResConfig;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
@ -38,14 +38,14 @@ import java.util.List;
|
||||
public class TypeBlock extends Chunk<TypeHeader>
|
||||
implements BlockLoad, JSONConvert<JSONObject>, Comparable<TypeBlock> {
|
||||
|
||||
private final EntryBlockArray mEntryArray;
|
||||
private final EntryArray mEntryArray;
|
||||
private TypeString mTypeString;
|
||||
public TypeBlock() {
|
||||
super(new TypeHeader(), 2);
|
||||
TypeHeader header = getHeaderBlock();
|
||||
|
||||
IntegerArray entryOffsets = new IntegerArray();
|
||||
this.mEntryArray = new EntryBlockArray(entryOffsets,
|
||||
this.mEntryArray = new EntryArray(entryOffsets,
|
||||
header.getCount(), header.getEntriesStart());
|
||||
|
||||
header.getFlags().setBlockLoad(this);
|
||||
@ -122,7 +122,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
onSetEntryCount(count);
|
||||
}
|
||||
public boolean isEmpty(){
|
||||
return getEntryBlockArray().isEmpty();
|
||||
return getEntryArray().isEmpty();
|
||||
}
|
||||
public boolean isDefault(){
|
||||
return getResConfig().isDefault();
|
||||
@ -134,7 +134,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
getResConfig().parseQualifiers(qualifiers);
|
||||
}
|
||||
public int countNonNullEntries(){
|
||||
return getEntryBlockArray().countNonNull();
|
||||
return getEntryArray().countNonNull();
|
||||
}
|
||||
public SpecTypePair getParentSpecTypePair(){
|
||||
Block parent=getParent();
|
||||
@ -148,29 +148,29 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
}
|
||||
public void cleanEntries(){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
List<EntryBlock> allEntries=listEntries(true);
|
||||
for(EntryBlock entryBlock:allEntries){
|
||||
List<Entry> allEntries=listEntries(true);
|
||||
for(Entry entry :allEntries){
|
||||
if(packageBlock!=null){
|
||||
packageBlock.removeEntryGroup(entryBlock);
|
||||
packageBlock.removeEntryGroup(entry);
|
||||
}
|
||||
entryBlock.setNull(true);
|
||||
entry.setNull(true);
|
||||
}
|
||||
}
|
||||
public void removeEntry(EntryBlock entryBlock){
|
||||
public void removeEntry(Entry entry){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock!=null){
|
||||
packageBlock.removeEntryGroup(entryBlock);
|
||||
packageBlock.removeEntryGroup(entry);
|
||||
}
|
||||
entryBlock.setNull(true);
|
||||
entry.setNull(true);
|
||||
}
|
||||
public EntryBlock getOrCreateEntry(String name){
|
||||
for(EntryBlock entryBlock:getEntryBlockArray().listItems()){
|
||||
if(name.equals(entryBlock.getName())){
|
||||
return entryBlock;
|
||||
public Entry getOrCreateEntry(String name){
|
||||
for(Entry entry : getEntryArray().listItems()){
|
||||
if(name.equals(entry.getName())){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
SpecTypePair specTypePair = getParentSpecTypePair();
|
||||
EntryBlock exist=specTypePair.getAnyEntry(name);
|
||||
Entry exist=specTypePair.getAnyEntry(name);
|
||||
int id;
|
||||
if(exist!=null){
|
||||
id=exist.getIndex();
|
||||
@ -179,47 +179,47 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
}
|
||||
SpecString specString = getPackageBlock()
|
||||
.getSpecStringPool().getOrCreate(name);
|
||||
EntryBlock entryBlock = getOrCreateEntry((short) id);
|
||||
if(entryBlock.isNull()){
|
||||
entryBlock.setValueAsRaw(ValueType.NULL, 0);
|
||||
Entry entry = getOrCreateEntry((short) id);
|
||||
if(entry.isNull()){
|
||||
entry.setValueAsRaw(ValueType.NULL, 0);
|
||||
}
|
||||
entryBlock.setSpecReference(specString.getIndex());
|
||||
return entryBlock;
|
||||
entry.setSpecReference(specString.getIndex());
|
||||
return entry;
|
||||
}
|
||||
public EntryBlock getOrCreateEntry(short entryId){
|
||||
return getEntryBlockArray().getOrCreate(entryId);
|
||||
public Entry getOrCreateEntry(short entryId){
|
||||
return getEntryArray().getOrCreate(entryId);
|
||||
}
|
||||
public EntryBlock getEntry(short entryId){
|
||||
return getEntryBlockArray().getEntry(entryId);
|
||||
public Entry getEntry(short entryId){
|
||||
return getEntryArray().getEntry(entryId);
|
||||
}
|
||||
public ResConfig getResConfig(){
|
||||
return getHeaderBlock().getConfig();
|
||||
}
|
||||
public EntryBlockArray getEntryBlockArray(){
|
||||
public EntryArray getEntryArray(){
|
||||
return mEntryArray;
|
||||
}
|
||||
public List<EntryBlock> listEntries(){
|
||||
public List<Entry> listEntries(){
|
||||
return listEntries(false);
|
||||
}
|
||||
public List<EntryBlock> listEntries(boolean skipNullBlock){
|
||||
List<EntryBlock> results=new ArrayList<>();
|
||||
Iterator<EntryBlock> itr = getEntryBlockArray().iterator(skipNullBlock);
|
||||
public List<Entry> listEntries(boolean skipNullBlock){
|
||||
List<Entry> results=new ArrayList<>();
|
||||
Iterator<Entry> itr = getEntryArray().iterator(skipNullBlock);
|
||||
while (itr.hasNext()){
|
||||
EntryBlock block=itr.next();
|
||||
Entry block=itr.next();
|
||||
results.add(block);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public EntryBlock getEntryBlock(int entryId){
|
||||
return getEntryBlockArray().get(entryId);
|
||||
public Entry getEntry(int entryId){
|
||||
return getEntryArray().get(entryId);
|
||||
}
|
||||
|
||||
private void onSetEntryCount(int count) {
|
||||
getEntryBlockArray().setChildesCount(count);
|
||||
getEntryArray().setChildesCount(count);
|
||||
}
|
||||
@Override
|
||||
protected void onChunkRefreshed() {
|
||||
getEntryBlockArray().refreshCountAndStart();
|
||||
getEntryArray().refreshCountAndStart();
|
||||
}
|
||||
@Override
|
||||
protected void onPreRefreshRefresh(){
|
||||
@ -246,7 +246,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
jsonObject.put(NAME_id, getId());
|
||||
jsonObject.put(NAME_name, getTypeName());
|
||||
jsonObject.put(NAME_config, getResConfig().toJson());
|
||||
jsonObject.put(NAME_entries, getEntryBlockArray().toJson());
|
||||
jsonObject.put(NAME_entries, getEntryArray().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
@ -256,7 +256,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
if(name!=null){
|
||||
setTypeName(name);
|
||||
}
|
||||
getEntryBlockArray()
|
||||
getEntryArray()
|
||||
.fromJson(json.getJSONArray(NAME_entries));
|
||||
getResConfig()
|
||||
.fromJson(json.getJSONObject(NAME_config));
|
||||
@ -270,7 +270,7 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
+getTypeId()+"!="+typeBlock.getTypeId());
|
||||
}
|
||||
setTypeName(typeBlock.getTypeName());
|
||||
getEntryBlockArray().merge(typeBlock.getEntryBlockArray());
|
||||
getEntryArray().merge(typeBlock.getEntryArray());
|
||||
}
|
||||
@Override
|
||||
public int compareTo(TypeBlock typeBlock) {
|
||||
@ -286,8 +286,8 @@ public class TypeBlock extends Chunk<TypeHeader>
|
||||
* Lets depreciate to warn developer
|
||||
*/
|
||||
@Deprecated
|
||||
public EntryBlock searchByEntryName(String entryName){
|
||||
return getEntryBlockArray().searchByEntryName(entryName);
|
||||
public Entry searchByEntryName(String entryName){
|
||||
return getEntryArray().searchByEntryName(entryName);
|
||||
}
|
||||
@Override
|
||||
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
|
||||
|
@ -18,10 +18,12 @@
|
||||
import com.reandroid.arsc.chunk.Chunk;
|
||||
import com.reandroid.arsc.chunk.ChunkType;
|
||||
import com.reandroid.arsc.chunk.MainChunk;
|
||||
import com.reandroid.arsc.chunk.ParentChunk;
|
||||
import com.reandroid.arsc.container.SingleBlockContainer;
|
||||
import com.reandroid.arsc.header.HeaderBlock;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.pool.ResXmlStringPool;
|
||||
import com.reandroid.arsc.pool.StringPool;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.common.EntryStore;
|
||||
import com.reandroid.json.JSONArray;
|
||||
@ -38,7 +40,7 @@
|
||||
import java.util.Set;
|
||||
|
||||
public class ResXmlDocument extends Chunk<HeaderBlock>
|
||||
implements MainChunk, JSONConvert<JSONObject> {
|
||||
implements MainChunk, ParentChunk, JSONConvert<JSONObject> {
|
||||
private final ResXmlStringPool mResXmlStringPool;
|
||||
private final ResXmlIDMap mResXmlIDMap;
|
||||
private ResXmlElement mResXmlElement;
|
||||
@ -166,6 +168,10 @@
|
||||
public ResXmlStringPool getStringPool(){
|
||||
return mResXmlStringPool;
|
||||
}
|
||||
@Override
|
||||
public StringPool<?> getSpecStringPool() {
|
||||
return null;
|
||||
}
|
||||
public ResXmlIDMap getResXmlIDMap(){
|
||||
return mResXmlIDMap;
|
||||
}
|
||||
|
@ -16,13 +16,13 @@
|
||||
package com.reandroid.arsc.container;
|
||||
|
||||
import com.reandroid.arsc.base.BlockContainer;
|
||||
import com.reandroid.arsc.value.BaseResValue;
|
||||
import com.reandroid.arsc.value.ValueItem;
|
||||
|
||||
public class ResValueContainer extends BlockContainer<BaseResValue> {
|
||||
private final BaseResValue[] mChildes;
|
||||
public class ResValueContainer extends BlockContainer<ValueItem> {
|
||||
private final ValueItem[] mChildes;
|
||||
public ResValueContainer(){
|
||||
super();
|
||||
mChildes=new BaseResValue[1];
|
||||
mChildes=new ValueItem[1];
|
||||
}
|
||||
@Override
|
||||
protected void onRefreshed(){
|
||||
@ -32,11 +32,11 @@ public class ResValueContainer extends BlockContainer<BaseResValue> {
|
||||
return mChildes.length;
|
||||
}
|
||||
@Override
|
||||
public BaseResValue[] getChildes() {
|
||||
public ValueItem[] getChildes() {
|
||||
return mChildes;
|
||||
}
|
||||
public void setResValue(BaseResValue resValue){
|
||||
BaseResValue old=getResValue();
|
||||
public void setResValue(ValueItem resValue){
|
||||
ValueItem old=getResValue();
|
||||
if(old!=null){
|
||||
old.setIndex(-1);
|
||||
old.setParent(null);
|
||||
@ -48,7 +48,7 @@ public class ResValueContainer extends BlockContainer<BaseResValue> {
|
||||
resValue.setIndex(0);
|
||||
resValue.setParent(this);
|
||||
}
|
||||
public BaseResValue getResValue(){
|
||||
public ValueItem getResValue(){
|
||||
if(mChildes.length==0){
|
||||
return null;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.header.HeaderBlock;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.TypeString;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResConfig;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
@ -53,11 +53,11 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
public SpecTypePair(){
|
||||
this(new SpecBlock(), new TypeBlockArray());
|
||||
}
|
||||
public EntryBlock getAnyEntry(String name){
|
||||
public Entry getAnyEntry(String name){
|
||||
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||
EntryBlock entryBlock=typeBlock.searchByEntryName(name);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock;
|
||||
Entry entry =typeBlock.searchByEntryName(name);
|
||||
if(entry !=null){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -74,10 +74,10 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
public int countTypeBlocks(){
|
||||
return getTypeBlockArray().childesCount();
|
||||
}
|
||||
public EntryBlock getOrCreateEntry(short entryId, String qualifiers){
|
||||
public Entry getOrCreateEntry(short entryId, String qualifiers){
|
||||
return getTypeBlockArray().getOrCreateEntry(entryId, qualifiers);
|
||||
}
|
||||
public EntryBlock getEntry(short entryId, String qualifiers){
|
||||
public Entry getEntry(short entryId, String qualifiers){
|
||||
return getTypeBlockArray().getEntry(entryId, qualifiers);
|
||||
}
|
||||
public TypeBlock getOrCreateTypeBlock(String qualifiers){
|
||||
@ -115,7 +115,7 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
* Lets depreciate to warn developer
|
||||
*/
|
||||
@Deprecated
|
||||
public EntryBlock searchByEntryName(String entryName){
|
||||
public Entry searchByEntryName(String entryName){
|
||||
return getTypeBlockArray().searchByEntryName(entryName);
|
||||
}
|
||||
public SpecBlock getSpecBlock(){
|
||||
@ -134,16 +134,16 @@ public class SpecTypePair extends BlockContainer<Block>
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public List<EntryBlock> listEntries(int entryId){
|
||||
List<EntryBlock> results=new ArrayList<>();
|
||||
public List<Entry> listEntries(int entryId){
|
||||
List<Entry> results=new ArrayList<>();
|
||||
Iterator<TypeBlock> itr = mTypeBlockArray.iterator(true);
|
||||
while (itr.hasNext()){
|
||||
TypeBlock typeBlock=itr.next();
|
||||
EntryBlock entryBlock=typeBlock.getEntryBlock(entryId);
|
||||
if(entryBlock==null||entryBlock.isNull()){
|
||||
Entry entry = typeBlock.getEntry(entryId);
|
||||
if(entry ==null|| entry.isNull()){
|
||||
continue;
|
||||
}
|
||||
results.add(entryBlock);
|
||||
results.add(entry);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -242,14 +242,14 @@ import java.util.regex.Pattern;
|
||||
if(entryGroup==null){
|
||||
return String.format("@0x%08x", resourceId);
|
||||
}
|
||||
EntryBlock entryBlock=entryGroup.pickOne();
|
||||
if(entryBlock==null){
|
||||
Entry entry =entryGroup.pickOne();
|
||||
if(entry ==null){
|
||||
return String.format("@0x%08x", resourceId);
|
||||
}
|
||||
String prefix=null;
|
||||
if(currentPackage!=null){
|
||||
String name=currentPackage.getName();
|
||||
String other=entryBlock.getPackageBlock().getName();
|
||||
String other= entry.getPackageBlock().getName();
|
||||
if(!name.equals(other)){
|
||||
prefix=other+":";
|
||||
}
|
||||
@ -300,34 +300,34 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return decode(valueType, data);
|
||||
}
|
||||
public static String decodeIntEntry(EntryStore store, EntryBlock entryBlock){
|
||||
if(entryBlock==null){
|
||||
public static String decodeIntEntry(EntryStore store, Entry entry){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
BaseResValue baseResValue = entryBlock.getResValue();
|
||||
if(!(baseResValue instanceof ResValueInt)){
|
||||
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
|
||||
return null;
|
||||
}
|
||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
||||
return decodeIntEntry(store, resValueInt);
|
||||
ResValue resValue =(ResValue) tableEntry.getValue();
|
||||
return decodeIntEntry(store, resValue);
|
||||
}
|
||||
public static String decodeIntEntry(EntryStore store, ResValueInt resValueInt){
|
||||
if(resValueInt==null){
|
||||
public static String decodeIntEntry(EntryStore store, ResValue resValue){
|
||||
if(resValue ==null){
|
||||
return null;
|
||||
}
|
||||
EntryBlock parentEntry=resValueInt.getEntryBlock();
|
||||
Entry parentEntry = resValue.getEntry();
|
||||
if(parentEntry==null){
|
||||
return null;
|
||||
}
|
||||
ValueType valueType=resValueInt.getValueType();
|
||||
int data=resValueInt.getData();
|
||||
ValueType valueType= resValue.getValueType();
|
||||
int data= resValue.getData();
|
||||
return decodeIntEntry(store, parentEntry, valueType, data);
|
||||
}
|
||||
public static String decodeIntEntry(EntryStore store, ResValueBagItem bagItem){
|
||||
public static String decodeIntEntry(EntryStore store, ResValueMap bagItem){
|
||||
if(bagItem==null){
|
||||
return null;
|
||||
}
|
||||
EntryBlock parentEntry=bagItem.getEntryBlock();
|
||||
Entry parentEntry=bagItem.getEntry();
|
||||
if(parentEntry==null){
|
||||
return null;
|
||||
}
|
||||
@ -335,7 +335,7 @@ import java.util.regex.Pattern;
|
||||
int data=bagItem.getData();
|
||||
return decodeIntEntry(store, parentEntry, valueType, data);
|
||||
}
|
||||
public static String decodeIntEntry(EntryStore store, EntryBlock parentEntry, ValueType valueType, int data){
|
||||
public static String decodeIntEntry(EntryStore store, Entry parentEntry, ValueType valueType, int data){
|
||||
if(valueType==ValueType.NULL){
|
||||
return "@empty";
|
||||
}
|
||||
@ -367,18 +367,18 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return decode(valueType, data);
|
||||
}
|
||||
public static String buildReferenceValue(EntryStore store, EntryBlock entryBlock){
|
||||
if(entryBlock==null){
|
||||
public static String buildReferenceValue(EntryStore store, Entry entry){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
BaseResValue baseResValue = entryBlock.getResValue();
|
||||
if(!(baseResValue instanceof ResValueInt)){
|
||||
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||
if(tableEntry == null || (tableEntry instanceof ResTableMapEntry)){
|
||||
return null;
|
||||
}
|
||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
||||
int resourceId=resValueInt.getData();
|
||||
ValueType valueType=resValueInt.getValueType();
|
||||
return buildReferenceValue(store, entryBlock, valueType, resourceId);
|
||||
ResValue resValue =(ResValue) tableEntry.getValue();
|
||||
int resourceId= resValue.getData();
|
||||
ValueType valueType= resValue.getValueType();
|
||||
return buildReferenceValue(store, entry, valueType, resourceId);
|
||||
}
|
||||
public static String decode(EntryStore entryStore, int currentPackageId, int nameResourceId, ValueType valueType, int rawVal){
|
||||
String currPackageName=getPackageName(entryStore, currentPackageId);
|
||||
@ -446,17 +446,17 @@ import java.util.regex.Pattern;
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static String buildReferenceValue(EntryStore store, EntryBlock entryBlock, ValueType valueType, int resourceId){
|
||||
if(entryBlock==null){
|
||||
private static String buildReferenceValue(EntryStore store, Entry entry, ValueType valueType, int resourceId){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
EntryGroup value=searchEntryGroup(store, entryBlock, resourceId);
|
||||
EntryGroup value=searchEntryGroup(store, entry, resourceId);
|
||||
if(value==null){
|
||||
return null;
|
||||
}
|
||||
return buildReferenceValue(valueType, entryBlock, value);
|
||||
return buildReferenceValue(valueType, entry, value);
|
||||
}
|
||||
private static String buildReferenceValue(ValueType valueType, EntryBlock entryBlock, EntryGroup value){
|
||||
private static String buildReferenceValue(ValueType valueType, Entry entry, EntryGroup value){
|
||||
char atOrQues;
|
||||
if(valueType==ValueType.REFERENCE){
|
||||
atOrQues='@';
|
||||
@ -465,7 +465,7 @@ import java.util.regex.Pattern;
|
||||
}else {
|
||||
atOrQues=0;
|
||||
}
|
||||
String currentPackageName=getPackageName(entryBlock);
|
||||
String currentPackageName=getPackageName(entry);
|
||||
String referredPackageName=getPackageName(value);
|
||||
String typeName=value.getTypeName();
|
||||
String name=value.getSpecName();
|
||||
@ -524,18 +524,18 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return getPackageName(entryGroup.pickOne());
|
||||
}
|
||||
private static String getPackageName(EntryBlock entryBlock){
|
||||
if(entryBlock==null){
|
||||
private static String getPackageName(Entry entry){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
||||
PackageBlock packageBlock= entry.getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
return packageBlock.getName();
|
||||
}
|
||||
private static EntryGroup searchEntryGroup(EntryStore store, EntryBlock entryBlock, int resourceId){
|
||||
EntryGroup entryGroup=searchEntryGroup(entryBlock, resourceId);
|
||||
private static EntryGroup searchEntryGroup(EntryStore store, Entry entry, int resourceId){
|
||||
EntryGroup entryGroup=searchEntryGroup(entry, resourceId);
|
||||
if(entryGroup!=null){
|
||||
return entryGroup;
|
||||
}
|
||||
@ -544,11 +544,11 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return store.getEntryGroup(resourceId);
|
||||
}
|
||||
private static EntryGroup searchEntryGroup(EntryBlock entryBlock, int resourceId){
|
||||
if(entryBlock==null){
|
||||
private static EntryGroup searchEntryGroup(Entry entry, int resourceId){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
||||
PackageBlock packageBlock= entry.getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
@ -581,11 +581,11 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static String decodeIntEntryString(EntryBlock entryBlock, int data){
|
||||
if(entryBlock==null){
|
||||
private static String decodeIntEntryString(Entry entry, int data){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
||||
PackageBlock packageBlock= entry.getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
@ -719,9 +719,9 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
private static String getResourceName(EntryStore store, EntryBlock entryBlock, int resourceId){
|
||||
if(entryBlock!=null){
|
||||
EntryGroup group=searchEntryGroup(entryBlock, resourceId);
|
||||
private static String getResourceName(EntryStore store, Entry entry, int resourceId){
|
||||
if(entry !=null){
|
||||
EntryGroup group=searchEntryGroup(entry, resourceId);
|
||||
if(group!=null){
|
||||
String name=group.getSpecName();
|
||||
if(name!=null){
|
||||
@ -748,58 +748,58 @@ import java.util.regex.Pattern;
|
||||
return null;
|
||||
}
|
||||
private static AttributeBag getAttributeBag(EntryStore store, int resourceId){
|
||||
ResValueBag resValueBag=getAttributeValueBag(store, resourceId);
|
||||
if(resValueBag==null){
|
||||
ResTableMapEntry mapEntry=getAttributeValueBag(store, resourceId);
|
||||
if(mapEntry==null){
|
||||
return null;
|
||||
}
|
||||
return AttributeBag.create(resValueBag);
|
||||
return AttributeBag.create(mapEntry.getValue());
|
||||
}
|
||||
private static ResValueBag getAttributeValueBag(EntryStore store, int resourceId){
|
||||
private static ResTableMapEntry getAttributeValueBag(EntryStore store, int resourceId){
|
||||
if(store==null){
|
||||
return null;
|
||||
}
|
||||
Collection<EntryGroup> foundGroups = store.getEntryGroups(resourceId);
|
||||
ResValueBag best=null;
|
||||
ResTableMapEntry best=null;
|
||||
for(EntryGroup group:foundGroups){
|
||||
ResValueBag valueBag= getAttributeValueBag(group);
|
||||
ResTableMapEntry valueBag = getAttributeValueBag(group);
|
||||
best=chooseBest(best, valueBag);
|
||||
}
|
||||
return best;
|
||||
}
|
||||
private static ResValueBag getAttributeValueBag(EntryGroup entryGroup){
|
||||
private static ResTableMapEntry getAttributeValueBag(EntryGroup entryGroup){
|
||||
if(entryGroup==null){
|
||||
return null;
|
||||
}
|
||||
ResValueBag best=null;
|
||||
Iterator<EntryBlock> iterator=entryGroup.iterator(true);
|
||||
ResTableMapEntry best=null;
|
||||
Iterator<Entry> iterator=entryGroup.iterator(true);
|
||||
while (iterator.hasNext()){
|
||||
EntryBlock entryBlock=iterator.next();
|
||||
ResValueBag valueBag= getAttributeValueBag(entryBlock);
|
||||
Entry entry =iterator.next();
|
||||
ResTableMapEntry valueBag = getAttributeValueBag(entry);
|
||||
best=chooseBest(best, valueBag);
|
||||
}
|
||||
return best;
|
||||
}
|
||||
private static ResValueBag getAttributeValueBag(EntryBlock entryBlock){
|
||||
if(entryBlock==null){
|
||||
private static ResTableMapEntry getAttributeValueBag(Entry entry){
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
BaseResValue baseResValue = entryBlock.getResValue();
|
||||
if(baseResValue instanceof ResValueBag){
|
||||
return (ResValueBag) baseResValue;
|
||||
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||
if(tableEntry instanceof ResTableMapEntry){
|
||||
return (ResTableMapEntry) tableEntry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static ResValueBag chooseBest(ResValueBag valueBag1, ResValueBag valueBag2){
|
||||
if(valueBag1==null){
|
||||
return valueBag2;
|
||||
private static ResTableMapEntry chooseBest(ResTableMapEntry entry1, ResTableMapEntry entry2){
|
||||
if(entry1==null){
|
||||
return entry2;
|
||||
}
|
||||
if(valueBag2==null){
|
||||
return valueBag1;
|
||||
if(entry2==null){
|
||||
return entry1;
|
||||
}
|
||||
if(valueBag2.getCount()>valueBag1.getCount()){
|
||||
return valueBag2;
|
||||
if(entry2.getValue().childesCount()>entry1.getValue().childesCount()){
|
||||
return entry2;
|
||||
}
|
||||
return valueBag1;
|
||||
return entry1;
|
||||
}
|
||||
private static String toHexResourceId(int resourceId){
|
||||
return String.format("0x%08x", resourceId);
|
||||
|
@ -21,11 +21,11 @@ import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.item.SpecString;
|
||||
import com.reandroid.arsc.item.TypeString;
|
||||
import com.reandroid.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
public class EntryGroup extends ItemGroup<Entry> {
|
||||
private final int resourceId;
|
||||
public EntryGroup(int resId) {
|
||||
super(create(), String.format("0x%08x", resId));
|
||||
@ -35,7 +35,7 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
return resourceId;
|
||||
}
|
||||
public boolean renameSpec(String name){
|
||||
EntryBlock[] items=getItems();
|
||||
Entry[] items=getItems();
|
||||
if(items==null || name==null){
|
||||
return false;
|
||||
}
|
||||
@ -56,25 +56,25 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
return (short) (getResourceId() & 0xffff);
|
||||
}
|
||||
private boolean isAllSameSpec(){
|
||||
EntryBlock first=null;
|
||||
for(EntryBlock entryBlock:listItems()){
|
||||
Entry first=null;
|
||||
for(Entry entry :listItems()){
|
||||
if(first==null){
|
||||
first=entryBlock;
|
||||
first= entry;
|
||||
continue;
|
||||
}
|
||||
if(first.getSpecReference()!=entryBlock.getSpecReference()){
|
||||
if(first.getSpecReference()!= entry.getSpecReference()){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public boolean renameSpec(int specReference){
|
||||
EntryBlock[] items=getItems();
|
||||
Entry[] items=getItems();
|
||||
if(items==null){
|
||||
return false;
|
||||
}
|
||||
boolean renameOk=false;
|
||||
for(EntryBlock block:items){
|
||||
for(Entry block:items){
|
||||
if(block==null){
|
||||
continue;
|
||||
}
|
||||
@ -86,45 +86,45 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
}
|
||||
return renameOk;
|
||||
}
|
||||
public EntryBlock pickOne(){
|
||||
EntryBlock[] items=getItems();
|
||||
public Entry pickOne(){
|
||||
Entry[] items=getItems();
|
||||
if(items==null){
|
||||
return null;
|
||||
}
|
||||
EntryBlock result = null;
|
||||
for(EntryBlock entryBlock:items){
|
||||
if(entryBlock==null){
|
||||
Entry result = null;
|
||||
for(Entry entry :items){
|
||||
if(entry ==null){
|
||||
continue;
|
||||
}
|
||||
if(result==null || result.isNull()){
|
||||
result=entryBlock;
|
||||
}else if(entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
result= entry;
|
||||
}else if(entry.isDefault()){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public EntryBlock getDefault(){
|
||||
Iterator<EntryBlock> itr=iterator(true);
|
||||
public Entry getDefault(){
|
||||
Iterator<Entry> itr=iterator(true);
|
||||
while (itr.hasNext()){
|
||||
EntryBlock entryBlock=itr.next();
|
||||
if(entryBlock.isDefault()){
|
||||
return entryBlock;
|
||||
Entry entry =itr.next();
|
||||
if(entry.isDefault()){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public TypeString getTypeString(){
|
||||
EntryBlock entryBlock=pickOne();
|
||||
if(entryBlock!=null){
|
||||
return entryBlock.getTypeString();
|
||||
Entry entry =pickOne();
|
||||
if(entry !=null){
|
||||
return entry.getTypeString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public SpecString getSpecString(){
|
||||
EntryBlock entryBlock=pickOne();
|
||||
if(entryBlock!=null){
|
||||
return entryBlock.getSpecString();
|
||||
Entry entry =pickOne();
|
||||
if(entry !=null){
|
||||
return entry.getSpecString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -143,11 +143,11 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
return specString.get();
|
||||
}
|
||||
private SpecStringPool getSpecStringPool(){
|
||||
EntryBlock entryBlock=get(0);
|
||||
if(entryBlock==null){
|
||||
Entry entry =get(0);
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
||||
TypeBlock typeBlock= entry.getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return null;
|
||||
}
|
||||
@ -159,22 +159,22 @@ public class EntryGroup extends ItemGroup<EntryBlock> {
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
EntryBlock entryBlock=pickOne();
|
||||
if(entryBlock==null){
|
||||
Entry entry =pickOne();
|
||||
if(entry ==null){
|
||||
return super.toString();
|
||||
}
|
||||
return super.toString()+"{"+entryBlock.toString()+"}";
|
||||
return super.toString()+"{"+ entry.toString()+"}";
|
||||
}
|
||||
private static BlockArrayCreator<EntryBlock> create(){
|
||||
return new BlockArrayCreator<EntryBlock>(){
|
||||
private static BlockArrayCreator<Entry> create(){
|
||||
return new BlockArrayCreator<Entry>(){
|
||||
@Override
|
||||
public EntryBlock newInstance() {
|
||||
return new EntryBlock();
|
||||
public Entry newInstance() {
|
||||
return new Entry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntryBlock[] newInstance(int len) {
|
||||
return new EntryBlock[len];
|
||||
public Entry[] newInstance(int len) {
|
||||
return new Entry[len];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import java.util.Objects;
|
||||
}
|
||||
public List<T> listItems(){
|
||||
return new AbstractList<T>() {
|
||||
private final int mSize = ItemGroup.this.size();
|
||||
@Override
|
||||
public T get(int i) {
|
||||
return ItemGroup.this.get(i);
|
||||
@ -49,7 +50,7 @@ import java.util.Objects;
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ItemGroup.this.size();
|
||||
return mSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -148,4 +148,21 @@ public abstract class BlockItem extends Block {
|
||||
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
||||
bts[offset]= (byte) (val & 0xff);
|
||||
}
|
||||
protected static boolean getBit(byte[] bts, int byteOffset, int bitIndex){
|
||||
return (((bts[byteOffset] & 0xff) >>bitIndex) & 0x1) == 1;
|
||||
}
|
||||
protected static void putBit(byte[] bts, int byteOffset, int bitIndex, boolean bit){
|
||||
int val=bts[byteOffset] & 0xff;
|
||||
int left=val>>bitIndex;
|
||||
if(bit){
|
||||
left=left|0x1;
|
||||
}else {
|
||||
left=left & 0xFE;
|
||||
}
|
||||
left=left<<bitIndex;
|
||||
bitIndex=8-bitIndex;
|
||||
int right=(0xFF>>bitIndex) & val;
|
||||
val=left|right;
|
||||
bts[byteOffset]=(byte) val;
|
||||
}
|
||||
}
|
||||
|
38
src/main/java/com/reandroid/arsc/item/ReferenceBlock.java
Normal file
38
src/main/java/com/reandroid/arsc/item/ReferenceBlock.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.item;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
|
||||
public class ReferenceBlock<T extends Block> implements ReferenceItem{
|
||||
private final T block;
|
||||
private final int offset;
|
||||
public ReferenceBlock(T block, int offset){
|
||||
this.block = block;
|
||||
this.offset = offset;
|
||||
}
|
||||
public T getBlock(){
|
||||
return this.block;
|
||||
}
|
||||
@Override
|
||||
public void set(int val) {
|
||||
BlockItem.putInteger(this.block.getBytes(), this.offset, val);
|
||||
}
|
||||
@Override
|
||||
public int get() {
|
||||
return BlockItem.getInteger(this.block.getBytes(), this.offset);
|
||||
}
|
||||
}
|
@ -97,9 +97,6 @@ public class StringItem extends BlockItem implements JSONConvert<JSONObject> {
|
||||
if(str==null){
|
||||
return null;
|
||||
}
|
||||
if(str.startsWith("*Plus taxes if applicable")){
|
||||
String junk="";
|
||||
}
|
||||
StyleItem styleItem=getStyle();
|
||||
if(styleItem==null){
|
||||
return str;
|
||||
|
@ -15,8 +15,9 @@
|
||||
*/
|
||||
package com.reandroid.arsc.item;
|
||||
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueReference;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -25,20 +26,20 @@ public class TableString extends StringItem {
|
||||
public TableString(boolean utf8) {
|
||||
super(utf8);
|
||||
}
|
||||
public List<EntryBlock> listReferencedEntries(boolean ignoreBagEntries){
|
||||
List<EntryBlock> results=new ArrayList<>();
|
||||
public List<Entry> listReferencedEntries(boolean ignoreBagEntries){
|
||||
List<Entry> results=new ArrayList<>();
|
||||
for(ReferenceItem ref:getReferencedList()){
|
||||
if(!(ref instanceof ResValueReference)){
|
||||
if(!(ref instanceof ReferenceBlock)){
|
||||
continue;
|
||||
}
|
||||
EntryBlock entryBlock=((ResValueReference)ref).getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
ValueItem valueItem = (ValueItem) ((ReferenceBlock)ref).getBlock();
|
||||
if(valueItem ==null){
|
||||
continue;
|
||||
}
|
||||
if(ignoreBagEntries && entryBlock.isEntryTypeBag()){
|
||||
if(ignoreBagEntries && (valueItem instanceof ResValueMap)){
|
||||
continue;
|
||||
}
|
||||
results.add(entryBlock);
|
||||
results.add(valueItem.getParentEntry());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResConfig;
|
||||
|
||||
import java.io.*;
|
||||
@ -45,9 +45,9 @@ public class FrameworkTable extends TableBlock {
|
||||
}
|
||||
|
||||
public int resolveResourceId(String typeName, String entryName){
|
||||
EntryBlock entryBlock=searchEntryBlock(typeName, entryName);
|
||||
if(entryBlock!=null){
|
||||
return entryBlock.getResourceId();
|
||||
Entry entry = searchEntry(typeName, entryName);
|
||||
if(entry !=null){
|
||||
return entry.getResourceId();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -81,7 +81,7 @@ public class FrameworkTable extends TableBlock {
|
||||
private boolean hasResourceGroupMap(){
|
||||
return mNameGroupMap!=null;
|
||||
}
|
||||
private EntryBlock searchEntryBlockFromMap(String typeName, String entryName){
|
||||
private Entry searchEntryFromMap(String typeName, String entryName){
|
||||
if(mNameGroupMap ==null){
|
||||
return null;
|
||||
}
|
||||
@ -91,16 +91,16 @@ public class FrameworkTable extends TableBlock {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public EntryBlock searchEntryBlock(String typeName, String entryName){
|
||||
public Entry searchEntry(String typeName, String entryName){
|
||||
if(hasResourceGroupMap()){
|
||||
return searchEntryBlockFromMap(typeName, entryName);
|
||||
return searchEntryFromMap(typeName, entryName);
|
||||
}
|
||||
return searchEntryBlockFromTable(typeName, entryName);
|
||||
return searchEntryFromTable(typeName, entryName);
|
||||
}
|
||||
/**
|
||||
* Since this is framework, we are sure of proper names.
|
||||
*/
|
||||
public EntryBlock searchEntryBlockFromTable(String typeName, String entryName){
|
||||
public Entry searchEntryFromTable(String typeName, String entryName){
|
||||
for(PackageBlock packageBlock:listPackages()){
|
||||
SpecTypePair specTypePair = packageBlock.searchByTypeName(typeName);
|
||||
if(specTypePair!=null){
|
||||
@ -166,8 +166,8 @@ public class FrameworkTable extends TableBlock {
|
||||
public void optimize(String frameworkName, String frameworkVersion){
|
||||
Map<Integer, EntryGroup> groupMap=scanAllEntryGroups();
|
||||
for(EntryGroup group:groupMap.values()){
|
||||
List<EntryBlock> entryBlockList=getEntriesToRemove(group);
|
||||
removeEntryBlocks(entryBlockList);
|
||||
List<Entry> entryList =getEntriesToRemove(group);
|
||||
removeEntries(entryList);
|
||||
}
|
||||
for(PackageBlock pkg:listPackages()){
|
||||
clearNonDefaultConfigs(pkg);
|
||||
@ -246,32 +246,32 @@ public class FrameworkTable extends TableBlock {
|
||||
}
|
||||
zero.addReference(allRef);
|
||||
}
|
||||
private void removeEntryBlocks(List<EntryBlock> removeList){
|
||||
for(EntryBlock entryBlock:removeList){
|
||||
removeEntryBlock(entryBlock);
|
||||
private void removeEntries(List<Entry> removeList){
|
||||
for(Entry entry :removeList){
|
||||
removeEntry(entry);
|
||||
}
|
||||
}
|
||||
private void removeEntryBlock(EntryBlock entryBlock){
|
||||
TypeBlock typeBlock=entryBlock.getTypeBlock();
|
||||
private void removeEntry(Entry entry){
|
||||
TypeBlock typeBlock= entry.getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return;
|
||||
}
|
||||
typeBlock.removeEntry(entryBlock);
|
||||
typeBlock.removeEntry(entry);
|
||||
|
||||
}
|
||||
private List<EntryBlock> getEntriesToRemove(EntryGroup group){
|
||||
List<EntryBlock> results=new ArrayList<>();
|
||||
EntryBlock mainEntry=group.pickOne();
|
||||
private List<Entry> getEntriesToRemove(EntryGroup group){
|
||||
List<Entry> results=new ArrayList<>();
|
||||
Entry mainEntry=group.pickOne();
|
||||
if(mainEntry==null){
|
||||
return results;
|
||||
}
|
||||
Iterator<EntryBlock> itr = group.iterator(true);
|
||||
Iterator<Entry> itr = group.iterator(true);
|
||||
while (itr.hasNext()){
|
||||
EntryBlock entryBlock=itr.next();
|
||||
if(entryBlock==mainEntry){
|
||||
Entry entry =itr.next();
|
||||
if(entry ==mainEntry){
|
||||
continue;
|
||||
}
|
||||
results.add(entryBlock);
|
||||
results.add(entry);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.item.BlockItem;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public abstract class BaseResValue extends BlockItem implements JSONConvert<JSONObject> {
|
||||
BaseResValue(int bytesLength){
|
||||
super(bytesLength);
|
||||
}
|
||||
|
||||
protected void onRemoved(){
|
||||
}
|
||||
|
||||
public EntryBlock getEntryBlock(){
|
||||
Block parent=getParent();
|
||||
while(parent!=null){
|
||||
if(parent instanceof EntryBlock){
|
||||
return (EntryBlock)parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
boolean removeSpecReference(ReferenceItem ref){
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return false;
|
||||
}
|
||||
return entryBlock.removeSpecReference(ref);
|
||||
}
|
||||
boolean removeTableReference(ReferenceItem ref){
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return false;
|
||||
}
|
||||
return entryBlock.removeTableReference(ref);
|
||||
}
|
||||
void addSpecReference(ReferenceItem ref){
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return;
|
||||
}
|
||||
entryBlock.addSpecReference(ref);
|
||||
}
|
||||
void addTableReference(ReferenceItem ref){
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return;
|
||||
}
|
||||
entryBlock.addTableReference(ref);
|
||||
}
|
||||
void onDataLoaded() {
|
||||
|
||||
}
|
||||
int getInt(int offset){
|
||||
byte[] bts = getBytesInternal();
|
||||
return bts[offset] & 0xff |
|
||||
(bts[offset+1] & 0xff) << 8 |
|
||||
(bts[offset+2] & 0xff) << 16 |
|
||||
(bts[offset+3] & 0xff) << 24;
|
||||
}
|
||||
void setInt(int offset, int val){
|
||||
if(val==getInt(offset)){
|
||||
return;
|
||||
}
|
||||
byte[] bts = getBytesInternal();
|
||||
bts[offset+3]= (byte) (val >>> 24 & 0xff);
|
||||
bts[offset+2]= (byte) (val >>> 16 & 0xff);
|
||||
bts[offset+1]= (byte) (val >>> 8 & 0xff);
|
||||
bts[offset]= (byte) (val & 0xff);
|
||||
onBytesChanged();
|
||||
}
|
||||
void setShort(int offset, short val){
|
||||
if(val==getShort(offset)){
|
||||
return;
|
||||
}
|
||||
byte[] bts = getBytesInternal();
|
||||
bts[offset+1]= (byte) (val >>> 8 & 255);
|
||||
bts[offset]= (byte) (val & 255);
|
||||
onBytesChanged();
|
||||
}
|
||||
short getShort(int offset){
|
||||
byte[] bts=getBytesInternal();
|
||||
int i= bts[offset] & 0xff |
|
||||
(bts[offset+1] & 0xff) << 8 ;
|
||||
return (short)i;
|
||||
}
|
||||
void setByte(int offset, byte b){
|
||||
byte[] bts=getBytesInternal();
|
||||
if(b==bts[offset]){
|
||||
return;
|
||||
}
|
||||
bts[offset]=b;
|
||||
onBytesChanged();
|
||||
}
|
||||
byte getByte(int offset){
|
||||
return getBytesInternal()[offset];
|
||||
}
|
||||
|
||||
static final String NAME_data = "data";
|
||||
static final String NAME_value_type="value_type";
|
||||
static final String NAME_id="id";
|
||||
static final String NAME_parent="parent";
|
||||
static final String NAME_items="items";
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
|
||||
public abstract class BaseResValueItem extends BaseResValue implements ResValueItem {
|
||||
|
||||
private ReferenceItem mReferenceItem;
|
||||
BaseResValueItem(int bytesLength) {
|
||||
super(bytesLength);
|
||||
}
|
||||
|
||||
public TableString getValueAsPoolString(){
|
||||
return getTableString(getData());
|
||||
}
|
||||
String getString(int ref){
|
||||
TableString tableString=getTableString(ref);
|
||||
if(tableString==null){
|
||||
return null;
|
||||
}
|
||||
return tableString.getHtml();
|
||||
}
|
||||
TableString getTableString(int ref){
|
||||
TableStringPool stringPool=getTableStringPool();
|
||||
if(stringPool==null){
|
||||
return null;
|
||||
}
|
||||
return stringPool.get(ref);
|
||||
}
|
||||
TableStringPool getTableStringPool(){
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock=entryBlock.getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
||||
if(tableBlock!=null){
|
||||
return tableBlock.getTableStringPool();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ReferenceItem getTableStringReference(){
|
||||
if(getValueType()!=ValueType.STRING || getEntryBlock()==null){
|
||||
return null;
|
||||
}
|
||||
if(mReferenceItem==null){
|
||||
mReferenceItem=new ResValueReference(this);
|
||||
}
|
||||
return mReferenceItem;
|
||||
}
|
||||
boolean hasTableReference(){
|
||||
return mReferenceItem!=null;
|
||||
}
|
||||
boolean removeTableReference(){
|
||||
ReferenceItem ref=mReferenceItem;
|
||||
if(ref==null){
|
||||
return false;
|
||||
}
|
||||
EntryBlock entryBlock=getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return false;
|
||||
}
|
||||
mReferenceItem=null;
|
||||
return entryBlock.removeTableReference(ref);
|
||||
}
|
||||
@Override
|
||||
public ValueType getValueType(){
|
||||
return ValueType.valueOf(getType());
|
||||
}
|
||||
@Override
|
||||
public void setValueType(ValueType valueType){
|
||||
byte type=0;
|
||||
if(valueType!=null){
|
||||
type=valueType.getByte();
|
||||
}
|
||||
setType(type);
|
||||
}
|
||||
}
|
438
src/main/java/com/reandroid/arsc/value/Entry.java
Executable file
438
src/main/java/com/reandroid/arsc/value/Entry.java
Executable file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.base.BlockCounter;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.group.EntryGroup;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.*;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class Entry extends Block implements JSONConvert<JSONObject> {
|
||||
private TableEntry<?, ?> mTableEntry;
|
||||
|
||||
public Entry(){
|
||||
super();
|
||||
}
|
||||
|
||||
public int getId(){
|
||||
return getIndex();
|
||||
}
|
||||
public String getName(){
|
||||
SpecString specString = getSpecString();
|
||||
if(specString!=null){
|
||||
return specString.get();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String getTypeName(){
|
||||
TypeBlock typeBlock = getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.getTypeName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public int getResourceId(){
|
||||
PackageBlock packageBlock = getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return 0;
|
||||
}
|
||||
TypeBlock typeBlock = getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return 0;
|
||||
}
|
||||
return (packageBlock.getId()<<24)
|
||||
| (typeBlock.getId() << 16)
|
||||
| getId();
|
||||
}
|
||||
public int getSpecReference(){
|
||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||
if(tableEntry == null){
|
||||
return 0;
|
||||
}
|
||||
return tableEntry.getHeader().getKey();
|
||||
}
|
||||
public TypeString getTypeString(){
|
||||
TypeBlock typeBlock = getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.getTypeString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public boolean isDefault(){
|
||||
ResConfig resConfig = getResConfig();
|
||||
if(resConfig!=null){
|
||||
return resConfig.isDefault();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public void setSpecReference(StringItem specReference){
|
||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||
if(tableEntry == null){
|
||||
return;
|
||||
}
|
||||
tableEntry.getHeader().setKey(specReference);
|
||||
}
|
||||
public void setSpecReference(int ref){
|
||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||
if(tableEntry == null){
|
||||
return;
|
||||
}
|
||||
tableEntry.getHeader().setKey(ref);
|
||||
}
|
||||
private Entry searchEntry(int resourceId){
|
||||
if(resourceId==getResourceId()){
|
||||
return this;
|
||||
}
|
||||
PackageBlock packageBlock= getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
TableBlock tableBlock = packageBlock.getTableBlock();
|
||||
if(tableBlock==null){
|
||||
return null;
|
||||
}
|
||||
EntryGroup entryGroup = tableBlock.search(resourceId);
|
||||
if(entryGroup!=null){
|
||||
return entryGroup.pickOne();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ResValue setValueAsRaw(ValueType valueType, int data){
|
||||
TableEntry<?, ?> tableEntry = ensureTableEntry(false);
|
||||
ResValue resValue = (ResValue) tableEntry.getValue();
|
||||
resValue.setTypeAndData(valueType, data);
|
||||
return resValue;
|
||||
}
|
||||
public ResValue setValueAsBoolean(boolean val){
|
||||
int data = val?0xffffffff:0;
|
||||
return setValueAsRaw(ValueType.INT_BOOLEAN, data);
|
||||
}
|
||||
public ResValue setValueAsReference(int resourceId){
|
||||
return setValueAsRaw(ValueType.REFERENCE, resourceId);
|
||||
}
|
||||
public ResValue setValueAsString(String str){
|
||||
TableEntry<?, ?> tableEntry = ensureTableEntry(false);
|
||||
ResValue resValue = (ResValue) tableEntry.getValue();
|
||||
resValue.setValueAsString(str);
|
||||
return resValue;
|
||||
}
|
||||
public SpecString getSpecString(){
|
||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||
if(tableEntry == null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock = getPackageBlock();
|
||||
if(packageBlock == null){
|
||||
return null;
|
||||
}
|
||||
return packageBlock.getSpecStringPool()
|
||||
.get(tableEntry.getHeader().getKey());
|
||||
}
|
||||
public ResConfig getResConfig(){
|
||||
TypeBlock typeBlock = getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.getResConfig();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypeBlock getTypeBlock(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof TypeBlock){
|
||||
return (TypeBlock) parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private String getPackageName(){
|
||||
PackageBlock packageBlock = getPackageBlock();
|
||||
if(packageBlock!=null){
|
||||
return packageBlock.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public PackageBlock getPackageBlock(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof PackageBlock){
|
||||
return (PackageBlock) parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private TableEntry<?, ?> ensureTableEntry(boolean is_complex){
|
||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||
if(tableEntry == null){
|
||||
tableEntry = createTableEntry(is_complex);
|
||||
setTableEntry(tableEntry);
|
||||
return tableEntry;
|
||||
}
|
||||
if(is_complex){
|
||||
if(tableEntry instanceof ResTableMapEntry){
|
||||
return tableEntry;
|
||||
}
|
||||
tableEntry = createTableEntry(true);
|
||||
setTableEntry(tableEntry);
|
||||
return tableEntry;
|
||||
}
|
||||
tableEntry = createTableEntry(false);
|
||||
setTableEntry(tableEntry);
|
||||
return tableEntry;
|
||||
}
|
||||
|
||||
public TableEntry<?, ?> getTableEntry(){
|
||||
return mTableEntry;
|
||||
}
|
||||
public Header getHeader(){
|
||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||
if(tableEntry!=null){
|
||||
return tableEntry.getHeader();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull(){
|
||||
return getTableEntry()==null;
|
||||
}
|
||||
@Override
|
||||
public void setNull(boolean is_null){
|
||||
if(is_null){
|
||||
setTableEntry(null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
return getTableEntry().getBytes();
|
||||
}
|
||||
@Override
|
||||
public int countBytes() {
|
||||
if(isNull()){
|
||||
return 0;
|
||||
}
|
||||
return getTableEntry().countBytes();
|
||||
}
|
||||
@Override
|
||||
public void onCountUpTo(BlockCounter counter) {
|
||||
if(counter.FOUND){
|
||||
return;
|
||||
}
|
||||
if(counter.END==this){
|
||||
counter.FOUND=true;
|
||||
return;
|
||||
}
|
||||
if(isNull()){
|
||||
return;
|
||||
}
|
||||
counter.addCount(getTableEntry().countBytes());
|
||||
}
|
||||
@Override
|
||||
protected int onWriteBytes(OutputStream stream) throws IOException {
|
||||
if(isNull()){
|
||||
return 0;
|
||||
}
|
||||
return getTableEntry().writeBytes(stream);
|
||||
}
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException {
|
||||
TableEntry<?, ?> tableEntry = createTableEntry(reader);
|
||||
setTableEntry(tableEntry);
|
||||
tableEntry.readBytes(reader);
|
||||
}
|
||||
|
||||
public boolean isComplex(){
|
||||
return getTableEntry() instanceof ResTableMapEntry;
|
||||
}
|
||||
public void setTableEntry(TableEntry<?, ?> tableEntry){
|
||||
if(tableEntry==this.mTableEntry){
|
||||
return;
|
||||
}
|
||||
onTableEntryRemoved();
|
||||
if(tableEntry==null){
|
||||
return;
|
||||
}
|
||||
tableEntry.setIndex(0);
|
||||
tableEntry.setParent(this);
|
||||
this.mTableEntry = tableEntry;
|
||||
onTableEntryAdded();
|
||||
}
|
||||
private void onTableEntryAdded(){
|
||||
PackageBlock packageBlock = getPackageBlock();
|
||||
if(packageBlock!=null){
|
||||
packageBlock.onEntryAdded(this);
|
||||
}
|
||||
}
|
||||
private void onTableEntryRemoved(){
|
||||
TableEntry<?, ?> exist = this.mTableEntry;
|
||||
if(exist == null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock = getPackageBlock();
|
||||
if(packageBlock!=null){
|
||||
packageBlock.removeEntryGroup(this);
|
||||
}
|
||||
exist.onRemoved();
|
||||
exist.setIndex(-1);
|
||||
exist.setParent(null);
|
||||
this.mTableEntry = null;
|
||||
}
|
||||
private TableEntry<?, ?> createTableEntry(BlockReader reader) throws IOException {
|
||||
int startPosition = reader.getPosition();
|
||||
reader.offset(2);
|
||||
boolean is_complex = (0x0001 & reader.readShort()) == 0x0001;
|
||||
reader.seek(startPosition);
|
||||
return createTableEntry(is_complex);
|
||||
}
|
||||
private TableEntry<?, ?> createTableEntry(boolean is_complex) {
|
||||
if(is_complex){
|
||||
return new ResTableMapEntry();
|
||||
}else {
|
||||
return new ResTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
return getTableEntry().toJson();
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
if(json==null){
|
||||
setNull(true);
|
||||
return;
|
||||
}
|
||||
boolean is_complex = json.optBoolean(Header.NAME_is_complex, false);
|
||||
TableEntry<?, ?> entry = createTableEntry(is_complex);
|
||||
setTableEntry(entry);
|
||||
entry.fromJson(json);
|
||||
}
|
||||
|
||||
public void merge(Entry entry){
|
||||
if(!shouldMerge(entry)){
|
||||
return;
|
||||
}
|
||||
TableEntry<?, ?> tableEntry = entry.getTableEntry();
|
||||
TableEntry<?, ?> existEntry = ensureTableEntry(tableEntry instanceof ResTableMapEntry);
|
||||
existEntry.merge(tableEntry);
|
||||
}
|
||||
private boolean shouldMerge(Entry coming){
|
||||
if(coming == null || coming == this || coming.isNull()){
|
||||
return false;
|
||||
}
|
||||
if(this.isNull()){
|
||||
return true;
|
||||
}
|
||||
return coming.getTableEntry().shouldMerge(coming.getTableEntry());
|
||||
}
|
||||
|
||||
public String buildResourceName(int resourceId, char prefix, boolean includeType){
|
||||
if(resourceId==0){
|
||||
return null;
|
||||
}
|
||||
Entry entry=searchEntry(resourceId);
|
||||
return buildResourceName(entry, prefix, includeType);
|
||||
}
|
||||
public String buildResourceName(Entry entry, char prefix, boolean includeType){
|
||||
if(entry==null){
|
||||
return null;
|
||||
}
|
||||
String pkgName=entry.getPackageName();
|
||||
if(getResourceId()==entry.getResourceId()){
|
||||
pkgName=null;
|
||||
}else if(pkgName!=null){
|
||||
if(pkgName.equals(this.getPackageName())){
|
||||
pkgName=null;
|
||||
}
|
||||
}
|
||||
String type=null;
|
||||
if(includeType){
|
||||
type=entry.getTypeName();
|
||||
}
|
||||
String name=entry.getName();
|
||||
return buildResourceName(prefix, pkgName, type, name);
|
||||
}
|
||||
public String getResourceName(){
|
||||
return buildResourceName('@',null, getTypeName(), getName());
|
||||
}
|
||||
public String getResourceName(char prefix){
|
||||
return getResourceName(prefix, false, true);
|
||||
}
|
||||
public String getResourceName(char prefix, boolean includePackage, boolean includeType){
|
||||
String pkg=includePackage?getPackageName():null;
|
||||
String type=includeType?getTypeName():null;
|
||||
return buildResourceName(prefix,pkg, type, getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(String.format("0x%08x", getResourceId()));
|
||||
builder.append(' ');
|
||||
ResConfig resConfig = getResConfig();
|
||||
if(resConfig!=null){
|
||||
builder.append(resConfig);
|
||||
builder.append(' ');
|
||||
}
|
||||
if(isNull()){
|
||||
builder.append("NULL");
|
||||
return builder.toString();
|
||||
}
|
||||
builder.append('@');
|
||||
builder.append(getTypeName());
|
||||
builder.append('/');
|
||||
builder.append(getName());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static String buildResourceName(char prefix, String packageName, String type, String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if(prefix!=0){
|
||||
builder.append(prefix);
|
||||
}
|
||||
if(packageName!=null){
|
||||
builder.append(packageName);
|
||||
builder.append(':');
|
||||
}
|
||||
if(type!=null){
|
||||
builder.append(type);
|
||||
builder.append('/');
|
||||
}
|
||||
builder.append(name);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -1,836 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.base.BlockCounter;
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.chunk.TypeBlock;
|
||||
import com.reandroid.arsc.group.EntryGroup;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.*;
|
||||
import com.reandroid.arsc.pool.SpecStringPool;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
private ByteArray entryHeader;
|
||||
private IntegerItem mSpecReference;
|
||||
private BaseResValue mResValue;
|
||||
private boolean mUnLocked;
|
||||
public EntryBlock() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ResValueInt setValueAsRaw(ValueType valueType, int rawValue){
|
||||
ResValueInt resValueInt;
|
||||
BaseResValue res = getResValue();
|
||||
if(res instanceof ResValueInt){
|
||||
resValueInt=(ResValueInt) res;
|
||||
}else {
|
||||
resValueInt=new ResValueInt();
|
||||
setResValue(resValueInt);
|
||||
}
|
||||
resValueInt.setValueType(valueType);
|
||||
resValueInt.setData(rawValue);
|
||||
return resValueInt;
|
||||
}
|
||||
public ResValueInt setValueAsBoolean(boolean val){
|
||||
ResValueInt resValueInt;
|
||||
BaseResValue res = getResValue();
|
||||
if(res instanceof ResValueInt){
|
||||
resValueInt=(ResValueInt) res;
|
||||
}else {
|
||||
resValueInt=new ResValueInt();
|
||||
setResValue(resValueInt);
|
||||
}
|
||||
resValueInt.setValueType(ValueType.INT_BOOLEAN);
|
||||
resValueInt.setData(val?0xffffffff:0);
|
||||
return resValueInt;
|
||||
}
|
||||
public ResValueInt setValueAsInteger(int val){
|
||||
ResValueInt resValueInt;
|
||||
BaseResValue res = getResValue();
|
||||
if(res instanceof ResValueInt){
|
||||
resValueInt=(ResValueInt) res;
|
||||
}else {
|
||||
resValueInt=new ResValueInt();
|
||||
setResValue(resValueInt);
|
||||
}
|
||||
resValueInt.setValueType(ValueType.INT_DEC);
|
||||
resValueInt.setData(val);
|
||||
return resValueInt;
|
||||
}
|
||||
public ResValueInt setValueAsReference(int resId){
|
||||
ResValueInt resValueInt;
|
||||
BaseResValue res = getResValue();
|
||||
if(res instanceof ResValueInt){
|
||||
resValueInt=(ResValueInt) res;
|
||||
}else {
|
||||
resValueInt=new ResValueInt();
|
||||
setResValue(resValueInt);
|
||||
}
|
||||
resValueInt.setValueType(ValueType.REFERENCE);
|
||||
resValueInt.setData(resId);
|
||||
return resValueInt;
|
||||
}
|
||||
public ResValueInt setValueAsString(String str){
|
||||
TableStringPool stringPool=getTableStringPool();
|
||||
if(stringPool==null){
|
||||
throw new IllegalArgumentException("TableStringPool = null, EntryBlock not added to parent TableBlock");
|
||||
}
|
||||
TableString tableString = stringPool.getOrCreate(str);
|
||||
ResValueInt resValueInt;
|
||||
BaseResValue res = getResValue();
|
||||
if(res instanceof ResValueInt){
|
||||
resValueInt=(ResValueInt) res;
|
||||
}else {
|
||||
resValueInt=new ResValueInt();
|
||||
setResValue(resValueInt);
|
||||
}
|
||||
resValueInt.setValueType(ValueType.STRING);
|
||||
resValueInt.setData(tableString.getIndex());
|
||||
return resValueInt;
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
int data = ((ResValueInt)getResValue()).getData();
|
||||
return data!=0;
|
||||
}
|
||||
public String getValueAsString(){
|
||||
TableString tableString= getValueAsTableString();
|
||||
if(tableString==null){
|
||||
return null;
|
||||
}
|
||||
return tableString.getHtml();
|
||||
}
|
||||
public TableString getValueAsTableString(){
|
||||
TableStringPool stringPool = getTableStringPool();
|
||||
if(stringPool==null){
|
||||
return null;
|
||||
}
|
||||
BaseResValue baseResValue = getResValue();
|
||||
if(!(baseResValue instanceof ResValueInt)){
|
||||
return null;
|
||||
}
|
||||
ResValueInt resValueInt = (ResValueInt)baseResValue;
|
||||
return stringPool.get(resValueInt.getData());
|
||||
}
|
||||
private TableStringPool getTableStringPool(){
|
||||
PackageBlock pkg=getPackageBlock();
|
||||
if(pkg==null){
|
||||
return null;
|
||||
}
|
||||
TableBlock table = pkg.getTableBlock();
|
||||
if(table==null){
|
||||
return null;
|
||||
}
|
||||
return table.getTableStringPool();
|
||||
}
|
||||
public boolean isDefault(){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.isDefault();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public List<ReferenceItem> getTableStringReferences(){
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
List<ReferenceItem> results=null;
|
||||
BaseResValue resValue=getResValue();
|
||||
if(resValue instanceof ResValueInt){
|
||||
ResValueInt resValueInt=(ResValueInt)resValue;
|
||||
ReferenceItem ref=resValueInt.getTableStringReference();
|
||||
if(ref!=null){
|
||||
results=new ArrayList<>();
|
||||
results.add(ref);
|
||||
}
|
||||
}else if(resValue instanceof ResValueBag){
|
||||
ResValueBag resValueBag=(ResValueBag)resValue;
|
||||
results=resValueBag.getTableStringReferences();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
boolean removeSpecReference(ReferenceItem ref){
|
||||
if(ref==null){
|
||||
return false;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return false;
|
||||
}
|
||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
||||
return specStringPool.removeReference(ref);
|
||||
}
|
||||
boolean removeTableReference(ReferenceItem ref){
|
||||
if(ref==null){
|
||||
return false;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return false;
|
||||
}
|
||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
||||
if(tableBlock==null){
|
||||
return false;
|
||||
}
|
||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
||||
return tableStringPool.removeReference(ref);
|
||||
}
|
||||
|
||||
void addSpecReference(ReferenceItem ref){
|
||||
if(ref==null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
||||
specStringPool.addReference(ref);
|
||||
}
|
||||
void addTableReference(ReferenceItem ref){
|
||||
if(ref==null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
||||
if(tableBlock==null){
|
||||
return;
|
||||
}
|
||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
||||
tableStringPool.addReference(ref);
|
||||
}
|
||||
private void removeTableReferences(){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
TableBlock tableBlock=packageBlock.getTableBlock();
|
||||
if(tableBlock==null){
|
||||
return;
|
||||
}
|
||||
TableStringPool tableStringPool=tableBlock.getTableStringPool();
|
||||
tableStringPool.removeReferences(getTableStringReferences());
|
||||
}
|
||||
private void removeSpecReferences(){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
||||
specStringPool.removeReference(getSpecReferenceBlock());
|
||||
}
|
||||
private void removeAllReferences(){
|
||||
removeTableReferences();
|
||||
removeSpecReferences();
|
||||
}
|
||||
private void setEntryTypeBag(boolean b){
|
||||
entryHeader.putBit(OFFSET_FLAGS, 0, b);
|
||||
refreshHeaderSize();
|
||||
}
|
||||
public boolean isEntryTypeBag(){
|
||||
return entryHeader.getBit(OFFSET_FLAGS,0);
|
||||
}
|
||||
public void setPublic(boolean b){
|
||||
entryHeader.putBit(OFFSET_FLAGS,1, b);
|
||||
}
|
||||
public boolean isPublic(){
|
||||
return entryHeader.getBit(OFFSET_FLAGS,1);
|
||||
}
|
||||
public void setWeak(boolean b){
|
||||
entryHeader.putBit(OFFSET_FLAGS, 2, b);
|
||||
}
|
||||
public boolean isWeak(){
|
||||
return entryHeader.getBit(OFFSET_FLAGS,2);
|
||||
}
|
||||
private IntegerItem getSpecReferenceBlock(){
|
||||
return mSpecReference;
|
||||
}
|
||||
public int getSpecReference(){
|
||||
if(mSpecReference==null){
|
||||
return -1;
|
||||
}
|
||||
return mSpecReference.get();
|
||||
}
|
||||
public void setSpecReference(int ref){
|
||||
boolean created = createNullSpecReference();
|
||||
int old=mSpecReference.get();
|
||||
if(ref==old){
|
||||
return;
|
||||
}
|
||||
mSpecReference.set(ref);
|
||||
updateSpecRef(old, ref);
|
||||
if(created){
|
||||
updatePackage();
|
||||
}
|
||||
}
|
||||
public void setSpecReference(SpecString specString){
|
||||
removeSpecRef();
|
||||
if(specString==null){
|
||||
return;
|
||||
}
|
||||
boolean created = createNullSpecReference();
|
||||
mSpecReference.set(specString.getIndex());
|
||||
if(created){
|
||||
updatePackage();
|
||||
}
|
||||
}
|
||||
private boolean createNullSpecReference(){
|
||||
if(mSpecReference==null){
|
||||
mSpecReference = new IntegerItem();
|
||||
mSpecReference.setNull(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public BaseResValue getResValue(){
|
||||
return mResValue;
|
||||
}
|
||||
public void setResValue(BaseResValue resValue){
|
||||
if(resValue==mResValue){
|
||||
return;
|
||||
}
|
||||
setResValueInternal(resValue);
|
||||
if(resValue==null){
|
||||
setNull(true);
|
||||
}else {
|
||||
setNull(false);
|
||||
boolean is_bag=(resValue instanceof ResValueBag);
|
||||
setEntryTypeBag(is_bag);
|
||||
updatePackage();
|
||||
updateSpecRef();
|
||||
}
|
||||
}
|
||||
private void setResValueInternal(BaseResValue resValue){
|
||||
if(resValue==mResValue){
|
||||
return;
|
||||
}
|
||||
if(resValue!=null){
|
||||
resValue.setIndex(2);
|
||||
resValue.setParent(this);
|
||||
}
|
||||
if(mResValue!=null){
|
||||
mResValue.setIndex(-1);
|
||||
mResValue.setParent(null);
|
||||
mResValue.onRemoved();
|
||||
}
|
||||
if(resValue!=null){
|
||||
setNull(false);
|
||||
}
|
||||
mResValue=resValue;
|
||||
}
|
||||
|
||||
public ResConfig getResConfig(){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.getResConfig();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String getName(){
|
||||
SpecString specString=getSpecString();
|
||||
if(specString==null){
|
||||
return null;
|
||||
}
|
||||
return specString.get();
|
||||
}
|
||||
public String getNameOrHex(){
|
||||
String name = getName();
|
||||
if(name==null){
|
||||
name = String.format("@0x%08x", getResourceId());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
private void setName(String name){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
EntryGroup entryGroup = packageBlock.getEntryGroup(getResourceId());
|
||||
if(entryGroup!=null){
|
||||
entryGroup.renameSpec(name);
|
||||
return;
|
||||
}
|
||||
SpecStringPool specStringPool= packageBlock.getSpecStringPool();
|
||||
SpecString specString=specStringPool.getOrCreate(name);
|
||||
setSpecReference(specString.getIndex());
|
||||
}
|
||||
public String getTypeName(){
|
||||
TypeString typeString=getTypeString();
|
||||
if(typeString==null){
|
||||
return null;
|
||||
}
|
||||
return typeString.get();
|
||||
}
|
||||
public String getPackageName(){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
return packageBlock.getName();
|
||||
}
|
||||
public SpecString getSpecString(){
|
||||
if(mSpecReference==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
||||
return specStringPool.get(getSpecReference());
|
||||
}
|
||||
public TypeString getTypeString(){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.getTypeString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String buildResourceName(int resourceId, char prefix, boolean includeType){
|
||||
if(resourceId==0){
|
||||
return null;
|
||||
}
|
||||
EntryBlock entryBlock=searchEntry(resourceId);
|
||||
return buildResourceName(entryBlock, prefix, includeType);
|
||||
}
|
||||
private EntryBlock searchEntry(int resourceId){
|
||||
if(resourceId==getResourceId()){
|
||||
return this;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return null;
|
||||
}
|
||||
TableBlock tableBlock= packageBlock.getTableBlock();
|
||||
if(tableBlock==null){
|
||||
return null;
|
||||
}
|
||||
EntryGroup entryGroup = tableBlock.search(resourceId);
|
||||
if(entryGroup!=null){
|
||||
return entryGroup.pickOne();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public String buildResourceName(EntryBlock entryBlock, char prefix, boolean includeType){
|
||||
if(entryBlock==null){
|
||||
return null;
|
||||
}
|
||||
String pkgName=entryBlock.getPackageName();
|
||||
if(getResourceId()==entryBlock.getResourceId()){
|
||||
pkgName=null;
|
||||
}else if(pkgName!=null){
|
||||
if(pkgName.equals(this.getPackageName())){
|
||||
pkgName=null;
|
||||
}
|
||||
}
|
||||
String type=null;
|
||||
if(includeType){
|
||||
type=entryBlock.getTypeName();
|
||||
}
|
||||
String name=entryBlock.getName();
|
||||
return buildResourceName(prefix, pkgName, type, name);
|
||||
}
|
||||
public String getResourceName(){
|
||||
return buildResourceName('@',null, getTypeName(), getName());
|
||||
}
|
||||
public String getResourceName(char prefix){
|
||||
return getResourceName(prefix, false, true);
|
||||
}
|
||||
public String getResourceName(char prefix, boolean includePackage, boolean includeType){
|
||||
String pkg=includePackage?getPackageName():null;
|
||||
String type=includeType?getTypeName():null;
|
||||
return buildResourceName(prefix,pkg, type, getName());
|
||||
}
|
||||
public int getResourceId(){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return 0;
|
||||
}
|
||||
PackageBlock packageBlock=typeBlock.getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return 0;
|
||||
}
|
||||
int pkgId=packageBlock.getId();
|
||||
int typeId=typeBlock.getId();
|
||||
int entryId=getIndex();
|
||||
return ((pkgId << 24) | (typeId << 16) | entryId);
|
||||
}
|
||||
public PackageBlock getPackageBlock(){
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock!=null){
|
||||
return typeBlock.getPackageBlock();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public TypeBlock getTypeBlock(){
|
||||
Block parent=getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof TypeBlock){
|
||||
return (TypeBlock)parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void unlockEntry(){
|
||||
if(mUnLocked){
|
||||
return;
|
||||
}
|
||||
mUnLocked = true;
|
||||
entryHeader = new ByteArray(4);
|
||||
if(mSpecReference==null){
|
||||
this.mSpecReference = new IntegerItem();
|
||||
}else if(mSpecReference.isNull()){
|
||||
mSpecReference.setNull(false);
|
||||
}
|
||||
entryHeader.setIndex(0);
|
||||
mSpecReference.setIndex(1);
|
||||
entryHeader.setParent(this);
|
||||
mSpecReference.setParent(this);
|
||||
}
|
||||
private void lockEntry(){
|
||||
if(!mUnLocked){
|
||||
return;
|
||||
}
|
||||
removeAllReferences();
|
||||
mUnLocked = false;
|
||||
entryHeader.setParent(null);
|
||||
mSpecReference.setParent(null);
|
||||
|
||||
entryHeader.setIndex(-1);
|
||||
mSpecReference.setIndex(-1);
|
||||
removeResValue();
|
||||
|
||||
this.entryHeader = null;
|
||||
this.mSpecReference =null;
|
||||
}
|
||||
private void removeResValue(){
|
||||
if(mResValue!=null){
|
||||
mResValue.setParent(null);
|
||||
mResValue.setIndex(-1);
|
||||
mResValue=null;
|
||||
}
|
||||
}
|
||||
private void refreshHeaderSize(){
|
||||
short size;
|
||||
if(isEntryTypeBag()){
|
||||
size=HEADER_SIZE_BAG;
|
||||
}else {
|
||||
size=HEADER_SIZE_INT;
|
||||
}
|
||||
entryHeader.putShort(OFFSET_SIZE, size);
|
||||
}
|
||||
private void createResValue(){
|
||||
if(getResValue()!=null){
|
||||
return;
|
||||
}
|
||||
BaseResValue resValue;
|
||||
if(isEntryTypeBag()){
|
||||
resValue=new ResValueBag();
|
||||
}else {
|
||||
resValue=new ResValueInt();
|
||||
}
|
||||
setResValueInternal(resValue);
|
||||
}
|
||||
@Override
|
||||
public void setNull(boolean is_null){
|
||||
if(is_null){
|
||||
lockEntry();
|
||||
}else {
|
||||
unlockEntry();
|
||||
}
|
||||
super.setNull(is_null);
|
||||
}
|
||||
@Override
|
||||
public boolean isNull(){
|
||||
if(super.isNull() || !mUnLocked){
|
||||
return true;
|
||||
}
|
||||
return mResValue==null;
|
||||
}
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
byte[] results=entryHeader.getBytes();
|
||||
results=addBytes(results, mSpecReference.getBytes());
|
||||
results=addBytes(results, mResValue.getBytes());
|
||||
return results;
|
||||
}
|
||||
@Override
|
||||
public int countBytes() {
|
||||
if(isNull()){
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
entryHeader -> 4 bytes
|
||||
mSpecReference -> 4 bytes
|
||||
-------
|
||||
Total = 8 bytes, thus this value is always fixed no need to re-count
|
||||
*/
|
||||
return 8 + mResValue.countBytes();
|
||||
}
|
||||
@Override
|
||||
public void onCountUpTo(BlockCounter counter) {
|
||||
if(counter.FOUND){
|
||||
return;
|
||||
}
|
||||
if(counter.END==this){
|
||||
counter.FOUND=true;
|
||||
return;
|
||||
}
|
||||
if(isNull()){
|
||||
return;
|
||||
}
|
||||
//counter.addCount(countBytes());
|
||||
entryHeader.onCountUpTo(counter);
|
||||
mSpecReference.onCountUpTo(counter);
|
||||
mResValue.onCountUpTo(counter);
|
||||
}
|
||||
@Override
|
||||
protected int onWriteBytes(OutputStream stream) throws IOException {
|
||||
if(isNull()){
|
||||
return 0;
|
||||
}
|
||||
int result=entryHeader.writeBytes(stream);
|
||||
result+= mSpecReference.writeBytes(stream);
|
||||
result+=mResValue.writeBytes(stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void updateSpecRef(){
|
||||
updateSpecRef(-1, getSpecReference());
|
||||
}
|
||||
private void updateSpecRef(int oldRef, int newNef){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
||||
SpecString specString=specStringPool.get(oldRef);
|
||||
if(specString!=null){
|
||||
specString.removeReference(getSpecReferenceBlock());
|
||||
}
|
||||
SpecString specStringNew=specStringPool.get(newNef);
|
||||
if(specStringNew!=null){
|
||||
specStringNew.addReference(getSpecReferenceBlock());
|
||||
}
|
||||
}
|
||||
private void removeSpecRef(){
|
||||
if(mSpecReference==null){
|
||||
return;
|
||||
}
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
SpecStringPool specStringPool=packageBlock.getSpecStringPool();
|
||||
SpecString specString=specStringPool.get(getSpecReference());
|
||||
if(specString!=null){
|
||||
specString.removeReference(getSpecReferenceBlock());
|
||||
}
|
||||
}
|
||||
private void updatePackage(){
|
||||
PackageBlock packageBlock=getPackageBlock();
|
||||
if(packageBlock==null){
|
||||
return;
|
||||
}
|
||||
packageBlock.onEntryAdded(this);
|
||||
}
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException{
|
||||
setNull(false);
|
||||
removeResValue();
|
||||
entryHeader.readBytes(reader);
|
||||
mSpecReference.readBytes(reader);
|
||||
createResValue();
|
||||
mResValue.readBytes(reader);
|
||||
updatePackage();
|
||||
updateSpecRef();
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_entry_name, getSpecString().get());
|
||||
if(isEntryTypeBag()){
|
||||
jsonObject.put(NAME_is_bag, true);
|
||||
}
|
||||
if(isWeak()){
|
||||
jsonObject.put(NAME_is_weak, true);
|
||||
}
|
||||
if(isPublic()){
|
||||
jsonObject.put(NAME_is_shared, true);
|
||||
}
|
||||
jsonObject.put(NAME_value, getResValue().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
if(json==null){
|
||||
setNull(true);
|
||||
return;
|
||||
}
|
||||
BaseResValue baseResValue;
|
||||
if(json.optBoolean(NAME_is_bag, false)){
|
||||
baseResValue=new ResValueBag();
|
||||
}else {
|
||||
baseResValue=new ResValueInt();
|
||||
}
|
||||
setResValue(baseResValue);
|
||||
setPublic(json.optBoolean(NAME_is_shared, false));
|
||||
setWeak(json.optBoolean(NAME_is_weak, false));
|
||||
setName(json.getString(NAME_entry_name));
|
||||
baseResValue.fromJson(json.getJSONObject(NAME_value));
|
||||
mResValue.onDataLoaded();
|
||||
}
|
||||
public void merge(EntryBlock entryBlock){
|
||||
if(!shouldMerge(entryBlock)){
|
||||
return;
|
||||
}
|
||||
String name=entryBlock.getName();
|
||||
if(name==null){
|
||||
name="";
|
||||
}
|
||||
if(!entryBlock.isEntryTypeBag()){
|
||||
ResValueInt comingValue = (ResValueInt) entryBlock.getResValue();
|
||||
ResValueInt exist = getOrCreateResValueInt();
|
||||
setResValue(exist);
|
||||
exist.merge(comingValue);
|
||||
}else {
|
||||
ResValueBag comingValue = (ResValueBag) entryBlock.getResValue();
|
||||
ResValueBag exist=getOrCreateResValueBag();
|
||||
setResValue(exist);
|
||||
exist.merge(comingValue);
|
||||
}
|
||||
SpecString spec = getPackageBlock()
|
||||
.getSpecStringPool().getOrCreate(name);
|
||||
setSpecReference(spec.getIndex());
|
||||
setPublic(entryBlock.isPublic());
|
||||
setWeak(entryBlock.isWeak());
|
||||
}
|
||||
private boolean shouldMerge(EntryBlock coming){
|
||||
if(coming == null || coming == this || coming.isNull()){
|
||||
return false;
|
||||
}
|
||||
if(this.isNull()){
|
||||
return true;
|
||||
}
|
||||
BaseResValue value = this.getResValue();
|
||||
if(value instanceof ResValueInt){
|
||||
ValueType valueType = ((ResValueInt)value).getValueType();
|
||||
if(valueType==null || valueType==ValueType.NULL){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
value = coming.getResValue();
|
||||
if(value instanceof ResValueInt){
|
||||
ValueType valueType = ((ResValueInt)value).getValueType();
|
||||
return valueType!=null && valueType != ValueType.NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private ResValueBag getOrCreateResValueBag(){
|
||||
if(mResValue instanceof ResValueBag){
|
||||
return (ResValueBag) mResValue;
|
||||
}
|
||||
return new ResValueBag();
|
||||
}
|
||||
private ResValueInt getOrCreateResValueInt(){
|
||||
if(mResValue instanceof ResValueInt){
|
||||
return (ResValueInt) mResValue;
|
||||
}
|
||||
return new ResValueInt();
|
||||
}
|
||||
public static String buildResourceName(char prefix, String packageName, String type, String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if(prefix!=0){
|
||||
builder.append(prefix);
|
||||
}
|
||||
if(packageName!=null){
|
||||
builder.append(packageName);
|
||||
builder.append(':');
|
||||
}
|
||||
if(type!=null){
|
||||
builder.append(type);
|
||||
builder.append('/');
|
||||
}
|
||||
builder.append(name);
|
||||
return builder.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(": ");
|
||||
ResConfig resConfig=getResConfig();
|
||||
if(resConfig!=null){
|
||||
builder.append(resConfig.toString());
|
||||
builder.append(", ");
|
||||
}
|
||||
String name=getResourceName();
|
||||
if(name==null){
|
||||
name=getNameOrHex();
|
||||
}else{
|
||||
builder.append(" id=");
|
||||
builder.append(String.format("0x%08x", getResourceId()));
|
||||
}
|
||||
builder.append('(');
|
||||
builder.append(name);
|
||||
builder.append(')');
|
||||
if(isNull()){
|
||||
builder.append(", null entry");
|
||||
return builder.toString();
|
||||
}
|
||||
BaseResValue baseResValue=getResValue();
|
||||
if(baseResValue instanceof ResValueInt){
|
||||
ResValueInt resValueInt=(ResValueInt)baseResValue;
|
||||
builder.append(" '");
|
||||
builder.append(resValueInt.toString());
|
||||
builder.append(" '");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final int OFFSET_SIZE = 0;
|
||||
private static final int OFFSET_FLAGS = 2;
|
||||
private static final short HEADER_SIZE_BAG = 0x0010;
|
||||
private static final short HEADER_SIZE_INT = 0x0008;
|
||||
|
||||
public static final String NAME_entry_name ="entry_name";
|
||||
private static final String NAME_is_bag="is_bag";
|
||||
private static final String NAME_is_shared="is_shared";
|
||||
private static final String NAME_is_weak = "is_weak";
|
||||
private static final String NAME_value="value";
|
||||
|
||||
}
|
56
src/main/java/com/reandroid/arsc/value/EntryHeader.java
Normal file
56
src/main/java/com/reandroid/arsc/value/EntryHeader.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
public class EntryHeader extends Header{
|
||||
public EntryHeader(){
|
||||
super(HEADER_SIZE_SCALAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
if(isNull()){
|
||||
return "null";
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
int byte_size = getSize();
|
||||
int read_size = readSize();
|
||||
if(byte_size!=8){
|
||||
builder.append("size=").append(byte_size);
|
||||
}
|
||||
if(byte_size!=read_size){
|
||||
builder.append(" readSize=").append(read_size);
|
||||
}
|
||||
if(isComplex()){
|
||||
builder.append(" complex");
|
||||
}
|
||||
if(isPublic()){
|
||||
builder.append(" public");
|
||||
}
|
||||
if(isWeak()){
|
||||
builder.append(" weak");
|
||||
}
|
||||
String name = getName();
|
||||
if(name!=null){
|
||||
builder.append(" name=").append(name);
|
||||
}else {
|
||||
builder.append(" key=").append(getKey());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final short HEADER_SIZE_SCALAR = 8;
|
||||
}
|
107
src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java
Normal file
107
src/main/java/com/reandroid/arsc/value/EntryHeaderMap.java
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public class EntryHeaderMap extends Header{
|
||||
public EntryHeaderMap(){
|
||||
super(HEADER_SIZE_COMPLEX);
|
||||
setComplex(true);
|
||||
}
|
||||
public int getParentId(){
|
||||
return getInteger(getBytesInternal(), OFFSET_PARENT_ID);
|
||||
}
|
||||
public void setParentId(int parentId){
|
||||
putInteger(getBytesInternal(), OFFSET_PARENT_ID, parentId);
|
||||
}
|
||||
public int getValuesCount(){
|
||||
return getInteger(getBytesInternal(), OFFSET_VALUE_COUNT);
|
||||
}
|
||||
public void setValuesCount(int valuesCount){
|
||||
putInteger(getBytesInternal(), OFFSET_VALUE_COUNT, valuesCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(Header header){
|
||||
if(header == this || !(header instanceof EntryHeaderMap)){
|
||||
return;
|
||||
}
|
||||
super.merge(header);
|
||||
EntryHeaderMap entryHeaderMap = (EntryHeaderMap) header;
|
||||
setParentId(entryHeaderMap.getParentId());
|
||||
setValuesCount(entryHeaderMap.getValuesCount());
|
||||
}
|
||||
@Override
|
||||
public void toJson(JSONObject jsonObject) {
|
||||
super.toJson(jsonObject);
|
||||
jsonObject.put(NAME_is_complex, true);
|
||||
int parent_id = getParentId();
|
||||
if(parent_id!=0){
|
||||
jsonObject.put(NAME_parent_id, parent_id);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
super.fromJson(json);
|
||||
setComplex(json.optBoolean(NAME_is_complex, true));
|
||||
setParentId(json.optInt(NAME_parent_id));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
if(isNull()){
|
||||
return "null";
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
int byte_size = getSize();
|
||||
int read_size = readSize();
|
||||
if(byte_size!=16){
|
||||
builder.append("size=").append(byte_size);
|
||||
}
|
||||
if(byte_size!=read_size){
|
||||
builder.append(", readSize=").append(read_size);
|
||||
}
|
||||
if(isComplex()){
|
||||
builder.append(" complex");
|
||||
}
|
||||
if(isPublic()){
|
||||
builder.append(", public");
|
||||
}
|
||||
if(isWeak()){
|
||||
builder.append(", weak");
|
||||
}
|
||||
String name = getName();
|
||||
if(name!=null){
|
||||
builder.append(", name=").append(name);
|
||||
}else {
|
||||
builder.append(", key=").append(getKey());
|
||||
}
|
||||
int parentId = getParentId();
|
||||
if(parentId!=0){
|
||||
builder.append(", parentId=");
|
||||
builder.append(String.format("0x%08x", getParentId()));
|
||||
}
|
||||
builder.append(", count=").append(getValuesCount());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final short HEADER_SIZE_COMPLEX = 16;
|
||||
|
||||
private static final int OFFSET_PARENT_ID = 8;
|
||||
private static final int OFFSET_VALUE_COUNT = 12;
|
||||
|
||||
public static final String NAME_parent_id = "parent_id";
|
||||
}
|
236
src/main/java/com/reandroid/arsc/value/Header.java
Normal file
236
src/main/java/com/reandroid/arsc/value/Header.java
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.chunk.ParentChunk;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.*;
|
||||
import com.reandroid.arsc.pool.StringPool;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Header extends BlockItem implements JSONConvert<JSONObject> {
|
||||
private ReferenceItem mStringReference;
|
||||
public Header(int size){
|
||||
super(size);
|
||||
writeSize();
|
||||
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, -1);
|
||||
}
|
||||
public void onRemoved(){
|
||||
unLinkStringReference();
|
||||
}
|
||||
public String getName(){
|
||||
StringItem stringItem = getNameString();
|
||||
if(stringItem!=null){
|
||||
return stringItem.get();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public boolean isComplex(){
|
||||
return getBit(getBytesInternal(), OFFSET_FLAGS,0);
|
||||
}
|
||||
public void setComplex(boolean complex){
|
||||
putBit(getBytesInternal(), OFFSET_FLAGS, 0, complex);
|
||||
}
|
||||
public void setPublic(boolean b){
|
||||
putBit(getBytesInternal(), OFFSET_FLAGS,1, b);
|
||||
}
|
||||
public boolean isPublic(){
|
||||
return getBit(getBytesInternal(), OFFSET_FLAGS,1);
|
||||
}
|
||||
public void setWeak(boolean b){
|
||||
putBit(getBytesInternal(), OFFSET_FLAGS, 2, b);
|
||||
}
|
||||
public boolean isWeak(){
|
||||
return getBit(getBytesInternal(), OFFSET_FLAGS,2);
|
||||
}
|
||||
|
||||
public int getKey(){
|
||||
return getInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE);
|
||||
}
|
||||
public void setKey(int key){
|
||||
if(key == getKey()){
|
||||
return;
|
||||
}
|
||||
unLinkStringReference();
|
||||
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, key);
|
||||
linkStringReference();
|
||||
}
|
||||
public void setKey(StringItem stringItem){
|
||||
unLinkStringReference();
|
||||
int key = -1;
|
||||
if(stringItem!=null){
|
||||
key=stringItem.getIndex();
|
||||
}
|
||||
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, key);
|
||||
linkStringReference(stringItem);
|
||||
}
|
||||
public void setSize(int size){
|
||||
super.setBytesLength(size, false);
|
||||
writeSize();
|
||||
}
|
||||
public int getSize(){
|
||||
return getBytesInternal().length;
|
||||
}
|
||||
int readSize(){
|
||||
if(getSize()<2){
|
||||
return 0;
|
||||
}
|
||||
return 0xffff & getShort(getBytesInternal(), OFFSET_SIZE);
|
||||
}
|
||||
private void writeSize(){
|
||||
int size = getSize();
|
||||
if(size>1){
|
||||
putShort(getBytesInternal(), OFFSET_SIZE, (short) size);
|
||||
}
|
||||
}
|
||||
|
||||
private void linkStringReference(){
|
||||
linkStringReference(getNameString());
|
||||
}
|
||||
private void linkStringReference(StringItem stringItem){
|
||||
unLinkStringReference();
|
||||
if(stringItem==null){
|
||||
return;
|
||||
}
|
||||
ReferenceItem stringReference = new ReferenceBlock<>(this, OFFSET_SPEC_REFERENCE);
|
||||
mStringReference = stringReference;
|
||||
stringItem.addReference(stringReference);
|
||||
}
|
||||
private void unLinkStringReference(){
|
||||
ReferenceItem stringReference = mStringReference;
|
||||
if(stringReference==null){
|
||||
return;
|
||||
}
|
||||
mStringReference = null;
|
||||
StringItem stringItem = getNameString();
|
||||
if(stringItem == null){
|
||||
return;
|
||||
}
|
||||
stringItem.removeReference(stringReference);
|
||||
}
|
||||
public StringItem getNameString(){
|
||||
StringPool<?> specStringPool = getSpecStringPool();
|
||||
if(specStringPool==null){
|
||||
return null;
|
||||
}
|
||||
return specStringPool.get(getKey());
|
||||
}
|
||||
private StringPool<?> getSpecStringPool(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof ParentChunk){
|
||||
return ((ParentChunk) parent).getSpecStringPool();
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException {
|
||||
int size = reader.readUnsignedShort();
|
||||
setBytesLength(size, false);
|
||||
reader.readFully(getBytesInternal());
|
||||
linkStringReference();
|
||||
}
|
||||
private void setName(String name){
|
||||
if(name==null){
|
||||
name = "";
|
||||
}
|
||||
StringPool<?> stringPool = getSpecStringPool();
|
||||
if(stringPool==null){
|
||||
return;
|
||||
}
|
||||
StringItem stringItem = stringPool.getOrCreate(name);
|
||||
setKey(stringItem.getIndex());
|
||||
linkStringReference(stringItem);
|
||||
}
|
||||
public void merge(Header header){
|
||||
if(header == null || header ==this){
|
||||
return;
|
||||
}
|
||||
setComplex(header.isComplex());
|
||||
setWeak(header.isWeak());
|
||||
setPublic(header.isPublic());
|
||||
setName(header.getName());
|
||||
}
|
||||
public void toJson(JSONObject jsonObject) {
|
||||
jsonObject.put(NAME_entry_name, getName());
|
||||
if(isWeak()){
|
||||
jsonObject.put(NAME_is_weak, true);
|
||||
}
|
||||
if(isPublic()){
|
||||
jsonObject.put(NAME_is_public, true);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
toJson(jsonObject);
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setWeak(json.optBoolean(NAME_is_weak, false));
|
||||
setPublic(json.optBoolean(NAME_is_public, false));
|
||||
setName(json.optString(NAME_entry_name));
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
if(isNull()){
|
||||
return "null";
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
int byte_size = getSize();
|
||||
int read_size = readSize();
|
||||
if(byte_size!=8){
|
||||
builder.append("size=").append(byte_size);
|
||||
}
|
||||
if(byte_size!=read_size){
|
||||
builder.append(", readSize=").append(read_size);
|
||||
}
|
||||
if(isComplex()){
|
||||
builder.append(", complex");
|
||||
}
|
||||
if(isPublic()){
|
||||
builder.append(", public");
|
||||
}
|
||||
if(isWeak()){
|
||||
builder.append(", weak");
|
||||
}
|
||||
String name = getName();
|
||||
if(name!=null){
|
||||
builder.append(", name=").append(name);
|
||||
}else {
|
||||
builder.append(", key=").append(getKey());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final int OFFSET_SIZE = 0;
|
||||
private static final int OFFSET_FLAGS = 2;
|
||||
private static final int OFFSET_SPEC_REFERENCE = 4;
|
||||
|
||||
|
||||
public static final String NAME_is_complex = "is_complex";
|
||||
public static final String NAME_is_public = "is_public";
|
||||
public static final String NAME_is_weak = "is_weak";
|
||||
|
||||
public static final String NAME_entry_name = "entry_name";
|
||||
}
|
66
src/main/java/com/reandroid/arsc/value/ResTableEntry.java
Normal file
66
src/main/java/com/reandroid/arsc/value/ResTableEntry.java
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public class ResTableEntry extends TableEntry<EntryHeader, ResValue> {
|
||||
public ResTableEntry() {
|
||||
super(new EntryHeader(), new ResValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
void onRemoved(){
|
||||
getHeader().onRemoved();
|
||||
getValue().onRemoved();
|
||||
}
|
||||
@Override
|
||||
boolean shouldMerge(TableEntry<?, ?> tableEntry){
|
||||
if(tableEntry == this || !(tableEntry instanceof ResTableEntry)){
|
||||
return false;
|
||||
}
|
||||
ResValue coming = ((ResTableEntry) tableEntry).getValue();
|
||||
ValueType valueType = coming.getValueType();
|
||||
if(valueType == null || valueType == ValueType.NULL){
|
||||
return false;
|
||||
}
|
||||
valueType = getValue().getValueType();
|
||||
return valueType == null || valueType == ValueType.NULL;
|
||||
}
|
||||
@Override
|
||||
public void merge(TableEntry<?, ?> tableEntry){
|
||||
if(tableEntry == this || !(tableEntry instanceof ResTableEntry)){
|
||||
return;
|
||||
}
|
||||
getHeader().merge(tableEntry.getHeader());
|
||||
getValue().merge((ValueItem) tableEntry.getValue());
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
getHeader().toJson(jsonObject);
|
||||
jsonObject.put(NAME_value, getValue().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
getHeader().fromJson(json);
|
||||
JSONObject jsonObject = json.getJSONObject(NAME_value);
|
||||
getValue().fromJson(jsonObject);
|
||||
}
|
||||
|
||||
public static final String NAME_value = "value";
|
||||
}
|
114
src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java
Normal file
114
src/main/java/com/reandroid/arsc/value/ResTableMapEntry.java
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.array.ResValueMapArray;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArray> {
|
||||
public ResTableMapEntry(){
|
||||
super(new EntryHeaderMap(), new ResValueMapArray());
|
||||
}
|
||||
public void refresh(){
|
||||
getHeader().setValuesCount(getValue().childesCount());
|
||||
}
|
||||
public ResValueMap[] listResValueMap(){
|
||||
return getValue().getChildes();
|
||||
}
|
||||
public int getParentId(){
|
||||
return getHeader().getParentId();
|
||||
}
|
||||
public void setParentId(int parentId){
|
||||
getHeader().setParentId(parentId);
|
||||
}
|
||||
public int getValuesCount(){
|
||||
return getHeader().getValuesCount();
|
||||
}
|
||||
public void setValuesCount(int valuesCount){
|
||||
getHeader().setValuesCount(valuesCount);
|
||||
getValue().setChildesCount(valuesCount);
|
||||
}
|
||||
@Override
|
||||
void onHeaderLoaded(Header header){
|
||||
getValue().setChildesCount(getValuesCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
void onRemoved(){
|
||||
getHeader().onRemoved();
|
||||
getValue().onRemoved();
|
||||
}
|
||||
@Override
|
||||
boolean shouldMerge(TableEntry<?, ?> tableEntry){
|
||||
if(tableEntry == this || !(tableEntry instanceof ResTableMapEntry)){
|
||||
return false;
|
||||
}
|
||||
ResValueMapArray coming = ((ResTableMapEntry) tableEntry).getValue();
|
||||
if(coming.childesCount() == 0){
|
||||
return false;
|
||||
}
|
||||
return getValue().childesCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void merge(TableEntry<?, ?> tableEntry){
|
||||
if(tableEntry==null || tableEntry==this){
|
||||
return;
|
||||
}
|
||||
ResTableMapEntry coming = (ResTableMapEntry) tableEntry;
|
||||
getHeader().merge(coming.getHeader());
|
||||
getValue().merge(coming.getValue());
|
||||
refresh();
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
getHeader().toJson(jsonObject);
|
||||
jsonObject.put(NAME_values, getValue().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
getHeader().fromJson(json);
|
||||
getValue().fromJson(json.optJSONArray(NAME_values));
|
||||
refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getHeader());
|
||||
ResValueMap[] valueMaps = listResValueMap();
|
||||
int len = valueMaps.length;
|
||||
int max = len;
|
||||
if(max>4){
|
||||
max = 4;
|
||||
}
|
||||
for(int i=0;i<max;i++){
|
||||
builder.append("\n ");
|
||||
builder.append(valueMaps[i]);
|
||||
}
|
||||
if(len>0){
|
||||
if(max!=len){
|
||||
builder.append("\n ...");
|
||||
}
|
||||
builder.append("\n ");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static final String NAME_values = "values";
|
||||
}
|
43
src/main/java/com/reandroid/arsc/value/ResValue.java
Executable file
43
src/main/java/com/reandroid/arsc/value/ResValue.java
Executable file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
|
||||
public class ResValue extends ValueItem {
|
||||
public ResValue() {
|
||||
super(8);
|
||||
}
|
||||
public Entry getEntry(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof Entry){
|
||||
return (Entry) parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
int getSizeOffset(){
|
||||
return OFFSET_SIZE;
|
||||
}
|
||||
|
||||
|
||||
private static final int OFFSET_SIZE = 0;
|
||||
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.array.ResValueBagItemArray;
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.base.BlockCounter;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.IntegerItem;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.*;
|
||||
|
||||
public class ResValueBag extends BaseResValue {
|
||||
|
||||
private final IntegerItem mParentId;
|
||||
private final IntegerItem mCount;
|
||||
private final ResValueBagItemArray mResValueBagItemArray;
|
||||
public ResValueBag(){
|
||||
super(0);
|
||||
mParentId =new IntegerItem();
|
||||
mCount=new IntegerItem();
|
||||
mResValueBagItemArray=new ResValueBagItemArray();
|
||||
|
||||
mParentId.setParent(this);
|
||||
mParentId.setIndex(0);
|
||||
mCount.setParent(this);
|
||||
mCount.setIndex(1);
|
||||
mResValueBagItemArray.setParent(this);
|
||||
mResValueBagItemArray.setIndex(2);
|
||||
}
|
||||
public ResValueBagItem[] getBagItems(){
|
||||
return getResValueBagItemArray().getChildes();
|
||||
}
|
||||
public List<ReferenceItem> getTableStringReferences(){
|
||||
List<ReferenceItem> results=null;
|
||||
for(ResValueBagItem bagItem:getResValueBagItemArray().listItems()){
|
||||
ReferenceItem ref=bagItem.getTableStringReference();
|
||||
if(ref==null){
|
||||
continue;
|
||||
}
|
||||
if(results==null){
|
||||
results=new ArrayList<>();
|
||||
}
|
||||
results.add(ref);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public ResValueBagItemArray getResValueBagItemArray(){
|
||||
return mResValueBagItemArray;
|
||||
}
|
||||
|
||||
public int getParentId(){
|
||||
return mParentId.get();
|
||||
}
|
||||
public void setParentId(int id){
|
||||
mParentId.set(id);
|
||||
}
|
||||
public int getCount(){
|
||||
return mCount.get();
|
||||
}
|
||||
public void setCount(int count){
|
||||
if(count<0){
|
||||
count=0;
|
||||
}
|
||||
mCount.set(count);
|
||||
mResValueBagItemArray.setChildesCount(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
byte[] results = mParentId.getBytes();
|
||||
results=addBytes(results, mCount.getBytes());
|
||||
results=addBytes(results, mResValueBagItemArray.getBytes());
|
||||
return results;
|
||||
}
|
||||
@Override
|
||||
public int countBytes() {
|
||||
int result;
|
||||
result = mParentId.countBytes();
|
||||
result+=mCount.countBytes();
|
||||
result+=mResValueBagItemArray.countBytes();
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public void onCountUpTo(BlockCounter counter) {
|
||||
if(countSubChildes(counter, mParentId)){
|
||||
return;
|
||||
}
|
||||
if(countSubChildes(counter, mCount)){
|
||||
return;
|
||||
}
|
||||
countSubChildes(counter, mResValueBagItemArray);
|
||||
}
|
||||
private boolean countSubChildes(BlockCounter counter, Block child){
|
||||
if(counter.FOUND){
|
||||
return true;
|
||||
}
|
||||
if(counter.END==child){
|
||||
counter.FOUND=true;
|
||||
return true;
|
||||
}
|
||||
int c=child.countBytes();
|
||||
counter.addCount(c);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void refreshCount(){
|
||||
mCount.set(getResValueBagItemArray().childesCount());
|
||||
}
|
||||
@Override
|
||||
protected int onWriteBytes(OutputStream writer) throws IOException {
|
||||
if(isNull()){
|
||||
return 0;
|
||||
}
|
||||
int result;
|
||||
result=mParentId.writeBytes(writer);
|
||||
result+=mCount.writeBytes(writer);
|
||||
result+=mResValueBagItemArray.writeBytes(writer);
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException{
|
||||
mResValueBagItemArray.clearChildes();
|
||||
mParentId.readBytes(reader);
|
||||
mCount.readBytes(reader);
|
||||
mResValueBagItemArray.setChildesCount(mCount.get());
|
||||
mResValueBagItemArray.readBytes(reader);
|
||||
}
|
||||
@Override
|
||||
void onDataLoaded() {
|
||||
for(ResValueBagItem item: mResValueBagItemArray.listItems()){
|
||||
item.refreshTableReference();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.put(NAME_parent, getParentId());
|
||||
jsonObject.put(NAME_items, getResValueBagItemArray().toJson());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
setParentId(json.getInt(NAME_parent));
|
||||
getResValueBagItemArray().fromJson(json.getJSONArray(NAME_items));
|
||||
refreshCount();
|
||||
}
|
||||
public void merge(ResValueBag resValueBag){
|
||||
if(resValueBag==null || resValueBag==this || resValueBag.getCount()==0){
|
||||
return;
|
||||
}
|
||||
setParentId(resValueBag.getParentId());
|
||||
getResValueBagItemArray().merge(resValueBag.getResValueBagItemArray());
|
||||
refreshCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(": parent=");
|
||||
builder.append(String.format("0x%08x", getParentId()));
|
||||
builder.append(", count=");
|
||||
builder.append(getCount());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public class ResValueBagItem extends BaseResValueItem{
|
||||
|
||||
public ResValueBagItem() {
|
||||
super(BYTES_COUNT);
|
||||
setHeaderSize(BYTES_SIZE);
|
||||
}
|
||||
@Override
|
||||
public void onRemoved(){
|
||||
removeTableReference();
|
||||
}
|
||||
public String getValueAsString(){
|
||||
return getTableString(getData()).getHtml();
|
||||
}
|
||||
public void setValueAsString(String str){
|
||||
this.setValueType(ValueType.STRING);
|
||||
TableString tableString=getTableStringPool().getOrCreate(str);
|
||||
setData(tableString.getIndex());
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
return getData()!=0;
|
||||
}
|
||||
public void setValueAsBoolean(boolean val){
|
||||
this.setValueType(ValueType.INT_BOOLEAN);
|
||||
int data=val?0xffffffff:0;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
public ResValueBag getParentBag(){
|
||||
Block parent=getParent();
|
||||
while(parent!=null){
|
||||
if(parent instanceof ResValueBag){
|
||||
return (ResValueBag) parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeaderSize(short size) {
|
||||
setShort(OFFSET_SIZE, size);
|
||||
}
|
||||
@Override
|
||||
public short getHeaderSize() {
|
||||
return getShort(OFFSET_SIZE);
|
||||
}
|
||||
@Override
|
||||
public void setReserved(byte reserved) {
|
||||
setByte(OFFSET_RESERVED, reserved);
|
||||
}
|
||||
@Override
|
||||
public byte getReserved() {
|
||||
return getByte(OFFSET_RESERVED);
|
||||
}
|
||||
|
||||
public void setId(int id){
|
||||
setInt(OFFSET_ID, id);
|
||||
}
|
||||
public int getId(){
|
||||
return getInt(OFFSET_ID);
|
||||
}
|
||||
|
||||
public void setTypeAndData(ValueType valueType, int data){
|
||||
this.setValueType(valueType);
|
||||
setData(data);
|
||||
}
|
||||
@Override
|
||||
public void setType(byte type){
|
||||
byte old=getType();
|
||||
if(type==old){
|
||||
return;
|
||||
}
|
||||
removeTableReference();
|
||||
setByte(OFFSET_TYPE, type);
|
||||
if(type==ValueType.STRING.getByte()){
|
||||
ReferenceItem ref=getTableStringReference();
|
||||
removeTableReference(ref);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public byte getType(){
|
||||
return getByte(OFFSET_TYPE);
|
||||
}
|
||||
@Override
|
||||
public int getData(){
|
||||
return getInt(OFFSET_DATA);
|
||||
}
|
||||
@Override
|
||||
public void setData(int data){
|
||||
int old=getData();
|
||||
if(data==old){
|
||||
return;
|
||||
}
|
||||
beforeDataValueChanged();
|
||||
setInt(OFFSET_DATA, data);
|
||||
afterDataValueChanged();
|
||||
}
|
||||
@Override
|
||||
public void onSetReference(int data){
|
||||
setInt(OFFSET_DATA, data);
|
||||
}
|
||||
private void beforeDataValueChanged(){
|
||||
if(getValueType()==ValueType.STRING){
|
||||
removeTableReference();
|
||||
}
|
||||
}
|
||||
private void afterDataValueChanged(){
|
||||
refreshTableReference();
|
||||
}
|
||||
void refreshTableReference(){
|
||||
if(getValueType()==ValueType.STRING){
|
||||
if(!hasTableReference()){
|
||||
addTableReference(getTableStringReference());
|
||||
}
|
||||
}else {
|
||||
removeTableReference();
|
||||
}
|
||||
}
|
||||
public short getIdHigh(){
|
||||
return getShort(OFFSET_ID+2);
|
||||
}
|
||||
public short getIdLow(){
|
||||
return getShort(OFFSET_ID);
|
||||
}
|
||||
public void setIdHigh(short val){
|
||||
setShort(OFFSET_ID+2, val);
|
||||
}
|
||||
public void setIdLow(short val){
|
||||
setShort(OFFSET_ID, val);
|
||||
}
|
||||
public short getDataHigh(){
|
||||
return getShort(OFFSET_DATA+2);
|
||||
}
|
||||
public short getDataLow(){
|
||||
return getShort(OFFSET_DATA);
|
||||
}
|
||||
public void setDataHigh(short val){
|
||||
if(val==getDataHigh()){
|
||||
return;
|
||||
}
|
||||
beforeDataValueChanged();
|
||||
setShort(OFFSET_DATA+2, val);
|
||||
afterDataValueChanged();
|
||||
}
|
||||
public void setDataLow(short val){
|
||||
if(val==getDataLow()){
|
||||
return;
|
||||
}
|
||||
beforeDataValueChanged();
|
||||
setShort(OFFSET_DATA, val);
|
||||
afterDataValueChanged();
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
ValueType valueType=getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
jsonObject.put(NAME_id, getId());
|
||||
if(valueType==ValueType.STRING){
|
||||
jsonObject.put(NAME_data, getValueAsString());
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||
}else {
|
||||
jsonObject.put(NAME_data, getData());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
||||
this.setValueType(valueType);
|
||||
setId(json.getInt(NAME_id));
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(json.optString(NAME_data, ""));
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||
}else {
|
||||
setData(json.getInt(NAME_data));
|
||||
}
|
||||
}
|
||||
public void merge(ResValueBagItem bagItem){
|
||||
if(bagItem==null||bagItem==this){
|
||||
return;
|
||||
}
|
||||
setId(bagItem.getId());
|
||||
ValueType valueType=bagItem.getValueType();
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(bagItem.getValueAsString());
|
||||
}else {
|
||||
this.setValueType(valueType);
|
||||
setData(bagItem.getData());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(" type=");
|
||||
ValueType vt=getValueType();
|
||||
if(vt!=null){
|
||||
builder.append(vt.name());
|
||||
}else {
|
||||
builder.append("Unknown");
|
||||
}
|
||||
builder.append(" size=").append(getHeaderSize());
|
||||
builder.append(" bytes=").append(countBytes());
|
||||
builder.append('(');
|
||||
builder.append(String.format("0x%02x", getType()));
|
||||
builder.append(") id=");
|
||||
builder.append(String.format("0x%08x", getId()));
|
||||
builder.append(", data=");
|
||||
builder.append(String.format("0x%08x", getData()));
|
||||
if(vt==ValueType.STRING){
|
||||
TableString ts=getTableString(getData());
|
||||
if(ts==null){
|
||||
builder.append(" Null table string");
|
||||
}else {
|
||||
builder.append(" \"").append(ts.getHtml()).append("\"");
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
private static final int OFFSET_ID=0;
|
||||
private static final int OFFSET_SIZE=4;
|
||||
private static final int OFFSET_RESERVED=6;
|
||||
private static final int OFFSET_TYPE=7;
|
||||
private static final int OFFSET_DATA=8;
|
||||
|
||||
private static final int BYTES_COUNT=12;
|
||||
|
||||
private static final short BYTES_SIZE=0x08;
|
||||
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public class ResValueInt extends BaseResValueItem {
|
||||
public ResValueInt() {
|
||||
super(BYTES_COUNT);
|
||||
setHeaderSize(BYTES_SIZE);
|
||||
}
|
||||
protected void onRemoved(){
|
||||
removeTableReference();
|
||||
}
|
||||
public String getValueAsString(){
|
||||
return getString(getData());
|
||||
}
|
||||
public void setValueAsString(String str){
|
||||
setValueType(ValueType.STRING);
|
||||
TableString tableString=getTableStringPool().getOrCreate(str);
|
||||
setData(tableString.getIndex());
|
||||
}
|
||||
public void setValueAsBoolean(boolean val){
|
||||
setValueType(ValueType.INT_BOOLEAN);
|
||||
int data=val?0xffffffff:0;
|
||||
setData(data);
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
return getData()!=0;
|
||||
}
|
||||
@Override
|
||||
void onDataLoaded() {
|
||||
if(getValueType()==ValueType.STRING){
|
||||
if(!hasTableReference()){
|
||||
addTableReference(getTableStringReference());
|
||||
}
|
||||
}else {
|
||||
removeTableReference();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setHeaderSize(short size) {
|
||||
setShort(OFFSET_SIZE, size);
|
||||
}
|
||||
@Override
|
||||
public short getHeaderSize() {
|
||||
return getShort(OFFSET_SIZE);
|
||||
}
|
||||
@Override
|
||||
public void setReserved(byte reserved) {
|
||||
setByte(OFFSET_RESERVED, reserved);
|
||||
}
|
||||
@Override
|
||||
public byte getReserved() {
|
||||
return getByte(OFFSET_RESERVED);
|
||||
}
|
||||
@Override
|
||||
public void setType(byte type){
|
||||
byte old=getType();
|
||||
if(type==old){
|
||||
return;
|
||||
}
|
||||
removeTableReference();
|
||||
setByte(OFFSET_TYPE, type);
|
||||
if(type==ValueType.STRING.getByte()){
|
||||
addTableReference(getTableStringReference());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public byte getType(){
|
||||
return getByte(OFFSET_TYPE);
|
||||
}
|
||||
@Override
|
||||
public int getData(){
|
||||
return getInt(OFFSET_DATA);
|
||||
}
|
||||
@Override
|
||||
public void setData(int data){
|
||||
int old=getData();
|
||||
if(data==old){
|
||||
return;
|
||||
}
|
||||
removeTableReference();
|
||||
setInt(OFFSET_DATA, data);
|
||||
if(getValueType()==ValueType.STRING){
|
||||
addTableReference(getTableStringReference());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onSetReference(int data){
|
||||
setInt(OFFSET_DATA, data);
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject=new JSONObject();
|
||||
ValueType valueType=getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
if(valueType==ValueType.STRING){
|
||||
jsonObject.put(NAME_data, getValueAsString());
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||
}else {
|
||||
jsonObject.put(NAME_data, getData());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(json.optString(NAME_data, ""));
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||
}else {
|
||||
setValueType(valueType);
|
||||
setData(json.getInt(NAME_data));
|
||||
}
|
||||
}
|
||||
public void merge(ResValueInt resValueInt){
|
||||
if(resValueInt==null||resValueInt==this){
|
||||
return;
|
||||
}
|
||||
ValueType valueType=resValueInt.getValueType();
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(resValueInt.getValueAsString());
|
||||
}else {
|
||||
setValueType(valueType);
|
||||
setData(resValueInt.getData());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder=new StringBuilder();
|
||||
builder.append(getClass().getSimpleName());
|
||||
builder.append(" type=");
|
||||
ValueType vt=getValueType();
|
||||
if(vt!=null){
|
||||
builder.append(vt.name());
|
||||
}else {
|
||||
builder.append("Unknown");
|
||||
}
|
||||
String data=null;
|
||||
if(vt==ValueType.STRING){
|
||||
data=getString(getData());
|
||||
}else{
|
||||
data= ValueDecoder.decode(vt, getData());
|
||||
}
|
||||
if(data==null){
|
||||
data=String.format("0x%08x", getData());
|
||||
}
|
||||
builder.append('(');
|
||||
builder.append(String.format("0x%02x", getType()));
|
||||
builder.append("), data=");
|
||||
builder.append(data);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final int OFFSET_SIZE=0;
|
||||
private static final int OFFSET_RESERVED=2;
|
||||
private static final int OFFSET_TYPE=3;
|
||||
private static final int OFFSET_DATA=4;
|
||||
|
||||
private static final int BYTES_COUNT=8;
|
||||
private static final short BYTES_SIZE=0x08;
|
||||
|
||||
}
|
115
src/main/java/com/reandroid/arsc/value/ResValueMap.java
Executable file
115
src/main/java/com/reandroid/arsc/value/ResValueMap.java
Executable file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
public class ResValueMap extends ValueItem{
|
||||
|
||||
public ResValueMap() {
|
||||
super(12);
|
||||
}
|
||||
|
||||
public Entry getEntry(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof Entry){
|
||||
return (Entry) parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ResTableMapEntry getParentMapEntry(){
|
||||
Block parent=getParent();
|
||||
while(parent!=null){
|
||||
if(parent instanceof ResTableMapEntry){
|
||||
return (ResTableMapEntry) parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getName(){
|
||||
return getInteger(getBytesInternal(), OFFSET_NAME);
|
||||
}
|
||||
public void setName(int name){
|
||||
putInteger(getBytesInternal(), OFFSET_NAME, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getSizeOffset(){
|
||||
return OFFSET_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
JSONObject jsonObject = super.toJson();
|
||||
if(jsonObject==null){
|
||||
return null;
|
||||
}
|
||||
jsonObject.put(NAME_name, getName());
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
super.fromJson(json);
|
||||
setName(json.getInt(NAME_name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "name="+String.format("0x%08x", getName())
|
||||
+", "+super.toString();
|
||||
}
|
||||
|
||||
private static final int OFFSET_NAME = 0;
|
||||
private static final int OFFSET_SIZE = 4;
|
||||
|
||||
public static final String NAME_name = "name";
|
||||
|
||||
public void setNameHigh(short val){
|
||||
int name = getName() & 0xffff;
|
||||
name = ((val & 0xffff) <<16 ) | name;
|
||||
setName(name);
|
||||
}
|
||||
public void setNameLow(short val){
|
||||
int name = getName() & 0xffff0000;
|
||||
name = (val & 0xffff) | name;
|
||||
setName(name);
|
||||
}
|
||||
public void setDataHigh(short val){
|
||||
int data = getData() & 0xffff;
|
||||
data = ((val & 0xffff) <<16 ) | data;
|
||||
setData(data);
|
||||
}
|
||||
public void setDataLow(short val){
|
||||
int data = getData() & 0xffff0000;
|
||||
data = (val & 0xffff) | data;
|
||||
setData(data);
|
||||
}
|
||||
public void merge(ResValueMap resValueMap){
|
||||
if(resValueMap==null||resValueMap==this){
|
||||
return;
|
||||
}
|
||||
super.merge(resValueMap);
|
||||
setName(resValueMap.getName());
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ResValueReference implements ReferenceItem {
|
||||
private final BaseResValueItem resValueItem;
|
||||
public ResValueReference(BaseResValueItem resValueItem){
|
||||
this.resValueItem=resValueItem;
|
||||
}
|
||||
public EntryBlock getEntryBlock(){
|
||||
return resValueItem.getEntryBlock();
|
||||
}
|
||||
@Override
|
||||
public void set(int val) {
|
||||
resValueItem.onSetReference(val);
|
||||
}
|
||||
@Override
|
||||
public int get() {
|
||||
return resValueItem.getData();
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ResValueReference that = (ResValueReference) o;
|
||||
return Objects.equals(resValueItem, that.resValueItem);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(resValueItem);
|
||||
}
|
||||
}
|
116
src/main/java/com/reandroid/arsc/value/TableEntry.java
Normal file
116
src/main/java/com/reandroid/arsc/value/TableEntry.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.base.BlockCounter;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public abstract class TableEntry<HEADER extends Header, VALUE extends Block> extends Block implements
|
||||
JSONConvert<JSONObject> {
|
||||
private final HEADER header;
|
||||
private final VALUE resValue;
|
||||
|
||||
TableEntry(HEADER header, VALUE resValue){
|
||||
super();
|
||||
this.header = header;
|
||||
this.resValue = resValue;
|
||||
|
||||
this.header.setParent(this);
|
||||
this.header.setIndex(0);
|
||||
this.resValue.setParent(this);
|
||||
this.resValue.setIndex(1);
|
||||
}
|
||||
public Entry getParentEntry(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof Entry){
|
||||
return (Entry) parent;
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void refresh(){
|
||||
}
|
||||
public final HEADER getHeader() {
|
||||
return header;
|
||||
}
|
||||
public VALUE getValue(){
|
||||
return resValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
byte[] results = getHeader().getBytes();
|
||||
results = addBytes(results, getValue().getBytes());
|
||||
return results;
|
||||
}
|
||||
@Override
|
||||
public int countBytes() {
|
||||
int result = getHeader().countBytes();
|
||||
result += getValue().countBytes();
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public void onCountUpTo(BlockCounter counter) {
|
||||
if(counter.FOUND){
|
||||
return;
|
||||
}
|
||||
if(counter.END==this){
|
||||
counter.FOUND=true;
|
||||
return;
|
||||
}
|
||||
getHeader().onCountUpTo(counter);
|
||||
getValue().onCountUpTo(counter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException {
|
||||
Header header = getHeader();
|
||||
header.readBytes(reader);
|
||||
onHeaderLoaded(header);
|
||||
getValue().readBytes(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int onWriteBytes(OutputStream stream) throws IOException {
|
||||
int result;
|
||||
result = getHeader().writeBytes(stream);
|
||||
result += getValue().writeBytes(stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
void onHeaderLoaded(Header header){
|
||||
}
|
||||
abstract void onRemoved();
|
||||
abstract boolean shouldMerge(TableEntry<?, ?> tableEntry);
|
||||
|
||||
public abstract void merge(TableEntry<?, ?> tableEntry);
|
||||
@Override
|
||||
public abstract JSONObject toJson();
|
||||
@Override
|
||||
public abstract void fromJson(JSONObject json);
|
||||
@Override
|
||||
public String toString(){
|
||||
return getHeader()+", value={"+getValue()+"}";
|
||||
}
|
||||
}
|
295
src/main/java/com/reandroid/arsc/value/ValueItem.java
Executable file
295
src/main/java/com/reandroid/arsc/value/ValueItem.java
Executable file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.arsc.value;
|
||||
|
||||
import com.reandroid.arsc.base.Block;
|
||||
import com.reandroid.arsc.chunk.MainChunk;
|
||||
import com.reandroid.arsc.io.BlockReader;
|
||||
import com.reandroid.arsc.item.BlockItem;
|
||||
import com.reandroid.arsc.item.ReferenceBlock;
|
||||
import com.reandroid.arsc.item.ReferenceItem;
|
||||
import com.reandroid.arsc.item.StringItem;
|
||||
import com.reandroid.arsc.pool.StringPool;
|
||||
import com.reandroid.json.JSONConvert;
|
||||
import com.reandroid.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class ValueItem extends BlockItem implements Value,
|
||||
JSONConvert<JSONObject>{
|
||||
private ReferenceItem mStringReference;
|
||||
public ValueItem(int bytesLength) {
|
||||
super(bytesLength);
|
||||
writeSize();
|
||||
}
|
||||
public void onRemoved(){
|
||||
unLinkStringReference();
|
||||
}
|
||||
public Entry getParentEntry(){
|
||||
Block parent=getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof Entry){
|
||||
return (Entry) parent;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void refresh(){
|
||||
writeSize();
|
||||
}
|
||||
public ReferenceItem getTableStringReference(){
|
||||
return mStringReference;
|
||||
}
|
||||
|
||||
abstract int getSizeOffset();
|
||||
|
||||
byte getRes0(){
|
||||
return getBytesInternal()[getSizeOffset()+OFFSET_RES0];
|
||||
}
|
||||
public byte getType(){
|
||||
return getBytesInternal()[getSizeOffset()+OFFSET_TYPE];
|
||||
}
|
||||
public void setType(byte type){
|
||||
if(type == getType()){
|
||||
return;
|
||||
}
|
||||
byte[] bts = getBytesInternal();
|
||||
int offset = getSizeOffset()+OFFSET_TYPE;
|
||||
byte old = bts[offset];
|
||||
bts[offset] = type;
|
||||
onTypeChanged(old, type);
|
||||
}
|
||||
public int getSize(){
|
||||
return 0xffff & getShort(getBytesInternal(), getSizeOffset()+OFFSET_SIZE);
|
||||
}
|
||||
public void setSize(int size){
|
||||
size = getSizeOffset() + size;
|
||||
setBytesLength(size, false);
|
||||
writeSize();
|
||||
}
|
||||
private void writeSize(){
|
||||
int offset = getSizeOffset();
|
||||
int size = countBytes() - offset;
|
||||
putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size);
|
||||
}
|
||||
private void onDataLoaded(){
|
||||
if(getValueType() == ValueType.STRING){
|
||||
linkStringReference();
|
||||
}else {
|
||||
unLinkStringReference();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public ValueType getValueType(){
|
||||
return ValueType.valueOf(getType());
|
||||
}
|
||||
@Override
|
||||
public void setValueType(ValueType valueType){
|
||||
byte type = 0;
|
||||
if(valueType!=null){
|
||||
type = valueType.getByte();
|
||||
}
|
||||
setType(type);
|
||||
}
|
||||
@Override
|
||||
public int getData(){
|
||||
return getInteger(getBytesInternal(), getSizeOffset()+OFFSET_DATA);
|
||||
}
|
||||
@Override
|
||||
public void setData(int data){
|
||||
byte[] bts = getBytesInternal();
|
||||
int old = getInteger(bts, getSizeOffset()+OFFSET_DATA);
|
||||
if(old == data){
|
||||
return;
|
||||
}
|
||||
unLinkStringReference();
|
||||
putInteger(bts, getSizeOffset()+OFFSET_DATA, data);
|
||||
if(ValueType.STRING==getValueType()){
|
||||
linkStringReference();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public StringItem getDataAsPoolString(){
|
||||
StringPool<?> stringPool = getStringPool();
|
||||
if(stringPool == null){
|
||||
return null;
|
||||
}
|
||||
return stringPool.get(getData());
|
||||
}
|
||||
private void onTypeChanged(byte old, byte type){
|
||||
byte typeString = ValueType.STRING.getByte();
|
||||
if(old == typeString){
|
||||
unLinkStringReference();
|
||||
}else if(type == typeString){
|
||||
linkStringReference();
|
||||
}
|
||||
}
|
||||
private void linkStringReference(){
|
||||
StringItem tableString = getDataAsPoolString();
|
||||
if(tableString==null){
|
||||
return;
|
||||
}
|
||||
ReferenceItem stringReference = mStringReference;
|
||||
if(stringReference!=null){
|
||||
unLinkStringReference();
|
||||
}
|
||||
stringReference = new ReferenceBlock<>(this, getSizeOffset()+OFFSET_DATA);
|
||||
mStringReference = stringReference;
|
||||
tableString.addReference(stringReference);
|
||||
}
|
||||
private void unLinkStringReference(){
|
||||
ReferenceItem stringReference = mStringReference;
|
||||
if(stringReference==null){
|
||||
return;
|
||||
}
|
||||
mStringReference = null;
|
||||
StringPool<?> stringPool = getStringPool();
|
||||
if(stringPool == null){
|
||||
return;
|
||||
}
|
||||
stringPool.removeReference(stringReference);
|
||||
}
|
||||
private StringPool<?> getStringPool(){
|
||||
Block parent = getParent();
|
||||
while (parent!=null){
|
||||
if(parent instanceof MainChunk){
|
||||
return ((MainChunk) parent).getStringPool();
|
||||
}
|
||||
parent=parent.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public void onReadBytes(BlockReader reader) throws IOException {
|
||||
initializeBytes(reader);
|
||||
super.onReadBytes(reader);
|
||||
onDataLoaded();
|
||||
}
|
||||
private void initializeBytes(BlockReader reader) throws IOException {
|
||||
int position = reader.getPosition();
|
||||
int offset = getSizeOffset();
|
||||
reader.offset(offset);
|
||||
int size = reader.readUnsignedShort();
|
||||
reader.seek(position);
|
||||
setBytesLength(offset + size, false);
|
||||
}
|
||||
public String getValueAsString(){
|
||||
StringItem stringItem = getDataAsPoolString();
|
||||
if(stringItem!=null){
|
||||
return stringItem.getHtml();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void setValueAsString(String str){
|
||||
StringItem stringItem = getStringPool().getOrCreate(str);
|
||||
setData(stringItem.getIndex());
|
||||
setValueType(ValueType.STRING);
|
||||
}
|
||||
public boolean getValueAsBoolean(){
|
||||
return getData()!=0;
|
||||
}
|
||||
public void setValueAsBoolean(boolean val){
|
||||
setValueType(ValueType.INT_BOOLEAN);
|
||||
int data=val?0xffffffff:0;
|
||||
setData(data);
|
||||
}
|
||||
public void setTypeAndData(ValueType valueType, int data){
|
||||
setData(data);
|
||||
setValueType(valueType);
|
||||
}
|
||||
public void merge(ValueItem valueItem){
|
||||
if(valueItem == null || valueItem==this){
|
||||
return;
|
||||
}
|
||||
setSize(valueItem.getSize());
|
||||
ValueType coming = valueItem.getValueType();
|
||||
if(coming == ValueType.STRING){
|
||||
setValueAsString(valueItem.getValueAsString());
|
||||
}else {
|
||||
setTypeAndData(coming, valueItem.getData());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(isNull()){
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
ValueType valueType = getValueType();
|
||||
jsonObject.put(NAME_value_type, valueType.name());
|
||||
if(valueType==ValueType.STRING){
|
||||
jsonObject.put(NAME_data, getValueAsString());
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||
}else {
|
||||
jsonObject.put(NAME_data, getData());
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
@Override
|
||||
public void fromJson(JSONObject json) {
|
||||
ValueType valueType = ValueType.fromName(json.getString(NAME_value_type));
|
||||
if(valueType==ValueType.STRING){
|
||||
setValueAsString(json.optString(NAME_data, ""));
|
||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||
}else {
|
||||
setValueType(valueType);
|
||||
setData(json.getInt(NAME_data));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int size = getSize();
|
||||
if(size!=8){
|
||||
builder.append("size=").append(getSize());
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append("type=");
|
||||
ValueType valueType=getValueType();
|
||||
if(valueType!=null){
|
||||
builder.append(valueType);
|
||||
}else {
|
||||
builder.append(String.format("0x%02x", (0xff & getType())));
|
||||
}
|
||||
builder.append(", data=");
|
||||
int data = getData();
|
||||
if(valueType==ValueType.STRING){
|
||||
StringItem tableString = getDataAsPoolString();
|
||||
if(tableString!=null){
|
||||
builder.append(tableString.getHtml());
|
||||
}else {
|
||||
builder.append(String.format("0x%08x", data));
|
||||
}
|
||||
}else {
|
||||
builder.append(String.format("0x%08x", data));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static final int OFFSET_SIZE = 0;
|
||||
private static final int OFFSET_RES0 = 2;
|
||||
private static final int OFFSET_TYPE = 3;
|
||||
private static final int OFFSET_DATA = 4;
|
||||
|
||||
|
||||
static final String NAME_data = "data";
|
||||
static final String NAME_value_type = "value_type";
|
||||
}
|
@ -15,9 +15,9 @@
|
||||
*/
|
||||
package com.reandroid.arsc.value.array;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -19,19 +19,19 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayBagItem {
|
||||
private final ResValueBagItem mBagItem;
|
||||
public ArrayBagItem(ResValueBagItem bagItem){
|
||||
private final ResValueMap mBagItem;
|
||||
public ArrayBagItem(ResValueMap bagItem){
|
||||
this.mBagItem=bagItem;
|
||||
}
|
||||
public ResValueBagItem getBagItem() {
|
||||
public ResValueMap getBagItem() {
|
||||
return mBagItem;
|
||||
}
|
||||
|
||||
@ -39,11 +39,11 @@ import java.util.List;
|
||||
return getBagItem().getValueType();
|
||||
}
|
||||
private TableStringPool getStringPool(){
|
||||
EntryBlock entryBlock=getBagItem().getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
Entry entry =getBagItem().getEntry();
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock pkg = entryBlock.getPackageBlock();
|
||||
PackageBlock pkg = entry.getPackageBlock();
|
||||
if(pkg==null){
|
||||
return null;
|
||||
}
|
||||
@ -88,17 +88,17 @@ import java.util.List;
|
||||
builder.append("</item>");
|
||||
return builder.toString();
|
||||
}
|
||||
public static ArrayBagItem[] create(ResValueBagItem[] resValueBagItems){
|
||||
if(resValueBagItems==null){
|
||||
public static ArrayBagItem[] create(ResValueMap[] resValueMaps){
|
||||
if(resValueMaps ==null){
|
||||
return null;
|
||||
}
|
||||
int len=resValueBagItems.length;
|
||||
int len= resValueMaps.length;
|
||||
if(len==0){
|
||||
return null;
|
||||
}
|
||||
List<ArrayBagItem> results=new ArrayList<>();
|
||||
for(int i=0;i<len;i++){
|
||||
ArrayBagItem item=create(resValueBagItems[i]);
|
||||
ArrayBagItem item=create(resValueMaps[i]);
|
||||
if(item==null){
|
||||
return null;
|
||||
}
|
||||
@ -106,11 +106,11 @@ import java.util.List;
|
||||
}
|
||||
return results.toArray(new ArrayBagItem[0]);
|
||||
}
|
||||
public static ArrayBagItem create(ResValueBagItem resValueBagItem){
|
||||
if(resValueBagItem==null){
|
||||
public static ArrayBagItem create(ResValueMap resValueMap){
|
||||
if(resValueMap ==null){
|
||||
return null;
|
||||
}
|
||||
ArrayBagItem item=new ArrayBagItem(resValueBagItem);
|
||||
ArrayBagItem item=new ArrayBagItem(resValueMap);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,10 @@
|
||||
*/
|
||||
package com.reandroid.arsc.value.attribute;
|
||||
|
||||
import com.reandroid.arsc.array.ResValueMapArray;
|
||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
import com.reandroid.common.EntryStore;
|
||||
|
||||
@ -220,9 +221,9 @@ public class AttributeBag {
|
||||
AttributeBagItem[] bagItems= getBagItems();
|
||||
StringBuilder builder=new StringBuilder();
|
||||
AttributeBagItem format=getFormat();
|
||||
EntryBlock entryBlock=format.getBagItem().getEntryBlock();
|
||||
if(entryBlock!=null){
|
||||
builder.append(entryBlock.getSpecString());
|
||||
Entry entry =format.getBagItem().getEntry();
|
||||
if(entry !=null){
|
||||
builder.append(entry.getSpecString());
|
||||
}
|
||||
int len=bagItems.length;
|
||||
builder.append(", childes=").append(len);
|
||||
@ -234,21 +235,21 @@ public class AttributeBag {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static AttributeBag create(ResValueBag resValueBag){
|
||||
if(resValueBag==null){
|
||||
public static AttributeBag create(ResValueMapArray resValueMapArray){
|
||||
if(resValueMapArray==null){
|
||||
return null;
|
||||
}
|
||||
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueBag.getBagItems());
|
||||
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueMapArray.getChildes());
|
||||
if(bagItems==null){
|
||||
return null;
|
||||
}
|
||||
return new AttributeBag(bagItems);
|
||||
}
|
||||
public static boolean isAttribute(ResValueBag resValueBag){
|
||||
if(resValueBag==null){
|
||||
public static boolean isAttribute(ResTableMapEntry mapEntry){
|
||||
if(mapEntry==null){
|
||||
return false;
|
||||
}
|
||||
AttributeBagItem[] bagItems=AttributeBagItem.create(resValueBag.getBagItems());
|
||||
AttributeBagItem[] bagItems=AttributeBagItem.create(mapEntry.listResValueMap());
|
||||
return bagItems!=null;
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ package com.reandroid.arsc.value.attribute;
|
||||
|
||||
import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.group.EntryGroup;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.common.EntryStore;
|
||||
|
||||
|
||||
public class AttributeBagItem {
|
||||
private final ResValueBagItem mBagItem;
|
||||
public AttributeBagItem(ResValueBagItem bagItem){
|
||||
private final ResValueMap mBagItem;
|
||||
public AttributeBagItem(ResValueMap bagItem){
|
||||
this.mBagItem=bagItem;
|
||||
}
|
||||
public int getData(){
|
||||
@ -36,7 +36,7 @@ public class AttributeBagItem {
|
||||
public String getNameOrHex(EntryStore entryStore){
|
||||
String name=getName(entryStore);
|
||||
if(name==null){
|
||||
name=String.format("@0x%08x", getBagItem().getId());
|
||||
name=String.format("@0x%08x", getBagItem().getName());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@ -47,9 +47,9 @@ public class AttributeBagItem {
|
||||
if(isType()){
|
||||
return null;
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
int id=item.getId();
|
||||
EntryBlock parentEntry=item.getEntryBlock();
|
||||
ResValueMap item=getBagItem();
|
||||
int id=item.getName();
|
||||
Entry parentEntry=item.getEntry();
|
||||
if(parentEntry!=null){
|
||||
PackageBlock packageBlock=parentEntry.getPackageBlock();
|
||||
if(packageBlock!=null){
|
||||
@ -70,26 +70,27 @@ public class AttributeBagItem {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public ResValueBagItem getBagItem() {
|
||||
public ResValueMap getBagItem() {
|
||||
return mBagItem;
|
||||
}
|
||||
public AttributeItemType getItemType(){
|
||||
if(!isType()){
|
||||
return null;
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
return AttributeItemType.valueOf(item.getIdLow());
|
||||
ResValueMap item=getBagItem();
|
||||
int low = item.getName() & 0xffff;
|
||||
return AttributeItemType.valueOf((short) low);
|
||||
}
|
||||
public boolean isType(){
|
||||
ResValueBagItem item=getBagItem();
|
||||
return item.getIdHigh()==0x0100;
|
||||
ResValueMap item=getBagItem();
|
||||
return ((item.getName()>>16) & 0xffff)==0x0100;
|
||||
}
|
||||
public boolean contains(AttributeValueType valueType){
|
||||
if(valueType == null || getItemType()!=AttributeItemType.FORMAT){
|
||||
return false;
|
||||
}
|
||||
int value = 0xff & valueType.getByte();
|
||||
int dataLow = 0xffff & getBagItem().getDataLow();
|
||||
int dataLow = 0xffff & getBagItem().getData();
|
||||
return (dataLow & value) == value;
|
||||
}
|
||||
public boolean isEqualType(AttributeValueType valueType){
|
||||
@ -97,7 +98,7 @@ public class AttributeBagItem {
|
||||
return false;
|
||||
}
|
||||
int value = 0xff & valueType.getByte();
|
||||
int dataLow = 0xffff & getBagItem().getDataLow();
|
||||
int dataLow = 0xffff & getBagItem().getData();
|
||||
return (dataLow == value);
|
||||
}
|
||||
public AttributeValueType[] getValueTypes(){
|
||||
@ -105,8 +106,8 @@ public class AttributeBagItem {
|
||||
if(type!=AttributeItemType.FORMAT){
|
||||
return null;
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
short low=item.getDataLow();
|
||||
ResValueMap item=getBagItem();
|
||||
short low = (short) (item.getData() & 0xffff);
|
||||
return AttributeValueType.valuesOf(low);
|
||||
}
|
||||
public Integer getBound(){
|
||||
@ -114,7 +115,7 @@ public class AttributeBagItem {
|
||||
if(type==null || type==AttributeItemType.FORMAT){
|
||||
return null;
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
ResValueMap item=getBagItem();
|
||||
return item.getData();
|
||||
}
|
||||
public boolean isEnum(){
|
||||
@ -122,16 +123,18 @@ public class AttributeBagItem {
|
||||
if(type!=AttributeItemType.FORMAT){
|
||||
return false;
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
return item.getDataHigh()==AttributeBag.TYPE_ENUM;
|
||||
ResValueMap item=getBagItem();
|
||||
int high = (item.getData() >> 16) & 0xffff;
|
||||
return high==AttributeBag.TYPE_ENUM;
|
||||
}
|
||||
public boolean isFlag(){
|
||||
AttributeItemType type=getItemType();
|
||||
if(type!=AttributeItemType.FORMAT){
|
||||
return false;
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
return item.getDataHigh()==AttributeBag.TYPE_FLAG;
|
||||
ResValueMap item=getBagItem();
|
||||
int high = (item.getData() >> 16) & 0xffff;
|
||||
return high==AttributeBag.TYPE_FLAG;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
@ -157,7 +160,7 @@ public class AttributeBagItem {
|
||||
builder.append(bound);
|
||||
return builder.toString();
|
||||
}
|
||||
ResValueBagItem item=getBagItem();
|
||||
ResValueMap item=getBagItem();
|
||||
builder.append(getNameOrHex());
|
||||
builder.append("=").append(String.format("0x%x", item.getData()));
|
||||
return builder.toString();
|
||||
@ -190,15 +193,15 @@ public class AttributeBagItem {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static AttributeBagItem[] create(ResValueBagItem[] resValueBagItems){
|
||||
if(resValueBagItems==null){
|
||||
public static AttributeBagItem[] create(ResValueMap[] resValueMaps){
|
||||
if(resValueMaps ==null){
|
||||
return null;
|
||||
}
|
||||
AttributeBagItem format=null;
|
||||
int len=resValueBagItems.length;
|
||||
int len= resValueMaps.length;
|
||||
AttributeBagItem[] bagItems=new AttributeBagItem[len];
|
||||
for(int i=0;i<len;i++){
|
||||
AttributeBagItem item=new AttributeBagItem(resValueBagItems[i]);
|
||||
AttributeBagItem item=new AttributeBagItem(resValueMaps[i]);
|
||||
bagItems[i]=item;
|
||||
if(format==null){
|
||||
if(AttributeItemType.FORMAT==item.getItemType()){
|
||||
|
@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.reandroid.arsc.value.plurals;
|
||||
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBag;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||
|
||||
public class PluralsBag {
|
||||
private final PluralsBagItem[] mBagItems;
|
||||
@ -27,18 +27,18 @@ public class PluralsBag {
|
||||
return mBagItems;
|
||||
}
|
||||
public String getName(){
|
||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
return entryBlock.getName();
|
||||
return entry.getName();
|
||||
}
|
||||
public String getTypeName(){
|
||||
EntryBlock entryBlock=getBagItems()[0].getBagItem().getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
Entry entry =getBagItems()[0].getBagItem().getEntry();
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
return entryBlock.getTypeName();
|
||||
return entry.getTypeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,22 +63,18 @@ public class PluralsBag {
|
||||
|
||||
/** The result of this is not always 100% accurate,
|
||||
* in addition to this use your methods to cross check like type-name == "plurals"**/
|
||||
public static boolean isPlurals(ResValueBag resValueBag){
|
||||
if(resValueBag==null){
|
||||
public static boolean isPlurals(ResTableMapEntry mapEntry){
|
||||
if(mapEntry==null){
|
||||
return false;
|
||||
}
|
||||
EntryBlock entryBlock = resValueBag.getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
return false;
|
||||
}
|
||||
return PluralsBagItem.create(resValueBag.getBagItems()) != null;
|
||||
return PluralsBagItem.create(mapEntry.listResValueMap()) != null;
|
||||
}
|
||||
|
||||
public static PluralsBag create(ResValueBag resValueBag){
|
||||
if(resValueBag==null){
|
||||
public static PluralsBag create(ResTableMapEntry mapEntry){
|
||||
if(mapEntry==null){
|
||||
return null;
|
||||
}
|
||||
PluralsBagItem[] bagItems=PluralsBagItem.create(resValueBag.getBagItems());
|
||||
PluralsBagItem[] bagItems=PluralsBagItem.create(mapEntry.listResValueMap());
|
||||
if(bagItems==null){
|
||||
return null;
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.arsc.pool.TableStringPool;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -29,26 +29,27 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PluralsBagItem {
|
||||
private final ResValueBagItem mBagItem;
|
||||
private PluralsBagItem(ResValueBagItem bagItem){
|
||||
private final ResValueMap mBagItem;
|
||||
private PluralsBagItem(ResValueMap bagItem){
|
||||
this.mBagItem=bagItem;
|
||||
}
|
||||
public ResValueBagItem getBagItem() {
|
||||
public ResValueMap getBagItem() {
|
||||
return mBagItem;
|
||||
}
|
||||
public PluralsQuantity getQuantity(){
|
||||
ResValueBagItem item=getBagItem();
|
||||
return PluralsQuantity.valueOf(item.getIdLow());
|
||||
ResValueMap item=getBagItem();
|
||||
int low = item.getName() & 0xffff;
|
||||
return PluralsQuantity.valueOf((short) low);
|
||||
}
|
||||
public ValueType getValueType(){
|
||||
return getBagItem().getValueType();
|
||||
}
|
||||
private TableStringPool getStringPool(){
|
||||
EntryBlock entryBlock=getBagItem().getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
Entry entry =getBagItem().getEntry();
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
PackageBlock pkg = entryBlock.getPackageBlock();
|
||||
PackageBlock pkg = entry.getPackageBlock();
|
||||
if(pkg==null){
|
||||
return null;
|
||||
}
|
||||
@ -96,22 +97,23 @@ public class PluralsBagItem {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static PluralsBagItem[] create(ResValueBagItem[] resValueBagItems){
|
||||
if(resValueBagItems==null){
|
||||
public static PluralsBagItem[] create(ResValueMap[] resValueMaps){
|
||||
if(resValueMaps ==null){
|
||||
return null;
|
||||
}
|
||||
int len=resValueBagItems.length;
|
||||
int len= resValueMaps.length;
|
||||
if(len==0){
|
||||
return null;
|
||||
}
|
||||
Set<PluralsQuantity> duplicates=new HashSet<>();
|
||||
List<PluralsBagItem> results=new ArrayList<>();
|
||||
for(int i=0;i<len;i++){
|
||||
ResValueBagItem resValueBagItem = resValueBagItems[i];
|
||||
if(resValueBagItem.getIdHigh() != 0x0100){
|
||||
ResValueMap resValueMap = resValueMaps[i];
|
||||
int high = (resValueMap.getName() >> 16) & 0xffff;
|
||||
if(high != 0x0100){
|
||||
return null;
|
||||
}
|
||||
PluralsBagItem item=create(resValueBagItem);
|
||||
PluralsBagItem item=create(resValueMap);
|
||||
if(item==null){
|
||||
// If it reaches here type name is obfuscated
|
||||
return null;
|
||||
@ -125,8 +127,8 @@ public class PluralsBagItem {
|
||||
}
|
||||
return results.toArray(new PluralsBagItem[0]);
|
||||
}
|
||||
public static PluralsBagItem create(ResValueBagItem resValueBagItem){
|
||||
PluralsBagItem item=new PluralsBagItem(resValueBagItem);
|
||||
public static PluralsBagItem create(ResValueMap resValueMap){
|
||||
PluralsBagItem item=new PluralsBagItem(resValueMap);
|
||||
if(item.getQuantity()==null){
|
||||
return null;
|
||||
}
|
||||
|
@ -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 entry.getTypeName();
|
||||
}
|
||||
return typeString.get();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -15,24 +15,24 @@
|
||||
*/
|
||||
package com.reandroid.arsc.value.style;
|
||||
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.ResValueBagItem;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.ResValueMap;
|
||||
import com.reandroid.arsc.value.ValueType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StyleBagItem {
|
||||
private final ResValueBagItem mBagItem;
|
||||
public StyleBagItem(ResValueBagItem bagItem){
|
||||
private final ResValueMap mBagItem;
|
||||
public StyleBagItem(ResValueMap bagItem){
|
||||
this.mBagItem=bagItem;
|
||||
}
|
||||
public ResValueBagItem getBagItem() {
|
||||
public ResValueMap getBagItem() {
|
||||
return mBagItem;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
EntryBlock block=getBagItem().getEntryBlock();
|
||||
Entry block=getBagItem().getEntry();
|
||||
if(block==null){
|
||||
return null;
|
||||
}
|
||||
@ -40,7 +40,7 @@ public class StyleBagItem {
|
||||
return block.buildResourceName(getNameId(), prefix, false);
|
||||
}
|
||||
public int getNameId(){
|
||||
return getBagItem().getId();
|
||||
return getBagItem().getName();
|
||||
}
|
||||
public boolean hasStringValue(){
|
||||
return getValueType()== ValueType.STRING;
|
||||
@ -56,8 +56,8 @@ public class StyleBagItem {
|
||||
if(valueType!=ValueType.REFERENCE && valueType!=ValueType.ATTRIBUTE){
|
||||
throw new IllegalArgumentException("Not REF ValueType="+valueType);
|
||||
}
|
||||
EntryBlock entryBlock=getBagItem().getEntryBlock();
|
||||
if(entryBlock==null){
|
||||
Entry entry =getBagItem().getEntry();
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
char prefix='@';
|
||||
@ -67,7 +67,7 @@ public class StyleBagItem {
|
||||
includeType=false;
|
||||
}
|
||||
int id=getValue();
|
||||
return entryBlock.buildResourceName(id, prefix, includeType);
|
||||
return entry.buildResourceName(id, prefix, includeType);
|
||||
}
|
||||
public String getStringValue(){
|
||||
return mBagItem.getValueAsString();
|
||||
@ -102,17 +102,17 @@ public class StyleBagItem {
|
||||
builder.append("</item>");
|
||||
return builder.toString();
|
||||
}
|
||||
public static StyleBagItem[] create(ResValueBagItem[] resValueBagItems){
|
||||
if(resValueBagItems==null){
|
||||
public static StyleBagItem[] create(ResValueMap[] resValueMaps){
|
||||
if(resValueMaps ==null){
|
||||
return null;
|
||||
}
|
||||
int len=resValueBagItems.length;
|
||||
int len= resValueMaps.length;
|
||||
if(len==0){
|
||||
return null;
|
||||
}
|
||||
List<StyleBagItem> results=new ArrayList<>();
|
||||
for(int i=0;i<len;i++){
|
||||
StyleBagItem item=create(resValueBagItems[i]);
|
||||
StyleBagItem item=create(resValueMaps[i]);
|
||||
if(item==null){
|
||||
return null;
|
||||
}
|
||||
@ -120,10 +120,10 @@ public class StyleBagItem {
|
||||
}
|
||||
return results.toArray(new StyleBagItem[0]);
|
||||
}
|
||||
public static StyleBagItem create(ResValueBagItem resValueBagItem){
|
||||
if(resValueBagItem==null){
|
||||
public static StyleBagItem create(ResValueMap resValueMap){
|
||||
if(resValueMap ==null){
|
||||
return null;
|
||||
}
|
||||
return new StyleBagItem(resValueBagItem);
|
||||
return new StyleBagItem(resValueMap);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
||||
import com.reandroid.arsc.chunk.TableBlock;
|
||||
import com.reandroid.arsc.group.EntryGroup;
|
||||
import com.reandroid.arsc.item.TableString;
|
||||
import com.reandroid.arsc.value.EntryBlock;
|
||||
import com.reandroid.arsc.value.Entry;
|
||||
import com.reandroid.arsc.value.StagedAliasEntry;
|
||||
|
||||
import java.util.*;
|
||||
@ -31,13 +31,13 @@ public class TableEntryStore implements EntryStore{
|
||||
}
|
||||
|
||||
public String getEntryName(int resourceId){
|
||||
EntryBlock entryBlock=getEntryBlock(resourceId);
|
||||
if(entryBlock==null){
|
||||
Entry entry = getEntry(resourceId);
|
||||
if(entry ==null){
|
||||
return null;
|
||||
}
|
||||
return entryBlock.getName();
|
||||
return entry.getName();
|
||||
}
|
||||
public EntryBlock getEntryBlock(int resourceId){
|
||||
public Entry getEntry(int resourceId){
|
||||
if(resourceId==0){
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user