mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-29 22:04:25 +02:00
better hex conversion
This commit is contained in:
parent
1b240b2281
commit
f5ec1381a4
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.apk;
|
package com.reandroid.apk;
|
||||||
|
|
||||||
import com.reandroid.archive.InputSource;
|
import com.reandroid.archive.InputSource;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -148,7 +149,7 @@ public class PathSanitizer {
|
|||||||
}
|
}
|
||||||
private static String createUniqueName(String name){
|
private static String createUniqueName(String name){
|
||||||
int hash = name.hashCode();
|
int hash = name.hashCode();
|
||||||
return String.format("alias_%08x", hash).toLowerCase();
|
return "alias_" + HexUtil.toHexNoPrefix8(hash);
|
||||||
}
|
}
|
||||||
private static boolean isGoodSimpleName(String name){
|
private static boolean isGoodSimpleName(String name){
|
||||||
if(name==null){
|
if(name==null){
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,6 +19,7 @@ import com.reandroid.arsc.chunk.PackageBlock;
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.util.ResNameMap;
|
import com.reandroid.arsc.util.ResNameMap;
|
||||||
import com.reandroid.json.JSONArray;
|
import com.reandroid.json.JSONArray;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
@ -379,7 +380,7 @@ import java.util.*;
|
|||||||
type.add(entry);
|
type.add(entry);
|
||||||
}
|
}
|
||||||
public String getHexId(){
|
public String getHexId(){
|
||||||
return String.format("0x%02x", id);
|
return HexUtil.toHex2(id);
|
||||||
}
|
}
|
||||||
public JSONObject toJson(){
|
public JSONObject toJson(){
|
||||||
JSONObject jsonObject=new JSONObject();
|
JSONObject jsonObject=new JSONObject();
|
||||||
@ -575,7 +576,7 @@ import java.util.*;
|
|||||||
return entryMap.get(entryId);
|
return entryMap.get(entryId);
|
||||||
}
|
}
|
||||||
public String getHexId(){
|
public String getHexId(){
|
||||||
return String.format("0x%02x", id);
|
return HexUtil.toHex2(id);
|
||||||
}
|
}
|
||||||
public void add(Entry entry){
|
public void add(Entry entry){
|
||||||
if(entry==null){
|
if(entry==null){
|
||||||
@ -733,7 +734,7 @@ import java.util.*;
|
|||||||
| (getEntryId() & 0xffff);
|
| (getEntryId() & 0xffff);
|
||||||
}
|
}
|
||||||
public String getHexId(){
|
public String getHexId(){
|
||||||
return String.format("0x%08x", getResourceId());
|
return HexUtil.toHex8(getResourceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeXml(String indent, Writer writer) throws IOException{
|
public void writeXml(String indent, Writer writer) throws IOException{
|
||||||
|
@ -21,6 +21,7 @@ import com.reandroid.arsc.chunk.StagedAlias;
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
import com.reandroid.arsc.chunk.TypeBlock;
|
||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -73,7 +74,7 @@ public class TableBlockJson {
|
|||||||
private String getFileName(TypeBlock typeBlock){
|
private String getFileName(TypeBlock typeBlock){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(String.format("%03d-", typeBlock.getIndex()));
|
builder.append(String.format("%03d-", typeBlock.getIndex()));
|
||||||
builder.append(String.format("0x%02x", typeBlock.getTypeId()));
|
builder.append(HexUtil.toHex2(typeBlock.getTypeId()));
|
||||||
String name= typeBlock.getTypeName();
|
String name= typeBlock.getTypeName();
|
||||||
builder.append('-').append(name);
|
builder.append('-').append(name);
|
||||||
builder.append(typeBlock.getResConfig().getQualifiers());
|
builder.append(typeBlock.getResConfig().getQualifiers());
|
||||||
@ -81,7 +82,7 @@ public class TableBlockJson {
|
|||||||
}
|
}
|
||||||
private String getDirName(PackageBlock packageBlock){
|
private String getDirName(PackageBlock packageBlock){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(String.format("0x%02x", packageBlock.getId()));
|
builder.append(HexUtil.toHex2((byte) packageBlock.getId()));
|
||||||
builder.append("-");
|
builder.append("-");
|
||||||
builder.append(packageBlock.getIndex());
|
builder.append(packageBlock.getIndex());
|
||||||
String name= ApkUtil.sanitizeForFileName(packageBlock.getName());
|
String name= ApkUtil.sanitizeForFileName(packageBlock.getName());
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.apk.xmldecoder;
|
package com.reandroid.apk.xmldecoder;
|
||||||
|
|
||||||
import com.reandroid.apk.XmlHelper;
|
import com.reandroid.apk.XmlHelper;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResTableMapEntry;
|
import com.reandroid.arsc.value.ResTableMapEntry;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
@ -58,7 +59,7 @@ class BagDecoderAttr<OUTPUT> extends BagDecoder<OUTPUT>{
|
|||||||
int rawVal = item.getData();
|
int rawVal = item.getData();
|
||||||
String value;
|
String value;
|
||||||
if(item.getBagItem().getValueType() == ValueType.INT_HEX){
|
if(item.getBagItem().getValueType() == ValueType.INT_HEX){
|
||||||
value = String.format("0x%08x", rawVal);
|
value = HexUtil.toHex8(rawVal);
|
||||||
}else {
|
}else {
|
||||||
value = String.valueOf(rawVal);
|
value = String.valueOf(rawVal);
|
||||||
}
|
}
|
||||||
|
@ -1,359 +1,360 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.apk.xmlencoder;
|
package com.reandroid.apk.xmlencoder;
|
||||||
|
|
||||||
import com.reandroid.apk.APKLogger;
|
import com.reandroid.apk.APKLogger;
|
||||||
import com.reandroid.apk.FrameworkApk;
|
import com.reandroid.apk.FrameworkApk;
|
||||||
import com.reandroid.apk.ResourceIds;
|
import com.reandroid.apk.ResourceIds;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.chunk.TypeBlock;
|
import com.reandroid.arsc.chunk.TypeBlock;
|
||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.item.SpecString;
|
import com.reandroid.arsc.item.SpecString;
|
||||||
import com.reandroid.arsc.util.FrameworkTable;
|
import com.reandroid.arsc.util.FrameworkTable;
|
||||||
import com.reandroid.arsc.util.ResNameMap;
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.util.ResNameMap;
|
||||||
import com.reandroid.common.Frameworks;
|
import com.reandroid.arsc.value.Entry;
|
||||||
|
import com.reandroid.common.Frameworks;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
public class EncodeMaterials {
|
public class EncodeMaterials {
|
||||||
private final Set<ResourceIds.Table.Package> packageIdSet = new HashSet<>();
|
private final Set<ResourceIds.Table.Package> packageIdSet = new HashSet<>();
|
||||||
private PackageBlock currentPackage;
|
private PackageBlock currentPackage;
|
||||||
private final Set<FrameworkTable> frameworkTables = new HashSet<>();
|
private final Set<FrameworkTable> frameworkTables = new HashSet<>();
|
||||||
private APKLogger apkLogger;
|
private APKLogger apkLogger;
|
||||||
private boolean mForceCreateNamespaces = true;
|
private boolean mForceCreateNamespaces = true;
|
||||||
private Set<String> mFrameworkPackageNames;
|
private Set<String> mFrameworkPackageNames;
|
||||||
private final ResNameMap<Entry> mLocalResNameMap = new ResNameMap<>();
|
private final ResNameMap<Entry> mLocalResNameMap = new ResNameMap<>();
|
||||||
public EncodeMaterials(){
|
public EncodeMaterials(){
|
||||||
}
|
}
|
||||||
public SpecString getSpecString(String name){
|
public SpecString getSpecString(String name){
|
||||||
return currentPackage.getSpecStringPool()
|
return currentPackage.getSpecStringPool()
|
||||||
.get(name)
|
.get(name)
|
||||||
.get(0);
|
.get(0);
|
||||||
}
|
}
|
||||||
public Entry getAttributeBlock(String refString){
|
public Entry getAttributeBlock(String refString){
|
||||||
String type = "attr";
|
String type = "attr";
|
||||||
Entry entry = getAttributeBlock(type, refString);
|
Entry entry = getAttributeBlock(type, refString);
|
||||||
if(entry == null){
|
if(entry == null){
|
||||||
type = "^attr-private";
|
type = "^attr-private";
|
||||||
entry = getAttributeBlock(type, refString);
|
entry = getAttributeBlock(type, refString);
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
private Entry getAttributeBlock(String type, String refString){
|
private Entry getAttributeBlock(String type, String refString){
|
||||||
String packageName = null;
|
String packageName = null;
|
||||||
String name = refString;
|
String name = refString;
|
||||||
int i=refString.lastIndexOf(':');
|
int i=refString.lastIndexOf(':');
|
||||||
if(i>=0){
|
if(i>=0){
|
||||||
packageName=refString.substring(0, i);
|
packageName=refString.substring(0, i);
|
||||||
name=refString.substring(i+1);
|
name=refString.substring(i+1);
|
||||||
}
|
}
|
||||||
if(EncodeUtil.isEmpty(packageName)
|
if(EncodeUtil.isEmpty(packageName)
|
||||||
|| packageName.equals(getCurrentPackageName())
|
|| packageName.equals(getCurrentPackageName())
|
||||||
|| !isFrameworkPackageName(packageName)){
|
|| !isFrameworkPackageName(packageName)){
|
||||||
|
|
||||||
return getLocalEntry(type, name);
|
return getLocalEntry(type, name);
|
||||||
}
|
}
|
||||||
return getFrameworkEntry(type, name);
|
return getFrameworkEntry(type, name);
|
||||||
}
|
}
|
||||||
public int resolveReference(String refString){
|
public int resolveReference(String refString){
|
||||||
if("@null".equals(refString)){
|
if("@null".equals(refString)){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Matcher matcher = ValueDecoder.PATTERN_REFERENCE.matcher(refString);
|
Matcher matcher = ValueDecoder.PATTERN_REFERENCE.matcher(refString);
|
||||||
if(!matcher.find()){
|
if(!matcher.find()){
|
||||||
ValueDecoder.EncodeResult ref = ValueDecoder.encodeHexReference(refString);
|
ValueDecoder.EncodeResult ref = ValueDecoder.encodeHexReference(refString);
|
||||||
if(ref!=null){
|
if(ref!=null){
|
||||||
return ref.value;
|
return ref.value;
|
||||||
}
|
}
|
||||||
ref = ValueDecoder.encodeNullReference(refString);
|
ref = ValueDecoder.encodeNullReference(refString);
|
||||||
if(ref!=null){
|
if(ref!=null){
|
||||||
return ref.value;
|
return ref.value;
|
||||||
}
|
}
|
||||||
throw new EncodeException(
|
throw new EncodeException(
|
||||||
"Not proper reference string: '"+refString+"'");
|
"Not proper reference string: '"+refString+"'");
|
||||||
}
|
}
|
||||||
String prefix=matcher.group(1);
|
String prefix=matcher.group(1);
|
||||||
String packageName = matcher.group(2);
|
String packageName = matcher.group(2);
|
||||||
if(packageName!=null && packageName.endsWith(":")){
|
if(packageName!=null && packageName.endsWith(":")){
|
||||||
packageName=packageName.substring(0, packageName.length()-1);
|
packageName=packageName.substring(0, packageName.length()-1);
|
||||||
}
|
}
|
||||||
String type = matcher.group(4);
|
String type = matcher.group(4);
|
||||||
String name = matcher.group(5);
|
String name = matcher.group(5);
|
||||||
if(EncodeUtil.isEmpty(packageName)
|
if(EncodeUtil.isEmpty(packageName)
|
||||||
|| packageName.equals(getCurrentPackageName())
|
|| packageName.equals(getCurrentPackageName())
|
||||||
|| !isFrameworkPackageName(packageName)){
|
|| !isFrameworkPackageName(packageName)){
|
||||||
return resolveLocalResourceId(type, name);
|
return resolveLocalResourceId(type, name);
|
||||||
}
|
}
|
||||||
return resolveFrameworkResourceId(packageName, type, name);
|
return resolveFrameworkResourceId(packageName, type, name);
|
||||||
}
|
}
|
||||||
public int resolveLocalResourceId(String type, String name){
|
public int resolveLocalResourceId(String type, String name){
|
||||||
for(ResourceIds.Table.Package pkg:packageIdSet){
|
for(ResourceIds.Table.Package pkg:packageIdSet){
|
||||||
Integer resId = pkg.getResourceId(type, name);
|
Integer resId = pkg.getResourceId(type, name);
|
||||||
if(resId!=null){
|
if(resId!=null){
|
||||||
return resId;
|
return resId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EntryGroup entryGroup=getLocalEntryGroup(type, name);
|
EntryGroup entryGroup=getLocalEntryGroup(type, name);
|
||||||
if(entryGroup!=null){
|
if(entryGroup!=null){
|
||||||
return entryGroup.getResourceId();
|
return entryGroup.getResourceId();
|
||||||
}
|
}
|
||||||
throw new EncodeException("Local entry not found: " +
|
throw new EncodeException("Local entry not found: " +
|
||||||
"type="+type+
|
"type="+type+
|
||||||
", name="+name);
|
", name="+name);
|
||||||
}
|
}
|
||||||
public int resolveFrameworkResourceId(String packageName, String type, String name){
|
public int resolveFrameworkResourceId(String packageName, String type, String name){
|
||||||
Entry entry = getFrameworkEntry(packageName, type, name);
|
Entry entry = getFrameworkEntry(packageName, type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry.getResourceId();
|
return entry.getResourceId();
|
||||||
}
|
}
|
||||||
throw new EncodeException("Framework entry not found: " +
|
throw new EncodeException("Framework entry not found: " +
|
||||||
"package="+packageName+
|
"package="+packageName+
|
||||||
", type="+type+
|
", type="+type+
|
||||||
", name="+name);
|
", name="+name);
|
||||||
}
|
}
|
||||||
public int resolveFrameworkResourceId(int packageId, String type, String name){
|
public int resolveFrameworkResourceId(int packageId, String type, String name){
|
||||||
Entry entry = getFrameworkEntry(packageId, type, name);
|
Entry entry = getFrameworkEntry(packageId, type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry.getResourceId();
|
return entry.getResourceId();
|
||||||
}
|
}
|
||||||
throw new EncodeException("Framework entry not found: " +
|
throw new EncodeException("Framework entry not found: " +
|
||||||
"packageId="+String.format("0x%02x", packageId)+
|
"packageId=" + HexUtil.toHex2((byte) packageId)+
|
||||||
", type="+type+
|
", type="+type+
|
||||||
", name="+name);
|
", name="+name);
|
||||||
}
|
}
|
||||||
public EntryGroup getLocalEntryGroup(String type, String name){
|
public EntryGroup getLocalEntryGroup(String type, String name){
|
||||||
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
||||||
if(type.equals(entryGroup.getTypeName()) &&
|
if(type.equals(entryGroup.getTypeName()) &&
|
||||||
name.equals(entryGroup.getSpecName())){
|
name.equals(entryGroup.getSpecName())){
|
||||||
return entryGroup;
|
return entryGroup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
||||||
for(EntryGroup entryGroup : packageBlock.listEntryGroup()){
|
for(EntryGroup entryGroup : packageBlock.listEntryGroup()){
|
||||||
if(type.equals(entryGroup.getTypeName()) &&
|
if(type.equals(entryGroup.getTypeName()) &&
|
||||||
name.equals(entryGroup.getSpecName())){
|
name.equals(entryGroup.getSpecName())){
|
||||||
return entryGroup;
|
return entryGroup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public Entry getLocalEntry(String type, String name){
|
public Entry getLocalEntry(String type, String name){
|
||||||
Entry entry =mLocalResNameMap.get(type, name);
|
Entry entry =mLocalResNameMap.get(type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
loadLocalEntryMap(type);
|
loadLocalEntryMap(type);
|
||||||
entry =mLocalResNameMap.get(type, name);
|
entry =mLocalResNameMap.get(type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
entry = searchLocalEntry(type, name);
|
entry = searchLocalEntry(type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
mLocalResNameMap.add(type, name, entry);
|
mLocalResNameMap.add(type, name, entry);
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
private Entry searchLocalEntry(String type, String name){
|
private Entry searchLocalEntry(String type, String name){
|
||||||
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
for(EntryGroup entryGroup : currentPackage.listEntryGroup()){
|
||||||
if(type.equals(entryGroup.getTypeName()) &&
|
if(type.equals(entryGroup.getTypeName()) &&
|
||||||
name.equals(entryGroup.getSpecName())){
|
name.equals(entryGroup.getSpecName())){
|
||||||
return entryGroup.pickOne();
|
return entryGroup.pickOne();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpecTypePair specTypePair=currentPackage.searchByTypeName(type);
|
SpecTypePair specTypePair=currentPackage.searchByTypeName(type);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||||
for(Entry entry :typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
if(name.equals(entry.getName())){
|
if(name.equals(entry.getName())){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
||||||
if(packageBlock==currentPackage){
|
if(packageBlock==currentPackage){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
specTypePair=packageBlock.searchByTypeName(type);
|
specTypePair=packageBlock.searchByTypeName(type);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||||
for(Entry entry :typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
if(name.equals(entry.getName())){
|
if(name.equals(entry.getName())){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private void loadLocalEntryMap(String type){
|
private void loadLocalEntryMap(String type){
|
||||||
ResNameMap<Entry> localMap = mLocalResNameMap;
|
ResNameMap<Entry> localMap = mLocalResNameMap;
|
||||||
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
for(PackageBlock packageBlock:currentPackage.getTableBlock().listPackages()){
|
||||||
SpecTypePair specTypePair=packageBlock.searchByTypeName(type);
|
SpecTypePair specTypePair=packageBlock.searchByTypeName(type);
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
for(TypeBlock typeBlock:specTypePair.listTypeBlocks()){
|
||||||
for(Entry entry :typeBlock.listEntries(true)){
|
for(Entry entry :typeBlock.listEntries(true)){
|
||||||
localMap.add(entry.getTypeName(),
|
localMap.add(entry.getTypeName(),
|
||||||
entry.getName(), entry);
|
entry.getName(), entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Entry getFrameworkEntry(String type, String name){
|
public Entry getFrameworkEntry(String type, String name){
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
Entry entry = table.searchEntry(type, name);
|
Entry entry = table.searchEntry(type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private boolean isFrameworkPackageName(String packageName){
|
private boolean isFrameworkPackageName(String packageName){
|
||||||
return getFrameworkPackageNames().contains(packageName);
|
return getFrameworkPackageNames().contains(packageName);
|
||||||
}
|
}
|
||||||
private Set<String> getFrameworkPackageNames(){
|
private Set<String> getFrameworkPackageNames(){
|
||||||
if(mFrameworkPackageNames!=null){
|
if(mFrameworkPackageNames!=null){
|
||||||
return mFrameworkPackageNames;
|
return mFrameworkPackageNames;
|
||||||
}
|
}
|
||||||
Set<String> results=new HashSet<>();
|
Set<String> results=new HashSet<>();
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
for(PackageBlock packageBlock:table.listPackages()){
|
for(PackageBlock packageBlock:table.listPackages()){
|
||||||
results.add(packageBlock.getName());
|
results.add(packageBlock.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mFrameworkPackageNames=results;
|
mFrameworkPackageNames=results;
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
public Entry getFrameworkEntry(String packageName, String type, String name){
|
public Entry getFrameworkEntry(String packageName, String type, String name){
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
for(PackageBlock packageBlock:table.listPackages()){
|
for(PackageBlock packageBlock:table.listPackages()){
|
||||||
if(packageName.equals(packageBlock.getName())){
|
if(packageName.equals(packageBlock.getName())){
|
||||||
Entry entry = table.searchEntry(type, name);
|
Entry entry = table.searchEntry(type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public Entry getFrameworkEntry(int packageId, String type, String name){
|
public Entry getFrameworkEntry(int packageId, String type, String name){
|
||||||
for(FrameworkTable table:frameworkTables){
|
for(FrameworkTable table:frameworkTables){
|
||||||
for(PackageBlock packageBlock:table.listPackages()){
|
for(PackageBlock packageBlock:table.listPackages()){
|
||||||
if(packageId==packageBlock.getId()){
|
if(packageId==packageBlock.getId()){
|
||||||
Entry entry = table.searchEntry(type, name);
|
Entry entry = table.searchEntry(type, name);
|
||||||
if(entry !=null){
|
if(entry !=null){
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public EncodeMaterials setForceCreateNamespaces(boolean force) {
|
public EncodeMaterials setForceCreateNamespaces(boolean force) {
|
||||||
this.mForceCreateNamespaces = force;
|
this.mForceCreateNamespaces = force;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public EncodeMaterials addPackageIds(ResourceIds.Table.Package packageIds) {
|
public EncodeMaterials addPackageIds(ResourceIds.Table.Package packageIds) {
|
||||||
packageIds.loadEntryMap();
|
packageIds.loadEntryMap();
|
||||||
this.packageIdSet.add(packageIds);
|
this.packageIdSet.add(packageIds);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public EncodeMaterials setCurrentPackage(PackageBlock currentPackage) {
|
public EncodeMaterials setCurrentPackage(PackageBlock currentPackage) {
|
||||||
this.currentPackage = currentPackage;
|
this.currentPackage = currentPackage;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public EncodeMaterials addFramework(FrameworkApk frameworkApk) {
|
public EncodeMaterials addFramework(FrameworkApk frameworkApk) {
|
||||||
if(frameworkApk!=null){
|
if(frameworkApk!=null){
|
||||||
addFramework(frameworkApk.getTableBlock());
|
addFramework(frameworkApk.getTableBlock());
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public EncodeMaterials addFramework(FrameworkTable frameworkTable) {
|
public EncodeMaterials addFramework(FrameworkTable frameworkTable) {
|
||||||
frameworkTable.loadResourceNameMap();
|
frameworkTable.loadResourceNameMap();
|
||||||
this.frameworkTables.add(frameworkTable);
|
this.frameworkTables.add(frameworkTable);
|
||||||
this.mFrameworkPackageNames=null;
|
this.mFrameworkPackageNames=null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public EncodeMaterials setAPKLogger(APKLogger logger) {
|
public EncodeMaterials setAPKLogger(APKLogger logger) {
|
||||||
this.apkLogger = logger;
|
this.apkLogger = logger;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageBlock getCurrentPackage() {
|
public PackageBlock getCurrentPackage() {
|
||||||
return currentPackage;
|
return currentPackage;
|
||||||
}
|
}
|
||||||
public boolean isForceCreateNamespaces() {
|
public boolean isForceCreateNamespaces() {
|
||||||
return mForceCreateNamespaces;
|
return mForceCreateNamespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrentPackageName(){
|
public String getCurrentPackageName(){
|
||||||
return currentPackage.getName();
|
return currentPackage.getName();
|
||||||
}
|
}
|
||||||
public int getCurrentPackageId(){
|
public int getCurrentPackageId(){
|
||||||
return currentPackage.getId();
|
return currentPackage.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logMessage(String msg) {
|
public void logMessage(String msg) {
|
||||||
if(apkLogger!=null){
|
if(apkLogger!=null){
|
||||||
apkLogger.logMessage(msg);
|
apkLogger.logMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void logError(String msg, Throwable tr) {
|
public void logError(String msg, Throwable tr) {
|
||||||
if(apkLogger!=null){
|
if(apkLogger!=null){
|
||||||
apkLogger.logError(msg, tr);
|
apkLogger.logError(msg, tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void logVerbose(String msg) {
|
public void logVerbose(String msg) {
|
||||||
if(apkLogger!=null){
|
if(apkLogger!=null){
|
||||||
apkLogger.logVerbose(msg);
|
apkLogger.logVerbose(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static EncodeMaterials create(TableBlock tableBlock){
|
public static EncodeMaterials create(TableBlock tableBlock){
|
||||||
PackageBlock packageBlock = tableBlock.pickOne();
|
PackageBlock packageBlock = tableBlock.pickOne();
|
||||||
if(packageBlock==null){
|
if(packageBlock==null){
|
||||||
throw new EncodeException("No packages found on table block");
|
throw new EncodeException("No packages found on table block");
|
||||||
}
|
}
|
||||||
return create(packageBlock);
|
return create(packageBlock);
|
||||||
}
|
}
|
||||||
public static EncodeMaterials create(PackageBlock packageBlock){
|
public static EncodeMaterials create(PackageBlock packageBlock){
|
||||||
ResourceIds resourceIds = new ResourceIds();
|
ResourceIds resourceIds = new ResourceIds();
|
||||||
resourceIds.loadPackageBlock(packageBlock);
|
resourceIds.loadPackageBlock(packageBlock);
|
||||||
ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0);
|
ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0);
|
||||||
EncodeMaterials encodeMaterials = new EncodeMaterials()
|
EncodeMaterials encodeMaterials = new EncodeMaterials()
|
||||||
.addPackageIds(packageId)
|
.addPackageIds(packageId)
|
||||||
.setCurrentPackage(packageBlock);
|
.setCurrentPackage(packageBlock);
|
||||||
TableBlock tableBlock = packageBlock.getTableBlock();
|
TableBlock tableBlock = packageBlock.getTableBlock();
|
||||||
for(TableBlock frameworkTable:tableBlock.getFrameWorks()){
|
for(TableBlock frameworkTable:tableBlock.getFrameWorks()){
|
||||||
if(frameworkTable instanceof FrameworkTable){
|
if(frameworkTable instanceof FrameworkTable){
|
||||||
encodeMaterials.addFramework((FrameworkTable) frameworkTable);
|
encodeMaterials.addFramework((FrameworkTable) frameworkTable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return encodeMaterials;
|
return encodeMaterials;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package com.reandroid.archive2;
|
|||||||
|
|
||||||
import com.reandroid.archive2.block.CentralEntryHeader;
|
import com.reandroid.archive2.block.CentralEntryHeader;
|
||||||
import com.reandroid.archive2.block.LocalFileHeader;
|
import com.reandroid.archive2.block.LocalFileHeader;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
@ -116,6 +117,7 @@ public class ArchiveEntry extends ZipEntry {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "["+ getFileOffset()+"] "+getName()+getComment()+String.format(" 0x%08x", getCrc());
|
return "["+ getFileOffset()+"] " + getName() + getComment()
|
||||||
|
+ HexUtil.toHex(" 0x", getCrc(), 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.archive2.block;
|
package com.reandroid.archive2.block;
|
||||||
|
|
||||||
import com.reandroid.archive2.ZipSignature;
|
import com.reandroid.archive2.ZipSignature;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -134,12 +135,12 @@ public class CentralEntryHeader extends CommonHeader {
|
|||||||
builder.append(", ");
|
builder.append(", ");
|
||||||
}
|
}
|
||||||
builder.append("SIG=").append(getSignature());
|
builder.append("SIG=").append(getSignature());
|
||||||
builder.append(", versionMadeBy=").append(String.format("0x%04x", getVersionMadeBy()));
|
builder.append(", versionMadeBy=").append(HexUtil.toHex4((short) getVersionMadeBy()));
|
||||||
builder.append(", versionExtract=").append(String.format("0x%04x", getVersionExtract()));
|
builder.append(", versionExtract=").append(HexUtil.toHex4((short) getVersionExtract()));
|
||||||
builder.append(", GP={").append(getGeneralPurposeFlag()).append("}");
|
builder.append(", GP={").append(getGeneralPurposeFlag()).append("}");
|
||||||
builder.append(", method=").append(getMethod());
|
builder.append(", method=").append(getMethod());
|
||||||
builder.append(", date=").append(getDate());
|
builder.append(", date=").append(getDate());
|
||||||
builder.append(", crc=").append(String.format("0x%08x", getCrc()));
|
builder.append(", crc=").append(HexUtil.toHex8(getCrc()));
|
||||||
builder.append(", cSize=").append(getCompressedSize());
|
builder.append(", cSize=").append(getCompressedSize());
|
||||||
builder.append(", size=").append(getSize());
|
builder.append(", size=").append(getSize());
|
||||||
builder.append(", fileNameLength=").append(getFileNameLength());
|
builder.append(", fileNameLength=").append(getFileNameLength());
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.archive2.block;
|
package com.reandroid.archive2.block;
|
||||||
|
|
||||||
import com.reandroid.archive2.ZipSignature;
|
import com.reandroid.archive2.ZipSignature;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -287,12 +288,12 @@ public abstract class CommonHeader extends ZipHeader {
|
|||||||
builder.append(", ");
|
builder.append(", ");
|
||||||
}
|
}
|
||||||
builder.append("SIG=").append(getSignature());
|
builder.append("SIG=").append(getSignature());
|
||||||
builder.append(", versionMadeBy=").append(String.format("0x%04x", getVersionMadeBy()));
|
builder.append(", versionMadeBy=").append(HexUtil.toHex4((short) getVersionMadeBy()));
|
||||||
builder.append(", platform=").append(String.format("0x%02x", getPlatform()));
|
builder.append(", platform=").append(HexUtil.toHex2((byte) getPlatform()));
|
||||||
builder.append(", GP={").append(getGeneralPurposeFlag()).append("}");
|
builder.append(", GP={").append(getGeneralPurposeFlag()).append("}");
|
||||||
builder.append(", method=").append(getMethod());
|
builder.append(", method=").append(getMethod());
|
||||||
builder.append(", date=").append(getDate());
|
builder.append(", date=").append(getDate());
|
||||||
builder.append(", crc=").append(String.format("0x%08x", getCrc()));
|
builder.append(", crc=").append(HexUtil.toHex8(getCrc()));
|
||||||
builder.append(", cSize=").append(getCompressedSize());
|
builder.append(", cSize=").append(getCompressedSize());
|
||||||
builder.append(", size=").append(getSize());
|
builder.append(", size=").append(getSize());
|
||||||
builder.append(", fileNameLength=").append(getFileNameLength());
|
builder.append(", fileNameLength=").append(getFileNameLength());
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.archive2.block;
|
package com.reandroid.archive2.block;
|
||||||
|
|
||||||
import com.reandroid.archive2.ZipSignature;
|
import com.reandroid.archive2.ZipSignature;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
public class DataDescriptor extends ZipHeader{
|
public class DataDescriptor extends ZipHeader{
|
||||||
public DataDescriptor() {
|
public DataDescriptor() {
|
||||||
@ -44,7 +45,7 @@ public class DataDescriptor extends ZipHeader{
|
|||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append(getSignature());
|
builder.append(getSignature());
|
||||||
builder.append(", crc=").append(String.format("0x%08x", getCrc()));
|
builder.append(", crc=").append(HexUtil.toHex8(getCrc()));
|
||||||
builder.append(", compressed=").append(getCompressedSize());
|
builder.append(", compressed=").append(getCompressedSize());
|
||||||
builder.append(", size=").append(getSize());
|
builder.append(", size=").append(getSize());
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.archive2.block;
|
package com.reandroid.archive2.block;
|
||||||
|
|
||||||
import com.reandroid.archive2.ZipSignature;
|
import com.reandroid.archive2.ZipSignature;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
public class EndRecord extends ZipHeader{
|
public class EndRecord extends ZipHeader{
|
||||||
public EndRecord() {
|
public EndRecord() {
|
||||||
@ -78,7 +79,7 @@ public class EndRecord extends ZipHeader{
|
|||||||
builder.append(", total dirs=").append(getTotalNumberOfDirectories());
|
builder.append(", total dirs=").append(getTotalNumberOfDirectories());
|
||||||
builder.append(", length=").append(getLengthOfCentralDirectory());
|
builder.append(", length=").append(getLengthOfCentralDirectory());
|
||||||
builder.append(", offset=").append(getOffsetOfCentralDirectory());
|
builder.append(", offset=").append(getOffsetOfCentralDirectory());
|
||||||
builder.append(", last=").append(String.format("0x%08x", getLastShort()));
|
builder.append(", last=").append(HexUtil.toHex8(getLastShort()));
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.reandroid.archive2.block;
|
package com.reandroid.archive2.block;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ public class SignatureId implements Comparable<SignatureId>{
|
|||||||
if (this.name != null) {
|
if (this.name != null) {
|
||||||
return name + FILE_EXT_RAW;
|
return name + FILE_EXT_RAW;
|
||||||
}
|
}
|
||||||
return String.format("0x%08x", id) + FILE_EXT_RAW;
|
return HexUtil.toHex8(id) + FILE_EXT_RAW;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
@ -66,7 +67,7 @@ public class SignatureId implements Comparable<SignatureId>{
|
|||||||
if (name != null) {
|
if (name != null) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
return "UNKNOWN(" + String.format("0x%08x", id) + ")";
|
return "UNKNOWN(" + HexUtil.toHex8(id) + ")";
|
||||||
}
|
}
|
||||||
public static SignatureId valueOf(String name) {
|
public static SignatureId valueOf(String name) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.archive2.io;
|
package com.reandroid.archive2.io;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
@ -124,6 +126,6 @@ public class CountingInputStream<T extends InputStream> extends InputStream {
|
|||||||
if(!mFinished || crc==null){
|
if(!mFinished || crc==null){
|
||||||
return "[" + size + "]: " + inputStream.getClass().getSimpleName();
|
return "[" + size + "]: " + inputStream.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
return "[size=" + size +", crc=" + String.format("0x%08x", mCheckSum) + "]: " + inputStream.getClass().getSimpleName();
|
return "[size=" + size +", crc=" + HexUtil.toHex8(mCheckSum) + "]: " + inputStream.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.chunk;
|
package com.reandroid.arsc.chunk;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
public enum ChunkType {
|
public enum ChunkType {
|
||||||
NULL((short)0x0000),
|
NULL((short)0x0000),
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ public enum ChunkType {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return name()+String.format("(0x%04x)", ((int) ID));
|
return name() + "(" + HexUtil.toHex4(ID) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ChunkType get(short id){
|
public static ChunkType get(short id){
|
||||||
|
@ -29,6 +29,7 @@ import com.reandroid.arsc.list.StagedAliasList;
|
|||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.LibraryInfo;
|
import com.reandroid.arsc.value.LibraryInfo;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
@ -466,7 +467,7 @@ public class PackageBlock extends Chunk<PackageHeader>
|
|||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(super.toString());
|
builder.append(super.toString());
|
||||||
builder.append(", id=");
|
builder.append(", id=");
|
||||||
builder.append(String.format("0x%02x", getId()));
|
builder.append(HexUtil.toHex2((byte) getId()));
|
||||||
builder.append(", name=");
|
builder.append(", name=");
|
||||||
builder.append(getName());
|
builder.append(getName());
|
||||||
int libCount=getLibraryBlock().getLibraryCount();
|
int libCount=getLibraryBlock().getLibraryCount();
|
||||||
|
@ -1,162 +1,163 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.chunk;
|
package com.reandroid.arsc.chunk;
|
||||||
|
|
||||||
import com.reandroid.arsc.array.TypeBlockArray;
|
import com.reandroid.arsc.array.TypeBlockArray;
|
||||||
import com.reandroid.arsc.container.SpecTypePair;
|
import com.reandroid.arsc.container.SpecTypePair;
|
||||||
import com.reandroid.arsc.header.SpecHeader;
|
import com.reandroid.arsc.header.SpecHeader;
|
||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONConvert;
|
||||||
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SpecBlock extends Chunk<SpecHeader> implements JSONConvert<JSONObject> {
|
public class SpecBlock extends Chunk<SpecHeader> implements JSONConvert<JSONObject> {
|
||||||
private final SpecFlagsArray specFlagsArray;
|
private final SpecFlagsArray specFlagsArray;
|
||||||
public SpecBlock() {
|
public SpecBlock() {
|
||||||
super(new SpecHeader(), 1);
|
super(new SpecHeader(), 1);
|
||||||
SpecHeader header = getHeaderBlock();
|
SpecHeader header = getHeaderBlock();
|
||||||
this.specFlagsArray = new SpecFlagsArray(header.getEntryCount());
|
this.specFlagsArray = new SpecFlagsArray(header.getEntryCount());
|
||||||
addChild(specFlagsArray);
|
addChild(specFlagsArray);
|
||||||
}
|
}
|
||||||
public void destroy(){
|
public void destroy(){
|
||||||
setParent(null);
|
setParent(null);
|
||||||
getSpecFlagsArray().clear();
|
getSpecFlagsArray().clear();
|
||||||
}
|
}
|
||||||
public SpecFlag getSpecFlag(int id){
|
public SpecFlag getSpecFlag(int id){
|
||||||
return getSpecFlagsArray().getFlag(id);
|
return getSpecFlagsArray().getFlag(id);
|
||||||
}
|
}
|
||||||
public SpecFlagsArray getSpecFlagsArray(){
|
public SpecFlagsArray getSpecFlagsArray(){
|
||||||
return specFlagsArray;
|
return specFlagsArray;
|
||||||
}
|
}
|
||||||
public List<Integer> listSpecFlags(){
|
public List<Integer> listSpecFlags(){
|
||||||
return specFlagsArray.toList();
|
return specFlagsArray.toList();
|
||||||
}
|
}
|
||||||
public byte getTypeId(){
|
public byte getTypeId(){
|
||||||
return getHeaderBlock().getId().get();
|
return getHeaderBlock().getId().get();
|
||||||
}
|
}
|
||||||
public int getId(){
|
public int getId(){
|
||||||
return getHeaderBlock().getId().unsignedInt();
|
return getHeaderBlock().getId().unsignedInt();
|
||||||
}
|
}
|
||||||
public void setId(int id){
|
public void setId(int id){
|
||||||
setTypeId((byte) (0xff & id));
|
setTypeId((byte) (0xff & id));
|
||||||
}
|
}
|
||||||
public void setTypeId(byte id){
|
public void setTypeId(byte id){
|
||||||
getHeaderBlock().getId().set(id);
|
getHeaderBlock().getId().set(id);
|
||||||
getTypeBlockArray().setTypeId(id);
|
getTypeBlockArray().setTypeId(id);
|
||||||
}
|
}
|
||||||
public TypeBlockArray getTypeBlockArray(){
|
public TypeBlockArray getTypeBlockArray(){
|
||||||
SpecTypePair specTypePair=getSpecTypePair();
|
SpecTypePair specTypePair=getSpecTypePair();
|
||||||
if(specTypePair!=null){
|
if(specTypePair!=null){
|
||||||
return specTypePair.getTypeBlockArray();
|
return specTypePair.getTypeBlockArray();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SpecTypePair getSpecTypePair(){
|
SpecTypePair getSpecTypePair(){
|
||||||
return getParent(SpecTypePair.class);
|
return getParent(SpecTypePair.class);
|
||||||
}
|
}
|
||||||
public int getEntryCount() {
|
public int getEntryCount() {
|
||||||
return specFlagsArray.size();
|
return specFlagsArray.size();
|
||||||
}
|
}
|
||||||
public void setEntryCount(int count){
|
public void setEntryCount(int count){
|
||||||
specFlagsArray.setSize(count);
|
specFlagsArray.setSize(count);
|
||||||
specFlagsArray.refresh();
|
specFlagsArray.refresh();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onChunkRefreshed() {
|
protected void onChunkRefreshed() {
|
||||||
specFlagsArray.refresh();
|
specFlagsArray.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void merge(SpecBlock specBlock){
|
public void merge(SpecBlock specBlock){
|
||||||
if(specBlock == null || specBlock==this){
|
if(specBlock == null || specBlock==this){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.getSpecFlagsArray().merge(specBlock.getSpecFlagsArray());
|
this.getSpecFlagsArray().merge(specBlock.getSpecFlagsArray());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(super.toString());
|
builder.append(super.toString());
|
||||||
TypeBlockArray typeBlockArray=getTypeBlockArray();
|
TypeBlockArray typeBlockArray=getTypeBlockArray();
|
||||||
if(typeBlockArray!=null){
|
if(typeBlockArray!=null){
|
||||||
builder.append(", typesCount=");
|
builder.append(", typesCount=");
|
||||||
builder.append(typeBlockArray.childesCount());
|
builder.append(typeBlockArray.childesCount());
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
JSONObject jsonObject=new JSONObject();
|
JSONObject jsonObject=new JSONObject();
|
||||||
jsonObject.put(TypeBlock.NAME_id, getId());
|
jsonObject.put(TypeBlock.NAME_id, getId());
|
||||||
jsonObject.put(NAME_spec_flags, getSpecFlagsArray().toJson());
|
jsonObject.put(NAME_spec_flags, getSpecFlagsArray().toJson());
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromJson(JSONObject json) {
|
public void fromJson(JSONObject json) {
|
||||||
setId(json.getInt(TypeBlock.NAME_id));
|
setId(json.getInt(TypeBlock.NAME_id));
|
||||||
getSpecFlagsArray().fromJson(json.optJSONArray(NAME_spec_flags));
|
getSpecFlagsArray().fromJson(json.optJSONArray(NAME_spec_flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Flag{
|
public enum Flag{
|
||||||
SPEC_PUBLIC((byte) 0x40),
|
SPEC_PUBLIC((byte) 0x40),
|
||||||
SPEC_STAGED_API((byte) 0x20);
|
SPEC_STAGED_API((byte) 0x20);
|
||||||
|
|
||||||
private final byte flag;
|
private final byte flag;
|
||||||
Flag(byte flag) {
|
Flag(byte flag) {
|
||||||
this.flag = flag;
|
this.flag = flag;
|
||||||
}
|
}
|
||||||
public byte getFlag() {
|
public byte getFlag() {
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
public static boolean isPublic(byte flag){
|
public static boolean isPublic(byte flag){
|
||||||
return (SPEC_PUBLIC.flag & flag) == SPEC_PUBLIC.flag;
|
return (SPEC_PUBLIC.flag & flag) == SPEC_PUBLIC.flag;
|
||||||
}
|
}
|
||||||
public static boolean isStagedApi(byte flag){
|
public static boolean isStagedApi(byte flag){
|
||||||
return (SPEC_STAGED_API.flag & flag) == SPEC_STAGED_API.flag;
|
return (SPEC_STAGED_API.flag & flag) == SPEC_STAGED_API.flag;
|
||||||
}
|
}
|
||||||
public static String toString(byte flagValue){
|
public static String toString(byte flagValue){
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
boolean appendOnce = false;
|
boolean appendOnce = false;
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
int flagValueInt = flagValue & 0xff;
|
int flagValueInt = flagValue & 0xff;
|
||||||
for(Flag flag:values()){
|
for(Flag flag:values()){
|
||||||
int flagInt = flag.flag & 0xff;
|
int flagInt = flag.flag & 0xff;
|
||||||
if((flagInt & flagValueInt) != flagInt){
|
if((flagInt & flagValueInt) != flagInt){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(appendOnce){
|
if(appendOnce){
|
||||||
builder.append('|');
|
builder.append('|');
|
||||||
}
|
}
|
||||||
builder.append(flag);
|
builder.append(flag);
|
||||||
appendOnce = true;
|
appendOnce = true;
|
||||||
sum = sum | flagInt;
|
sum = sum | flagInt;
|
||||||
}
|
}
|
||||||
if(sum != flagValueInt){
|
if(sum != flagValueInt){
|
||||||
if(appendOnce){
|
if(appendOnce){
|
||||||
builder.append('|');
|
builder.append('|');
|
||||||
}
|
}
|
||||||
builder.append(String.format("0x%02x", flagValueInt));
|
builder.append(HexUtil.toHex2((byte) flagValueInt));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String NAME_spec = "spec";
|
public static final String NAME_spec = "spec";
|
||||||
public static final String NAME_spec_flags = "spec_flags";
|
public static final String NAME_spec_flags = "spec_flags";
|
||||||
public static final String NAME_flag = "flag";
|
public static final String NAME_flag = "flag";
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import com.reandroid.arsc.io.BlockReader;
|
|||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
import com.reandroid.arsc.pool.ResXmlStringPool;
|
import com.reandroid.arsc.pool.ResXmlStringPool;
|
||||||
import com.reandroid.arsc.pool.StringPool;
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.AttributeValue;
|
import com.reandroid.arsc.value.AttributeValue;
|
||||||
import com.reandroid.arsc.value.ValueItem;
|
import com.reandroid.arsc.value.ValueItem;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
@ -419,10 +420,10 @@ public class ResXmlAttribute extends ValueItem implements AttributeValue, Compar
|
|||||||
if(group==null){
|
if(group==null){
|
||||||
//Lets ignore such error until XML encoder implemented
|
//Lets ignore such error until XML encoder implemented
|
||||||
//throw new XMLException("Failed to decode attribute name: "
|
//throw new XMLException("Failed to decode attribute name: "
|
||||||
//+ String.format("@0x%08x", resourceId));
|
//HexUtil.toHex8("@0x", resourceId));
|
||||||
name=String.format("@0x%08x", resourceId);
|
name = HexUtil.toHex8("@0x", resourceId);
|
||||||
}else {
|
}else {
|
||||||
name=group.getSpecName();
|
name = group.getSpecName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String prefix = getNamePrefix();
|
String prefix = getNamePrefix();
|
||||||
@ -445,7 +446,7 @@ public class ResXmlAttribute extends ValueItem implements AttributeValue, Compar
|
|||||||
if(fullName!=null ){
|
if(fullName!=null ){
|
||||||
int id=getNameResourceID();
|
int id=getNameResourceID();
|
||||||
if(id!=0){
|
if(id!=0){
|
||||||
fullName=fullName+"(@"+String.format("0x%08x",id)+")";
|
fullName=fullName+"(@"+ HexUtil.toHex8(id)+")";
|
||||||
}
|
}
|
||||||
String valStr;
|
String valStr;
|
||||||
ValueType valueType=getValueType();
|
ValueType valueType=getValueType();
|
||||||
@ -456,7 +457,7 @@ public class ResXmlAttribute extends ValueItem implements AttributeValue, Compar
|
|||||||
}else if (valueType==ValueType.INT_DEC){
|
}else if (valueType==ValueType.INT_DEC){
|
||||||
valStr = String.valueOf(getData());
|
valStr = String.valueOf(getData());
|
||||||
}else {
|
}else {
|
||||||
valStr = "["+valueType+"] " + String.format("0x%08x",getData());
|
valStr = "["+valueType+"] " + HexUtil.toHex8(getData());
|
||||||
}
|
}
|
||||||
if(valStr!=null){
|
if(valStr!=null){
|
||||||
return fullName+"=\""+valStr+"\"";
|
return fullName+"=\""+valStr+"\"";
|
||||||
|
@ -27,6 +27,7 @@ import com.reandroid.arsc.io.BlockReader;
|
|||||||
import com.reandroid.arsc.item.TypeString;
|
import com.reandroid.arsc.item.TypeString;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResConfig;
|
import com.reandroid.arsc.value.ResConfig;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
@ -338,7 +339,7 @@ public class SpecTypePair extends BlockContainer<Block>
|
|||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append(String.format("0x%02x", getTypeId()));
|
builder.append(HexUtil.toHex2(getTypeId()));
|
||||||
builder.append(" (");
|
builder.append(" (");
|
||||||
TypeString ts = getTypeString();
|
TypeString ts = getTypeString();
|
||||||
if(ts!=null){
|
if(ts!=null){
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.decoder;
|
package com.reandroid.arsc.decoder;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -43,7 +44,7 @@ public class ColorUtil {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String hex = String.format("%08x", data);
|
String hex = HexUtil.toHexNoPrefix8(data);
|
||||||
return "#" + hex.substring(index);
|
return "#" + hex.substring(index);
|
||||||
}
|
}
|
||||||
public static ValueDecoder.EncodeResult encode(String hexColor){
|
public static ValueDecoder.EncodeResult encode(String hexColor){
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.decoder;
|
package com.reandroid.arsc.decoder;
|
||||||
|
|
||||||
import com.reandroid.apk.AndroidFrameworks;
|
import com.reandroid.apk.AndroidFrameworks;
|
||||||
@ -25,6 +25,7 @@ import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
|||||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.util.FrameworkTable;
|
import com.reandroid.arsc.util.FrameworkTable;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.AttributeValue;
|
import com.reandroid.arsc.value.AttributeValue;
|
||||||
import com.reandroid.arsc.value.Value;
|
import com.reandroid.arsc.value.Value;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
@ -57,7 +58,7 @@ public class Decoder {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private String hexResourceName(int resourceId){
|
private String hexResourceName(int resourceId){
|
||||||
return String.format("@0x%08x", resourceId);
|
return HexUtil.toHex8("@0x", resourceId);
|
||||||
}
|
}
|
||||||
public String decodeValue(Value value){
|
public String decodeValue(Value value){
|
||||||
if(value==null){
|
if(value==null){
|
||||||
|
@ -20,6 +20,7 @@ import com.reandroid.arsc.chunk.TableBlock;
|
|||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.*;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
@ -265,11 +266,11 @@ public class ValueDecoder {
|
|||||||
public static String decodeAttributeName(EntryStore store, PackageBlock currentPackage, int resourceId){
|
public static String decodeAttributeName(EntryStore store, PackageBlock currentPackage, int resourceId){
|
||||||
EntryGroup entryGroup=searchEntryGroup(store, currentPackage, resourceId);
|
EntryGroup entryGroup=searchEntryGroup(store, currentPackage, resourceId);
|
||||||
if(entryGroup==null){
|
if(entryGroup==null){
|
||||||
return String.format("@0x%08x", resourceId);
|
return HexUtil.toHex8("@0x", resourceId);
|
||||||
}
|
}
|
||||||
Entry entry =entryGroup.pickOne();
|
Entry entry = entryGroup.pickOne();
|
||||||
if(entry ==null){
|
if(entry == null){
|
||||||
return String.format("@0x%08x", resourceId);
|
return HexUtil.toHex8("@0x", resourceId);
|
||||||
}
|
}
|
||||||
String prefix=null;
|
String prefix=null;
|
||||||
if(currentPackage!=null){
|
if(currentPackage!=null){
|
||||||
@ -705,7 +706,7 @@ public class ValueDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String decodeHex(int rawVal){
|
private static String decodeHex(int rawVal){
|
||||||
return String.format("0x%x", rawVal);
|
return HexUtil.toHex(rawVal, 1);
|
||||||
}
|
}
|
||||||
private static String decodeInt(int rawVal){
|
private static String decodeInt(int rawVal){
|
||||||
return String.valueOf(rawVal);
|
return String.valueOf(rawVal);
|
||||||
@ -786,7 +787,7 @@ public class ValueDecoder {
|
|||||||
return entry1;
|
return entry1;
|
||||||
}
|
}
|
||||||
private static String toHexResourceId(int resourceId){
|
private static String toHexResourceId(int resourceId){
|
||||||
return String.format("0x%08x", resourceId);
|
return HexUtil.toHex8(resourceId);
|
||||||
}
|
}
|
||||||
private static boolean isEqualString(String str1, String str2){
|
private static boolean isEqualString(String str1, String str2){
|
||||||
if(isEmpty(str1)){
|
if(isEmpty(str1)){
|
||||||
@ -810,7 +811,7 @@ public class ValueDecoder {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return valueType+": "+String.format("0x%08x", value);
|
return valueType+": "+HexUtil.toHex8(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.header;
|
package com.reandroid.arsc.header;
|
||||||
|
|
||||||
import com.reandroid.arsc.base.BlockContainer;
|
import com.reandroid.arsc.base.BlockContainer;
|
||||||
@ -27,11 +27,12 @@ import com.reandroid.arsc.item.ByteArray;
|
|||||||
import com.reandroid.arsc.item.IntegerItem;
|
import com.reandroid.arsc.item.IntegerItem;
|
||||||
import com.reandroid.arsc.item.ShortItem;
|
import com.reandroid.arsc.item.ShortItem;
|
||||||
import com.reandroid.arsc.util.HexBytesWriter;
|
import com.reandroid.arsc.util.HexBytesWriter;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HeaderBlock extends ExpandableBlockContainer implements BlockLoad {
|
public class HeaderBlock extends ExpandableBlockContainer implements BlockLoad {
|
||||||
private final ShortItem mType;
|
private final ShortItem mType;
|
||||||
private final ShortItem mHeaderSize;
|
private final ShortItem mHeaderSize;
|
||||||
private final IntegerItem mChunkSize;
|
private final IntegerItem mChunkSize;
|
||||||
@ -57,7 +58,7 @@ import java.util.List;
|
|||||||
return countBytes();
|
return countBytes();
|
||||||
}
|
}
|
||||||
public ByteArray getExtraBytes() {
|
public ByteArray getExtraBytes() {
|
||||||
return extraBytes;
|
return extraBytes;
|
||||||
}
|
}
|
||||||
public void setHeaderLoaded(HeaderLoaded headerLoaded){
|
public void setHeaderLoaded(HeaderLoaded headerLoaded){
|
||||||
this.mHeaderLoaded=headerLoaded;
|
this.mHeaderLoaded=headerLoaded;
|
||||||
@ -111,9 +112,9 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
/**Non buffering reader*/
|
/**Non buffering reader*/
|
||||||
public int readBytes(InputStream inputStream) throws IOException{
|
public int readBytes(InputStream inputStream) throws IOException{
|
||||||
int result = onReadBytes(inputStream);
|
int result = onReadBytes(inputStream);
|
||||||
super.notifyBlockLoad();
|
super.notifyBlockLoad();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
private int onReadBytes(InputStream inputStream) throws IOException {
|
private int onReadBytes(InputStream inputStream) throws IOException {
|
||||||
int readCount = readBytes(inputStream, this);
|
int readCount = readBytes(inputStream, this);
|
||||||
@ -218,7 +219,7 @@ import java.util.List;
|
|||||||
builder.append(type.toString());
|
builder.append(type.toString());
|
||||||
}else {
|
}else {
|
||||||
builder.append("Unknown type=");
|
builder.append("Unknown type=");
|
||||||
builder.append(String.format("0x%02x", (0xffff & t)));
|
builder.append(HexUtil.toHex4(t));
|
||||||
}
|
}
|
||||||
builder.append("{ValueHeader=");
|
builder.append("{ValueHeader=");
|
||||||
builder.append(getHeaderSize());
|
builder.append(getHeaderSize());
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -16,7 +16,9 @@
|
|||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
|
|
||||||
public class ByteItem extends BlockItem {
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
|
public class ByteItem extends BlockItem {
|
||||||
public ByteItem() {
|
public ByteItem() {
|
||||||
super(1);
|
super(1);
|
||||||
}
|
}
|
||||||
@ -47,7 +49,7 @@ public class ByteItem extends BlockItem {
|
|||||||
return 0xff & get();
|
return 0xff & get();
|
||||||
}
|
}
|
||||||
public String toHex(){
|
public String toHex(){
|
||||||
return String.format("0x%02x", unsignedInt());
|
return HexUtil.toHex2(get());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
public class IntegerItem extends BlockItem implements ReferenceItem{
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class IntegerItem extends BlockItem implements ReferenceItem{
|
|
||||||
private int mCache;
|
private int mCache;
|
||||||
public IntegerItem(){
|
public IntegerItem(){
|
||||||
super(4);
|
super(4);
|
||||||
@ -50,7 +50,7 @@ package com.reandroid.arsc.item;
|
|||||||
return get() & 0x00000000ffffffffL;
|
return get() & 0x00000000ffffffffL;
|
||||||
}
|
}
|
||||||
public String toHex(){
|
public String toHex(){
|
||||||
return String.format("0x%08x", get());
|
return HexUtil.toHex8(get());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onBytesChanged() {
|
protected void onBytesChanged() {
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
public class LongItem extends BlockItem{
|
public class LongItem extends BlockItem{
|
||||||
private long mCache;
|
private long mCache;
|
||||||
public LongItem() {
|
public LongItem() {
|
||||||
@ -31,7 +33,7 @@ public class LongItem extends BlockItem{
|
|||||||
return mCache;
|
return mCache;
|
||||||
}
|
}
|
||||||
public String toHex(){
|
public String toHex(){
|
||||||
return String.format("0x%016x", get());
|
return HexUtil.toHex(get(), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
|
||||||
import com.reandroid.arsc.pool.ResXmlStringPool;
|
import com.reandroid.arsc.pool.ResXmlStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -90,7 +91,7 @@ public class ResXmlID extends IntegerItem {
|
|||||||
builder.append(getIndex());
|
builder.append(getIndex());
|
||||||
}
|
}
|
||||||
builder.append(':');
|
builder.append(':');
|
||||||
builder.append(String.format("0x%08x", get()));
|
builder.append(HexUtil.toHex8(get()));
|
||||||
builder.append('}');
|
builder.append('}');
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class ShortItem extends BlockItem {
|
public class ShortItem extends BlockItem {
|
||||||
private short mCache;
|
private short mCache;
|
||||||
|
|
||||||
public ShortItem(){
|
public ShortItem(){
|
||||||
@ -46,7 +47,7 @@ package com.reandroid.arsc.item;
|
|||||||
return 0xffff & get();
|
return 0xffff & get();
|
||||||
}
|
}
|
||||||
public String toHex(){
|
public String toHex(){
|
||||||
return String.format("0x%04x", unsignedInt());
|
return HexUtil.toHex4(get());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void onBytesChanged() {
|
protected void onBytesChanged() {
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.item;
|
package com.reandroid.arsc.item;
|
||||||
|
|
||||||
import com.reandroid.arsc.chunk.SpecBlock;
|
import com.reandroid.arsc.chunk.SpecBlock;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
public class SpecFlag extends IndirectItem<SpecFlagsArray> {
|
public class SpecFlag extends IndirectItem<SpecFlagsArray> {
|
||||||
public SpecFlag(SpecFlagsArray specFlagsArray, int offset) {
|
public SpecFlag(SpecFlagsArray specFlagsArray, int offset) {
|
||||||
@ -58,7 +59,7 @@ public class SpecFlag extends IndirectItem<SpecFlagsArray> {
|
|||||||
}
|
}
|
||||||
int val = getInteger();
|
int val = getInteger();
|
||||||
if(val != 0){
|
if(val != 0){
|
||||||
return String.format("0x%08x", val);
|
return HexUtil.toHex8(val);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package com.reandroid.arsc.item;
|
|||||||
|
|
||||||
|
|
||||||
import com.reandroid.arsc.pool.TypeStringPool;
|
import com.reandroid.arsc.pool.TypeStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
|
|
||||||
public class TypeString extends StringItem {
|
public class TypeString extends StringItem {
|
||||||
public TypeString(boolean utf8) {
|
public TypeString(boolean utf8) {
|
||||||
@ -40,6 +41,6 @@ public class TypeString extends StringItem {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return String.format("0x%02x", getId())+':'+get();
|
return HexUtil.toHex2((byte) getId())+':'+get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ public class HexBytesWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void writeHex(Writer writer, byte b) throws IOException {
|
private void writeHex(Writer writer, byte b) throws IOException {
|
||||||
String hex = String.format("%02x", (0xff & b)).toUpperCase();
|
String hex = HexUtil.toHex(null, (0xff & b), 2).toUpperCase();
|
||||||
writer.write(hex);
|
writer.write(hex);
|
||||||
}
|
}
|
||||||
private void writeString(Writer writer, int width, int position) throws IOException {
|
private void writeString(Writer writer, int width, int position) throws IOException {
|
||||||
|
84
src/main/java/com/reandroid/arsc/util/HexUtil.java
Normal file
84
src/main/java/com/reandroid/arsc/util/HexUtil.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
public class HexUtil {
|
||||||
|
public static String toHex2(byte num){
|
||||||
|
return toHex((long)(num & 0x00000000000000ffL), 2);
|
||||||
|
}
|
||||||
|
public static String toHex4(short num){
|
||||||
|
return toHex((long)(num & 0x000000000000ffffL), 4);
|
||||||
|
}
|
||||||
|
public static String toHex8(int num){
|
||||||
|
return toHex(num, 8);
|
||||||
|
}
|
||||||
|
public static String toHex8(long num){
|
||||||
|
return toHex(num, 8);
|
||||||
|
}
|
||||||
|
public static String toHex(int num, int minLength){
|
||||||
|
return toHex((0x00000000ffffffffL & num), minLength);
|
||||||
|
}
|
||||||
|
public static String toHex(long num, int minLength){
|
||||||
|
String hex = Long.toHexString(num);
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append('0');
|
||||||
|
builder.append('x');
|
||||||
|
int rem = minLength - hex.length();
|
||||||
|
for(int i=0; i < rem; i++){
|
||||||
|
builder.append('0');
|
||||||
|
}
|
||||||
|
builder.append(hex);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
public static String toHexNoPrefix8(int num){
|
||||||
|
return toHex(null, (0x00000000ffffffffL & num), 8);
|
||||||
|
}
|
||||||
|
public static String toHexNoPrefix(int num, int minLength){
|
||||||
|
return toHex(null, (0x00000000ffffffffL & num), minLength);
|
||||||
|
}
|
||||||
|
public static String toHex8(String prefix, int num){
|
||||||
|
return toHex(prefix, (0x00000000ffffffffL & num), 8);
|
||||||
|
}
|
||||||
|
public static String toHex(String prefix, int num, int minLength){
|
||||||
|
return toHex(prefix, (0x00000000ffffffffL & num), minLength);
|
||||||
|
}
|
||||||
|
public static String toHex(String prefix, long num, int minLength){
|
||||||
|
String hex = Long.toHexString(num);
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
if(prefix != null){
|
||||||
|
builder.append(prefix);
|
||||||
|
}
|
||||||
|
int rem = minLength - hex.length();
|
||||||
|
for(int i=0; i < rem; i++){
|
||||||
|
builder.append('0');
|
||||||
|
}
|
||||||
|
builder.append(hex);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
public static int parseHex(String hexString){
|
||||||
|
hexString = trim0x(hexString);
|
||||||
|
return (int) Long.parseLong(hexString, 16);
|
||||||
|
}
|
||||||
|
private static String trim0x(String hexString){
|
||||||
|
if(hexString == null || hexString.length() < 3){
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
|
if(hexString.charAt(0) == '0' && hexString.charAt(1) == 'x'){
|
||||||
|
hexString = hexString.substring(2);
|
||||||
|
}
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,7 @@ import com.reandroid.arsc.io.BlockReader;
|
|||||||
import com.reandroid.arsc.item.*;
|
import com.reandroid.arsc.item.*;
|
||||||
import com.reandroid.arsc.pool.SpecStringPool;
|
import com.reandroid.arsc.pool.SpecStringPool;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
@ -429,7 +430,7 @@ public class Entry extends Block implements JSONConvert<JSONObject> {
|
|||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append(String.format("0x%08x", getResourceId()));
|
builder.append(HexUtil.toHex8(getResourceId()));
|
||||||
builder.append(' ');
|
builder.append(' ');
|
||||||
ResConfig resConfig = getResConfig();
|
ResConfig resConfig = getResConfig();
|
||||||
if(resConfig!=null){
|
if(resConfig!=null){
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
public class EntryHeaderMap extends ValueHeader {
|
public class EntryHeaderMap extends ValueHeader {
|
||||||
@ -92,7 +93,7 @@ public class EntryHeaderMap extends ValueHeader {
|
|||||||
int parentId = getParentId();
|
int parentId = getParentId();
|
||||||
if(parentId!=0){
|
if(parentId!=0){
|
||||||
builder.append(", parentId=");
|
builder.append(", parentId=");
|
||||||
builder.append(String.format("0x%08x", getParentId()));
|
builder.append(HexUtil.toHex8(getParentId()));
|
||||||
}
|
}
|
||||||
builder.append(", count=").append(getValuesCount());
|
builder.append(", count=").append(getValuesCount());
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
import com.reandroid.arsc.base.Block;
|
import com.reandroid.arsc.base.Block;
|
||||||
@ -20,6 +20,7 @@ import com.reandroid.arsc.base.BlockCounter;
|
|||||||
import com.reandroid.arsc.io.BlockReader;
|
import com.reandroid.arsc.io.BlockReader;
|
||||||
import com.reandroid.arsc.item.FixedLengthString;
|
import com.reandroid.arsc.item.FixedLengthString;
|
||||||
import com.reandroid.arsc.item.IntegerItem;
|
import com.reandroid.arsc.item.IntegerItem;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ public class LibraryInfo extends Block implements JSONConvert<JSONObject> {
|
|||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder builder=new StringBuilder();
|
StringBuilder builder=new StringBuilder();
|
||||||
builder.append("LIBRARY{");
|
builder.append("LIBRARY{");
|
||||||
builder.append(String.format("0x%02x", getPackageId()));
|
builder.append(HexUtil.toHex2((byte) getPackageId()));
|
||||||
builder.append(':');
|
builder.append(':');
|
||||||
String name=getPackageName();
|
String name=getPackageName();
|
||||||
if(name==null){
|
if(name==null){
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
import com.reandroid.arsc.base.Block;
|
import com.reandroid.arsc.base.Block;
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
public class ResValueMap extends ValueItem implements AttributeValue{
|
public class ResValueMap extends ValueItem implements AttributeValue{
|
||||||
@ -110,7 +111,7 @@ public class ResValueMap extends ValueItem implements AttributeValue{
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "name="+String.format("0x%08x", getName())
|
return "name=" + HexUtil.toHex8(getName())
|
||||||
+", "+super.toString();
|
+", "+super.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +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.
|
||||||
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
import com.reandroid.arsc.item.ByteArray;
|
import com.reandroid.arsc.item.ByteArray;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
@ -22,7 +38,7 @@ public class StagedAliasEntry extends ByteArray implements JSONConvert<JSONObjec
|
|||||||
return getInteger(0);
|
return getInteger(0);
|
||||||
}
|
}
|
||||||
public void setStagedResId(int id){
|
public void setStagedResId(int id){
|
||||||
putInteger(0, id);
|
putInteger(0, id);
|
||||||
}
|
}
|
||||||
public int getFinalizedResId(){
|
public int getFinalizedResId(){
|
||||||
return getInteger(4);
|
return getInteger(4);
|
||||||
@ -32,8 +48,8 @@ public class StagedAliasEntry extends ByteArray implements JSONConvert<JSONObjec
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return "stagedResId="+String.format("0x%08x",getStagedResId())
|
return "stagedResId=" + HexUtil.toHex8(getStagedResId())
|
||||||
+", finalizedResId="+String.format("0x%08x",getFinalizedResId());
|
+", finalizedResId=" + HexUtil.toHex8(getFinalizedResId());
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value;
|
package com.reandroid.arsc.value;
|
||||||
|
|
||||||
import com.reandroid.arsc.base.Block;
|
import com.reandroid.arsc.base.Block;
|
||||||
@ -24,308 +24,309 @@ import com.reandroid.arsc.item.ReferenceItem;
|
|||||||
import com.reandroid.arsc.item.StringItem;
|
import com.reandroid.arsc.item.StringItem;
|
||||||
import com.reandroid.arsc.pool.StringPool;
|
import com.reandroid.arsc.pool.StringPool;
|
||||||
import com.reandroid.arsc.pool.TableStringPool;
|
import com.reandroid.arsc.pool.TableStringPool;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.json.JSONConvert;
|
import com.reandroid.json.JSONConvert;
|
||||||
import com.reandroid.json.JSONObject;
|
import com.reandroid.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class ValueItem extends BlockItem implements Value,
|
public abstract class ValueItem extends BlockItem implements Value,
|
||||||
JSONConvert<JSONObject>{
|
JSONConvert<JSONObject>{
|
||||||
private ReferenceItem mStringReference;
|
private ReferenceItem mStringReference;
|
||||||
private final int sizeOffset;
|
private final int sizeOffset;
|
||||||
public ValueItem(int bytesLength, int sizeOffset) {
|
public ValueItem(int bytesLength, int sizeOffset) {
|
||||||
super(bytesLength);
|
super(bytesLength);
|
||||||
this.sizeOffset = sizeOffset;
|
this.sizeOffset = sizeOffset;
|
||||||
|
|
||||||
writeSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void linkTableStrings(TableStringPool tableStringPool){
|
writeSize();
|
||||||
if(getValueType() == ValueType.STRING){
|
}
|
||||||
linkStringReference(tableStringPool);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void onRemoved(){
|
|
||||||
unLinkStringReference();
|
|
||||||
}
|
|
||||||
protected void onDataChanged(){
|
|
||||||
}
|
|
||||||
public void refresh(){
|
|
||||||
writeSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getRes0(){
|
void linkTableStrings(TableStringPool tableStringPool){
|
||||||
return getBytesInternal()[this.sizeOffset + OFFSET_RES0];
|
if(getValueType() == ValueType.STRING){
|
||||||
}
|
linkStringReference(tableStringPool);
|
||||||
public byte getType(){
|
}
|
||||||
return getBytesInternal()[this.sizeOffset + OFFSET_TYPE];
|
}
|
||||||
}
|
public void onRemoved(){
|
||||||
public void setType(byte type){
|
unLinkStringReference();
|
||||||
if(type == getType()){
|
}
|
||||||
return;
|
protected void onDataChanged(){
|
||||||
}
|
}
|
||||||
byte[] bts = getBytesInternal();
|
public void refresh(){
|
||||||
int offset = this.sizeOffset + OFFSET_TYPE;
|
writeSize();
|
||||||
byte old = bts[offset];
|
}
|
||||||
bts[offset] = type;
|
|
||||||
onTypeChanged(old, type);
|
byte getRes0(){
|
||||||
onDataChanged();
|
return getBytesInternal()[this.sizeOffset + OFFSET_RES0];
|
||||||
}
|
}
|
||||||
public int getSize(){
|
public byte getType(){
|
||||||
return 0xffff & getShort(getBytesInternal(), this.sizeOffset + OFFSET_SIZE);
|
return getBytesInternal()[this.sizeOffset + OFFSET_TYPE];
|
||||||
}
|
}
|
||||||
public void setSize(int size){
|
public void setType(byte type){
|
||||||
size = this.sizeOffset + size;
|
if(type == getType()){
|
||||||
setBytesLength(size, false);
|
return;
|
||||||
writeSize();
|
}
|
||||||
}
|
byte[] bts = getBytesInternal();
|
||||||
private void writeSize(){
|
int offset = this.sizeOffset + OFFSET_TYPE;
|
||||||
int offset = this.sizeOffset;
|
byte old = bts[offset];
|
||||||
int size = countBytes() - offset;
|
bts[offset] = type;
|
||||||
putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size);
|
onTypeChanged(old, type);
|
||||||
}
|
onDataChanged();
|
||||||
protected void onDataLoaded(){
|
}
|
||||||
if(getValueType() == ValueType.STRING){
|
public int getSize(){
|
||||||
linkStringReference();
|
return 0xffff & getShort(getBytesInternal(), this.sizeOffset + OFFSET_SIZE);
|
||||||
}else {
|
}
|
||||||
unLinkStringReference();
|
public void setSize(int size){
|
||||||
}
|
size = this.sizeOffset + size;
|
||||||
}
|
setBytesLength(size, false);
|
||||||
@Override
|
writeSize();
|
||||||
public ValueType getValueType(){
|
}
|
||||||
return ValueType.valueOf(getType());
|
private void writeSize(){
|
||||||
}
|
int offset = this.sizeOffset;
|
||||||
@Override
|
int size = countBytes() - offset;
|
||||||
public void setValueType(ValueType valueType){
|
putShort(getBytesInternal(), offset + OFFSET_SIZE, (short) size);
|
||||||
byte type = 0;
|
}
|
||||||
if(valueType!=null){
|
protected void onDataLoaded(){
|
||||||
type = valueType.getByte();
|
if(getValueType() == ValueType.STRING){
|
||||||
}
|
linkStringReference();
|
||||||
setType(type);
|
}else {
|
||||||
}
|
unLinkStringReference();
|
||||||
@Override
|
}
|
||||||
public int getData(){
|
}
|
||||||
return getInteger(getBytesInternal(), this.sizeOffset + OFFSET_DATA);
|
@Override
|
||||||
}
|
public ValueType getValueType(){
|
||||||
@Override
|
return ValueType.valueOf(getType());
|
||||||
public void setData(int data){
|
}
|
||||||
byte[] bts = getBytesInternal();
|
@Override
|
||||||
int old = getInteger(bts, this.sizeOffset + OFFSET_DATA);
|
public void setValueType(ValueType valueType){
|
||||||
if(old == data){
|
byte type = 0;
|
||||||
return;
|
if(valueType!=null){
|
||||||
}
|
type = valueType.getByte();
|
||||||
unLinkStringReference();
|
}
|
||||||
putInteger(bts, this.sizeOffset + OFFSET_DATA, data);
|
setType(type);
|
||||||
if(ValueType.STRING==getValueType()){
|
}
|
||||||
linkStringReference();
|
@Override
|
||||||
}
|
public int getData(){
|
||||||
onDataChanged();
|
return getInteger(getBytesInternal(), this.sizeOffset + OFFSET_DATA);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public void setData(int data){
|
||||||
|
byte[] bts = getBytesInternal();
|
||||||
|
int old = getInteger(bts, this.sizeOffset + OFFSET_DATA);
|
||||||
|
if(old == data){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unLinkStringReference();
|
||||||
|
putInteger(bts, this.sizeOffset + OFFSET_DATA, data);
|
||||||
|
if(ValueType.STRING==getValueType()){
|
||||||
|
linkStringReference();
|
||||||
|
}
|
||||||
|
onDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public StringItem getDataAsPoolString(){
|
public StringItem getDataAsPoolString(){
|
||||||
if(getValueType()!=ValueType.STRING){
|
if(getValueType()!=ValueType.STRING){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringPool<?> stringPool = getStringPool();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(stringPool == null){
|
if(stringPool == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return stringPool.get(getData());
|
return stringPool.get(getData());
|
||||||
}
|
}
|
||||||
private void onTypeChanged(byte old, byte type){
|
private void onTypeChanged(byte old, byte type){
|
||||||
byte typeString = ValueType.STRING.getByte();
|
byte typeString = ValueType.STRING.getByte();
|
||||||
if(old == typeString){
|
if(old == typeString){
|
||||||
unLinkStringReference();
|
unLinkStringReference();
|
||||||
}else if(type == typeString){
|
}else if(type == typeString){
|
||||||
linkStringReference();
|
linkStringReference();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void linkStringReference(){
|
private void linkStringReference(){
|
||||||
StringPool<?> stringPool = getStringPool();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(stringPool == null || stringPool.isStringLinkLocked()){
|
if(stringPool == null || stringPool.isStringLinkLocked()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
linkStringReference(stringPool);
|
linkStringReference(stringPool);
|
||||||
}
|
}
|
||||||
private void linkStringReference(StringPool<?> stringPool){
|
private void linkStringReference(StringPool<?> stringPool){
|
||||||
StringItem tableString = stringPool.get(getData());
|
StringItem tableString = stringPool.get(getData());
|
||||||
if(tableString == null){
|
if(tableString == null){
|
||||||
unLinkStringReference();
|
unLinkStringReference();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ReferenceItem stringReference = mStringReference;
|
ReferenceItem stringReference = mStringReference;
|
||||||
if(stringReference!=null){
|
if(stringReference!=null){
|
||||||
unLinkStringReference();
|
unLinkStringReference();
|
||||||
}
|
}
|
||||||
stringReference = new ReferenceBlock<>(this, this.sizeOffset + OFFSET_DATA);
|
stringReference = new ReferenceBlock<>(this, this.sizeOffset + OFFSET_DATA);
|
||||||
mStringReference = stringReference;
|
mStringReference = stringReference;
|
||||||
tableString.addReference(stringReference);
|
tableString.addReference(stringReference);
|
||||||
}
|
}
|
||||||
private void unLinkStringReference(){
|
private void unLinkStringReference(){
|
||||||
ReferenceItem stringReference = mStringReference;
|
ReferenceItem stringReference = mStringReference;
|
||||||
if(stringReference==null){
|
if(stringReference==null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mStringReference = null;
|
mStringReference = null;
|
||||||
onUnlinkDataString(stringReference);
|
onUnlinkDataString(stringReference);
|
||||||
}
|
}
|
||||||
protected void onUnlinkDataString(ReferenceItem referenceItem){
|
protected void onUnlinkDataString(ReferenceItem referenceItem){
|
||||||
StringPool<?> stringPool = getStringPool();
|
StringPool<?> stringPool = getStringPool();
|
||||||
if(stringPool == null){
|
if(stringPool == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stringPool.removeReference(referenceItem);
|
stringPool.removeReference(referenceItem);
|
||||||
}
|
}
|
||||||
public StringPool<?> getStringPool(){
|
public StringPool<?> getStringPool(){
|
||||||
Block parent = getParent();
|
Block parent = getParent();
|
||||||
while (parent!=null){
|
while (parent!=null){
|
||||||
if(parent instanceof MainChunk){
|
if(parent instanceof MainChunk){
|
||||||
return ((MainChunk) parent).getStringPool();
|
return ((MainChunk) parent).getStringPool();
|
||||||
}
|
}
|
||||||
parent=parent.getParent();
|
parent=parent.getParent();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onReadBytes(BlockReader reader) throws IOException {
|
public void onReadBytes(BlockReader reader) throws IOException {
|
||||||
int readSize = initializeBytes(reader);
|
int readSize = initializeBytes(reader);
|
||||||
super.onReadBytes(reader);
|
super.onReadBytes(reader);
|
||||||
if(readSize<8){
|
if(readSize<8){
|
||||||
setBytesLength(this.sizeOffset + 8, false);
|
setBytesLength(this.sizeOffset + 8, false);
|
||||||
writeSize();
|
writeSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private int initializeBytes(BlockReader reader) throws IOException {
|
private int initializeBytes(BlockReader reader) throws IOException {
|
||||||
int position = reader.getPosition();
|
int position = reader.getPosition();
|
||||||
int offset = this.sizeOffset;
|
int offset = this.sizeOffset;
|
||||||
reader.offset(offset);
|
reader.offset(offset);
|
||||||
int readSize = reader.readUnsignedShort();
|
int readSize = reader.readUnsignedShort();
|
||||||
int size = readSize;
|
int size = readSize;
|
||||||
if(size<8){
|
if(size<8){
|
||||||
if(reader.available()>=8){
|
if(reader.available()>=8){
|
||||||
size = 8;
|
size = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.seek(position);
|
reader.seek(position);
|
||||||
setBytesLength(offset + size, false);
|
setBytesLength(offset + size, false);
|
||||||
return readSize;
|
return readSize;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String getValueAsString(){
|
public String getValueAsString(){
|
||||||
StringItem stringItem = getDataAsPoolString();
|
StringItem stringItem = getDataAsPoolString();
|
||||||
if(stringItem!=null){
|
if(stringItem!=null){
|
||||||
String value = stringItem.getHtml();
|
String value = stringItem.getHtml();
|
||||||
if(value == null){
|
if(value == null){
|
||||||
value = "";
|
value = "";
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public void setValueAsString(String str){
|
public void setValueAsString(String str){
|
||||||
if(getValueType() == ValueType.STRING
|
if(getValueType() == ValueType.STRING
|
||||||
&& Objects.equals(str, getValueAsString())){
|
&& Objects.equals(str, getValueAsString())){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(str == null){
|
if(str == null){
|
||||||
str = "";
|
str = "";
|
||||||
}
|
}
|
||||||
StringItem stringItem = getStringPool().getOrCreate(str);
|
StringItem stringItem = getStringPool().getOrCreate(str);
|
||||||
setData(stringItem.getIndex());
|
setData(stringItem.getIndex());
|
||||||
setValueType(ValueType.STRING);
|
setValueType(ValueType.STRING);
|
||||||
}
|
}
|
||||||
public boolean getValueAsBoolean(){
|
public boolean getValueAsBoolean(){
|
||||||
return getData()!=0;
|
return getData()!=0;
|
||||||
}
|
}
|
||||||
public void setValueAsBoolean(boolean val){
|
public void setValueAsBoolean(boolean val){
|
||||||
setValueType(ValueType.INT_BOOLEAN);
|
setValueType(ValueType.INT_BOOLEAN);
|
||||||
int data=val?0xffffffff:0;
|
int data=val?0xffffffff:0;
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
public void setTypeAndData(ValueType valueType, int data){
|
public void setTypeAndData(ValueType valueType, int data){
|
||||||
setData(data);
|
setData(data);
|
||||||
setValueType(valueType);
|
setValueType(valueType);
|
||||||
}
|
}
|
||||||
public void merge(ValueItem valueItem){
|
public void merge(ValueItem valueItem){
|
||||||
if(valueItem == null || valueItem==this){
|
if(valueItem == null || valueItem==this){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSize(valueItem.getSize());
|
setSize(valueItem.getSize());
|
||||||
ValueType coming = valueItem.getValueType();
|
ValueType coming = valueItem.getValueType();
|
||||||
if(coming == ValueType.STRING){
|
if(coming == ValueType.STRING){
|
||||||
setValueAsString(valueItem.getValueAsString());
|
setValueAsString(valueItem.getValueAsString());
|
||||||
}else {
|
}else {
|
||||||
setTypeAndData(coming, valueItem.getData());
|
setTypeAndData(coming, valueItem.getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public JSONObject toJson() {
|
public JSONObject toJson() {
|
||||||
if(isNull()){
|
if(isNull()){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
ValueType valueType = getValueType();
|
ValueType valueType = getValueType();
|
||||||
jsonObject.put(NAME_value_type, valueType.name());
|
jsonObject.put(NAME_value_type, valueType.name());
|
||||||
if(valueType==ValueType.STRING){
|
if(valueType==ValueType.STRING){
|
||||||
jsonObject.put(NAME_data, getValueAsString());
|
jsonObject.put(NAME_data, getValueAsString());
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||||
jsonObject.put(NAME_data, getValueAsBoolean());
|
jsonObject.put(NAME_data, getValueAsBoolean());
|
||||||
}else {
|
}else {
|
||||||
jsonObject.put(NAME_data, getData());
|
jsonObject.put(NAME_data, getData());
|
||||||
}
|
}
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void fromJson(JSONObject json) {
|
public void fromJson(JSONObject json) {
|
||||||
ValueType valueType = ValueType.fromName(json.getString(NAME_value_type));
|
ValueType valueType = ValueType.fromName(json.getString(NAME_value_type));
|
||||||
if(valueType==ValueType.STRING){
|
if(valueType==ValueType.STRING){
|
||||||
setValueAsString(json.optString(NAME_data, ""));
|
setValueAsString(json.optString(NAME_data, ""));
|
||||||
}else if(valueType==ValueType.INT_BOOLEAN){
|
}else if(valueType==ValueType.INT_BOOLEAN){
|
||||||
setValueAsBoolean(json.getBoolean(NAME_data));
|
setValueAsBoolean(json.getBoolean(NAME_data));
|
||||||
}else {
|
}else {
|
||||||
setValueType(valueType);
|
setValueType(valueType);
|
||||||
setData(json.getInt(NAME_data));
|
setData(json.getInt(NAME_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
int size = getSize();
|
int size = getSize();
|
||||||
if(size!=8){
|
if(size!=8){
|
||||||
builder.append("size=").append(getSize());
|
builder.append("size=").append(getSize());
|
||||||
builder.append(", ");
|
builder.append(", ");
|
||||||
}
|
}
|
||||||
builder.append("type=");
|
builder.append("type=");
|
||||||
ValueType valueType=getValueType();
|
ValueType valueType=getValueType();
|
||||||
if(valueType!=null){
|
if(valueType!=null){
|
||||||
builder.append(valueType);
|
builder.append(valueType);
|
||||||
}else {
|
}else {
|
||||||
builder.append(String.format("0x%02x", (0xff & getType())));
|
builder.append(HexUtil.toHex2(getType()));
|
||||||
}
|
}
|
||||||
builder.append(", data=");
|
builder.append(", data=");
|
||||||
int data = getData();
|
int data = getData();
|
||||||
if(valueType==ValueType.STRING){
|
if(valueType==ValueType.STRING){
|
||||||
StringItem tableString = getDataAsPoolString();
|
StringItem tableString = getDataAsPoolString();
|
||||||
if(tableString!=null){
|
if(tableString!=null){
|
||||||
builder.append(tableString.getHtml());
|
builder.append(tableString.getHtml());
|
||||||
}else {
|
}else {
|
||||||
builder.append(String.format("0x%08x", data));
|
builder.append(HexUtil.toHex8(data));
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
builder.append(String.format("0x%08x", data));
|
builder.append(HexUtil.toHex8(data));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int OFFSET_SIZE = 0;
|
private static final int OFFSET_SIZE = 0;
|
||||||
private static final int OFFSET_RES0 = 2;
|
private static final int OFFSET_RES0 = 2;
|
||||||
private static final int OFFSET_TYPE = 3;
|
private static final int OFFSET_TYPE = 3;
|
||||||
private static final int OFFSET_DATA = 4;
|
private static final int OFFSET_DATA = 4;
|
||||||
|
|
||||||
|
|
||||||
public static final String NAME_data = "data";
|
public static final String NAME_data = "data";
|
||||||
public static final String NAME_value_type = "value_type";
|
public static final String NAME_value_type = "value_type";
|
||||||
}
|
}
|
||||||
|
@ -1,95 +1,96 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.array;
|
package com.reandroid.arsc.value.array;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.item.StringItem;
|
import com.reandroid.arsc.item.StringItem;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.bag.BagItem;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
import com.reandroid.arsc.value.ResValueMap;
|
import com.reandroid.arsc.value.bag.BagItem;
|
||||||
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
|
|
||||||
public class ArrayBagItem extends BagItem {
|
public class ArrayBagItem extends BagItem {
|
||||||
private ArrayBagItem(ResValueMap valueMap) {
|
private ArrayBagItem(ResValueMap valueMap) {
|
||||||
super(valueMap);
|
super(valueMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayBagItem(StringItem str) {
|
private ArrayBagItem(StringItem str) {
|
||||||
super(str);
|
super(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayBagItem(ValueType valueType, int value) {
|
private ArrayBagItem(ValueType valueType, int value) {
|
||||||
super(valueType, value);
|
super(valueType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("<item>");
|
builder.append("<item>");
|
||||||
if (hasStringValue()) {
|
if (hasStringValue()) {
|
||||||
builder.append(getStringValue());
|
builder.append(getStringValue());
|
||||||
} else {
|
} else {
|
||||||
builder.append(String.format("0x%08x", getValue()));
|
builder.append(HexUtil.toHex8(getValue()));
|
||||||
}
|
}
|
||||||
builder.append("</item>");
|
builder.append("</item>");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ArrayBagItem create(ResValueMap valueMap) {
|
protected static ArrayBagItem create(ResValueMap valueMap) {
|
||||||
if (valueMap == null) {
|
if (valueMap == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new ArrayBagItem(valueMap);
|
return new ArrayBagItem(valueMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayBagItem create(ValueType valueType, int value) {
|
public static ArrayBagItem create(ValueType valueType, int value) {
|
||||||
if (valueType == null || valueType == ValueType.STRING) {
|
if (valueType == null || valueType == ValueType.STRING) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new ArrayBagItem(valueType, value);
|
return new ArrayBagItem(valueType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ArrayBagItem copyOf(ResValueMap resValueMap) {
|
protected static ArrayBagItem copyOf(ResValueMap resValueMap) {
|
||||||
ValueType valueType = resValueMap.getValueType();
|
ValueType valueType = resValueMap.getValueType();
|
||||||
if (valueType == ValueType.STRING) {
|
if (valueType == ValueType.STRING) {
|
||||||
return new ArrayBagItem(resValueMap.getDataAsPoolString());
|
return new ArrayBagItem(resValueMap.getDataAsPoolString());
|
||||||
} else {
|
} else {
|
||||||
return new ArrayBagItem(valueType, resValueMap.getData());
|
return new ArrayBagItem(valueType, resValueMap.getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayBagItem encoded(ValueDecoder.EncodeResult encodeResult) {
|
public static ArrayBagItem encoded(ValueDecoder.EncodeResult encodeResult) {
|
||||||
if (encodeResult == null) {
|
if (encodeResult == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return create(encodeResult.valueType, encodeResult.value);
|
return create(encodeResult.valueType, encodeResult.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayBagItem integer(int n) {
|
public static ArrayBagItem integer(int n) {
|
||||||
return create(ValueType.INT_DEC, n);
|
return create(ValueType.INT_DEC, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayBagItem string(TableString str) {
|
public static ArrayBagItem string(TableString str) {
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new ArrayBagItem(str);
|
return new ArrayBagItem(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayBagItem reference(int resourceId) {
|
public static ArrayBagItem reference(int resourceId) {
|
||||||
return create(ValueType.REFERENCE, resourceId);
|
return create(ValueType.REFERENCE, resourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.attribute;
|
package com.reandroid.arsc.value.attribute;
|
||||||
|
|
||||||
import com.reandroid.arsc.chunk.PackageBlock;
|
import com.reandroid.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.arsc.group.EntryGroup;
|
import com.reandroid.arsc.group.EntryGroup;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ResValueMap;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.common.EntryStore;
|
||||||
@ -36,7 +37,7 @@ public class AttributeBagItem {
|
|||||||
public String getNameOrHex(EntryStore entryStore){
|
public String getNameOrHex(EntryStore entryStore){
|
||||||
String name=getName(entryStore);
|
String name=getName(entryStore);
|
||||||
if(name==null){
|
if(name==null){
|
||||||
name=String.format("@0x%08x", getBagItem().getName());
|
name=HexUtil.toHex8("@0x", getBagItem().getName());
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -162,7 +163,7 @@ public class AttributeBagItem {
|
|||||||
}
|
}
|
||||||
ResValueMap item=getBagItem();
|
ResValueMap item=getBagItem();
|
||||||
builder.append(getNameOrHex());
|
builder.append(getNameOrHex());
|
||||||
builder.append("=").append(String.format("0x%x", item.getData()));
|
builder.append("=").append(HexUtil.toHex8(item.getData()));
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +215,4 @@ public class AttributeBagItem {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
import com.reandroid.arsc.chunk.TableBlock;
|
import com.reandroid.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.arsc.item.StringItem;
|
import com.reandroid.arsc.item.StringItem;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.*;
|
import com.reandroid.arsc.value.*;
|
||||||
import com.reandroid.arsc.value.bag.BagItem;
|
import com.reandroid.arsc.value.bag.BagItem;
|
||||||
|
|
||||||
@ -83,7 +84,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String formattedRefValue() {
|
private String formattedRefValue() {
|
||||||
return String.format("@0x%08x", getValue());
|
return HexUtil.toHex8("@0x", getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,189 +1,190 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 github.com/REAndroid
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.reandroid.arsc.value.style;
|
package com.reandroid.arsc.value.style;
|
||||||
|
|
||||||
import com.reandroid.arsc.decoder.ValueDecoder;
|
import com.reandroid.arsc.decoder.ValueDecoder;
|
||||||
import com.reandroid.arsc.item.StringItem;
|
import com.reandroid.arsc.item.StringItem;
|
||||||
import com.reandroid.arsc.item.TableString;
|
import com.reandroid.arsc.item.TableString;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBag;
|
import com.reandroid.arsc.util.HexUtil;
|
||||||
import com.reandroid.arsc.value.attribute.AttributeBagItem;
|
import com.reandroid.arsc.value.attribute.AttributeBag;
|
||||||
import com.reandroid.arsc.value.bag.BagItem;
|
import com.reandroid.arsc.value.attribute.AttributeBagItem;
|
||||||
import com.reandroid.arsc.value.Entry;
|
import com.reandroid.arsc.value.bag.BagItem;
|
||||||
import com.reandroid.arsc.value.ResValueMap;
|
import com.reandroid.arsc.value.Entry;
|
||||||
import com.reandroid.arsc.value.ValueType;
|
import com.reandroid.arsc.value.ResValueMap;
|
||||||
import com.reandroid.common.EntryStore;
|
import com.reandroid.arsc.value.ValueType;
|
||||||
|
import com.reandroid.common.EntryStore;
|
||||||
|
|
||||||
public class StyleBagItem extends BagItem {
|
public class StyleBagItem extends BagItem {
|
||||||
private StyleBagItem(ResValueMap bagItem) {
|
private StyleBagItem(ResValueMap bagItem) {
|
||||||
super(bagItem);
|
super(bagItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StyleBagItem(ValueType valueType, int data) {
|
private StyleBagItem(ValueType valueType, int data) {
|
||||||
super(valueType, data);
|
super(valueType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StyleBagItem(StringItem str) {
|
private StyleBagItem(StringItem str) {
|
||||||
super(str);
|
super(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
if (mBagItem == null) {
|
if (mBagItem == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Entry block = mBagItem.getEntry();
|
Entry block = mBagItem.getEntry();
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
char prefix = 0;
|
char prefix = 0;
|
||||||
return block.buildResourceName(mBagItem.getName(), prefix, false);
|
return block.buildResourceName(mBagItem.getName(), prefix, false);
|
||||||
}
|
}
|
||||||
public Entry getAttributeEntry(EntryStore entryStore) {
|
public Entry getAttributeEntry(EntryStore entryStore) {
|
||||||
if (mBagItem == null) {
|
if (mBagItem == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return entryStore.getEntryGroup(mBagItem.getName()).pickOne();
|
return entryStore.getEntryGroup(mBagItem.getName()).pickOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNameId() {
|
public int getNameId() {
|
||||||
if (mBagItem == null) {
|
if (mBagItem == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return mBagItem.getName();
|
return mBagItem.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAttributeValue() {
|
public boolean hasAttributeValue() {
|
||||||
return getValueType() == ValueType.ATTRIBUTE;
|
return getValueType() == ValueType.ATTRIBUTE;
|
||||||
}
|
}
|
||||||
public boolean hasIntValue() {
|
public boolean hasIntValue() {
|
||||||
ValueType valueType = getValueType();
|
ValueType valueType = getValueType();
|
||||||
return valueType == ValueType.INT_DEC || valueType == ValueType.INT_HEX;
|
return valueType == ValueType.INT_DEC || valueType == ValueType.INT_HEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValueAsReference() {
|
public String getValueAsReference() {
|
||||||
ValueType valueType = getValueType();
|
ValueType valueType = getValueType();
|
||||||
if (valueType != ValueType.REFERENCE && valueType != ValueType.ATTRIBUTE) {
|
if (valueType != ValueType.REFERENCE && valueType != ValueType.ATTRIBUTE) {
|
||||||
throw new IllegalArgumentException("Not REF ValueType=" + valueType);
|
throw new IllegalArgumentException("Not REF ValueType=" + valueType);
|
||||||
}
|
}
|
||||||
Entry entry = getBagItem().getEntry();
|
Entry entry = getBagItem().getEntry();
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
char prefix = '@';
|
char prefix = '@';
|
||||||
boolean includeType = true;
|
boolean includeType = true;
|
||||||
if (valueType == ValueType.ATTRIBUTE) {
|
if (valueType == ValueType.ATTRIBUTE) {
|
||||||
prefix = '?';
|
prefix = '?';
|
||||||
includeType = false;
|
includeType = false;
|
||||||
}
|
}
|
||||||
int id = getValue();
|
int id = getValue();
|
||||||
return entry.buildResourceName(id, prefix, includeType);
|
return entry.buildResourceName(id, prefix, includeType);
|
||||||
}
|
}
|
||||||
public String decodeAttributeValue(AttributeBag attr, EntryStore entryStore) {
|
public String decodeAttributeValue(AttributeBag attr, EntryStore entryStore) {
|
||||||
if (!hasIntValue()) {
|
if (!hasIntValue()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return attr.decodeAttributeValue(entryStore, getValue());
|
return attr.decodeAttributeValue(entryStore, getValue());
|
||||||
}
|
}
|
||||||
public AttributeBagItem[] getFlagsOrEnum(AttributeBag attr) {
|
public AttributeBagItem[] getFlagsOrEnum(AttributeBag attr) {
|
||||||
if (!hasIntValue()) {
|
if (!hasIntValue()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return attr.searchValue(getValue());
|
return attr.searchValue(getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("<item name=\"");
|
builder.append("<item name=\"");
|
||||||
String name = getName();
|
String name = getName();
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = String.format("@0x%08x", getNameId());
|
name = HexUtil.toHex8("@0x", getNameId());
|
||||||
}
|
}
|
||||||
builder.append(name);
|
builder.append(name);
|
||||||
builder.append("\">");
|
builder.append("\">");
|
||||||
if (hasStringValue()) {
|
if (hasStringValue()) {
|
||||||
builder.append(getStringValue());
|
builder.append(getStringValue());
|
||||||
}
|
}
|
||||||
String val = null;
|
String val = null;
|
||||||
if (hasReferenceValue() || hasAttributeValue()) {
|
if (hasReferenceValue() || hasAttributeValue()) {
|
||||||
val = getValueAsReference();
|
val = getValueAsReference();
|
||||||
}
|
}
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
val = String.format("0x%08x", getValue());
|
val = HexUtil.toHex8(getValue());
|
||||||
}
|
}
|
||||||
builder.append(val);
|
builder.append(val);
|
||||||
builder.append("</item>");
|
builder.append("</item>");
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static StyleBagItem create(ResValueMap resValueMap) {
|
protected static StyleBagItem create(ResValueMap resValueMap) {
|
||||||
if (resValueMap == null) {
|
if (resValueMap == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new StyleBagItem(resValueMap);
|
return new StyleBagItem(resValueMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StyleBagItem create(ValueType valueType, int value) {
|
public static StyleBagItem create(ValueType valueType, int value) {
|
||||||
if (valueType == null || valueType == ValueType.STRING) {
|
if (valueType == null || valueType == ValueType.STRING) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new StyleBagItem(valueType, value);
|
return new StyleBagItem(valueType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static StyleBagItem copyOf(ResValueMap resValueMap) {
|
protected static StyleBagItem copyOf(ResValueMap resValueMap) {
|
||||||
ValueType valueType = resValueMap.getValueType();
|
ValueType valueType = resValueMap.getValueType();
|
||||||
if (valueType == ValueType.STRING) {
|
if (valueType == ValueType.STRING) {
|
||||||
return new StyleBagItem(resValueMap.getDataAsPoolString());
|
return new StyleBagItem(resValueMap.getDataAsPoolString());
|
||||||
} else {
|
} else {
|
||||||
return new StyleBagItem(valueType, resValueMap.getData());
|
return new StyleBagItem(valueType, resValueMap.getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StyleBagItem integer(int n) {
|
public static StyleBagItem integer(int n) {
|
||||||
return new StyleBagItem(ValueType.INT_DEC, n);
|
return new StyleBagItem(ValueType.INT_DEC, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StyleBagItem string(TableString str) {
|
public static StyleBagItem string(TableString str) {
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new StyleBagItem(str);
|
return new StyleBagItem(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StyleBagItem reference(int resourceId) {
|
public static StyleBagItem reference(int resourceId) {
|
||||||
return new StyleBagItem(ValueType.REFERENCE, resourceId);
|
return new StyleBagItem(ValueType.REFERENCE, resourceId);
|
||||||
}
|
}
|
||||||
public static StyleBagItem attribute(int resourceId) {
|
public static StyleBagItem attribute(int resourceId) {
|
||||||
return new StyleBagItem(ValueType.ATTRIBUTE, resourceId);
|
return new StyleBagItem(ValueType.ATTRIBUTE, resourceId);
|
||||||
}
|
}
|
||||||
public static StyleBagItem encoded(ValueDecoder.EncodeResult encodeResult) {
|
public static StyleBagItem encoded(ValueDecoder.EncodeResult encodeResult) {
|
||||||
if (encodeResult == null) {
|
if (encodeResult == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return create(encodeResult.valueType, encodeResult.value);
|
return create(encodeResult.valueType, encodeResult.value);
|
||||||
}
|
}
|
||||||
public static StyleBagItem color(String color) {
|
public static StyleBagItem color(String color) {
|
||||||
return encoded(ValueDecoder.encodeColor(color));
|
return encoded(ValueDecoder.encodeColor(color));
|
||||||
}
|
}
|
||||||
public static StyleBagItem dimensionOrFraction(String str) {
|
public static StyleBagItem dimensionOrFraction(String str) {
|
||||||
return encoded(ValueDecoder.encodeDimensionOrFraction(str));
|
return encoded(ValueDecoder.encodeDimensionOrFraction(str));
|
||||||
}
|
}
|
||||||
public static StyleBagItem createFloat(float n) {
|
public static StyleBagItem createFloat(float n) {
|
||||||
return new StyleBagItem(ValueType.FLOAT, Float.floatToIntBits(n));
|
return new StyleBagItem(ValueType.FLOAT, Float.floatToIntBits(n));
|
||||||
}
|
}
|
||||||
public static StyleBagItem enumOrFlag(AttributeBag attr, String valueString) {
|
public static StyleBagItem enumOrFlag(AttributeBag attr, String valueString) {
|
||||||
return encoded(attr.encodeEnumOrFlagValue(valueString));
|
return encoded(attr.encodeEnumOrFlagValue(valueString));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user