From 21569db1f3a0d032deab1f71cb7bdb3970eb0c0f Mon Sep 17 00:00:00 2001 From: REAndroid Date: Thu, 27 Apr 2023 19:12:39 +0200 Subject: [PATCH] full implementation of SPARSE type entries --- .../com/reandroid/arsc/array/EntryArray.java | 122 ++- .../com/reandroid/arsc/array/OffsetArray.java | 40 + .../arsc/array/OffsetBlockArray.java | 45 +- .../arsc/array/ResXmlStringArray.java | 34 +- .../arsc/array/SparseOffsetsArray.java | 87 ++ .../arsc/array/SparseTypeBlockArray.java | 39 - .../arsc/array/SparseTypeEntryArray.java | 42 - .../reandroid/arsc/array/SpecStringArray.java | 33 +- .../arsc/array/SpecTypePairArray.java | 26 +- .../com/reandroid/arsc/array/StringArray.java | 5 +- .../com/reandroid/arsc/array/StyleArray.java | 33 +- .../arsc/array/TableStringArray.java | 33 +- .../reandroid/arsc/array/TypeBlockArray.java | 82 +- .../reandroid/arsc/array/TypeStringArray.java | 5 +- .../com/reandroid/arsc/base/BlockArray.java | 10 +- .../reandroid/arsc/chunk/SparseTypeBlock.java | 42 - .../com/reandroid/arsc/chunk/TypeBlock.java | 70 +- .../reandroid/arsc/container/PackageBody.java | 9 +- .../arsc/container/SpecTypePair.java | 37 +- .../com/reandroid/arsc/header/TypeHeader.java | 3 +- .../com/reandroid/arsc/io/BlockReader.java | 2 +- .../com/reandroid/arsc/item/IntegerArray.java | 8 + .../reandroid/arsc/pool/ResXmlStringPool.java | 39 +- .../reandroid/arsc/pool/SpecStringPool.java | 35 +- .../com/reandroid/arsc/pool/StringPool.java | 65 +- .../reandroid/arsc/pool/TableStringPool.java | 43 +- .../reandroid/arsc/pool/TypeStringPool.java | 33 +- .../java/com/reandroid/arsc/value/Entry.java | 892 +++++++++--------- .../reandroid/arsc/value/SparseTypeEntry.java | 40 - 29 files changed, 1008 insertions(+), 946 deletions(-) create mode 100644 src/main/java/com/reandroid/arsc/array/OffsetArray.java create mode 100644 src/main/java/com/reandroid/arsc/array/SparseOffsetsArray.java delete mode 100644 src/main/java/com/reandroid/arsc/array/SparseTypeBlockArray.java delete mode 100644 src/main/java/com/reandroid/arsc/array/SparseTypeEntryArray.java delete mode 100644 src/main/java/com/reandroid/arsc/chunk/SparseTypeBlock.java delete mode 100644 src/main/java/com/reandroid/arsc/value/SparseTypeEntry.java diff --git a/src/main/java/com/reandroid/arsc/array/EntryArray.java b/src/main/java/com/reandroid/arsc/array/EntryArray.java index 7dd0514..2935670 100755 --- a/src/main/java/com/reandroid/arsc/array/EntryArray.java +++ b/src/main/java/com/reandroid/arsc/array/EntryArray.java @@ -15,7 +15,6 @@ */ package com.reandroid.arsc.array; -import com.reandroid.arsc.item.IntegerArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.arsc.value.Entry; import com.reandroid.json.JSONConvert; @@ -26,9 +25,32 @@ import java.util.Iterator; public class EntryArray extends OffsetBlockArray implements JSONConvert { - public EntryArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){ + public EntryArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart){ super(offsets, itemCount, itemStart); } + public int getHighestEntryId(){ + if(isSparse()){ + return ((SparseOffsetsArray) getOffsetArray()).getHighestId(); + } + return childesCount(); + } + public int getEntryId(int index){ + OffsetArray offsetArray = getOffsetArray(); + if(offsetArray instanceof SparseOffsetsArray){ + return ((SparseOffsetsArray) offsetArray).getIdx(index); + } + return index; + } + public int getEntryIndex(int entryId){ + OffsetArray offsetArray = getOffsetArray(); + if(offsetArray instanceof SparseOffsetsArray){ + return ((SparseOffsetsArray) offsetArray).indexOf(entryId); + } + return entryId; + } + public boolean isSparse(){ + return super.getOffsetArray() instanceof SparseOffsetsArray; + } public void destroy(){ for(Entry entry:listItems()){ if(entry!=null){ @@ -47,26 +69,41 @@ public class EntryArray extends OffsetBlockArray implements JSONConvert implements JSONConvert implements JSONConvert itr = entryArray.iterator(true); + while (itr.hasNext()){ + Entry comingBlock = itr.next(); + Entry existingBlock = getOrCreate((short) comingBlock.getId()); + existingBlock.merge(comingBlock); } + } + private void mergeNonSparse(EntryArray entryArray){ ensureSize(entryArray.childesCount()); Iterator itr = entryArray.iterator(true); while (itr.hasNext()){ Entry comingBlock = itr.next(); - Entry existingBlock = get(comingBlock.getIndex()); + Entry existingBlock = super.get(comingBlock.getIndex()); existingBlock.merge(comingBlock); } - refreshCountAndStart(); } @Override public String toString(){ diff --git a/src/main/java/com/reandroid/arsc/array/OffsetArray.java b/src/main/java/com/reandroid/arsc/array/OffsetArray.java new file mode 100644 index 0000000..dd88d02 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/array/OffsetArray.java @@ -0,0 +1,40 @@ +/* + * 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.array; + +import com.reandroid.arsc.item.IntegerArray; + +public class OffsetArray extends IntegerArray { + public OffsetArray(){ + super(); + } + public int getOffset(int i){ + return super.getAt(i); + } + public void setOffset(int index, int value){ + super.put(index, value); + } + public int[] getOffsets(){ + int length = size(); + int[] result = new int[length]; + for(int i=0;i extends BlockArray implements BlockLoad { - private final IntegerArray mOffsets; + private final OffsetArray mOffsets; private final IntegerItem mItemStart; private final IntegerItem mItemCount; private final ByteArray mEnd4Block; private byte mEnd4Type; - public OffsetBlockArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart){ + public OffsetBlockArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart){ super(); this.mOffsets=offsets; this.mItemCount=itemCount; @@ -43,6 +42,9 @@ public abstract class OffsetBlockArray extends BlockArray im this.mEnd4Block=new ByteArray(); mItemCount.setBlockLoad(this); } + OffsetArray getOffsetArray(){ + return mOffsets; + } void setEndBytes(byte b){ this.mEnd4Type=b; this.mEnd4Block.fill(b); @@ -91,7 +93,8 @@ public abstract class OffsetBlockArray extends BlockArray im @Override protected void onRefreshed() { int count=childesCount(); - mOffsets.setSize(count); + OffsetArray offsetArray = this.mOffsets; + offsetArray.setSize(count); T[] childes=getChildes(); int sum=0; if(childes!=null){ @@ -105,7 +108,7 @@ public abstract class OffsetBlockArray extends BlockArray im offset=sum; sum+=item.countBytes(); } - mOffsets.put(i, offset); + offsetArray.setOffset(i, offset); } } refreshCount(); @@ -167,7 +170,7 @@ public abstract class OffsetBlockArray extends BlockArray im if(childes==null||childes.length==0){ return; } - int[] offsetArray=mOffsets.toArray(); + int[] offsetArray=mOffsets.getOffsets(); int max=childes.length; int start=mItemStart.get(); reader.seek(start); diff --git a/src/main/java/com/reandroid/arsc/array/ResXmlStringArray.java b/src/main/java/com/reandroid/arsc/array/ResXmlStringArray.java index 8ed95bb..20a9384 100755 --- a/src/main/java/com/reandroid/arsc/array/ResXmlStringArray.java +++ b/src/main/java/com/reandroid/arsc/array/ResXmlStringArray.java @@ -1,18 +1,18 @@ - /* - * 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. - */ +/* + * 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.array; import com.reandroid.arsc.chunk.xml.ResXmlDocument; @@ -24,8 +24,8 @@ import com.reandroid.arsc.item.ResXmlString; import java.util.ArrayList; import java.util.List; - public class ResXmlStringArray extends StringArray { - public ResXmlStringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { +public class ResXmlStringArray extends StringArray { + public ResXmlStringArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { super(offsets, itemCount, itemStart, is_utf8); } @Override diff --git a/src/main/java/com/reandroid/arsc/array/SparseOffsetsArray.java b/src/main/java/com/reandroid/arsc/array/SparseOffsetsArray.java new file mode 100644 index 0000000..98f26a0 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/array/SparseOffsetsArray.java @@ -0,0 +1,87 @@ +/* + * 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.array; + +public class SparseOffsetsArray extends OffsetArray{ + public SparseOffsetsArray(){ + super(); + } + public int getHighestId(){ + int result = NO_ENTRY; + int size = size(); + for(int i=0; i result){ + result = id; + } + } + if(result == NO_ENTRY){ + result = 0; + } + return result; + } + public int indexOf(int idx){ + int size = super.size(); + for(int i=0; i>> 16) & 0xffff; + return value * 4; + } + @Override + public void setOffset(int index, int offset){ + int value; + if(offset == NO_ENTRY){ + value = 0; + }else { + int idx = getAt(0); + idx = idx & 0xffff; + offset = offset & 0xffff; + offset = offset / 4; + offset = offset << 16; + value = offset | idx; + } + super.put(index, value); + } +} diff --git a/src/main/java/com/reandroid/arsc/array/SparseTypeBlockArray.java b/src/main/java/com/reandroid/arsc/array/SparseTypeBlockArray.java deleted file mode 100644 index 213dd3f..0000000 --- a/src/main/java/com/reandroid/arsc/array/SparseTypeBlockArray.java +++ /dev/null @@ -1,39 +0,0 @@ - /* - * Copyright (C) 2022 github.com/REAndroid - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.reandroid.arsc.array; - -import com.reandroid.arsc.base.BlockArray; -import com.reandroid.arsc.chunk.SparseTypeBlock; - -public class SparseTypeBlockArray extends BlockArray { - @Override - public SparseTypeBlock[] newInstance(int len) { - return new SparseTypeBlock[len]; - } - @Override - public SparseTypeBlock newInstance() { - return new SparseTypeBlock(); - } - @Override - protected void onRefreshed() { - } - public void merge(SparseTypeBlockArray sparse){ - if(sparse == null || sparse == this){ - return; - } - addAll(sparse.getChildes()); - } -} diff --git a/src/main/java/com/reandroid/arsc/array/SparseTypeEntryArray.java b/src/main/java/com/reandroid/arsc/array/SparseTypeEntryArray.java deleted file mode 100644 index 7a09b8e..0000000 --- a/src/main/java/com/reandroid/arsc/array/SparseTypeEntryArray.java +++ /dev/null @@ -1,42 +0,0 @@ - /* - * Copyright (C) 2022 github.com/REAndroid - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.reandroid.arsc.array; - -import com.reandroid.arsc.base.BlockArray; -import com.reandroid.arsc.io.BlockReader; -import com.reandroid.arsc.value.SparseTypeEntry; - -import java.io.IOException; - -public class SparseTypeEntryArray extends BlockArray { - @Override - public SparseTypeEntry[] newInstance(int len) { - return new SparseTypeEntry[len]; - } - @Override - public SparseTypeEntry newInstance() { - return new SparseTypeEntry(); - } - @Override - protected void onRefreshed() { - } - @Override - public void onReadBytes(BlockReader reader) throws IOException { - int count = reader.available() / 4; - setChildesCount(count); - super.onReadBytes(reader); - } -} diff --git a/src/main/java/com/reandroid/arsc/array/SpecStringArray.java b/src/main/java/com/reandroid/arsc/array/SpecStringArray.java index 8b9278d..82e2c1b 100755 --- a/src/main/java/com/reandroid/arsc/array/SpecStringArray.java +++ b/src/main/java/com/reandroid/arsc/array/SpecStringArray.java @@ -1,26 +1,25 @@ - /* - * 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. - */ +/* + * 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.array; -import com.reandroid.arsc.item.IntegerArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.arsc.item.SpecString; public class SpecStringArray extends StringArray { - public SpecStringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + public SpecStringArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { super(offsets, itemCount, itemStart, is_utf8); } @Override diff --git a/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java b/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java index d3de0cc..0629786 100755 --- a/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java +++ b/src/main/java/com/reandroid/arsc/array/SpecTypePairArray.java @@ -1,4 +1,4 @@ - /* +/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -90,11 +90,11 @@ public class SpecTypePairArray extends BlockArray return pair.getTypeBlockArray().getOrCreate(resConfig); } public SpecTypePair getOrCreate(byte typeId){ - SpecTypePair pair=getPair(typeId); + SpecTypePair pair = getPair(typeId); if(pair!=null){ return pair; } - pair=createNext(); + pair = createNext(); pair.setTypeId(typeId); return pair; } @@ -115,25 +115,9 @@ public class SpecTypePairArray extends BlockArray } return null; } - public byte getTypeId(){ - SpecTypePair[] items=getChildes(); - if(items==null){ - return 0; - } - int max=items.length; - for(int i=0;i protected void onPreRefreshRefresh(){ validateEntryCounts(); } - // For android API < 26, it is required to have equal entry count on all SpecTypePair + private void validateEntryCounts(){ Map entryCountMap=mapHighestEntryCount(); for(Map.Entry entry:entryCountMap.entrySet()){ diff --git a/src/main/java/com/reandroid/arsc/array/StringArray.java b/src/main/java/com/reandroid/arsc/array/StringArray.java index 4826916..14d434a 100755 --- a/src/main/java/com/reandroid/arsc/array/StringArray.java +++ b/src/main/java/com/reandroid/arsc/array/StringArray.java @@ -1,4 +1,4 @@ - /* +/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,7 +15,6 @@ */ package com.reandroid.arsc.array; -import com.reandroid.arsc.item.IntegerArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.arsc.item.StringItem; import com.reandroid.json.JSONConvert; @@ -29,7 +28,7 @@ import java.util.List; public abstract class StringArray extends OffsetBlockArray implements JSONConvert { private boolean mUtf8; - public StringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + public StringArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { super(offsets, itemCount, itemStart); this.mUtf8=is_utf8; setEndBytes((byte)0x00); diff --git a/src/main/java/com/reandroid/arsc/array/StyleArray.java b/src/main/java/com/reandroid/arsc/array/StyleArray.java index 25350d9..3b84b87 100755 --- a/src/main/java/com/reandroid/arsc/array/StyleArray.java +++ b/src/main/java/com/reandroid/arsc/array/StyleArray.java @@ -1,23 +1,22 @@ - /* - * 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. - */ +/* + * 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.array; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.item.ByteArray; -import com.reandroid.arsc.item.IntegerArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.arsc.item.StyleItem; import com.reandroid.json.JSONConvert; @@ -26,7 +25,7 @@ import com.reandroid.json.JSONArray; import java.io.IOException; public class StyleArray extends OffsetBlockArray implements JSONConvert { - public StyleArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart) { + public StyleArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart) { super(offsets, itemCount, itemStart); setEndBytes(END_BYTE); } diff --git a/src/main/java/com/reandroid/arsc/array/TableStringArray.java b/src/main/java/com/reandroid/arsc/array/TableStringArray.java index a21a1c5..3a7f909 100755 --- a/src/main/java/com/reandroid/arsc/array/TableStringArray.java +++ b/src/main/java/com/reandroid/arsc/array/TableStringArray.java @@ -1,26 +1,25 @@ - /* - * 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. - */ +/* + * 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.array; -import com.reandroid.arsc.item.IntegerArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.arsc.item.TableString; public class TableStringArray extends StringArray { - public TableStringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + public TableStringArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { super(offsets, itemCount, itemStart, is_utf8); } @Override diff --git a/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java b/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java index c16e340..2a5dd30 100755 --- a/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java +++ b/src/main/java/com/reandroid/arsc/array/TypeBlockArray.java @@ -1,4 +1,4 @@ - /* +/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -95,14 +95,17 @@ public class TypeBlockArray extends BlockArray return typeBlock.getEntry(entryId); } public TypeBlock getOrCreate(ResConfig resConfig){ - TypeBlock typeBlock=getTypeBlock(resConfig); - if(typeBlock!=null){ + return getOrCreate(resConfig, false); + } + public TypeBlock getOrCreate(ResConfig resConfig, boolean sparse){ + TypeBlock typeBlock = getTypeBlock(resConfig, sparse); + if(typeBlock != null){ return typeBlock; } - byte id=getTypeId(); - typeBlock=createNext(); + byte id = getTypeId(); + typeBlock = createNext(sparse); typeBlock.setTypeId(id); - ResConfig config=typeBlock.getResConfig(); + ResConfig config = typeBlock.getResConfig(); config.copyFrom(resConfig); return typeBlock; } @@ -131,18 +134,24 @@ public class TypeBlockArray extends BlockArray return null; } public TypeBlock getTypeBlock(ResConfig config){ + return getTypeBlock(config, false); + } + public TypeBlock getTypeBlock(ResConfig config, boolean sparse){ if(config==null){ return null; } - TypeBlock[] items=getChildes(); - if(items==null){ + TypeBlock[] items = getChildes(); + if(items == null){ return null; } - int max=items.length; - for(int i=0;i }; } private SpecBlock getSpecBlock(){ - Block parent=getParent(); - while(parent!=null){ - if(parent instanceof SpecTypePair){ - return ((SpecTypePair) parent).getSpecBlock(); - } - parent=parent.getParent(); + SpecTypePair parent = getParent(SpecTypePair.class); + if(parent != null){ + return parent.getSpecBlock(); } return null; } @@ -223,8 +229,8 @@ public class TypeBlockArray extends BlockArray } @Override public TypeBlock newInstance() { - byte id=getTypeId(); - TypeBlock typeBlock=new TypeBlock(); + byte id = getTypeId(); + TypeBlock typeBlock = new TypeBlock(false); typeBlock.setTypeId(id); return typeBlock; } @@ -232,6 +238,13 @@ public class TypeBlockArray extends BlockArray public TypeBlock[] newInstance(int len) { return new TypeBlock[len]; } + public TypeBlock createNext(boolean sparse){ + byte id = getTypeId(); + TypeBlock typeBlock = new TypeBlock(sparse); + typeBlock.setTypeId(id); + add(typeBlock); + return typeBlock; + } @Override protected void onRefreshed() { @@ -265,16 +278,18 @@ public class TypeBlockArray extends BlockArray public int getHighestEntryCount(){ int result=0; for(TypeBlock typeBlock:getChildes()){ - int count=typeBlock.getEntryArray().childesCount(); - if(count>result){ - result=count; + int high = typeBlock.getEntryArray().getHighestEntryId(); + if(high > result){ + result = high; } } return result; } public void setEntryCount(int count){ for(TypeBlock typeBlock:getChildes()){ - typeBlock.setEntryCount(count); + if(!typeBlock.isSparse()){ + typeBlock.setEntryCount(count); + } } } public TypeString getTypeString(){ @@ -305,21 +320,22 @@ public class TypeBlockArray extends BlockArray if(json == null){ return; } - int length= json.length(); - ensureSize(length); - for (int i=0;i { private int lastCreateIndex; - public TypeStringArray(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + public TypeStringArray(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { super(offsets, itemCount, itemStart, is_utf8); } @Override diff --git a/src/main/java/com/reandroid/arsc/base/BlockArray.java b/src/main/java/com/reandroid/arsc/base/BlockArray.java index aef6f8e..e079421 100755 --- a/src/main/java/com/reandroid/arsc/base/BlockArray.java +++ b/src/main/java/com/reandroid/arsc/base/BlockArray.java @@ -83,10 +83,13 @@ public abstract class BlockArray extends BlockContainer impl return results; } public Collection listItems(){ + return listItems(false); + } + public Collection listItems(boolean skipNullBlocks){ return new AbstractCollection() { @Override public Iterator iterator(){ - return BlockArray.this.iterator(); + return BlockArray.this.iterator(skipNullBlocks); } @Override public boolean contains(Object o){ @@ -277,12 +280,15 @@ public abstract class BlockArray extends BlockContainer impl } int len=items.length; for(int i=0;i blockList){ T[] items=elementData; if(items==null || items.length==0){ diff --git a/src/main/java/com/reandroid/arsc/chunk/SparseTypeBlock.java b/src/main/java/com/reandroid/arsc/chunk/SparseTypeBlock.java deleted file mode 100644 index 4bcf79c..0000000 --- a/src/main/java/com/reandroid/arsc/chunk/SparseTypeBlock.java +++ /dev/null @@ -1,42 +0,0 @@ - /* - * Copyright (C) 2022 github.com/REAndroid - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.reandroid.arsc.chunk; - -import com.reandroid.arsc.array.SparseTypeEntryArray; -import com.reandroid.arsc.header.TypeHeader; -import com.reandroid.arsc.value.SparseTypeEntry; - -import java.util.Collection; - -public class SparseTypeBlock extends Chunk{ - private final SparseTypeEntryArray entryArray; - public SparseTypeBlock() { - super(new TypeHeader(), 1); - entryArray = new SparseTypeEntryArray(); - addChild(entryArray); - getHeaderBlock().setSparse(true); - } - public Collection listEntries(){ - return getEntryArray().listItems(); - } - public SparseTypeEntryArray getEntryArray() { - return entryArray; - } - @Override - protected void onChunkRefreshed() { - getHeaderBlock().setSparse(true); - } -} diff --git a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java index 750c88c..f382836 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java @@ -1,21 +1,23 @@ - /* - * 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. - */ +/* + * 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.chunk; import com.reandroid.arsc.array.EntryArray; +import com.reandroid.arsc.array.OffsetArray; +import com.reandroid.arsc.array.SparseOffsetsArray; import com.reandroid.arsc.base.Block; import com.reandroid.arsc.container.SpecTypePair; import com.reandroid.arsc.header.TypeHeader; @@ -39,11 +41,16 @@ public class TypeBlock extends Chunk private final EntryArray mEntryArray; private TypeString mTypeString; - public TypeBlock() { - super(new TypeHeader(), 2); + public TypeBlock(boolean sparse) { + super(new TypeHeader(sparse), 2); TypeHeader header = getHeaderBlock(); - IntegerArray entryOffsets = new IntegerArray(); + OffsetArray entryOffsets; + if(sparse){ + entryOffsets = new SparseOffsetsArray(); + }else { + entryOffsets = new OffsetArray(); + } this.mEntryArray = new EntryArray(entryOffsets, header.getCount(), header.getEntriesStart()); @@ -52,6 +59,9 @@ public class TypeBlock extends Chunk addChild(entryOffsets); addChild(mEntryArray); } + public boolean isSparse(){ + return getHeaderBlock().isSparse(); + } public void destroy(){ getEntryArray().destroy(); setId(0); @@ -227,9 +237,9 @@ public class TypeBlock extends Chunk super.onPreRefreshRefresh(); } /* - * method Block.addBytes is inefficient for large size byte array - * so let's override here because this block is the largest - */ + * method Block.addBytes is inefficient for large size byte array + * so let's override here because this block is the largest + */ @Override public byte[] getBytes(){ ByteArrayOutputStream os=new ByteArrayOutputStream(); @@ -242,7 +252,10 @@ public class TypeBlock extends Chunk } @Override public JSONObject toJson() { - JSONObject jsonObject=new JSONObject(); + JSONObject jsonObject = new JSONObject(); + if(isSparse()){ + jsonObject.put(NAME_is_sparse, true); + } jsonObject.put(NAME_id, getId()); jsonObject.put(NAME_name, getTypeName()); jsonObject.put(NAME_config, getResConfig().toJson()); @@ -274,12 +287,16 @@ public class TypeBlock extends Chunk } @Override public int compareTo(TypeBlock typeBlock) { - int id1= getId(); - int id2=typeBlock.getId(); - if(id1!=id2){ + int id1 = getId(); + int id2 = typeBlock.getId(); + if(id1 != id2){ return Integer.compare(id1, id2); } - return getResConfig().compareTo(typeBlock.getResConfig()); + String q1 = (isSparse() ? "1" : "0") + + getResConfig().getQualifiers(); + String q2 = (typeBlock.isSparse() ? "1" : "0") + + typeBlock.getResConfig().getQualifiers(); + return q1.compareTo(q2); } /** * It is allowed to have duplicate entry name therefore it is not recommend to use this. @@ -311,4 +328,5 @@ public class TypeBlock extends Chunk public static final String NAME_config = "config"; public static final String NAME_id = "id"; public static final String NAME_entries = "entries"; + public static final String NAME_is_sparse = "is_sparse"; } diff --git a/src/main/java/com/reandroid/arsc/container/PackageBody.java b/src/main/java/com/reandroid/arsc/container/PackageBody.java index a6aba58..d657389 100755 --- a/src/main/java/com/reandroid/arsc/container/PackageBody.java +++ b/src/main/java/com/reandroid/arsc/container/PackageBody.java @@ -117,13 +117,10 @@ public class PackageBody extends FixedBlockContainer { TypeHeader typeHeader = reader.readTypeHeader(); SpecTypePair specTypePair = mSpecTypePairArray.getOrCreate(typeHeader.getId().get()); if(typeHeader.isSparse()){ - SparseTypeBlock sparseTypeBlock = specTypePair - .getSparseTypeBlockArray().createNext(); - sparseTypeBlock.readBytes(reader); - }else { - TypeBlock typeBlock = specTypePair.getTypeBlockArray().createNext(); - typeBlock.readBytes(reader); + String junk = ""; } + TypeBlock typeBlock = specTypePair.getTypeBlockArray().createNext(typeHeader.isSparse()); + typeBlock.readBytes(reader); } private void readLibraryBlock(BlockReader reader) throws IOException{ LibraryBlock libraryBlock=new LibraryBlock(); diff --git a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java index 1eb1068..ed688d5 100755 --- a/src/main/java/com/reandroid/arsc/container/SpecTypePair.java +++ b/src/main/java/com/reandroid/arsc/container/SpecTypePair.java @@ -1,4 +1,4 @@ - /* +/* * Copyright (C) 2022 github.com/REAndroid * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ package com.reandroid.arsc.container; import com.reandroid.arsc.array.EntryArray; -import com.reandroid.arsc.array.SparseTypeBlockArray; import com.reandroid.arsc.chunk.*; import com.reandroid.arsc.array.TypeBlockArray; import com.reandroid.arsc.base.Block; @@ -39,31 +38,23 @@ public class SpecTypePair extends BlockContainer private final Block[] mChildes; private final SpecBlock mSpecBlock; private final TypeBlockArray mTypeBlockArray; - private final SparseTypeBlockArray sparseTypeBlockArray; + public SpecTypePair(SpecBlock specBlock, TypeBlockArray typeBlockArray){ this.mSpecBlock = specBlock; this.mTypeBlockArray = typeBlockArray; - this.sparseTypeBlockArray = new SparseTypeBlockArray(); - this.mChildes=new Block[]{specBlock, typeBlockArray, sparseTypeBlockArray}; - mSpecBlock.setIndex(0); - mTypeBlockArray.setIndex(1); - sparseTypeBlockArray.setIndex(2); - mSpecBlock.setParent(this); - mTypeBlockArray.setParent(this); - sparseTypeBlockArray.setParent(this); + this.mChildes = new Block[]{specBlock, typeBlockArray}; + + specBlock.setIndex(0); + typeBlockArray.setIndex(1); + + specBlock.setParent(this); + typeBlockArray.setParent(this); } public SpecTypePair(){ this(new SpecBlock(), new TypeBlockArray()); } - public SparseTypeBlockArray getSparseTypeBlockArray() { - return sparseTypeBlockArray; - } - public Collection listSparseTypeBlock(){ - return sparseTypeBlockArray.listItems(); - } - public Map createEntryGroups(){ Map map = new HashMap<>(); for(TypeBlock typeBlock:listTypeBlocks()){ @@ -233,12 +224,8 @@ public class SpecTypePair extends BlockContainer } private void readTypeBlock(BlockReader reader) throws IOException { TypeHeader typeHeader = reader.readTypeHeader(); - if(typeHeader.isSparse()){ - SparseTypeBlock sparseTypeBlock = sparseTypeBlockArray.createNext(); - sparseTypeBlock.readBytes(reader); - return; - } - mTypeBlockArray.readBytes(reader); + TypeBlock typeBlock = mTypeBlockArray.createNext(typeHeader.isSparse()); + typeBlock.readBytes(reader); } private void readUnexpectedNonSpecBlock(BlockReader reader, HeaderBlock headerBlock) throws IOException{ throw new IOException("Unexpected block: "+headerBlock.toString()+", Should be: "+ChunkType.SPEC); @@ -281,7 +268,6 @@ public class SpecTypePair extends BlockContainer } getSpecBlock().merge(typePair.getSpecBlock()); getTypeBlockArray().merge(typePair.getTypeBlockArray()); - getSparseTypeBlockArray().merge(typePair.getSparseTypeBlockArray()); } @Override public int compareTo(SpecTypePair specTypePair) { @@ -304,4 +290,5 @@ public class SpecTypePair extends BlockContainer } public static final String NAME_types = "types"; + public static final String NAME_sparse_types = "sparse_types"; } diff --git a/src/main/java/com/reandroid/arsc/header/TypeHeader.java b/src/main/java/com/reandroid/arsc/header/TypeHeader.java index 675e0b1..ed1f9d9 100644 --- a/src/main/java/com/reandroid/arsc/header/TypeHeader.java +++ b/src/main/java/com/reandroid/arsc/header/TypeHeader.java @@ -27,7 +27,7 @@ public class TypeHeader extends HeaderBlock{ private final IntegerItem count; private final IntegerItem entriesStart; private final ResConfig config; - public TypeHeader() { + public TypeHeader(boolean sparse) { super(ChunkType.TYPE.ID); this.id = new ByteItem(); this.flags = new ByteItem(); @@ -42,6 +42,7 @@ public class TypeHeader extends HeaderBlock{ addChild(count); addChild(entriesStart); addChild(config); + setSparse(sparse); } public boolean isSparse(){ return (getFlags().get() & FLAG_SPARSE) == FLAG_SPARSE; diff --git a/src/main/java/com/reandroid/arsc/io/BlockReader.java b/src/main/java/com/reandroid/arsc/io/BlockReader.java index 7fd3cf3..d560549 100755 --- a/src/main/java/com/reandroid/arsc/io/BlockReader.java +++ b/src/main/java/com/reandroid/arsc/io/BlockReader.java @@ -69,7 +69,7 @@ import java.io.*; return specHeader; } public TypeHeader readTypeHeader() throws IOException{ - TypeHeader typeHeader = new TypeHeader(); + TypeHeader typeHeader = new TypeHeader(false); if(available() < typeHeader.getMinimumSize()){ return null; } diff --git a/src/main/java/com/reandroid/arsc/item/IntegerArray.java b/src/main/java/com/reandroid/arsc/item/IntegerArray.java index 4085933..b9e1fd8 100755 --- a/src/main/java/com/reandroid/arsc/item/IntegerArray.java +++ b/src/main/java/com/reandroid/arsc/item/IntegerArray.java @@ -113,6 +113,14 @@ public class IntegerArray extends BlockItem { (bts[i+2] & 0xff) << 16 | (bts[i+3] & 0xff) << 24; } + public int getAt(int index){ + int i=index*4; + byte[] bts = getBytesInternal(); + return bts[i] & 0xff | + (bts[i+1] & 0xff) << 8 | + (bts[i+2] & 0xff) << 16 | + (bts[i+3] & 0xff) << 24; + } public final int size(){ return getBytesLength()/4; } diff --git a/src/main/java/com/reandroid/arsc/pool/ResXmlStringPool.java b/src/main/java/com/reandroid/arsc/pool/ResXmlStringPool.java index be7ee18..594d457 100755 --- a/src/main/java/com/reandroid/arsc/pool/ResXmlStringPool.java +++ b/src/main/java/com/reandroid/arsc/pool/ResXmlStringPool.java @@ -1,24 +1,21 @@ - /* - * 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. - */ +/* + * 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.pool; -import com.reandroid.arsc.array.ResXmlIDArray; -import com.reandroid.arsc.array.StringArray; -import com.reandroid.arsc.array.ResXmlStringArray; -import com.reandroid.arsc.array.StyleArray; +import com.reandroid.arsc.array.*; import com.reandroid.arsc.chunk.xml.ResXmlDocument; import com.reandroid.arsc.chunk.xml.ResXmlIDMap; import com.reandroid.arsc.group.StringGroup; @@ -26,7 +23,7 @@ import com.reandroid.arsc.item.*; import java.util.Objects; - public class ResXmlStringPool extends StringPool { +public class ResXmlStringPool extends StringPool { public ResXmlStringPool(boolean is_utf8) { super(is_utf8); } @@ -55,7 +52,7 @@ import java.util.Objects; } } @Override - StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + StringArray newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { return new ResXmlStringArray(offsets, itemCount, itemStart, is_utf8); } public ResXmlString getOrCreate(String str){ diff --git a/src/main/java/com/reandroid/arsc/pool/SpecStringPool.java b/src/main/java/com/reandroid/arsc/pool/SpecStringPool.java index 157278d..758ebaf 100755 --- a/src/main/java/com/reandroid/arsc/pool/SpecStringPool.java +++ b/src/main/java/com/reandroid/arsc/pool/SpecStringPool.java @@ -1,25 +1,24 @@ - /* - * 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. - */ +/* + * 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.pool; +import com.reandroid.arsc.array.OffsetArray; import com.reandroid.arsc.array.SpecStringArray; import com.reandroid.arsc.array.StringArray; -import com.reandroid.arsc.base.Block; import com.reandroid.arsc.chunk.PackageBlock; -import com.reandroid.arsc.item.IntegerArray; import com.reandroid.arsc.item.IntegerItem; import com.reandroid.arsc.item.SpecString; @@ -29,7 +28,7 @@ public class SpecStringPool extends StringPool { } @Override - StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + StringArray newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { return new SpecStringArray(offsets, itemCount, itemStart, is_utf8); } public PackageBlock getPackageBlock(){ diff --git a/src/main/java/com/reandroid/arsc/pool/StringPool.java b/src/main/java/com/reandroid/arsc/pool/StringPool.java index 9818711..ffed592 100755 --- a/src/main/java/com/reandroid/arsc/pool/StringPool.java +++ b/src/main/java/com/reandroid/arsc/pool/StringPool.java @@ -1,37 +1,38 @@ - /* - * Copyright (C) 2022 github.com/REAndroid - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* + * 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.pool; - import com.reandroid.arsc.array.StringArray; - import com.reandroid.arsc.array.StyleArray; - import com.reandroid.arsc.base.Block; - import com.reandroid.arsc.chunk.Chunk; - import com.reandroid.arsc.group.StringGroup; - import com.reandroid.arsc.header.StringPoolHeader; - import com.reandroid.arsc.io.BlockLoad; - import com.reandroid.arsc.io.BlockReader; - import com.reandroid.arsc.item.*; - import com.reandroid.json.JSONArray; - import com.reandroid.json.JSONConvert; +import com.reandroid.arsc.array.OffsetArray; +import com.reandroid.arsc.array.StringArray; +import com.reandroid.arsc.array.StyleArray; +import com.reandroid.arsc.base.Block; +import com.reandroid.arsc.chunk.Chunk; +import com.reandroid.arsc.group.StringGroup; +import com.reandroid.arsc.header.StringPoolHeader; +import com.reandroid.arsc.io.BlockLoad; +import com.reandroid.arsc.io.BlockReader; +import com.reandroid.arsc.item.*; +import com.reandroid.json.JSONArray; +import com.reandroid.json.JSONConvert; - import java.io.IOException; - import java.util.*; +import java.io.IOException; +import java.util.*; - public abstract class StringPool extends Chunk implements BlockLoad, JSONConvert, Comparator { +public abstract class StringPool extends Chunk implements BlockLoad, JSONConvert, Comparator { private final StringArray mArrayStrings; private final StyleArray mArrayStyles; @@ -40,8 +41,8 @@ package com.reandroid.arsc.pool; StringPool(boolean is_utf8){ super(new StringPoolHeader(), 4); - IntegerArray offsetStrings = new IntegerArray(); - IntegerArray offsetStyles = new IntegerArray(); + OffsetArray offsetStrings = new OffsetArray(); + OffsetArray offsetStyles = new OffsetArray(); StringPoolHeader header = getHeaderBlock(); @@ -278,7 +279,7 @@ package com.reandroid.arsc.pool; getHeaderBlock().setSorted(sorted); } - abstract StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8); + abstract StringArray newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8); @Override protected void onChunkRefreshed() { mArrayStrings.refreshCountAndStart(); diff --git a/src/main/java/com/reandroid/arsc/pool/TableStringPool.java b/src/main/java/com/reandroid/arsc/pool/TableStringPool.java index c39e558..47e5c68 100755 --- a/src/main/java/com/reandroid/arsc/pool/TableStringPool.java +++ b/src/main/java/com/reandroid/arsc/pool/TableStringPool.java @@ -1,20 +1,21 @@ - /* - * 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. - */ +/* + * 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.pool; +import com.reandroid.arsc.array.OffsetArray; import com.reandroid.arsc.array.StringArray; import com.reandroid.arsc.array.TableStringArray; import com.reandroid.arsc.chunk.ChunkType; @@ -29,13 +30,13 @@ import com.reandroid.arsc.item.TableString; import java.io.IOException; import java.io.InputStream; - public class TableStringPool extends StringPool { +public class TableStringPool extends StringPool { public TableStringPool(boolean is_utf8) { super(is_utf8); } @Override - StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + StringArray newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { return new TableStringArray(offsets, itemCount, itemStart, is_utf8); } public void merge(TableStringPool stringPool){ @@ -58,10 +59,10 @@ import java.io.InputStream; refreshUniqueIdMap(); } - /** - * Loads string pool only from table block (resources.arsc) without - * loading other chunks - */ + /** + * Loads string pool only from table block (resources.arsc) without + * loading other chunks + */ public static TableStringPool readFromTable(InputStream inputStream) throws IOException { TableHeader tableHeader = new TableHeader(); tableHeader.readBytes(inputStream); diff --git a/src/main/java/com/reandroid/arsc/pool/TypeStringPool.java b/src/main/java/com/reandroid/arsc/pool/TypeStringPool.java index 9faabf2..1893df0 100755 --- a/src/main/java/com/reandroid/arsc/pool/TypeStringPool.java +++ b/src/main/java/com/reandroid/arsc/pool/TypeStringPool.java @@ -1,20 +1,21 @@ - /* - * 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. - */ +/* + * 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.pool; +import com.reandroid.arsc.array.OffsetArray; import com.reandroid.arsc.array.StringArray; import com.reandroid.arsc.array.TypeStringArray; import com.reandroid.arsc.chunk.TypeBlock; @@ -80,7 +81,7 @@ public class TypeStringPool extends StringPool { return group.get(0); } @Override - StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { + StringArray newInstance(OffsetArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { return new TypeStringArray(offsets, itemCount, itemStart, is_utf8); } } diff --git a/src/main/java/com/reandroid/arsc/value/Entry.java b/src/main/java/com/reandroid/arsc/value/Entry.java index 2383247..2739ab4 100755 --- a/src/main/java/com/reandroid/arsc/value/Entry.java +++ b/src/main/java/com/reandroid/arsc/value/Entry.java @@ -1,459 +1,465 @@ - /* - * 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; +/* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.arsc.value; - import com.reandroid.arsc.array.ResValueMapArray; - import com.reandroid.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.TableBlock; - import com.reandroid.arsc.chunk.TypeBlock; - import com.reandroid.arsc.container.SpecTypePair; - import com.reandroid.arsc.group.EntryGroup; - import com.reandroid.arsc.io.BlockReader; - import com.reandroid.arsc.item.*; - import com.reandroid.json.JSONConvert; - import com.reandroid.json.JSONObject; +import 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.TableBlock; +import com.reandroid.arsc.chunk.TypeBlock; +import com.reandroid.arsc.container.SpecTypePair; +import com.reandroid.arsc.group.EntryGroup; +import com.reandroid.arsc.io.BlockReader; +import com.reandroid.arsc.item.*; +import com.reandroid.json.JSONConvert; +import com.reandroid.json.JSONObject; - import java.io.IOException; - import java.io.OutputStream; +import java.io.IOException; +import java.io.OutputStream; - public class Entry extends Block implements JSONConvert { - private TableEntry mTableEntry; +public class Entry extends Block implements JSONConvert { + private TableEntry mTableEntry; - public Entry(){ - super(); - } + public Entry(){ + super(); + } - public ResValue getResValue(){ - TableEntry tableEntry = getTableEntry(); - if(tableEntry instanceof ResTableEntry){ - return ((ResTableEntry)tableEntry).getValue(); - } - return null; - } - public ResValueMapArray getResValueMapArray(){ - TableEntry tableEntry = getTableEntry(); - if(tableEntry instanceof ResTableMapEntry){ - return ((ResTableMapEntry)tableEntry).getValue(); - } - return null; - } - 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(){ - return getIndex(); - } - public String getName(){ - SpecString specString = getSpecString(); - if(specString!=null){ - return specString.get(); - } - return null; - } - public String getTypeName(){ - TypeBlock typeBlock = getTypeBlock(); - if(typeBlock!=null){ - return typeBlock.getTypeName(); - } - return null; - } - public int getResourceId(){ - PackageBlock packageBlock = getPackageBlock(); - if(packageBlock==null){ - return 0; - } - TypeBlock typeBlock = getTypeBlock(); - if(typeBlock==null){ - return 0; - } - return (packageBlock.getId()<<24) - | (typeBlock.getId() << 16) - | getId(); - } - public int getSpecReference(){ - TableEntry tableEntry = getTableEntry(); - if(tableEntry == null){ - return 0; - } - return tableEntry.getHeader().getKey(); - } - public TypeString getTypeString(){ - TypeBlock typeBlock = getTypeBlock(); - if(typeBlock!=null){ - return typeBlock.getTypeString(); - } - return null; - } - public boolean isDefault(){ - ResConfig resConfig = getResConfig(); - if(resConfig!=null){ - return resConfig.isDefault(); - } - return false; - } - public void setSpecReference(StringItem specReference){ - TableEntry tableEntry = getTableEntry(); - if(tableEntry == null){ - return; - } - tableEntry.getHeader().setKey(specReference); - } - public void setSpecReference(int ref){ - TableEntry tableEntry = getTableEntry(); - if(tableEntry == null){ - return; - } - tableEntry.getHeader().setKey(ref); - } - private Entry searchEntry(int resourceId){ - if(resourceId==getResourceId()){ - return this; - } - PackageBlock packageBlock= getPackageBlock(); - if(packageBlock==null){ - return null; - } - TableBlock tableBlock = packageBlock.getTableBlock(); - if(tableBlock==null){ - return null; - } - EntryGroup entryGroup = tableBlock.search(resourceId); - if(entryGroup!=null){ - return entryGroup.pickOne(); - } - return null; - } - public ResValue setValueAsRaw(ValueType valueType, int data){ - TableEntry tableEntry = ensureTableEntry(false); - ResValue resValue = (ResValue) tableEntry.getValue(); - resValue.setTypeAndData(valueType, data); - return resValue; - } - public ResValue setValueAsBoolean(boolean val){ - int data = val?0xffffffff:0; - return setValueAsRaw(ValueType.INT_BOOLEAN, data); - } - public ResValue setValueAsReference(int resourceId){ - return setValueAsRaw(ValueType.REFERENCE, resourceId); - } - public ResValue setValueAsString(String str){ - TableEntry tableEntry = ensureTableEntry(false); - ResValue resValue = (ResValue) tableEntry.getValue(); - resValue.setValueAsString(str); - return resValue; - } - public SpecString getSpecString(){ - TableEntry tableEntry = getTableEntry(); - if(tableEntry == null){ - return null; - } - PackageBlock packageBlock = getPackageBlock(); - if(packageBlock == null){ - return null; - } - return packageBlock.getSpecStringPool() - .get(tableEntry.getHeader().getKey()); - } - public ResConfig getResConfig(){ - TypeBlock typeBlock = getTypeBlock(); - if(typeBlock!=null){ - return typeBlock.getResConfig(); - } - return null; - } - public SpecBlock getSpecBlock(){ - TypeBlock typeBlock = getTypeBlock(); - if(typeBlock == null){ - return null; - } - SpecTypePair specTypePair = typeBlock.getParentSpecTypePair(); - if(specTypePair==null){ - return null; - } - return specTypePair.getSpecBlock(); - } - 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(); + public ResValue getResValue(){ + TableEntry tableEntry = getTableEntry(); + if(tableEntry instanceof ResTableEntry){ + return ((ResTableEntry)tableEntry).getValue(); + } + return null; + } + public ResValueMapArray getResValueMapArray(){ + TableEntry tableEntry = getTableEntry(); + if(tableEntry instanceof ResTableMapEntry){ + return ((ResTableMapEntry)tableEntry).getValue(); + } + return null; + } + 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; + } + public String getName(){ + SpecString specString = getSpecString(); + if(specString!=null){ + return specString.get(); + } + return null; + } + public String getTypeName(){ + TypeBlock typeBlock = getTypeBlock(); + if(typeBlock!=null){ + return typeBlock.getTypeName(); + } + return null; + } + public int getResourceId(){ + PackageBlock packageBlock = getPackageBlock(); + if(packageBlock==null){ + return 0; + } + TypeBlock typeBlock = getTypeBlock(); + if(typeBlock==null){ + return 0; + } + return (packageBlock.getId()<<24) + | (typeBlock.getId() << 16) + | getId(); + } + public int getSpecReference(){ + TableEntry tableEntry = getTableEntry(); + if(tableEntry == null){ + return 0; + } + return tableEntry.getHeader().getKey(); + } + public TypeString getTypeString(){ + TypeBlock typeBlock = getTypeBlock(); + if(typeBlock!=null){ + return typeBlock.getTypeString(); + } + return null; + } + public boolean isDefault(){ + ResConfig resConfig = getResConfig(); + if(resConfig!=null){ + return resConfig.isDefault(); + } + return false; + } + public void setSpecReference(StringItem specReference){ + TableEntry tableEntry = getTableEntry(); + if(tableEntry == null){ + return; + } + tableEntry.getHeader().setKey(specReference); + } + public void setSpecReference(int ref){ + TableEntry tableEntry = getTableEntry(); + if(tableEntry == null){ + return; + } + tableEntry.getHeader().setKey(ref); + } + private Entry searchEntry(int resourceId){ + if(resourceId==getResourceId()){ + return this; + } + PackageBlock packageBlock= getPackageBlock(); + if(packageBlock==null){ + return null; + } + TableBlock tableBlock = packageBlock.getTableBlock(); + if(tableBlock==null){ + return null; + } + EntryGroup entryGroup = tableBlock.search(resourceId); + if(entryGroup!=null){ + return entryGroup.pickOne(); + } + return null; + } + public ResValue setValueAsRaw(ValueType valueType, int data){ + TableEntry tableEntry = ensureTableEntry(false); + ResValue resValue = (ResValue) tableEntry.getValue(); + resValue.setTypeAndData(valueType, data); + return resValue; + } + public ResValue setValueAsBoolean(boolean val){ + int data = val?0xffffffff:0; + return setValueAsRaw(ValueType.INT_BOOLEAN, data); + } + public ResValue setValueAsReference(int resourceId){ + return setValueAsRaw(ValueType.REFERENCE, resourceId); + } + public ResValue setValueAsString(String str){ + TableEntry tableEntry = ensureTableEntry(false); + ResValue resValue = (ResValue) tableEntry.getValue(); + resValue.setValueAsString(str); + return resValue; + } + public SpecString getSpecString(){ + TableEntry tableEntry = getTableEntry(); + if(tableEntry == null){ + return null; + } + PackageBlock packageBlock = getPackageBlock(); + if(packageBlock == null){ + return null; + } + return packageBlock.getSpecStringPool() + .get(tableEntry.getHeader().getKey()); + } + public ResConfig getResConfig(){ + TypeBlock typeBlock = getTypeBlock(); + if(typeBlock!=null){ + return typeBlock.getResConfig(); + } + return null; + } + public SpecBlock getSpecBlock(){ + TypeBlock typeBlock = getTypeBlock(); + if(typeBlock == null){ + return null; + } + SpecTypePair specTypePair = typeBlock.getParentSpecTypePair(); + if(specTypePair==null){ + return null; + } + return specTypePair.getSpecBlock(); + } + 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; - } + 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; - } + 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; - } - 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); - } + @Override + public boolean isNull(){ + return getTableEntry()==null; + } + @Override + public void setNull(boolean is_null){ + if(is_null){ + setTableEntry(null); + } + } + @Override + public byte[] getBytes() { + if(isNull()){ + return null; + } + return getTableEntry().getBytes(); + } + @Override + public int countBytes() { + if(isNull()){ + return 0; + } + return getTableEntry().countBytes(); + } + @Override + public void onCountUpTo(BlockCounter counter) { + if(counter.FOUND){ + return; + } + if(counter.END==this){ + counter.FOUND=true; + return; + } + if(isNull()){ + return; + } + counter.addCount(getTableEntry().countBytes()); + } + @Override + protected int onWriteBytes(OutputStream stream) throws IOException { + if(isNull()){ + return 0; + } + return getTableEntry().writeBytes(stream); + } + @Override + public void onReadBytes(BlockReader reader) throws IOException { + TableEntry tableEntry = createTableEntry(reader); + setTableEntry(tableEntry); + tableEntry.readBytes(reader); + } - public boolean isComplex(){ - return getTableEntry() instanceof ResTableMapEntry; - } - public void setTableEntry(TableEntry tableEntry){ - if(tableEntry==this.mTableEntry){ - return; - } - onTableEntryRemoved(); - if(tableEntry==null){ - return; - } - tableEntry.setIndex(0); - tableEntry.setParent(this); - this.mTableEntry = tableEntry; - onTableEntryAdded(); - } - private void onTableEntryAdded(){ - PackageBlock packageBlock = getPackageBlock(); - if(packageBlock!=null){ - packageBlock.onEntryAdded(this); - } - } - private void onTableEntryRemoved(){ - TableEntry exist = this.mTableEntry; - if(exist == null){ - return; - } - PackageBlock packageBlock = getPackageBlock(); - if(packageBlock!=null){ - packageBlock.removeEntryGroup(this); - } - exist.onRemoved(); - exist.setIndex(-1); - exist.setParent(null); - this.mTableEntry = null; - } - private TableEntry createTableEntry(BlockReader reader) throws IOException { - int startPosition = reader.getPosition(); - reader.offset(2); - boolean is_complex = (0x0001 & reader.readShort()) == 0x0001; - reader.seek(startPosition); - return createTableEntry(is_complex); - } - private TableEntry createTableEntry(boolean is_complex) { - if(is_complex){ - return new ResTableMapEntry(); - }else { - return new ResTableEntry(); - } - } + public boolean isComplex(){ + return getTableEntry() instanceof ResTableMapEntry; + } + public void setTableEntry(TableEntry tableEntry){ + if(tableEntry==this.mTableEntry){ + return; + } + onTableEntryRemoved(); + if(tableEntry==null){ + return; + } + tableEntry.setIndex(0); + tableEntry.setParent(this); + this.mTableEntry = tableEntry; + onTableEntryAdded(); + } + private void onTableEntryAdded(){ + PackageBlock packageBlock = getPackageBlock(); + if(packageBlock!=null){ + packageBlock.onEntryAdded(this); + } + } + private void onTableEntryRemoved(){ + TableEntry exist = this.mTableEntry; + if(exist == null){ + return; + } + PackageBlock packageBlock = getPackageBlock(); + if(packageBlock!=null){ + packageBlock.removeEntryGroup(this); + } + exist.onRemoved(); + exist.setIndex(-1); + exist.setParent(null); + this.mTableEntry = null; + } + private TableEntry createTableEntry(BlockReader reader) throws IOException { + int startPosition = reader.getPosition(); + reader.offset(2); + boolean is_complex = (0x0001 & reader.readShort()) == 0x0001; + reader.seek(startPosition); + return createTableEntry(is_complex); + } + private TableEntry createTableEntry(boolean is_complex) { + if(is_complex){ + return new ResTableMapEntry(); + }else { + return new ResTableEntry(); + } + } - @Override - public JSONObject toJson() { - if(isNull()){ - return null; - } - return getTableEntry().toJson(); - } - @Override - public void fromJson(JSONObject json) { - if(json==null){ - setNull(true); - return; - } - boolean is_complex = json.optBoolean(ValueHeader.NAME_is_complex, false); - TableEntry entry = createTableEntry(is_complex); - setTableEntry(entry); - entry.fromJson(json); - } + @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()); - } + 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()); + } - public String buildResourceName(int resourceId, char prefix, boolean includeType){ - if(resourceId==0){ - return null; - } - Entry entry=searchEntry(resourceId); - return buildResourceName(entry, prefix, includeType); - } - public String buildResourceName(Entry entry, char prefix, boolean includeType){ - if(entry==null){ - return null; - } - String pkgName=entry.getPackageName(); - if(getResourceId()==entry.getResourceId()){ - pkgName=null; - }else if(pkgName!=null){ - if(pkgName.equals(this.getPackageName())){ - pkgName=null; - } - } - String type=null; - if(includeType){ - type=entry.getTypeName(); - } - String name=entry.getName(); - return buildResourceName(prefix, pkgName, type, name); - } - public String getResourceName(){ - return buildResourceName('@',null, getTypeName(), getName()); - } - public String getResourceName(char prefix){ - return getResourceName(prefix, false, true); - } - public String getResourceName(char prefix, boolean includePackage, boolean includeType){ - String pkg=includePackage?getPackageName():null; - String type=includeType?getTypeName():null; - return buildResourceName(prefix,pkg, type, getName()); - } + public String buildResourceName(int resourceId, char prefix, boolean includeType){ + if(resourceId==0){ + return null; + } + Entry entry=searchEntry(resourceId); + return buildResourceName(entry, prefix, includeType); + } + public String buildResourceName(Entry entry, char prefix, boolean includeType){ + if(entry==null){ + return null; + } + String pkgName=entry.getPackageName(); + if(getResourceId()==entry.getResourceId()){ + pkgName=null; + }else if(pkgName!=null){ + if(pkgName.equals(this.getPackageName())){ + pkgName=null; + } + } + String type=null; + if(includeType){ + type=entry.getTypeName(); + } + String name=entry.getName(); + return buildResourceName(prefix, pkgName, type, name); + } + public String getResourceName(){ + return buildResourceName('@',null, getTypeName(), getName()); + } + public String getResourceName(char prefix){ + return getResourceName(prefix, false, true); + } + public String getResourceName(char prefix, boolean includePackage, boolean includeType){ + String pkg=includePackage?getPackageName():null; + String type=includeType?getTypeName():null; + return buildResourceName(prefix,pkg, type, getName()); + } - @Override - public String toString(){ - StringBuilder builder = new StringBuilder(); - builder.append(String.format("0x%08x", getResourceId())); - builder.append(' '); - ResConfig resConfig = getResConfig(); - if(resConfig!=null){ - builder.append(resConfig); - builder.append(' '); - } - SpecFlag specFlag = getSpecFlag(); - if(specFlag!=null){ - builder.append(specFlag); - builder.append(' '); - } - if(isNull()){ - builder.append("NULL"); - return builder.toString(); - } - builder.append('@'); - builder.append(getTypeName()); - builder.append('/'); - builder.append(getName()); - return builder.toString(); - } + @Override + public String toString(){ + StringBuilder builder = new StringBuilder(); + builder.append(String.format("0x%08x", getResourceId())); + builder.append(' '); + ResConfig resConfig = getResConfig(); + if(resConfig!=null){ + builder.append(resConfig); + builder.append(' '); + } + SpecFlag specFlag = getSpecFlag(); + if(specFlag!=null){ + builder.append(specFlag); + builder.append(' '); + } + if(isNull()){ + builder.append("NULL"); + return builder.toString(); + } + builder.append('@'); + builder.append(getTypeName()); + builder.append('/'); + builder.append(getName()); + return builder.toString(); + } - public static String buildResourceName(char prefix, String packageName, String type, String name){ - if(name==null){ - return null; - } - StringBuilder builder=new StringBuilder(); - if(prefix!=0){ - builder.append(prefix); - } - if(packageName!=null){ - builder.append(packageName); - builder.append(':'); - } - if(type!=null){ - builder.append(type); - builder.append('/'); - } - builder.append(name); - return builder.toString(); - } + public static String buildResourceName(char prefix, String packageName, String type, String name){ + if(name==null){ + return null; + } + StringBuilder builder=new StringBuilder(); + if(prefix!=0){ + builder.append(prefix); + } + if(packageName!=null){ + builder.append(packageName); + builder.append(':'); + } + if(type!=null){ + builder.append(type); + builder.append('/'); + } + builder.append(name); + return builder.toString(); + } - public static final String NAME_id = "id"; - } + public static final String NAME_id = "id"; +} diff --git a/src/main/java/com/reandroid/arsc/value/SparseTypeEntry.java b/src/main/java/com/reandroid/arsc/value/SparseTypeEntry.java deleted file mode 100644 index 0a3d893..0000000 --- a/src/main/java/com/reandroid/arsc/value/SparseTypeEntry.java +++ /dev/null @@ -1,40 +0,0 @@ - /* - * Copyright (C) 2022 github.com/REAndroid - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.reandroid.arsc.value; - -import com.reandroid.arsc.item.BlockItem; - -public class SparseTypeEntry extends BlockItem { - public SparseTypeEntry() { - super(4); - } - public int getIdx(){ - return getShort(getBytesInternal(), 0) & 0xffff; - } - public void setIdx(int idx){ - putShort(getBytesInternal(), 0, (short) idx); - } - public int getOffset(){ - return getShort(getBytesInternal(), 2) & 0xffff; - } - public void setOffset(int offset){ - putShort(getBytesInternal(), 2, (short) offset); - } - @Override - public String toString(){ - return "idx=" + getIdx() + ", offset=" + getOffset(); - } -}