
com.reandroid.arsc.value.Entry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ARSCLib Show documentation
Show all versions of ARSCLib Show documentation
Android binary resources read/write library
/*
* 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.EntryArray;
import com.reandroid.arsc.array.ResValueMapArray;
import com.reandroid.arsc.base.Block;
import com.reandroid.arsc.base.BlockCounter;
import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.chunk.SpecBlock;
import com.reandroid.arsc.chunk.TypeBlock;
import com.reandroid.arsc.container.SpecTypePair;
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.utils.HexUtil;
import com.reandroid.json.JSONConvert;
import com.reandroid.json.JSONObject;
import com.reandroid.xml.StyleDocument;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
public class Entry extends Block implements JSONConvert {
private TableEntry, ?> mTableEntry;
private IntegerItem mNullSpecReference;
public Entry(){
super();
}
public void linkTableStringsInternal(TableStringPool tableStringPool){
TableEntry, ?> tableEntry = getTableEntry();
tableEntry.linkTableStringsInternal(tableStringPool);
}
public void linkSpecStringsInternal(SpecStringPool specStringPool){
TableEntry, ?> tableEntry = getTableEntry();
ValueHeader header = tableEntry.getHeader();
header.linkSpecStringsInternal(specStringPool);
}
public ResValue getResValue(){
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry instanceof ResTableEntry){
return ((ResTableEntry)tableEntry).getValue();
}
return null;
}
public ResValueMapArray getResValueMapArray(){
ResTableMapEntry resTableMapEntry = getResTableMapEntry();
if(resTableMapEntry != null){
return resTableMapEntry.getValue();
}
return null;
}
public ResTableMapEntry getResTableMapEntry(){
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry instanceof ResTableMapEntry){
return ((ResTableMapEntry)tableEntry);
}
return null;
}
public String getXmlTag(){
String tag = TypeString.toXmlTagName(getTypeName());
if(tag == null || !tag.contains("array")){
return tag;
}
ResTableMapEntry mapEntry = getResTableMapEntry();
if(mapEntry == null){
return tag;
}
ValueType allValueType = mapEntry.isAllSameValueType();
if(allValueType == null){
return tag;
}
if(allValueType == ValueType.STRING){
return "string-" + tag;
}
if(allValueType == ValueType.DEC){
return "integer-" + tag;
}
return tag;
}
public SpecFlag getSpecFlag(){
SpecBlock specBlock = getSpecBlock();
if(specBlock == null){
return null;
}
return specBlock.getSpecFlag(getId());
}
public void ensureComplex(boolean isComplex){
ensureTableEntry(isComplex);
}
public int getId(){
int id = getIndex();
EntryArray entryArray = getParentInstance(EntryArray.class);
if(entryArray != null){
id = entryArray.getEntryId(id);
}
return id;
}
/**
* renames this entry and all configuration on this package
* */
public SpecString reName(String name){
SpecTypePair specTypePair = getSpecTypePair();
if(specTypePair == null){
return null;
}
SpecString specString = null;
Iterator iterator = specTypePair.getEntries(getId(), false);
while (iterator.hasNext()){
Entry entry = iterator.next();
if(specString == null){
specString = entry.setName(name);
}else {
entry.updateSpecReference(specString);
}
}
return specString;
}
public SpecString setName(String name){
return setName(name, false);
}
/**
* Sets resource entry name
* */
public SpecString setName(String name, boolean holdIfNull){
if(name == null){
unlinkNullSpecString();
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry != null){
tableEntry.getHeader().setKey(null);
}
return null;
}
if(!holdIfNull && isNull()){
return null;
}
PackageBlock packageBlock = getPackageBlock();
if(packageBlock == null){
return null;
}
SpecStringPool specStringPool = packageBlock.getSpecStringPool();
int ref = getSpecReference();
SpecString specString = specStringPool.get(ref);
if(specString != null && name.equals(specString.get())){
return null;
}
specString = specStringPool.getOrCreate(name);
setSpecReference(specString);
return specString;
}
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 getTypeId(){
TypeBlock typeBlock = getTypeBlock();
if(typeBlock != null){
return typeBlock.getId();
}
return 0;
}
public int getResourceId(){
TypeBlock typeBlock = getTypeBlock();
if(typeBlock==null){
return 0;
}
PackageBlock packageBlock = typeBlock.getPackageBlock();
if(packageBlock == null){
return 0;
}
return (packageBlock.getId()<<24)
| (typeBlock.getId() << 16)
| getId();
}
public int getSpecReference(){
IntegerItem nullReference = this.mNullSpecReference;
if(nullReference != null){
return nullReference.get();
}
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry != null){
return tableEntry.getHeader().getKey();
}
return -1;
}
public TypeString getTypeString(){
TypeBlock typeBlock = getTypeBlock();
if(typeBlock!=null){
return typeBlock.getTypeString();
}
return null;
}
public boolean isDefined(){
return getSpecReference() != -1;
}
public boolean isDefault(){
ResConfig resConfig = getResConfig();
if(resConfig!=null){
return resConfig.isDefault();
}
return false;
}
public void setSpecReference(SpecString specString){
if(isSameSpecString(specString)){
return;
}
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry != null){
tableEntry.getHeader().setKey(specString);
unlinkNullSpecString();
return;
}
linkNullSpecString(specString);
}
public void updateSpecReference(SpecString specString){
if(isSameSpecString(specString)){
return;
}
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry != null){
tableEntry.getHeader().setKey(specString);
unlinkNullSpecString();
}else if(mNullSpecReference != null){
linkNullSpecString(specString);
}else if(specString == null){
unlinkNullSpecString();
}
}
public void setSpecReference(int ref){
if(ref == getSpecReference()){
return;
}
TableEntry, ?> tableEntry = getTableEntry();
if(tableEntry == null){
linkNullSpecString(ref);
return;
}
unlinkNullSpecString();
tableEntry.getHeader().setKey(ref);
}
private boolean isSameSpecString(SpecString specString){
int ref = getSpecReference();
if(specString == null){
return ref < 0;
}
if(ref != specString.getIndex()){
return false;
}
return mNullSpecReference == null
|| getTableEntry() == null;
}
private void linkNullSpecString(int ref){
if(ref < 0){
unlinkNullSpecString();
return;
}
SpecStringPool specStringPool = getSpecStringPool();
if(specStringPool == null){
unlinkNullSpecString();
return;
}
linkNullSpecString(specStringPool.get(ref));
}
private void linkNullSpecString(SpecString specString){
if(specString == null){
unlinkNullSpecString();
return;
}
IntegerItem nullReference = this.mNullSpecReference;
if(nullReference != null && nullReference.get() == specString.getIndex()){
return;
}
unlinkNullSpecString();
nullReference = new IntegerItem();
nullReference.setParent(this);
nullReference.setIndex(1);
nullReference.set(specString.getIndex());
specString.addReference(nullReference);
this.mNullSpecReference = nullReference;
}
private void unlinkNullSpecString(){
IntegerItem nullReference = this.mNullSpecReference;
if(nullReference == null){
return;
}
SpecStringPool specStringPool = getSpecStringPool();
if(specStringPool != null){
specStringPool.removeReference(nullReference);
}
nullReference.setParent(null);
nullReference.setIndex(-1);
this.mNullSpecReference = null;
}
private SpecStringPool getSpecStringPool(){
PackageBlock packageBlock = getPackageBlock();
if(packageBlock != null){
return packageBlock.getSpecStringPool();
}
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.BOOLEAN, data);
}
public ResValue setValueAsReference(int resourceId){
return setValueAsRaw(ValueType.REFERENCE, resourceId);
}
public ResValue setValueAsString(StyleDocument styledString){
TableEntry, ?> tableEntry = ensureTableEntry(false);
ResValue resValue = (ResValue) tableEntry.getValue();
resValue.setValueAsString(styledString);
return resValue;
}
public ResValue setValueAsString(String str){
TableEntry, ?> tableEntry = ensureTableEntry(false);
ResValue resValue = (ResValue) tableEntry.getValue();
resValue.setValueAsString(str);
return resValue;
}
public SpecString getSpecString(){
int ref = getSpecReference();
if(ref < 0){
return null;
}
PackageBlock packageBlock = getPackageBlock();
if(packageBlock == null){
return null;
}
SpecStringPool specStringPool = packageBlock.getSpecStringPool();
return specStringPool.get(ref);
}
public ResConfig getResConfig(){
TypeBlock typeBlock = getTypeBlock();
if(typeBlock!=null){
return typeBlock.getResConfig();
}
return null;
}
public SpecBlock getSpecBlock(){
SpecTypePair specTypePair = getSpecTypePair();
if(specTypePair != null){
return specTypePair.getSpecBlock();
}
return null;
}
private SpecTypePair getSpecTypePair(){
TypeBlock typeBlock = getTypeBlock();
if(typeBlock != null){
return typeBlock.getParentSpecTypePair();
}
return null;
}
public TypeBlock getTypeBlock(){
return getParent(TypeBlock.class);
}
private String getPackageName(){
PackageBlock packageBlock = getPackageBlock();
if(packageBlock!=null){
return packageBlock.getName();
}
return null;
}
public PackageBlock getPackageBlock(){
return getParent(PackageBlock.class);
}
private TableEntry, ?> ensureTableEntry(boolean is_complex){
TableEntry, ?> tableEntry = getTableEntry();
boolean is_correct_type = (is_complex && tableEntry instanceof ResTableMapEntry) || (!is_complex && tableEntry instanceof ResTableEntry);
if (tableEntry == null || !is_correct_type) {
tableEntry = createTableEntry(is_complex);
setTableEntry(tableEntry);
}
return tableEntry;
}
public TableEntry, ?> getTableEntry(){
return mTableEntry;
}
public ValueHeader 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;
}
counter.setCurrent(this);
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 CompoundEntry;
}
public boolean isScalar(){
return getTableEntry() instanceof ResTableEntry;
}
public void setTableEntry(TableEntry, ?> tableEntry){
if(tableEntry == this.mTableEntry){
return;
}
onTableEntryRemoved();
if(tableEntry==null){
return;
}
tableEntry.setIndex(0);
tableEntry.setParent(this);
this.mTableEntry = tableEntry;
transferSpecReference(tableEntry);
}
private void transferSpecReference(TableEntry, ?> tableEntry){
IntegerItem nullSpecReference = this.mNullSpecReference;
if(nullSpecReference == null){
return;
}
int ref = nullSpecReference.get();
unlinkNullSpecString();
ValueHeader valueHeader = tableEntry.getHeader();
if(valueHeader.getKey() < 0){
valueHeader.setKey(ref);
}
}
private void onTableEntryRemoved(){
TableEntry, ?> exist = this.mTableEntry;
if(exist == null){
return;
}
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(ValueHeader.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 getTableEntry().shouldMerge(coming.getTableEntry());
}
@Override
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append(HexUtil.toHex8(getResourceId()));
builder.append(' ');
ResConfig resConfig = getResConfig();
if(resConfig!=null){
builder.append(resConfig);
builder.append(' ');
}
SpecFlag specFlag = getSpecFlag();
if(specFlag!=null){
builder.append(specFlag);
builder.append(' ');
}
if(isNull()){
builder.append("NULL ");
}
builder.append('@');
builder.append(getTypeName());
builder.append('/');
builder.append(getName());
return builder.toString();
}
public static final String NAME_id = "id";
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy