mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 22:34:24 +02:00
816 lines
25 KiB
Java
Executable File
816 lines
25 KiB
Java
Executable File
/*
|
|
* 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.lib.arsc.value;
|
|
|
|
import com.reandroid.lib.arsc.base.Block;
|
|
import com.reandroid.lib.arsc.base.BlockCounter;
|
|
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
|
import com.reandroid.lib.arsc.chunk.TableBlock;
|
|
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
|
import com.reandroid.lib.arsc.group.EntryGroup;
|
|
import com.reandroid.lib.arsc.io.BlockReader;
|
|
import com.reandroid.lib.arsc.item.*;
|
|
import com.reandroid.lib.arsc.pool.SpecStringPool;
|
|
import com.reandroid.lib.arsc.pool.TableStringPool;
|
|
import com.reandroid.lib.json.JSONConvert;
|
|
import com.reandroid.lib.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.setType(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.setType(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.setType(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.setType(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.setType(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.getTypeIdInt();
|
|
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(entryBlock==null||entryBlock==this||entryBlock.isNull()){
|
|
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 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";
|
|
|
|
}
|