mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 22:54:26 +02:00
performance: link pool strings when only needed #36
This commit is contained in:
parent
c80e0943d3
commit
b6bbac2dcf
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -16,6 +16,8 @@
|
|||||||
package com.reandroid.arsc.array;
|
package com.reandroid.arsc.array;
|
||||||
|
|
||||||
import com.reandroid.arsc.item.IntegerItem;
|
import com.reandroid.arsc.item.IntegerItem;
|
||||||
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
@ -28,6 +30,20 @@ public class EntryArray extends OffsetBlockArray<Entry> implements JSONConvert<J
|
|||||||
public EntryArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
public EntryArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart){
|
||||||
super(offsets, itemCount, itemStart);
|
super(offsets, itemCount, itemStart);
|
||||||
}
|
}
|
||||||
|
public void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
Iterator<Entry> itr = iterator(true);
|
||||||
|
while (itr.hasNext()){
|
||||||
|
Entry entry = itr.next();
|
||||||
|
entry.linkTableStringsInternal(tableStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void linkSpecStringsInternal(SpecStringPool specStringPool){
|
||||||
|
Iterator<Entry> itr = iterator(true);
|
||||||
|
while (itr.hasNext()){
|
||||||
|
Entry entry = itr.next();
|
||||||
|
entry.linkSpecStringsInternal(specStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
public int getHighestEntryId(){
|
public int getHighestEntryId(){
|
||||||
if(isSparse()){
|
if(isSparse()){
|
||||||
return ((SparseOffsetsArray) getOffsetArray()).getHighestId();
|
return ((SparseOffsetsArray) getOffsetArray()).getHighestId();
|
||||||
|
@ -27,6 +27,7 @@ import com.reandroid.arsc.header.PackageHeader;
|
|||||||
import com.reandroid.arsc.list.OverlayableList;
|
import com.reandroid.arsc.list.OverlayableList;
|
||||||
import com.reandroid.arsc.list.StagedAliasList;
|
import com.reandroid.arsc.list.StagedAliasList;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.LibraryInfo;
|
import com.reandroid.arsc.value.LibraryInfo;
|
||||||
@ -68,6 +69,16 @@ public class PackageBlock extends Chunk<PackageHeader>
|
|||||||
addChild(mSpecStringPool);
|
addChild(mSpecStringPool);
|
||||||
addChild(mBody);
|
addChild(mBody);
|
||||||
}
|
}
|
||||||
|
public void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
for(SpecTypePair specTypePair : listAllSpecTypePair()){
|
||||||
|
specTypePair.linkTableStringsInternal(tableStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void linkSpecStringsInternal(SpecStringPool specStringPool){
|
||||||
|
for(SpecTypePair specTypePair : listAllSpecTypePair()){
|
||||||
|
specTypePair.linkSpecStringsInternal(specStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
public void destroy(){
|
public void destroy(){
|
||||||
getEntriesGroupMap().clear();
|
getEntriesGroupMap().clear();
|
||||||
getPackageBody().destroy();
|
getPackageBody().destroy();
|
||||||
@ -221,6 +232,7 @@ public class PackageBlock extends Chunk<PackageHeader>
|
|||||||
if(!this.entryGroupMapLocked){
|
if(!this.entryGroupMapLocked){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
entryGroupMapLocked = false;
|
||||||
Map<Integer, EntryGroup> map = this.mEntriesGroup;
|
Map<Integer, EntryGroup> map = this.mEntriesGroup;
|
||||||
map.clear();
|
map.clear();
|
||||||
createEntryGroupMap(map);
|
createEntryGroupMap(map);
|
||||||
|
@ -53,6 +53,11 @@ public class TableBlock extends Chunk<TableHeader>
|
|||||||
addChild(mPackageArray);
|
addChild(mPackageArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
for(PackageBlock packageBlock : listPackages()){
|
||||||
|
packageBlock.linkTableStringsInternal(tableStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
public List<Entry> resolveReference(int referenceId){
|
public List<Entry> resolveReference(int referenceId){
|
||||||
return resolveReference(referenceId, null);
|
return resolveReference(referenceId, null);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ import com.reandroid.arsc.header.TypeHeader;
|
|||||||
import com.reandroid.arsc.io.BlockLoad;
|
import com.reandroid.arsc.io.BlockLoad;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
@ -59,6 +61,14 @@ public class TypeBlock extends Chunk<TypeHeader>
|
|||||||
addChild(entryOffsets);
|
addChild(entryOffsets);
|
||||||
addChild(mEntryArray);
|
addChild(mEntryArray);
|
||||||
}
|
}
|
||||||
|
public void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
EntryArray entryArray = getEntryArray();
|
||||||
|
entryArray.linkTableStringsInternal(tableStringPool);
|
||||||
|
}
|
||||||
|
public void linkSpecStringsInternal(SpecStringPool specStringPool){
|
||||||
|
EntryArray entryArray = getEntryArray();
|
||||||
|
entryArray.linkSpecStringsInternal(specStringPool);
|
||||||
|
}
|
||||||
public boolean isSparse(){
|
public boolean isSparse(){
|
||||||
return getHeaderBlock().isSparse();
|
return getHeaderBlock().isSparse();
|
||||||
}
|
}
|
||||||
|
@ -1,489 +1,490 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.chunk.xml;
|
package com.reandroid.arsc.chunk.xml;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
import com.reandroid.arsc.pool.ResXmlStringPool;
|
import com.reandroid.arsc.pool.ResXmlStringPool;
|
||||||
import com.reandroid.arsc.pool.StringPool;
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
import com.reandroid.arsc.value.AttributeValue;
|
import com.reandroid.arsc.value.AttributeValue;
|
||||||
import com.reandroid.arsc.value.ValueItem;
|
import com.reandroid.arsc.value.ValueItem;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
import com.reandroid.xml.XMLAttribute;
|
import com.reandroid.xml.XMLAttribute;
|
||||||
import com.reandroid.xml.XMLException;
|
import com.reandroid.xml.XMLException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ResXmlAttribute extends ValueItem implements AttributeValue, Comparable<ResXmlAttribute>{
|
public class ResXmlAttribute extends ValueItem implements AttributeValue, Comparable<ResXmlAttribute>{
|
||||||
private ReferenceItem mNSReference;
|
private ReferenceItem mNSReference;
|
||||||
private ReferenceItem mNameReference;
|
private ReferenceItem mNameReference;
|
||||||
private ReferenceItem mNameIdReference;
|
private ReferenceItem mNameIdReference;
|
||||||
private ReferenceItem mValueStringReference;
|
private ReferenceItem mValueStringReference;
|
||||||
public ResXmlAttribute(int attributeUnitSize) {
|
public ResXmlAttribute(int attributeUnitSize) {
|
||||||
super(attributeUnitSize, OFFSET_SIZE);
|
super(attributeUnitSize, OFFSET_SIZE);
|
||||||
byte[] bts = getBytesInternal();
|
byte[] bts = getBytesInternal();
|
||||||
putInteger(bts, OFFSET_NS, -1);
|
putInteger(bts, OFFSET_NS, -1);
|
||||||
putInteger(bts, OFFSET_NAME, -1);
|
putInteger(bts, OFFSET_NAME, -1);
|
||||||
putInteger(bts, OFFSET_STRING, -1);
|
putInteger(bts, OFFSET_STRING, -1);
|
||||||
}
|
}
|
||||||
public ResXmlAttribute() {
|
public ResXmlAttribute() {
|
||||||
this(20);
|
this(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUri(){
|
public String getUri(){
|
||||||
return getString(getNamespaceReference());
|
return getString(getNamespaceReference());
|
||||||
}
|
}
|
||||||
public String getFullName(){
|
public String getFullName(){
|
||||||
String name=getName();
|
String name=getName();
|
||||||
if(name==null){
|
if(name==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String prefix=getNamePrefix();
|
String prefix=getNamePrefix();
|
||||||
if(prefix==null){
|
if(prefix==null){
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
return prefix+":"+name;
|
return prefix+":"+name;
|
||||||
}
|
}
|
||||||
public String getName(){
|
public String getName(){
|
||||||
return getString(getNameReference());
|
return getString(getNameReference());
|
||||||
}
|
}
|
||||||
public String getNamePrefix(){
|
public String getNamePrefix(){
|
||||||
ResXmlElement xmlElement=getParentResXmlElement();
|
ResXmlElement xmlElement=getParentResXmlElement();
|
||||||
if(xmlElement==null){
|
if(xmlElement==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
||||||
if(startNamespace==null){
|
if(startNamespace==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return startNamespace.getPrefix();
|
return startNamespace.getPrefix();
|
||||||
}
|
}
|
||||||
// WARN! Careful this is not real value
|
// WARN! Careful this is not real value
|
||||||
public String getValueString(){
|
public String getValueString(){
|
||||||
return getString(getValueStringReference());
|
return getString(getValueStringReference());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int getNameResourceID(){
|
public int getNameResourceID(){
|
||||||
ResXmlID xmlID = getResXmlID();
|
ResXmlID xmlID = getResXmlID();
|
||||||
if(xmlID != null){
|
if(xmlID != null){
|
||||||
return xmlID.get();
|
return xmlID.get();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setNameResourceID(int resourceId){
|
public void setNameResourceID(int resourceId){
|
||||||
ResXmlIDMap xmlIDMap=getResXmlIDMap();
|
ResXmlIDMap xmlIDMap=getResXmlIDMap();
|
||||||
if(xmlIDMap==null){
|
if(xmlIDMap==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResXmlID xmlID = xmlIDMap.getOrCreate(resourceId);
|
ResXmlID xmlID = xmlIDMap.getOrCreate(resourceId);
|
||||||
setNameReference(xmlID.getIndex());
|
setNameReference(xmlID.getIndex());
|
||||||
}
|
}
|
||||||
public void setName(String name, int resourceId){
|
public void setName(String name, int resourceId){
|
||||||
if(Objects.equals(name, getName()) && resourceId==getNameResourceID()){
|
if(Objects.equals(name, getName()) && resourceId==getNameResourceID()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unlink(mNameReference);
|
unlink(mNameReference);
|
||||||
unLinkNameId(getResXmlID());
|
unLinkNameId(getResXmlID());
|
||||||
ResXmlString xmlString = getOrCreateAttributeName(name, resourceId);
|
ResXmlString xmlString = getOrCreateAttributeName(name, resourceId);
|
||||||
if(xmlString==null){
|
if(xmlString==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setNameReference(xmlString.getIndex());
|
setNameReference(xmlString.getIndex());
|
||||||
mNameReference = link(OFFSET_NAME);
|
mNameReference = link(OFFSET_NAME);
|
||||||
linkNameId();
|
linkNameId();
|
||||||
}
|
}
|
||||||
private void linkStartNameSpace(){
|
private void linkStartNameSpace(){
|
||||||
ResXmlElement xmlElement=getParentResXmlElement();
|
ResXmlElement xmlElement=getParentResXmlElement();
|
||||||
if(xmlElement==null){
|
if(xmlElement==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
||||||
if(startNamespace==null){
|
if(startNamespace==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startNamespace.addAttributeReference(this);
|
startNamespace.addAttributeReference(this);
|
||||||
}
|
}
|
||||||
private void unLinkStartNameSpace(){
|
private void unLinkStartNameSpace(){
|
||||||
ResXmlElement xmlElement=getParentResXmlElement();
|
ResXmlElement xmlElement=getParentResXmlElement();
|
||||||
if(xmlElement==null){
|
if(xmlElement==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
ResXmlStartNamespace startNamespace=xmlElement.getStartNamespaceByUriRef(getNamespaceReference());
|
||||||
if(startNamespace==null){
|
if(startNamespace==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startNamespace.removeAttributeReference(this);
|
startNamespace.removeAttributeReference(this);
|
||||||
}
|
}
|
||||||
private ResXmlString getOrCreateAttributeName(String name, int resourceId){
|
private ResXmlString getOrCreateAttributeName(String name, int resourceId){
|
||||||
ResXmlStringPool stringPool = getStringPool();
|
ResXmlStringPool stringPool = getStringPool();
|
||||||
if(stringPool==null){
|
if(stringPool==null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return stringPool.getOrCreateAttribute(resourceId, name);
|
return stringPool.getOrCreateAttribute(resourceId, name);
|
||||||
}
|
}
|
||||||
public ResXmlElement getParentResXmlElement(){
|
public ResXmlElement getParentResXmlElement(){
|
||||||
return getParent(ResXmlElement.class);
|
return getParent(ResXmlElement.class);
|
||||||
}
|
}
|
||||||
public int getAttributesUnitSize(){
|
public int getAttributesUnitSize(){
|
||||||
return OFFSET_SIZE + super.getSize();
|
return OFFSET_SIZE + super.getSize();
|
||||||
}
|
}
|
||||||
public void setAttributesUnitSize(int size){
|
public void setAttributesUnitSize(int size){
|
||||||
int eight = size - OFFSET_SIZE;
|
int eight = size - OFFSET_SIZE;
|
||||||
super.setSize(eight);
|
super.setSize(eight);
|
||||||
}
|
}
|
||||||
private String getString(int ref){
|
private String getString(int ref){
|
||||||
if(ref<0){
|
if(ref<0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringPool<?> stringPool = getStringPool();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(stringPool == null){
|
if(stringPool == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringItem stringItem = stringPool.get(ref);
|
StringItem stringItem = stringPool.get(ref);
|
||||||
if(stringItem == null){
|
if(stringItem == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return stringItem.getHtml();
|
return stringItem.getHtml();
|
||||||
}
|
}
|
||||||
private ResXmlID getResXmlID(){
|
private ResXmlID getResXmlID(){
|
||||||
ResXmlIDMap xmlIDMap = getResXmlIDMap();
|
ResXmlIDMap xmlIDMap = getResXmlIDMap();
|
||||||
if(xmlIDMap == null){
|
if(xmlIDMap == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return xmlIDMap.getResXmlIDArray().get(getNameReference());
|
return xmlIDMap.getResXmlIDArray().get(getNameReference());
|
||||||
}
|
}
|
||||||
private ResXmlIDMap getResXmlIDMap(){
|
private ResXmlIDMap getResXmlIDMap(){
|
||||||
ResXmlElement xmlElement=getParentResXmlElement();
|
ResXmlElement xmlElement=getParentResXmlElement();
|
||||||
if(xmlElement!=null){
|
if(xmlElement!=null){
|
||||||
return xmlElement.getResXmlIDMap();
|
return xmlElement.getResXmlIDMap();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNamespaceReference(){
|
int getNamespaceReference(){
|
||||||
return getInteger(getBytesInternal(), OFFSET_NS);
|
return getInteger(getBytesInternal(), OFFSET_NS);
|
||||||
}
|
}
|
||||||
public void setNamespaceReference(int ref){
|
public void setNamespaceReference(int ref){
|
||||||
if(ref == getNamespaceReference()){
|
if(ref == getNamespaceReference()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unlink(mNSReference);
|
unlink(mNSReference);
|
||||||
putInteger(getBytesInternal(), OFFSET_NS, ref);
|
putInteger(getBytesInternal(), OFFSET_NS, ref);
|
||||||
mNSReference = link(OFFSET_NS);
|
mNSReference = link(OFFSET_NS);
|
||||||
linkStartNameSpace();
|
linkStartNameSpace();
|
||||||
}
|
}
|
||||||
int getNameReference(){
|
int getNameReference(){
|
||||||
return getInteger(getBytesInternal(), OFFSET_NAME);
|
return getInteger(getBytesInternal(), OFFSET_NAME);
|
||||||
}
|
}
|
||||||
void setNameReference(int ref){
|
void setNameReference(int ref){
|
||||||
if(ref == getNameReference()){
|
if(ref == getNameReference()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unLinkNameId(getResXmlID());
|
unLinkNameId(getResXmlID());
|
||||||
unlink(mNameReference);
|
unlink(mNameReference);
|
||||||
putInteger(getBytesInternal(), OFFSET_NAME, ref);
|
putInteger(getBytesInternal(), OFFSET_NAME, ref);
|
||||||
mNameReference = link(OFFSET_NAME);
|
mNameReference = link(OFFSET_NAME);
|
||||||
linkNameId();
|
linkNameId();
|
||||||
}
|
}
|
||||||
int getValueStringReference(){
|
int getValueStringReference(){
|
||||||
return getInteger(getBytesInternal(), OFFSET_STRING);
|
return getInteger(getBytesInternal(), OFFSET_STRING);
|
||||||
}
|
}
|
||||||
void setValueStringReference(int ref){
|
void setValueStringReference(int ref){
|
||||||
if(ref == getValueStringReference() && mValueStringReference!=null){
|
if(ref == getValueStringReference() && mValueStringReference!=null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StringPool<?> stringPool = getStringPool();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(stringPool == null){
|
if(stringPool == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StringItem stringItem = stringPool.get(ref);
|
StringItem stringItem = stringPool.get(ref);
|
||||||
unlink(mValueStringReference);
|
unlink(mValueStringReference);
|
||||||
if(stringItem!=null){
|
if(stringItem!=null){
|
||||||
ref = stringItem.getIndex();
|
ref = stringItem.getIndex();
|
||||||
}
|
}
|
||||||
putInteger(getBytesInternal(), OFFSET_STRING, ref);
|
putInteger(getBytesInternal(), OFFSET_STRING, ref);
|
||||||
ReferenceItem referenceItem = null;
|
ReferenceItem referenceItem = null;
|
||||||
if(stringItem!=null){
|
if(stringItem!=null){
|
||||||
referenceItem = new ReferenceBlock<>(this, OFFSET_STRING);
|
referenceItem = new ReferenceBlock<>(this, OFFSET_STRING);
|
||||||
stringItem.addReference(referenceItem);
|
stringItem.addReference(referenceItem);
|
||||||
}
|
}
|
||||||
mValueStringReference = referenceItem;
|
mValueStringReference = referenceItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReadBytes(BlockReader reader) throws IOException {
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
super.onReadBytes(reader);
|
super.onReadBytes(reader);
|
||||||
linkAll();
|
super.onDataLoaded();
|
||||||
linkStartNameSpace();
|
linkAll();
|
||||||
}
|
linkStartNameSpace();
|
||||||
@Override
|
}
|
||||||
public void onRemoved(){
|
@Override
|
||||||
super.onRemoved();
|
public void onRemoved(){
|
||||||
unLinkStartNameSpace();
|
super.onRemoved();
|
||||||
unlinkAll();
|
unLinkStartNameSpace();
|
||||||
}
|
unlinkAll();
|
||||||
@Override
|
}
|
||||||
protected void onUnlinkDataString(ReferenceItem referenceItem){
|
@Override
|
||||||
unlink(referenceItem);
|
protected void onUnlinkDataString(ReferenceItem referenceItem){
|
||||||
}
|
unlink(referenceItem);
|
||||||
@Override
|
}
|
||||||
protected void onDataChanged(){
|
@Override
|
||||||
if(getValueType()==ValueType.STRING){
|
protected void onDataChanged(){
|
||||||
setValueStringReference(getData());
|
if(getValueType()==ValueType.STRING){
|
||||||
}else {
|
setValueStringReference(getData());
|
||||||
setValueStringReference(-1);
|
}else {
|
||||||
}
|
setValueStringReference(-1);
|
||||||
}
|
}
|
||||||
@Override
|
}
|
||||||
public ResXmlDocument getParentChunk() {
|
@Override
|
||||||
ResXmlElement element = getParentResXmlElement();
|
public ResXmlDocument getParentChunk() {
|
||||||
if(element!=null){
|
ResXmlElement element = getParentResXmlElement();
|
||||||
return element.getParentDocument();
|
if(element!=null){
|
||||||
}
|
return element.getParentDocument();
|
||||||
return null;
|
}
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void linkNameId(){
|
private void linkNameId(){
|
||||||
ResXmlID xmlID = getResXmlID();
|
ResXmlID xmlID = getResXmlID();
|
||||||
if(xmlID==null){
|
if(xmlID==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unLinkNameId(xmlID);
|
unLinkNameId(xmlID);
|
||||||
ReferenceItem referenceItem = new ReferenceBlock<>(this, OFFSET_NAME);
|
ReferenceItem referenceItem = new ReferenceBlock<>(this, OFFSET_NAME);
|
||||||
xmlID.addReference(referenceItem);
|
xmlID.addReference(referenceItem);
|
||||||
mNameIdReference = referenceItem;
|
mNameIdReference = referenceItem;
|
||||||
}
|
}
|
||||||
private void unLinkNameId(ResXmlID xmlID){
|
private void unLinkNameId(ResXmlID xmlID){
|
||||||
ReferenceItem referenceItem = mNameIdReference;
|
ReferenceItem referenceItem = mNameIdReference;
|
||||||
if(referenceItem==null || xmlID == null){
|
if(referenceItem==null || xmlID == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xmlID.removeReference(referenceItem);
|
xmlID.removeReference(referenceItem);
|
||||||
mNameIdReference = null;
|
mNameIdReference = null;
|
||||||
if(xmlID.hasReference()){
|
if(xmlID.hasReference()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResXmlIDMap xmlIDMap = getResXmlIDMap();
|
ResXmlIDMap xmlIDMap = getResXmlIDMap();
|
||||||
if(xmlIDMap == null){
|
if(xmlIDMap == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xmlIDMap.removeSafely(xmlID);
|
xmlIDMap.removeSafely(xmlID);
|
||||||
}
|
}
|
||||||
private void linkAll(){
|
private void linkAll(){
|
||||||
unlink(mNSReference);
|
unlink(mNSReference);
|
||||||
mNSReference = link(OFFSET_NS);
|
mNSReference = link(OFFSET_NS);
|
||||||
unlink(mNameReference);
|
unlink(mNameReference);
|
||||||
mNameReference = link(OFFSET_NAME);
|
mNameReference = link(OFFSET_NAME);
|
||||||
unlink(mValueStringReference);
|
unlink(mValueStringReference);
|
||||||
mValueStringReference = link(OFFSET_STRING);
|
mValueStringReference = link(OFFSET_STRING);
|
||||||
|
|
||||||
linkNameId();
|
linkNameId();
|
||||||
}
|
}
|
||||||
private void unlinkAll(){
|
private void unlinkAll(){
|
||||||
unlink(mNSReference);
|
unlink(mNSReference);
|
||||||
unlink(mNameReference);
|
unlink(mNameReference);
|
||||||
unlink(mValueStringReference);
|
unlink(mValueStringReference);
|
||||||
mNSReference = null;
|
mNSReference = null;
|
||||||
mNameReference = null;
|
mNameReference = null;
|
||||||
mValueStringReference = null;
|
mValueStringReference = null;
|
||||||
|
|
||||||
unLinkNameId(getResXmlID());
|
unLinkNameId(getResXmlID());
|
||||||
}
|
}
|
||||||
private ReferenceItem link(int offset){
|
private ReferenceItem link(int offset){
|
||||||
if(offset<0){
|
if(offset<0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringPool<?> stringPool = getStringPool();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(stringPool == null){
|
if(stringPool == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int ref = getInteger(getBytesInternal(), offset);
|
int ref = getInteger(getBytesInternal(), offset);
|
||||||
StringItem stringItem = stringPool.get(ref);
|
StringItem stringItem = stringPool.get(ref);
|
||||||
if(stringItem == null){
|
if(stringItem == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ReferenceItem referenceItem = new ReferenceBlock<>(this, offset);
|
ReferenceItem referenceItem = new ReferenceBlock<>(this, offset);
|
||||||
stringItem.addReference(referenceItem);
|
stringItem.addReference(referenceItem);
|
||||||
return referenceItem;
|
return referenceItem;
|
||||||
}
|
}
|
||||||
private void unlink(ReferenceItem reference){
|
private void unlink(ReferenceItem reference){
|
||||||
if(reference == null){
|
if(reference == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResXmlStringPool stringPool = getStringPool();
|
ResXmlStringPool stringPool = getStringPool();
|
||||||
if(stringPool==null){
|
if(stringPool==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stringPool.removeReference(reference);
|
stringPool.removeReference(reference);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ResXmlStringPool getStringPool(){
|
public ResXmlStringPool getStringPool(){
|
||||||
StringPool<?> stringPool = super.getStringPool();
|
StringPool<?> stringPool = super.getStringPool();
|
||||||
if(stringPool instanceof ResXmlStringPool){
|
if(stringPool instanceof ResXmlStringPool){
|
||||||
return (ResXmlStringPool) stringPool;
|
return (ResXmlStringPool) stringPool;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(ResXmlAttribute other) {
|
public int compareTo(ResXmlAttribute other) {
|
||||||
int id1=getNameResourceID();
|
int id1=getNameResourceID();
|
||||||
int id2=other.getNameResourceID();
|
int id2=other.getNameResourceID();
|
||||||
if(id1==0 && id2!=0){
|
if(id1==0 && id2!=0){
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(id2==0 && id1!=0){
|
if(id2==0 && id1!=0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(id1!=0){
|
if(id1!=0){
|
||||||
return Integer.compare(id1, id2);
|
return Integer.compare(id1, id2);
|
||||||
}
|
}
|
||||||
String name1=getName();
|
String name1=getName();
|
||||||
if(name1==null){
|
if(name1==null){
|
||||||
name1="";
|
name1="";
|
||||||
}
|
}
|
||||||
String name2=other.getName();
|
String name2=other.getName();
|
||||||
if(name2==null){
|
if(name2==null){
|
||||||
name2="";
|
name2="";
|
||||||
}
|
}
|
||||||
return name1.compareTo(name2);
|
return name1.compareTo(name2);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
JSONObject jsonObject= new JSONObject();
|
JSONObject jsonObject= new JSONObject();
|
||||||
jsonObject.put(NAME_name, getName());
|
jsonObject.put(NAME_name, getName());
|
||||||
jsonObject.put(NAME_id, getNameResourceID());
|
jsonObject.put(NAME_id, getNameResourceID());
|
||||||
jsonObject.put(NAME_namespace_uri, getUri());
|
jsonObject.put(NAME_namespace_uri, getUri());
|
||||||
ValueType valueType=getValueType();
|
ValueType valueType=getValueType();
|
||||||
jsonObject.put(NAME_value_type, valueType.name());
|
jsonObject.put(NAME_value_type, valueType.name());
|
||||||
if(valueType==ValueType.STRING){
|
if(valueType==ValueType.STRING){
|
||||||
jsonObject.put(NAME_data, getValueAsString());
|
jsonObject.put(NAME_data, getValueAsString());
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||||
}else {
|
}else {
|
||||||
jsonObject.put(NAME_data, getData());
|
jsonObject.put(NAME_data, getData());
|
||||||
}
|
}
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void fromJson(JSONObject json) {
|
public void fromJson(JSONObject json) {
|
||||||
String name = json.optString(NAME_name, "");
|
String name = json.optString(NAME_name, "");
|
||||||
int id = json.optInt(NAME_id, 0);
|
int id = json.optInt(NAME_id, 0);
|
||||||
setName(name, id);
|
setName(name, id);
|
||||||
String uri= json.optString(NAME_namespace_uri, null);
|
String uri= json.optString(NAME_namespace_uri, null);
|
||||||
if(uri!=null){
|
if(uri!=null){
|
||||||
ResXmlStartNamespace ns = getParentResXmlElement().getStartNamespaceByUri(uri);
|
ResXmlStartNamespace ns = getParentResXmlElement().getStartNamespaceByUri(uri);
|
||||||
if(ns==null){
|
if(ns==null){
|
||||||
ns = getParentResXmlElement().getRootResXmlElement()
|
ns = getParentResXmlElement().getRootResXmlElement()
|
||||||
.getOrCreateNamespace(uri, "");
|
.getOrCreateNamespace(uri, "");
|
||||||
}
|
}
|
||||||
setNamespaceReference(ns.getUriReference());
|
setNamespaceReference(ns.getUriReference());
|
||||||
}
|
}
|
||||||
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
ValueType valueType=ValueType.fromName(json.getString(NAME_value_type));
|
||||||
if(valueType==ValueType.STRING){
|
if(valueType==ValueType.STRING){
|
||||||
setValueAsString(json.optString(NAME_data, ""));
|
setValueAsString(json.optString(NAME_data, ""));
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||||
}else {
|
}else {
|
||||||
setValueType(valueType);
|
setValueType(valueType);
|
||||||
setData(json.getInt(NAME_data));
|
setData(json.getInt(NAME_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public XMLAttribute decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException {
|
public XMLAttribute decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException {
|
||||||
int resourceId=getNameResourceID();
|
int resourceId=getNameResourceID();
|
||||||
String name;
|
String name;
|
||||||
if(resourceId==0){
|
if(resourceId==0){
|
||||||
name=getName();
|
name=getName();
|
||||||
}else {
|
}else {
|
||||||
EntryGroup group = entryStore.getEntryGroup(resourceId);
|
EntryGroup group = entryStore.getEntryGroup(resourceId);
|
||||||
if(group==null){
|
if(group==null){
|
||||||
//Lets ignore such error until XML encoder implemented
|
//Lets ignore such error until XML encoder implemented
|
||||||
//throw new XMLException("Failed to decode attribute name: "
|
//throw new XMLException("Failed to decode attribute name: "
|
||||||
//+ String.format("@0x%08x", resourceId));
|
//+ String.format("@0x%08x", resourceId));
|
||||||
name=String.format("@0x%08x", resourceId);
|
name=String.format("@0x%08x", resourceId);
|
||||||
}else {
|
}else {
|
||||||
name=group.getSpecName();
|
name=group.getSpecName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String prefix = getNamePrefix();
|
String prefix = getNamePrefix();
|
||||||
if(prefix!=null){
|
if(prefix!=null){
|
||||||
name=prefix+":"+name;
|
name=prefix+":"+name;
|
||||||
}
|
}
|
||||||
ValueType valueType = getValueType();
|
ValueType valueType = getValueType();
|
||||||
int raw = getData();
|
int raw = getData();
|
||||||
String value = ValueDecoder.decode(entryStore, currentPackageId, (AttributeValue) this);
|
String value = ValueDecoder.decode(entryStore, currentPackageId, (AttributeValue) this);
|
||||||
XMLAttribute attribute = new XMLAttribute(name, value);
|
XMLAttribute attribute = new XMLAttribute(name, value);
|
||||||
attribute.setNameId(resourceId);
|
attribute.setNameId(resourceId);
|
||||||
if(valueType==ValueType.REFERENCE||valueType==ValueType.ATTRIBUTE){
|
if(valueType==ValueType.REFERENCE||valueType==ValueType.ATTRIBUTE){
|
||||||
attribute.setValueId(raw);
|
attribute.setValueId(raw);
|
||||||
}
|
}
|
||||||
return attribute;
|
return attribute;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
String fullName = getFullName();
|
String fullName = getFullName();
|
||||||
if(fullName!=null ){
|
if(fullName!=null ){
|
||||||
int id=getNameResourceID();
|
int id=getNameResourceID();
|
||||||
if(id!=0){
|
if(id!=0){
|
||||||
fullName=fullName+"(@"+String.format("0x%08x",id)+")";
|
fullName=fullName+"(@"+String.format("0x%08x",id)+")";
|
||||||
}
|
}
|
||||||
String valStr;
|
String valStr;
|
||||||
ValueType valueType=getValueType();
|
ValueType valueType=getValueType();
|
||||||
if(valueType==ValueType.STRING){
|
if(valueType==ValueType.STRING){
|
||||||
valStr=getValueAsString();
|
valStr=getValueAsString();
|
||||||
}else if (valueType==ValueType.INT_BOOLEAN){
|
}else if (valueType==ValueType.INT_BOOLEAN){
|
||||||
valStr = String.valueOf(getValueAsBoolean());
|
valStr = String.valueOf(getValueAsBoolean());
|
||||||
}else if (valueType==ValueType.INT_DEC){
|
}else if (valueType==ValueType.INT_DEC){
|
||||||
valStr = String.valueOf(getData());
|
valStr = String.valueOf(getData());
|
||||||
}else {
|
}else {
|
||||||
valStr = "["+valueType+"] " + String.format("0x%08x",getData());
|
valStr = "["+valueType+"] " + String.format("0x%08x",getData());
|
||||||
}
|
}
|
||||||
if(valStr!=null){
|
if(valStr!=null){
|
||||||
return fullName+"=\""+valStr+"\"";
|
return fullName+"=\""+valStr+"\"";
|
||||||
}
|
}
|
||||||
return fullName+"["+valueType+"]=\""+ getData()+"\"";
|
return fullName+"["+valueType+"]=\""+ getData()+"\"";
|
||||||
}
|
}
|
||||||
StringBuilder builder= new StringBuilder();
|
StringBuilder builder= new StringBuilder();
|
||||||
builder.append(getClass().getSimpleName());
|
builder.append(getClass().getSimpleName());
|
||||||
builder.append(": ");
|
builder.append(": ");
|
||||||
builder.append(getIndex());
|
builder.append(getIndex());
|
||||||
builder.append("{NamespaceReference=").append(getNamespaceReference());
|
builder.append("{NamespaceReference=").append(getNamespaceReference());
|
||||||
builder.append(", NameReference=").append(getNameReference());
|
builder.append(", NameReference=").append(getNameReference());
|
||||||
builder.append(", ValueStringReference=").append(getValueStringReference());
|
builder.append(", ValueStringReference=").append(getValueStringReference());
|
||||||
builder.append(", ValueSize=").append(getSize());
|
builder.append(", ValueSize=").append(getSize());
|
||||||
builder.append(", ValueTypeByte=").append(getType() & 0xff);
|
builder.append(", ValueTypeByte=").append(getType() & 0xff);
|
||||||
builder.append(", Data=").append(getData());
|
builder.append(", Data=").append(getData());
|
||||||
builder.append("}");
|
builder.append("}");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final String NAME_id = "id";
|
public static final String NAME_id = "id";
|
||||||
public static final String NAME_name = "name";
|
public static final String NAME_name = "name";
|
||||||
public static final String NAME_namespace_uri = "namespace_uri";
|
public static final String NAME_namespace_uri = "namespace_uri";
|
||||||
|
|
||||||
private static final int OFFSET_NS = 0;
|
private static final int OFFSET_NS = 0;
|
||||||
private static final int OFFSET_NAME = 4;
|
private static final int OFFSET_NAME = 4;
|
||||||
private static final int OFFSET_STRING = 8;
|
private static final int OFFSET_STRING = 8;
|
||||||
|
|
||||||
private static final int OFFSET_SIZE = 12;
|
private static final int OFFSET_SIZE = 12;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ import com.reandroid.arsc.header.HeaderBlock;
|
|||||||
import com.reandroid.arsc.header.TypeHeader;
|
import com.reandroid.arsc.header.TypeHeader;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.item.TypeString;
|
||||||
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
@ -55,6 +57,16 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
this(new SpecBlock(), new TypeBlockArray());
|
this(new SpecBlock(), new TypeBlockArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||||
|
typeBlock.linkTableStringsInternal(tableStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void linkSpecStringsInternal(SpecStringPool specStringPool){
|
||||||
|
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||||
|
typeBlock.linkSpecStringsInternal(specStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
public Map<Integer, EntryGroup> createEntryGroups(){
|
public Map<Integer, EntryGroup> createEntryGroups(){
|
||||||
Map<Integer, EntryGroup> map = new HashMap<>();
|
Map<Integer, EntryGroup> map = new HashMap<>();
|
||||||
for(TypeBlock typeBlock:listTypeBlocks()){
|
for(TypeBlock typeBlock:listTypeBlocks()){
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
|
|
||||||
public class ResXmlString extends StringItem {
|
public class ResXmlString extends StringItem {
|
||||||
public ResXmlString(boolean utf8) {
|
public ResXmlString(boolean utf8) {
|
||||||
super(utf8);
|
super(utf8);
|
||||||
@ -24,4 +23,7 @@ public class ResXmlString extends StringItem {
|
|||||||
this(utf8);
|
this(utf8);
|
||||||
set(value);
|
set(value);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
void ensureStringLinkUnlocked(){
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,11 +49,19 @@ public class StringItem extends BlockItem implements JSONConvert<JSONObject> {
|
|||||||
mReferencedList.clear();
|
mReferencedList.clear();
|
||||||
}
|
}
|
||||||
public boolean hasReference(){
|
public boolean hasReference(){
|
||||||
|
ensureStringLinkUnlocked();
|
||||||
return mReferencedList.size()>0;
|
return mReferencedList.size()>0;
|
||||||
}
|
}
|
||||||
public Collection<ReferenceItem> getReferencedList(){
|
public Collection<ReferenceItem> getReferencedList(){
|
||||||
|
ensureStringLinkUnlocked();
|
||||||
return mReferencedList;
|
return mReferencedList;
|
||||||
}
|
}
|
||||||
|
void ensureStringLinkUnlocked(){
|
||||||
|
StringPool<?> stringPool = getParentInstance(StringPool.class);
|
||||||
|
if(stringPool != null){
|
||||||
|
stringPool.ensureStringLinkUnlockedInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
public void addReference(ReferenceItem ref){
|
public void addReference(ReferenceItem ref){
|
||||||
if(ref!=null){
|
if(ref!=null){
|
||||||
mReferencedList.add(ref);
|
mReferencedList.add(ref);
|
||||||
@ -265,11 +273,11 @@ public class StringItem extends BlockItem implements JSONConvert<JSONObject> {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
String str=getHtml();
|
String str = getHtml();
|
||||||
if(str==null){
|
if(str == null){
|
||||||
return "NULL";
|
return "NULL";
|
||||||
}
|
}
|
||||||
return "USED BY="+getReferencedList().size()+"{"+str+"}";
|
return "USED BY=" + mReferencedList.size() + "{" + str + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] decodeUtf8StringByteLength(byte[] lengthBytes) {
|
private static int[] decodeUtf8StringByteLength(byte[] lengthBytes) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
|
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
|
|
||||||
public class TypeString extends StringItem {
|
public class TypeString extends StringItem {
|
||||||
public TypeString(boolean utf8) {
|
public TypeString(boolean utf8) {
|
||||||
super(utf8);
|
super(utf8);
|
||||||
}
|
}
|
||||||
@ -36,6 +36,9 @@ package com.reandroid.arsc.item;
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
void ensureStringLinkUnlocked(){
|
||||||
|
}
|
||||||
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return String.format("0x%02x", getId())+':'+get();
|
return String.format("0x%02x", getId())+':'+get();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public class ResXmlStringPool extends StringPool<ResXmlString> {
|
public class ResXmlStringPool extends StringPool<ResXmlString> {
|
||||||
public ResXmlStringPool(boolean is_utf8) {
|
public ResXmlStringPool(boolean is_utf8) {
|
||||||
super(is_utf8);
|
super(is_utf8, false);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ResXmlString removeReference(ReferenceItem referenceItem){
|
public ResXmlString removeReference(ReferenceItem referenceItem){
|
||||||
|
@ -34,4 +34,12 @@ public class SpecStringPool extends StringPool<SpecString> {
|
|||||||
public PackageBlock getPackageBlock(){
|
public PackageBlock getPackageBlock(){
|
||||||
return getParent(PackageBlock.class);
|
return getParent(PackageBlock.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void linkStrings(){
|
||||||
|
PackageBlock packageBlock = getPackageBlock();
|
||||||
|
if(packageBlock != null){
|
||||||
|
packageBlock.linkSpecStringsInternal(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,12 +33,14 @@ import java.util.*;
|
|||||||
|
|
||||||
|
|
||||||
public abstract class StringPool<T extends StringItem> extends Chunk<StringPoolHeader> implements BlockLoad, JSONConvert<JSONArray>, Comparator<String> {
|
public abstract class StringPool<T extends StringItem> extends Chunk<StringPoolHeader> implements BlockLoad, JSONConvert<JSONArray>, Comparator<String> {
|
||||||
|
private final Object mLock = new Object();
|
||||||
private final StringArray<T> mArrayStrings;
|
private final StringArray<T> mArrayStrings;
|
||||||
private final StyleArray mArrayStyles;
|
private final StyleArray mArrayStyles;
|
||||||
|
|
||||||
private final Map<String, StringGroup<T>> mUniqueMap;
|
private final Map<String, StringGroup<T>> mUniqueMap;
|
||||||
|
private boolean stringLinkLocked;
|
||||||
|
|
||||||
StringPool(boolean is_utf8){
|
StringPool(boolean is_utf8, boolean stringLinkLocked){
|
||||||
super(new StringPoolHeader(), 4);
|
super(new StringPoolHeader(), 4);
|
||||||
|
|
||||||
OffsetArray offsetStrings = new OffsetArray();
|
OffsetArray offsetStrings = new OffsetArray();
|
||||||
@ -68,7 +70,30 @@ public abstract class StringPool<T extends StringItem> extends Chunk<StringPoolH
|
|||||||
header.getFlagUtf8().setBlockLoad(this);
|
header.getFlagUtf8().setBlockLoad(this);
|
||||||
|
|
||||||
mUniqueMap = new HashMap<>();
|
mUniqueMap = new HashMap<>();
|
||||||
|
this.stringLinkLocked = stringLinkLocked;
|
||||||
}
|
}
|
||||||
|
StringPool(boolean is_utf8){
|
||||||
|
this(is_utf8, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStringLinkLocked(){
|
||||||
|
return stringLinkLocked;
|
||||||
|
}
|
||||||
|
public void ensureStringLinkUnlockedInternal(){
|
||||||
|
if(!stringLinkLocked){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (mLock){
|
||||||
|
if(!stringLinkLocked){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stringLinkLocked = false;
|
||||||
|
linkStrings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void linkStrings(){
|
||||||
|
}
|
||||||
|
|
||||||
public void removeString(T item){
|
public void removeString(T item){
|
||||||
getStringsArray().remove(item);
|
getStringsArray().remove(item);
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ import com.reandroid.arsc.array.OffsetArray;
|
|||||||
import com.reandroid.arsc.array.StringArray;
|
import com.reandroid.arsc.array.StringArray;
|
||||||
import com.reandroid.arsc.array.TableStringArray;
|
import com.reandroid.arsc.array.TableStringArray;
|
||||||
import com.reandroid.arsc.chunk.ChunkType;
|
import com.reandroid.arsc.chunk.ChunkType;
|
||||||
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.chunk.UnknownChunk;
|
import com.reandroid.arsc.chunk.UnknownChunk;
|
||||||
import com.reandroid.arsc.header.HeaderBlock;
|
import com.reandroid.arsc.header.HeaderBlock;
|
||||||
import com.reandroid.arsc.header.TableHeader;
|
import com.reandroid.arsc.header.TableHeader;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.IntegerArray;
|
|
||||||
import com.reandroid.arsc.item.IntegerItem;
|
import com.reandroid.arsc.item.IntegerItem;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
|
|
||||||
@ -35,6 +35,13 @@ public class TableStringPool extends StringPool<TableString> {
|
|||||||
super(is_utf8);
|
super(is_utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void linkStrings(){
|
||||||
|
TableBlock tableBlock = getParentInstance(TableBlock.class);
|
||||||
|
if(tableBlock != null){
|
||||||
|
tableBlock.linkTableStringsInternal(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
StringArray<TableString> newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
StringArray<TableString> newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) {
|
||||||
return new TableStringArray(offsets, itemCount, itemStart, is_utf8);
|
return new TableStringArray(offsets, itemCount, itemStart, is_utf8);
|
||||||
|
@ -27,7 +27,7 @@ import com.reandroid.arsc.item.TypeString;
|
|||||||
public class TypeStringPool extends StringPool<TypeString> {
|
public class TypeStringPool extends StringPool<TypeString> {
|
||||||
private final IntegerItem mTypeIdOffset;
|
private final IntegerItem mTypeIdOffset;
|
||||||
public TypeStringPool(boolean is_utf8, IntegerItem typeIdOffset) {
|
public TypeStringPool(boolean is_utf8, IntegerItem typeIdOffset) {
|
||||||
super(is_utf8);
|
super(is_utf8, false);
|
||||||
this.mTypeIdOffset = typeIdOffset;
|
this.mTypeIdOffset = typeIdOffset;
|
||||||
}
|
}
|
||||||
public int idOf(String typeName){
|
public int idOf(String typeName){
|
||||||
|
@ -27,6 +27,8 @@ import com.reandroid.arsc.container.SpecTypePair;
|
|||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.*;
|
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.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
@ -41,6 +43,15 @@ public class Entry extends Block implements JSONConvert<JSONObject> {
|
|||||||
super();
|
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(){
|
public ResValue getResValue(){
|
||||||
TableEntry<?, ?> tableEntry = getTableEntry();
|
TableEntry<?, ?> tableEntry = getTableEntry();
|
||||||
if(tableEntry instanceof ResTableEntry){
|
if(tableEntry instanceof ResTableEntry){
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
public class ResTableEntry extends TableEntry<EntryHeader, ResValue> {
|
public class ResTableEntry extends TableEntry<EntryHeader, ResValue> {
|
||||||
@ -22,6 +23,10 @@ public class ResTableEntry extends TableEntry<EntryHeader, ResValue> {
|
|||||||
super(new EntryHeader(), new ResValue());
|
super(new EntryHeader(), new ResValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
getValue().linkTableStrings(tableStringPool);
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
void onRemoved(){
|
void onRemoved(){
|
||||||
getHeader().onRemoved();
|
getHeader().onRemoved();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.ResValueMapArray;
|
import com.reandroid.arsc.array.ResValueMapArray;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArray> {
|
public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArray> {
|
||||||
@ -42,6 +43,12 @@ public class ResTableMapEntry extends TableEntry<EntryHeaderMap, ResValueMapArra
|
|||||||
getValue().setChildesCount(valuesCount);
|
getValue().setChildesCount(valuesCount);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
void linkTableStringsInternal(TableStringPool tableStringPool){
|
||||||
|
for(ResValueMap resValueMap : listResValueMap()){
|
||||||
|
resValueMap.linkTableStrings(tableStringPool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
void onHeaderLoaded(ValueHeader valueHeader){
|
void onHeaderLoaded(ValueHeader valueHeader){
|
||||||
getValue().setChildesCount(getValuesCount());
|
getValue().setChildesCount(getValuesCount());
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
|
|
||||||
public class ResValue extends ValueItem {
|
public class ResValue extends ValueItem {
|
||||||
public ResValue() {
|
public ResValue() {
|
||||||
super(8, OFFSET_SIZE);
|
super(8, OFFSET_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,6 +18,7 @@ package com.reandroid.arsc.value;
|
|||||||
import com.reandroid.arsc.base.Block;
|
import com.reandroid.arsc.base.Block;
|
||||||
import com.reandroid.arsc.base.BlockCounter;
|
import com.reandroid.arsc.base.BlockCounter;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
@ -96,6 +97,7 @@ public abstract class TableEntry<HEADER extends ValueHeader, VALUE extends Block
|
|||||||
}
|
}
|
||||||
abstract void onRemoved();
|
abstract void onRemoved();
|
||||||
abstract boolean shouldMerge(TableEntry<?, ?> tableEntry);
|
abstract boolean shouldMerge(TableEntry<?, ?> tableEntry);
|
||||||
|
abstract void linkTableStringsInternal(TableStringPool tableStringPool);
|
||||||
|
|
||||||
public abstract void merge(TableEntry<?, ?> tableEntry);
|
public abstract void merge(TableEntry<?, ?> tableEntry);
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,7 @@ import com.reandroid.arsc.base.Block;
|
|||||||
import com.reandroid.arsc.chunk.ParentChunk;
|
import com.reandroid.arsc.chunk.ParentChunk;
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.pool.StringPool;
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
@ -32,6 +33,21 @@ public class ValueHeader extends BlockItem implements JSONConvert<JSONObject> {
|
|||||||
writeSize();
|
writeSize();
|
||||||
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, -1);
|
putInteger(getBytesInternal(), OFFSET_SPEC_REFERENCE, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void linkSpecStringsInternal(SpecStringPool specStringPool){
|
||||||
|
int key = getKey();
|
||||||
|
SpecString specString = specStringPool.get(key);
|
||||||
|
if(specString == null){
|
||||||
|
mStringReference = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(mStringReference != null){
|
||||||
|
specString.removeReference(mStringReference);
|
||||||
|
}
|
||||||
|
ReferenceItem stringReference = new ReferenceBlock<>(this, OFFSET_SPEC_REFERENCE);
|
||||||
|
mStringReference = stringReference;
|
||||||
|
specString.addReference(stringReference);
|
||||||
|
}
|
||||||
public void onRemoved(){
|
public void onRemoved(){
|
||||||
unLinkStringReference();
|
unLinkStringReference();
|
||||||
}
|
}
|
||||||
@ -116,7 +132,11 @@ public class ValueHeader extends BlockItem implements JSONConvert<JSONObject> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void linkStringReference(){
|
private void linkStringReference(){
|
||||||
linkStringReference(getNameString());
|
StringPool<?> specStringPool = getSpecStringPool();
|
||||||
|
if(specStringPool == null || specStringPool.isStringLinkLocked()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
linkStringReference(specStringPool.get(getKey()));
|
||||||
}
|
}
|
||||||
private void linkStringReference(StringItem stringItem){
|
private void linkStringReference(StringItem stringItem){
|
||||||
unLinkStringReference();
|
unLinkStringReference();
|
||||||
@ -167,7 +187,6 @@ public class ValueHeader extends BlockItem implements JSONConvert<JSONObject> {
|
|||||||
int size = reader.readUnsignedShort();
|
int size = reader.readUnsignedShort();
|
||||||
setBytesLength(size, false);
|
setBytesLength(size, false);
|
||||||
reader.readFully(getBytesInternal());
|
reader.readFully(getBytesInternal());
|
||||||
linkStringReference();
|
|
||||||
}
|
}
|
||||||
private void setName(String name){
|
private void setName(String name){
|
||||||
if(name==null){
|
if(name==null){
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -23,6 +23,7 @@ import com.reandroid.arsc.item.ReferenceBlock;
|
|||||||
import com.reandroid.arsc.item.ReferenceItem;
|
import com.reandroid.arsc.item.ReferenceItem;
|
||||||
import com.reandroid.arsc.item.StringItem;
|
import com.reandroid.arsc.item.StringItem;
|
||||||
import com.reandroid.arsc.pool.StringPool;
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
@ -39,6 +40,10 @@ import java.util.Objects;
|
|||||||
|
|
||||||
writeSize();
|
writeSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void linkTableStrings(TableStringPool tableStringPool){
|
||||||
|
linkStringReference(tableStringPool);
|
||||||
|
}
|
||||||
public void onRemoved(){
|
public void onRemoved(){
|
||||||
unLinkStringReference();
|
unLinkStringReference();
|
||||||
}
|
}
|
||||||
@ -78,7 +83,7 @@ import java.util.Objects;
|
|||||||
int size = countBytes() - offset;
|
int size = countBytes() - offset;
|
||||||
putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size);
|
putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size);
|
||||||
}
|
}
|
||||||
private void onDataLoaded(){
|
protected void onDataLoaded(){
|
||||||
if(getValueType() == ValueType.STRING){
|
if(getValueType() == ValueType.STRING){
|
||||||
linkStringReference();
|
linkStringReference();
|
||||||
}else {
|
}else {
|
||||||
@ -136,8 +141,16 @@ import java.util.Objects;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void linkStringReference(){
|
private void linkStringReference(){
|
||||||
StringItem tableString = getDataAsPoolString();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(tableString==null){
|
if(stringPool == null || stringPool.isStringLinkLocked()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
linkStringReference(stringPool);
|
||||||
|
}
|
||||||
|
private void linkStringReference(StringPool<?> stringPool){
|
||||||
|
StringItem tableString = stringPool.get(getData());
|
||||||
|
if(tableString == null){
|
||||||
|
unLinkStringReference();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ReferenceItem stringReference = mStringReference;
|
ReferenceItem stringReference = mStringReference;
|
||||||
@ -181,7 +194,6 @@ import java.util.Objects;
|
|||||||
setBytesLength(this.sizeOffset + 8, false);
|
setBytesLength(this.sizeOffset + 8, false);
|
||||||
writeSize();
|
writeSize();
|
||||||
}
|
}
|
||||||
onDataLoaded();
|
|
||||||
}
|
}
|
||||||
private int initializeBytes(BlockReader reader) throws IOException {
|
private int initializeBytes(BlockReader reader) throws IOException {
|
||||||
int position = reader.getPosition();
|
int position = reader.getPosition();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user