diff --git a/src/main/java/com/reandroid/arsc/array/ResXmlAttributeArray.java b/src/main/java/com/reandroid/arsc/array/ResXmlAttributeArray.java index 53ef1f1..5c5051d 100755 --- a/src/main/java/com/reandroid/arsc/array/ResXmlAttributeArray.java +++ b/src/main/java/com/reandroid/arsc/array/ResXmlAttributeArray.java @@ -59,6 +59,7 @@ public class ResXmlAttributeArray extends BlockArray } private void refreshStart(){ Block parent=getParent(); + clearChildes(); if(parent==null){ return; } @@ -87,6 +88,23 @@ public class ResXmlAttributeArray extends BlockArray super.onReadBytes(reader); } @Override + public void clearChildes(){ + ResXmlAttribute[] childes = getChildes(); + if(childes==null || childes.length==0){ + super.clearChildes(); + return; + } + int length = childes.length; + for(int i=0;i T getParent(Class parentClass){ + Block parent = getParent(); + while (parent!=null){ + if(parent.getClass() == parentClass){ + return (T) parent; + } + parent = parent.getParent(); + } + return null; + } protected static byte[] addBytes(byte[] bts1, byte[] bts2){ diff --git a/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java b/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java index 6aba598..3bd8210 100755 --- a/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java @@ -60,14 +60,7 @@ return null; } SpecTypePair getSpecTypePair(){ - Block parent=getParent(); - while (parent!=null){ - if(parent instanceof SpecTypePair){ - return (SpecTypePair)parent; - } - parent=parent.getParent(); - } - return null; + return getParent(SpecTypePair.class); } public int getEntryCount() { return specFlagsArray.size(); diff --git a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java index b110913..5596046 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java @@ -137,14 +137,7 @@ public class TypeBlock extends Chunk return getEntryArray().countNonNull(); } public SpecTypePair getParentSpecTypePair(){ - Block parent=getParent(); - while (parent!=null){ - if(parent instanceof SpecTypePair){ - return (SpecTypePair)parent; - } - parent=parent.getParent(); - } - return null; + return getParent(SpecTypePair.class); } public void cleanEntries(){ PackageBlock packageBlock=getPackageBlock(); diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/BaseXmlChunk.java b/src/main/java/com/reandroid/arsc/chunk/xml/BaseXmlChunk.java index 88b47a0..7135abf 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/BaseXmlChunk.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/BaseXmlChunk.java @@ -72,7 +72,6 @@ if(xmlString!=null){ xmlString.removeReference(item); } - return xmlString; } public void setLineNumber(int val){ getHeaderBlock().getLineNumber().set(val); @@ -181,14 +180,7 @@ } } public ResXmlElement getParentResXmlElement(){ - Block parent=getParent(); - while (parent!=null){ - if(parent instanceof ResXmlElement){ - return (ResXmlElement)parent; - } - parent=parent.getParent(); - } - return null; + return getParent(ResXmlElement.class); } @Override protected void onChunkRefreshed() { diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java index f4eba42..d008899 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlAttribute.java @@ -15,154 +15,40 @@ */ package com.reandroid.arsc.chunk.xml; - import com.reandroid.arsc.array.ResXmlAttributeArray; import com.reandroid.arsc.array.ResXmlIDArray; - import com.reandroid.arsc.base.Block; - import com.reandroid.arsc.container.FixedBlockContainer; import com.reandroid.arsc.decoder.ValueDecoder; import com.reandroid.arsc.group.EntryGroup; + import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.item.*; import com.reandroid.arsc.pool.ResXmlStringPool; - import com.reandroid.arsc.value.Value; + import com.reandroid.arsc.pool.StringPool; + import com.reandroid.arsc.value.ValueItem; import com.reandroid.arsc.value.ValueType; import com.reandroid.common.EntryStore; - import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; import com.reandroid.xml.XMLAttribute; import com.reandroid.xml.XMLException; - import java.util.HashSet; - import java.util.Set; + import java.io.IOException; - public class ResXmlAttribute extends FixedBlockContainer - implements Value, Comparable, JSONConvert { - private final IntegerItem mNamespaceReference; - private final IntegerItem mNameReference; - private final IntegerItem mValueStringReference; - private final ShortItem mNameType; - private final ByteItem mReserved; - private final ByteItem mValueTypeByte; - private final IntegerItem mData; - private final ByteArray extraBytes; - public ResXmlAttribute(int size) { - super(8); - mNamespaceReference = new IntegerItem(-1); - mNameReference = new IntegerItem(-1); - mValueStringReference = new IntegerItem(-1); - mNameType = new ShortItem((short) 0x0008); - mReserved = new ByteItem(); - mValueTypeByte = new ByteItem(); - mData = new IntegerItem(); - extraBytes = new ByteArray(); - addChild(0, mNamespaceReference); - addChild(1, mNameReference); - addChild(2, mValueStringReference); - addChild(3, mNameType); - addChild(4, mReserved); - addChild(5, mValueTypeByte); - addChild(6, mData); - addChild(7, extraBytes); - - extraBytes.setSize(size-20); + public class ResXmlAttribute extends ValueItem implements Comparable{ + private ReferenceItem mNSReference; + private ReferenceItem mNameReference; + private ReferenceItem mStringReference; + public ResXmlAttribute(int attributeUnitSize) { + super(attributeUnitSize, OFFSET_SIZE); + byte[] bts = getBytesInternal(); + putInteger(bts, OFFSET_NS, -1); + putInteger(bts, OFFSET_NAME, -1); + putInteger(bts, OFFSET_STRING, -1); } - public ResXmlAttribute(){ + public ResXmlAttribute() { this(20); } - public void setAttributesUnitSize(int size){ - extraBytes.setSize(size-20); - IntegerItem integerItem = new IntegerItem(this.hashCode()); - extraBytes.putByteArray(0, integerItem.getBytes()); - } - Set clearStringReferences(){ - Set results= new HashSet<>(); - ResXmlString xmlString; - xmlString=unLinkStringReference(mNamespaceReference); - if(xmlString!=null){ - results.add(xmlString); - } - xmlString=unLinkStringReference(mNameReference); - if(xmlString!=null){ - results.add(xmlString); - } - xmlString=unLinkStringReference(mValueStringReference); - if(xmlString!=null){ - results.add(xmlString); - } - xmlString=unLinkStringReference(mData); - if(xmlString!=null){ - results.add(xmlString); - } - return results; - } - public void linkStringReferences(){ - linkStringReference(mNamespaceReference); - linkStringReference(mNameReference); - linkStringReference(mValueStringReference); - if(getValueType()==ValueType.STRING){ - linkStringReference(mData); - } - } - private void linkStringReference(IntegerItem item){ - ResXmlString xmlString = getResXmlString(item.get()); - if(xmlString!=null){ - xmlString.addReferenceIfAbsent(item); - } - } - private ResXmlString unLinkStringReference(IntegerItem item){ - ResXmlString xmlString = getResXmlString(item.get()); - if(xmlString!=null){ - xmlString.removeReference(item); - } - return xmlString; - } public String getUri(){ return getString(getNamespaceReference()); } - int getNamespaceReference(){ - return mNamespaceReference.get(); - } - public void setNamespaceReference(int ref){ - mNamespaceReference.set(ref); - } - int getNameReference(){ - return mNameReference.get(); - } - void setNameReference(int ref){ - mNameReference.set(ref); - } - int getValueStringReference(){ - return mValueStringReference.get(); - } - void setValueStringReference(int ref){ - mValueStringReference.set(ref); - } - byte getValueTypeByte(){ - return mValueTypeByte.get(); - } - void setValueTypeByte(byte b){ - mValueTypeByte.set(b); - } - @Override - public int getData(){ - return mData.get(); - } - @Override - public void setData(int val){ - mData.set(val); - } - @Override - public ValueType getValueType(){ - return ValueType.valueOf(getValueTypeByte()); - } - @Override - public void setValueType(ValueType valueType){ - byte b=0; - if(valueType!=null){ - b=valueType.getByte(); - } - setValueTypeByte(b); - } public String getFullName(){ String name=getName(); if(name==null){ @@ -188,13 +74,6 @@ } return startNamespace.getPrefix(); } - public ResXmlStartNamespace getStartNamespace(){ - ResXmlElement xmlElement=getParentResXmlElement(); - if(xmlElement==null){ - return null; - } - return xmlElement.getStartNamespaceByUriRef(getNamespaceReference()); - } @Deprecated public String getValueString(){ return getString(getValueStringReference()); @@ -218,14 +97,39 @@ if(name==null){ name=""; } - ResXmlIDMap xmlIDMap=getResXmlIDMap(); - ResXmlStringPool stringPool=getStringPool(); + ResXmlIDMap xmlIDMap = getResXmlIDMap(); + StringPool stringPool = getStringPool(); if(stringPool==null || xmlIDMap==null){ return; } - ResXmlString xmlString = stringPool.getOrCreateAttributeName(xmlIDMap.getResXmlIDArray().childesCount(), name); + ResXmlStringPool resXmlStringPool = (ResXmlStringPool) stringPool; + ResXmlString xmlString = resXmlStringPool.getOrCreateAttributeName(xmlIDMap.getResXmlIDArray().childesCount(), name); setNameReference(xmlString.getIndex()); } + public ResXmlElement getParentResXmlElement(){ + return getParent(ResXmlElement.class); + } + public int getAttributesUnitSize(){ + return OFFSET_SIZE + super.getSize(); + } + public void setAttributesUnitSize(int size){ + int eight = size - OFFSET_SIZE; + super.setSize(eight); + } + private String getString(int ref){ + if(ref<0){ + return null; + } + StringPool stringPool = getStringPool(); + if(stringPool == null){ + return null; + } + StringItem stringItem = stringPool.get(ref); + if(stringItem == null){ + return null; + } + return stringItem.getHtml(); + } private int getResourceId(int ref){ if(ref<0){ return 0; @@ -241,38 +145,6 @@ } return 0; } - - private String getString(int ref){ - if(ref<0){ - return null; - } - ResXmlString xmlString=getResXmlString(ref); - if(xmlString!=null){ - return xmlString.getHtml(); - } - return null; - } - private ResXmlString getResXmlString(int ref){ - ResXmlStringPool stringPool=getStringPool(); - if(stringPool!=null){ - return stringPool.get(ref); - } - return null; - } - private ResXmlString getOrCreateResXmlString(String str){ - ResXmlStringPool stringPool=getStringPool(); - if(stringPool!=null){ - return stringPool.getOrCreate(str); - } - return null; - } - private ResXmlStringPool getStringPool(){ - ResXmlElement xmlElement=getParentResXmlElement(); - if(xmlElement!=null){ - return xmlElement.getStringPool(); - } - return null; - } private ResXmlIDMap getResXmlIDMap(){ ResXmlElement xmlElement=getParentResXmlElement(); if(xmlElement!=null){ @@ -280,118 +152,112 @@ } return null; } - public ResXmlElement getParentResXmlElement(){ - Block parent=getParent(); - while (parent!=null){ - if(parent instanceof ResXmlElement){ - return (ResXmlElement)parent; - } - parent=parent.getParent(); - } - return null; + + int getNamespaceReference(){ + return getInteger(getBytesInternal(), OFFSET_NS); } - public String getValueAsString(){ - int ref= getData(); - ResXmlString xmlString=getResXmlString(ref); - if(xmlString==null){ + public void setNamespaceReference(int ref){ + if(ref == getNamespaceReference()){ + return; + } + unlink(mNSReference); + putInteger(getBytesInternal(), OFFSET_NS, ref); + mNSReference = link(OFFSET_NS); + } + int getNameReference(){ + return getInteger(getBytesInternal(), OFFSET_NAME); + } + void setNameReference(int ref){ + if(ref == getNameReference()){ + return; + } + unlink(mNameReference); + putInteger(getBytesInternal(), OFFSET_NAME, ref); + mNameReference = link(OFFSET_NAME); + } + int getValueStringReference(){ + return getInteger(getBytesInternal(), OFFSET_STRING); + } + void setValueStringReference(int ref){ + if(ref == getValueStringReference()){ + return; + } + unlink(mStringReference); + putInteger(getBytesInternal(), OFFSET_STRING, ref); + mStringReference = link(OFFSET_STRING); + } + + @Override + public void onReadBytes(BlockReader reader) throws IOException { + super.onReadBytes(reader); + linkAll(); + } + @Override + public void onRemoved(){ + super.onRemoved(); + unlinkAll(); + } + @Override + protected void onUnlinkDataString(StringItem stringItem){ + if(stringItem.getReferencedList().size()==0){ + stringItem.set(""); + } + } + @Override + protected void onDataChanged(){ + if(getValueType()!=ValueType.STRING){ + setValueStringReference(-1); + } + } + private void linkAll(){ + unlink(mNSReference); + mNSReference = link(OFFSET_NS); + unlink(mNameReference); + mNameReference = link(OFFSET_NAME); + unlink(mStringReference); + mStringReference = link(OFFSET_STRING); + } + private void unlinkAll(){ + unlink(mNSReference); + unlink(mNameReference); + unlink(mStringReference); + } + private ReferenceItem link(int offset){ + if(offset<0){ return null; } - return xmlString.getHtml(); - } - public boolean getValueAsBoolean(){ - int ref= getData(); - return ref!=0; - } - public void setValueAsString(String str){ - setValueType(ValueType.STRING); - ResXmlString xmlString=getOrCreateResXmlString(str); - if(xmlString==null){ - throw new IllegalStateException("ResXmlString is null, attribute must be added to parent element first"); + StringPool stringPool = getStringPool(); + if(stringPool == null){ + return null; } - int ref=xmlString.getIndex(); - setData(ref); - setValueStringReference(ref); - } - public void setValueAsBoolean(boolean val){ - setValueType(ValueType.INT_BOOLEAN); - int ref=val?0xffffffff:0; - setData(ref); - setValueStringReference(-1); - } - public boolean hasIntegerValue(){ - ValueType valueType=getValueType(); - return valueType==ValueType.INT_DEC; - } - public Integer getValueAsInteger(){ - if(hasIntegerValue()){ - return getData(); + int ref = getInteger(getBytesInternal(), offset); + StringItem stringItem = stringPool.get(ref); + if(stringItem == null){ + return null; } - return null; + ReferenceItem referenceItem = new ReferenceBlock<>(this, offset); + stringItem.addReference(referenceItem); + return referenceItem; } - public void setValueAsInteger(int val){ - setValueType(ValueType.INT_DEC); - setData(val); - setValueStringReference(-1); - } - private ResXmlAttributeArray getParentResXmlAttributeArray(){ - Block parent=this; - while(parent!=null){ - if(parent instanceof ResXmlAttributeArray){ - return (ResXmlAttributeArray)parent; - } - parent=parent.getParent(); + private void unlink(ReferenceItem reference){ + if(reference == null){ + return; + } + StringPool stringPool = getStringPool(); + if(stringPool==null){ + return; + } + StringItem stringItem = stringPool.get(reference.get()); + if(stringItem==null){ + return; + } + stringItem.removeReference(reference); + if(stringItem.getReferencedList().size()==0){ + stringItem.set(""); } - return null; - } - public void setValueAsIntegerDec(int val){ - setValueType(ValueType.INT_DEC); - setData(val); - setValueStringReference(-1); - } - public void setValueAsHex(int val){ - setValueType(ValueType.INT_HEX); - setData(val); - setValueStringReference(-1); - } - public void setValueAsFraction(float fraction){ - int val=Float.floatToIntBits(fraction); - setValueAsFraction(val); - } - public void setValueAsFraction(int val){ - setValueType(ValueType.FRACTION); - setData(val); - setValueStringReference(-1); - } - public void setValueAsResourceId(int resId){ - setValueType(ValueType.REFERENCE); - setData(resId); - setValueStringReference(-1); - } - public void setValueAsAttributeId(int attrId){ - setValueType(ValueType.ATTRIBUTE); - setData(attrId); - setValueStringReference(-1); - } - public void setValueAsColorRGB4(int val){ - setValueType(ValueType.INT_COLOR_RGB4); - setData(val); - setValueStringReference(-1); - } - public void setValueAsColorRGB8(int val){ - setValueType(ValueType.INT_COLOR_RGB8); - setData(val); - setValueStringReference(-1); - } - public void setValueAsColorARGB4(int val){ - setValueType(ValueType.INT_COLOR_ARGB4); - setData(val); - setValueStringReference(-1); - } - public void setValueAsColorARGB8(int val){ - setValueType(ValueType.INT_COLOR_ARGB8); - setData(val); - setValueStringReference(-1); } + + @Override public int compareTo(ResXmlAttribute other) { int id1=getNameResourceID(); @@ -472,8 +338,8 @@ if(prefix!=null){ name=prefix+":"+name; } - ValueType valueType=getValueType(); - int raw= getData(); + ValueType valueType = getValueType(); + int raw = getData(); String value; if(valueType==ValueType.STRING){ value = ValueDecoder.escapeSpecialCharacter(getValueAsString()); @@ -493,10 +359,10 @@ } @Override public String toString(){ - String fullName=getFullName(); + String fullName = getFullName(); if(fullName!=null ){ int id=getNameResourceID(); - if(id>0){ + if(id!=0){ fullName=fullName+"(@"+String.format("0x%08x",id)+")"; } String valStr; @@ -504,9 +370,11 @@ if(valueType==ValueType.STRING){ valStr=getValueAsString(); }else if (valueType==ValueType.INT_BOOLEAN){ - valStr=String.valueOf(getValueAsBoolean()); + valStr = String.valueOf(getValueAsBoolean()); + }else if (valueType==ValueType.INT_DEC){ + valStr = String.valueOf(getData()); }else { - valStr="["+valueType+"] "+ getData(); + valStr = "["+valueType+"] " + String.format("0x%08x",getData()); } if(valStr!=null){ return fullName+"=\""+valStr+"\""; @@ -520,16 +388,22 @@ builder.append("{NamespaceReference=").append(getNamespaceReference()); builder.append(", NameReference=").append(getNameReference()); builder.append(", ValueStringReference=").append(getValueStringReference()); - builder.append(", NameType=").append(mNameType.unsignedInt()); - builder.append(", ReservedByte=").append(mReserved.unsignedInt()); - builder.append(", ValueTypeByte=").append(getValueTypeByte()); - builder.append(", RawValue=").append(getData()); + builder.append(", ValueSize=").append(getSize()); + builder.append(", ValueTypeByte=").append(getType() & 0xff); + builder.append(", Data=").append(getData()); builder.append("}"); return builder.toString(); } - static final String NAME_id = "id"; - public static final String NAME_value_type = "value_type"; + + + + public static final String NAME_id = "id"; public static final String NAME_name = "name"; public static final String NAME_namespace_uri = "namespace_uri"; - public static final String NAME_data= "data"; + + private static final int OFFSET_NS = 0; + private static final int OFFSET_NAME = 4; + private static final int OFFSET_STRING = 8; + + private static final int OFFSET_SIZE = 12; } diff --git a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java index d4e706a..281cfc5 100755 --- a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java +++ b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java @@ -125,14 +125,7 @@ public class SpecTypePair extends BlockContainer return mTypeBlockArray; } public PackageBlock getPackageBlock(){ - Block parent=getParent(); - while (parent!=null){ - if(parent instanceof PackageBlock){ - return (PackageBlock)parent; - } - parent=parent.getParent(); - } - return null; + return getParent(PackageBlock.class); } public List listEntries(int entryId){ List results=new ArrayList<>(); diff --git a/src/main/java/com/reandroid/arsc/item/TypeString.java b/src/main/java/com/reandroid/arsc/item/TypeString.java index 6ce504c..3806b69 100755 --- a/src/main/java/com/reandroid/arsc/item/TypeString.java +++ b/src/main/java/com/reandroid/arsc/item/TypeString.java @@ -16,7 +16,6 @@ package com.reandroid.arsc.item; - import com.reandroid.arsc.base.Block; import com.reandroid.arsc.pool.TypeStringPool; public class TypeString extends StringItem { @@ -24,7 +23,7 @@ package com.reandroid.arsc.item; super(utf8); } public int getId(){ - TypeStringPool stringPool=getTypeStringPool(); + TypeStringPool stringPool = getParent(TypeStringPool.class); if(stringPool!=null){ return stringPool.idOf(this); } @@ -36,14 +35,4 @@ package com.reandroid.arsc.item; // Type don't have style unless to obfuscate/confuse other decompilers return null; } - private TypeStringPool getTypeStringPool(){ - Block parent=this; - while (parent!=null){ - if(parent instanceof TypeStringPool){ - return (TypeStringPool) parent; - } - parent=parent.getParent(); - } - return null; - } } diff --git a/src/main/java/com/reandroid/arsc/value/Entry.java b/src/main/java/com/reandroid/arsc/value/Entry.java index 9d741d1..7263673 100755 --- a/src/main/java/com/reandroid/arsc/value/Entry.java +++ b/src/main/java/com/reandroid/arsc/value/Entry.java @@ -160,14 +160,7 @@ } public TypeBlock getTypeBlock(){ - Block parent = getParent(); - while (parent!=null){ - if(parent instanceof TypeBlock){ - return (TypeBlock) parent; - } - parent = parent.getParent(); - } - return null; + return getParent(TypeBlock.class); } private String getPackageName(){ PackageBlock packageBlock = getPackageBlock(); @@ -177,14 +170,7 @@ return null; } public PackageBlock getPackageBlock(){ - Block parent = getParent(); - while (parent!=null){ - if(parent instanceof PackageBlock){ - return (PackageBlock) parent; - } - parent = parent.getParent(); - } - return null; + return getParent(PackageBlock.class); } private TableEntry ensureTableEntry(boolean is_complex){ TableEntry tableEntry = getTableEntry(); diff --git a/src/main/java/com/reandroid/arsc/value/TableEntry.java b/src/main/java/com/reandroid/arsc/value/TableEntry.java index 8ecb21f..6bf57ca 100644 --- a/src/main/java/com/reandroid/arsc/value/TableEntry.java +++ b/src/main/java/com/reandroid/arsc/value/TableEntry.java @@ -40,14 +40,7 @@ public abstract class TableEntry
ext this.resValue.setIndex(1); } public Entry getParentEntry(){ - Block parent = getParent(); - while (parent!=null){ - if(parent instanceof Entry){ - return (Entry) parent; - } - parent=parent.getParent(); - } - return null; + return getParent(Entry.class); } public void refresh(){ } diff --git a/src/main/java/com/reandroid/arsc/value/ValueItem.java b/src/main/java/com/reandroid/arsc/value/ValueItem.java index bffe3d9..d3d0f4d 100755 --- a/src/main/java/com/reandroid/arsc/value/ValueItem.java +++ b/src/main/java/com/reandroid/arsc/value/ValueItem.java @@ -31,58 +31,49 @@ import java.io.IOException; public abstract class ValueItem extends BlockItem implements Value, JSONConvert{ private ReferenceItem mStringReference; - public ValueItem(int bytesLength) { + private final int sizeOffset; + public ValueItem(int bytesLength, int sizeOffset) { super(bytesLength); + this.sizeOffset = sizeOffset; + writeSize(); } public void onRemoved(){ unLinkStringReference(); } - public Entry getParentEntry(){ - Block parent=getParent(); - while (parent!=null){ - if(parent instanceof Entry){ - return (Entry) parent; - } - parent = parent.getParent(); - } - return null; + protected void onDataChanged(){ } public void refresh(){ writeSize(); } - public ReferenceItem getTableStringReference(){ - return mStringReference; - } - - abstract int getSizeOffset(); byte getRes0(){ - return getBytesInternal()[getSizeOffset()+OFFSET_RES0]; + return getBytesInternal()[this.sizeOffset + OFFSET_RES0]; } public byte getType(){ - return getBytesInternal()[getSizeOffset()+OFFSET_TYPE]; + return getBytesInternal()[this.sizeOffset + OFFSET_TYPE]; } public void setType(byte type){ if(type == getType()){ return; } byte[] bts = getBytesInternal(); - int offset = getSizeOffset()+OFFSET_TYPE; + int offset = this.sizeOffset + OFFSET_TYPE; byte old = bts[offset]; bts[offset] = type; onTypeChanged(old, type); + onDataChanged(); } public int getSize(){ - return 0xffff & getShort(getBytesInternal(), getSizeOffset()+OFFSET_SIZE); + return 0xffff & getShort(getBytesInternal(), this.sizeOffset + OFFSET_SIZE); } public void setSize(int size){ - size = getSizeOffset() + size; + size = this.sizeOffset + size; setBytesLength(size, false); writeSize(); } private void writeSize(){ - int offset = getSizeOffset(); + int offset = this.sizeOffset; int size = countBytes() - offset; putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size); } @@ -107,20 +98,21 @@ import java.io.IOException; } @Override public int getData(){ - return getInteger(getBytesInternal(), getSizeOffset()+OFFSET_DATA); + return getInteger(getBytesInternal(), this.sizeOffset + OFFSET_DATA); } @Override public void setData(int data){ byte[] bts = getBytesInternal(); - int old = getInteger(bts, getSizeOffset()+OFFSET_DATA); + int old = getInteger(bts, this.sizeOffset + OFFSET_DATA); if(old == data){ return; } unLinkStringReference(); - putInteger(bts, getSizeOffset()+OFFSET_DATA, data); + putInteger(bts, this.sizeOffset + OFFSET_DATA, data); if(ValueType.STRING==getValueType()){ linkStringReference(); } + onDataChanged(); } @@ -148,7 +140,7 @@ import java.io.IOException; if(stringReference!=null){ unLinkStringReference(); } - stringReference = new ReferenceBlock<>(this, getSizeOffset()+OFFSET_DATA); + stringReference = new ReferenceBlock<>(this, this.sizeOffset + OFFSET_DATA); mStringReference = stringReference; tableString.addReference(stringReference); } @@ -162,9 +154,14 @@ import java.io.IOException; if(stringPool == null){ return; } - stringPool.removeReference(stringReference); + StringItem stringItem = stringPool.removeReference(stringReference); + if(stringItem!=null){ + onUnlinkDataString(stringItem); + } } - private StringPool getStringPool(){ + protected void onUnlinkDataString(StringItem stringItem){ + } + public StringPool getStringPool(){ Block parent = getParent(); while (parent!=null){ if(parent instanceof MainChunk){ @@ -182,7 +179,7 @@ import java.io.IOException; } private void initializeBytes(BlockReader reader) throws IOException { int position = reader.getPosition(); - int offset = getSizeOffset(); + int offset = this.sizeOffset; reader.offset(offset); int size = reader.readUnsignedShort(); reader.seek(position); @@ -290,6 +287,6 @@ import java.io.IOException; private static final int OFFSET_DATA = 4; - static final String NAME_data = "data"; - static final String NAME_value_type = "value_type"; + public static final String NAME_data = "data"; + public static final String NAME_value_type = "value_type"; }