mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 22:34:24 +02:00
prepare for XMLEncode
This commit is contained in:
parent
d8065f0b9e
commit
a7424bbf96
@ -24,7 +24,6 @@ import com.reandroid.lib.json.JSONObject;
|
||||
import com.reandroid.xml.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
public class ResourceIds {
|
||||
@ -248,6 +247,21 @@ import java.util.*;
|
||||
this.id = id;
|
||||
this.typeMap = new HashMap<>();
|
||||
}
|
||||
public Type.Entry getEntry(String typeName, String name){
|
||||
Type type=getType(typeName);
|
||||
if(type==null){
|
||||
return null;
|
||||
}
|
||||
return type.getEntry(name);
|
||||
}
|
||||
private Type getType(String typeName){
|
||||
for(Type type:typeMap.values()){
|
||||
if(type.getName().equals(typeName)){
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public int getIdInt(){
|
||||
return 0xff & id;
|
||||
}
|
||||
@ -443,6 +457,14 @@ import java.util.*;
|
||||
this.id = id;
|
||||
this.entryMap = new HashMap<>();
|
||||
}
|
||||
public Entry getEntry(String entryName){
|
||||
for(Entry entry:entryMap.values()){
|
||||
if(entry.getName().equals(entryName)){
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public int getIdInt(){
|
||||
return 0xff & id;
|
||||
}
|
||||
|
@ -322,10 +322,6 @@ import java.util.Set;
|
||||
}
|
||||
public void setValueAsInteger(int val){
|
||||
setValueType(ValueType.INT_DEC);
|
||||
ResXmlAttributeArray array=getParentResXmlAttributeArray();
|
||||
if(array!=null && array.getFirstIntAttribute()==this){
|
||||
setValueType(ValueType.FIRST_INT);
|
||||
}
|
||||
setRawValue(val);
|
||||
setValueStringReference(-1);
|
||||
}
|
||||
|
@ -31,6 +31,49 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class ValueDecoder {
|
||||
|
||||
public static EncodeResult encodeGuessAny(String txt){
|
||||
if(txt==null){
|
||||
return null;
|
||||
}
|
||||
EncodeResult result=encodeColor(txt);
|
||||
if(result!=null){
|
||||
return result;
|
||||
}
|
||||
result=encodeDimensionOrFloat(txt);
|
||||
if(result!=null){
|
||||
return result;
|
||||
}
|
||||
result=encodeHexOrInt(txt);
|
||||
if(result!=null){
|
||||
return result;
|
||||
}
|
||||
return encodeBoolean(txt);
|
||||
}
|
||||
public static EncodeResult encodeBoolean(String txt){
|
||||
if(txt==null){
|
||||
return null;
|
||||
}
|
||||
txt=txt.trim().toLowerCase();
|
||||
if(txt.equals("true")){
|
||||
return new EncodeResult(ValueType.INT_BOOLEAN, 0xffffffff);
|
||||
}
|
||||
if(txt.equals("false")){
|
||||
return new EncodeResult(ValueType.INT_BOOLEAN, 0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static boolean isInteger(String txt){
|
||||
if(txt==null){
|
||||
return false;
|
||||
}
|
||||
return PATTERN_INTEGER.matcher(txt).matches();
|
||||
}
|
||||
public static boolean isHex(String txt){
|
||||
if(txt==null){
|
||||
return false;
|
||||
}
|
||||
return PATTERN_HEX.matcher(txt).matches();
|
||||
}
|
||||
public static boolean isReference(String txt){
|
||||
if(txt==null){
|
||||
return false;
|
||||
@ -49,33 +92,94 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static int encodeFloatOrDimension(String dimensionString){
|
||||
if(dimensionString==null){
|
||||
return 0;
|
||||
public static EncodeResult encodeColor(String value){
|
||||
if(value==null){
|
||||
return null;
|
||||
}
|
||||
Matcher matcher=PATTERN_DIMEN.matcher(dimensionString);
|
||||
Matcher matcher = PATTERN_COLOR.matcher(value);
|
||||
if(!matcher.find()){
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
value=matcher.group(1);
|
||||
ValueType valueType;
|
||||
if(value.length()==6){
|
||||
valueType=ValueType.INT_COLOR_RGB8;
|
||||
}else {
|
||||
valueType=ValueType.INT_COLOR_ARGB8;
|
||||
}
|
||||
return new EncodeResult(valueType, parseHex(value));
|
||||
}
|
||||
public static EncodeResult encodeHexOrInt(String numString){
|
||||
if(numString==null){
|
||||
return null;
|
||||
}
|
||||
if(isHex(numString)){
|
||||
return new EncodeResult(ValueType.INT_HEX, parseHex(numString));
|
||||
}
|
||||
if(isInteger(numString)){
|
||||
return new EncodeResult(ValueType.INT_DEC, parseHex(numString));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static int parseHex(String hexString){
|
||||
boolean negative=false;
|
||||
hexString=hexString.trim().toLowerCase();
|
||||
if(hexString.startsWith("-")){
|
||||
negative=true;
|
||||
hexString=hexString.substring(1);
|
||||
}
|
||||
if(!hexString.startsWith("0x")){
|
||||
hexString="0x"+hexString;
|
||||
}
|
||||
long l=Long.decode(hexString);
|
||||
if(negative){
|
||||
l=-l;
|
||||
}
|
||||
return (int) l;
|
||||
}
|
||||
public static int parseInteger(String intString){
|
||||
intString=intString.trim();
|
||||
boolean negative=false;
|
||||
if(intString.startsWith("-")){
|
||||
negative=true;
|
||||
intString=intString.substring(1);
|
||||
}
|
||||
long l=Long.parseLong(intString);
|
||||
if(negative){
|
||||
l=-l;
|
||||
}
|
||||
return (int) l;
|
||||
}
|
||||
public static EncodeResult encodeDimensionOrFloat(String value){
|
||||
if(value==null){
|
||||
return null;
|
||||
}
|
||||
Matcher matcher=PATTERN_DIMEN.matcher(value);
|
||||
if(!matcher.find()){
|
||||
return null;
|
||||
}
|
||||
String sign = matcher.group(1);
|
||||
String number = matcher.group(2);
|
||||
String unit = matcher.group(3);
|
||||
float value = Float.parseFloat(number);
|
||||
float fraction = Float.parseFloat(number);
|
||||
if("-".equals(sign)){
|
||||
value=-value;
|
||||
fraction=-fraction;
|
||||
}
|
||||
return encodeFloatOrDimension(value, unit);
|
||||
return encodeDimensionOrFloat(fraction, unit);
|
||||
}
|
||||
private static int encodeFloatOrDimension(float val, String unit){
|
||||
private static EncodeResult encodeDimensionOrFloat(float val, String unit){
|
||||
if(unit==null||"".equals(unit)){
|
||||
return Float.floatToIntBits(val);
|
||||
return new EncodeResult(ValueType.FLOAT,
|
||||
Float.floatToIntBits(val));
|
||||
}
|
||||
ValueType valueType = ValueType.DIMENSION;
|
||||
int index=0;
|
||||
if("%".equals(unit)||"%p".equals(unit)){
|
||||
val=val/100.0f;
|
||||
if("%p".equals(unit)){
|
||||
index=1;
|
||||
}
|
||||
valueType = ValueType.FRACTION;
|
||||
}else {
|
||||
index=ValueDecoder.getDimensionIndex(unit);
|
||||
}
|
||||
@ -93,10 +197,10 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
}
|
||||
}
|
||||
shift=shift<<4;
|
||||
result= result | shift;
|
||||
result= result | index;
|
||||
return result;
|
||||
shift = shift<<4;
|
||||
result = result | shift;
|
||||
result = result | index;
|
||||
return new EncodeResult(valueType, result);
|
||||
}
|
||||
|
||||
public static String decodeAttributeName(EntryStore store, PackageBlock currentPackage, int resourceId){
|
||||
@ -252,7 +356,7 @@ import java.util.regex.Pattern;
|
||||
// Should not happen the string could be in ResXmlBlock, but if you are lazy here it goes
|
||||
return decodeString(entryStore, currentPackageId, rawVal);
|
||||
}
|
||||
if(valueType==ValueType.FIRST_INT||valueType==ValueType.INT_HEX){
|
||||
if(valueType==ValueType.FIRST_INT||valueType==ValueType.INT_DEC||valueType==ValueType.INT_HEX){
|
||||
result=decodeAttribute(entryStore, nameResourceId, rawVal);
|
||||
if(result!=null){
|
||||
return result;
|
||||
@ -683,6 +787,18 @@ import java.util.regex.Pattern;
|
||||
str=str.trim();
|
||||
return str.length()==0;
|
||||
}
|
||||
public static class EncodeResult{
|
||||
public final ValueType valueType;
|
||||
public final int value;
|
||||
public EncodeResult(ValueType valueType, int value){
|
||||
this.valueType=valueType;
|
||||
this.value=value;
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return valueType+": "+String.format("0x%08x", value);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String[] DIMENSION_UNIT_STRS = new String[] { "px", "dip", "sp", "pt", "in", "mm" };
|
||||
private static final float MANTISSA_MULT = 1.0f / (1 << 8);
|
||||
@ -690,8 +806,8 @@ import java.util.regex.Pattern;
|
||||
1.0f * MANTISSA_MULT, 1.0f / (1 << 7) * MANTISSA_MULT,
|
||||
1.0f / (1 << 15) * MANTISSA_MULT, 1.0f / (1 << 23) * MANTISSA_MULT };
|
||||
|
||||
private static final Pattern PATTERN_COLOR = Pattern.compile("^#([0-9a-fA-F]{6,8})$");
|
||||
private static final Pattern PATTERN_DIMEN = Pattern.compile("^(-?)([0-9]+\\.[0-9E\\-+]+)([dimnpstx%]{0,3})$");
|
||||
public static final Pattern PATTERN_COLOR = Pattern.compile("^#([0-9a-fA-F]{6,8})$");
|
||||
public static final Pattern PATTERN_DIMEN = Pattern.compile("^(-?)([0-9]+\\.[0-9E\\-+]+)([dimnpstx%]{0,3})$");
|
||||
private static final Pattern PATTERN_INTEGER = Pattern.compile("^(-?)([0-9]+)$");
|
||||
private static final Pattern PATTERN_HEX = Pattern.compile("^0x[0-9a-fA-F]+$");
|
||||
public static final Pattern PATTERN_REFERENCE = Pattern.compile("^([?@])(([^\\s:@?/]+:)?)([^\\s:@?/]+)/([^\\s:@?/]+)$");
|
||||
|
@ -285,6 +285,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
return mSpecReference.get();
|
||||
}
|
||||
public void setSpecReference(int ref){
|
||||
if(mSpecReference==null){
|
||||
return;
|
||||
}
|
||||
int old=mSpecReference.get();
|
||||
if(ref==old){
|
||||
return;
|
||||
@ -294,7 +297,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
}
|
||||
public void setSpecReference(SpecString specString){
|
||||
removeSpecRef();
|
||||
mSpecReference.set(specString.getIndex());
|
||||
if(mSpecReference!=null){
|
||||
mSpecReference.set(specString.getIndex());
|
||||
}
|
||||
}
|
||||
public BaseResValue getResValue(){
|
||||
return mResValue;
|
||||
@ -639,6 +644,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
|
||||
}
|
||||
}
|
||||
private void removeSpecRef(){
|
||||
if(mSpecReference==null){
|
||||
return;
|
||||
}
|
||||
TypeBlock typeBlock=getTypeBlock();
|
||||
if(typeBlock==null){
|
||||
return;
|
||||
|
@ -80,6 +80,7 @@ public class ResValueBag extends BaseResValue {
|
||||
count=0;
|
||||
}
|
||||
mCount.set(count);
|
||||
mResValueBagItemArray.setChildesCount(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -121,7 +122,7 @@ public class ResValueBag extends BaseResValue {
|
||||
}
|
||||
|
||||
private void refreshCount(){
|
||||
setCount(getResValueBagItemArray().childesCount());
|
||||
mCount.set(getResValueBagItemArray().childesCount());
|
||||
}
|
||||
@Override
|
||||
protected int onWriteBytes(OutputStream writer) throws IOException {
|
||||
|
@ -171,7 +171,7 @@ public class ResValueBagItem extends BaseResValueItem{
|
||||
return;
|
||||
}
|
||||
beforeDataValueChanged();
|
||||
setShort(OFFSET_DATA+2, val);
|
||||
setShort(OFFSET_DATA, val);
|
||||
afterDataValueChanged();
|
||||
}
|
||||
@Override
|
||||
|
@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.reandroid.lib.arsc.value.attribute;
|
||||
|
||||
import com.reandroid.lib.arsc.decoder.ValueDecoder;
|
||||
import com.reandroid.lib.arsc.value.EntryBlock;
|
||||
import com.reandroid.lib.arsc.value.ResValueBag;
|
||||
import com.reandroid.lib.arsc.value.ValueType;
|
||||
import com.reandroid.lib.common.EntryStore;
|
||||
|
||||
|
||||
@ -25,6 +27,26 @@ public class AttributeBag {
|
||||
public AttributeBag(AttributeBagItem[] bagItems){
|
||||
this.mBagItems=bagItems;
|
||||
}
|
||||
public ValueDecoder.EncodeResult encodeName(String valueString){
|
||||
if(valueString==null){
|
||||
return null;
|
||||
}
|
||||
int value=0;
|
||||
boolean foundOnce=false;
|
||||
String[] names=valueString.split("[\\s|]+");
|
||||
for(String name:names){
|
||||
AttributeBagItem item=searchByName(name);
|
||||
if(item==null){
|
||||
continue;
|
||||
}
|
||||
value|=item.getBagItem().getData();
|
||||
foundOnce=true;
|
||||
}
|
||||
if(!foundOnce){
|
||||
return null;
|
||||
}
|
||||
return new ValueDecoder.EncodeResult(ValueType.INT_HEX, value);
|
||||
}
|
||||
public String decodeAttributeValue(EntryStore entryStore, int attrValue){
|
||||
AttributeBagItem[] bagItems=searchValue(attrValue);
|
||||
return AttributeBagItem.toString(entryStore, bagItems);
|
||||
@ -32,6 +54,18 @@ public class AttributeBag {
|
||||
public String decodeValueType(){
|
||||
return AttributeValueType.toString(getValueTypes());
|
||||
}
|
||||
public AttributeBagItem searchByName(String entryName){
|
||||
AttributeBagItem[] bagItems= getBagItems();
|
||||
for(AttributeBagItem item:bagItems){
|
||||
if(item.isType()){
|
||||
continue;
|
||||
}
|
||||
if(entryName.equals(item.getNameOrHex())){
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public AttributeBagItem[] searchValue(int attrValue){
|
||||
if(isFlag()){
|
||||
return searchFlagValue(attrValue);
|
||||
|
@ -45,6 +45,9 @@ public enum AttributeItemType {
|
||||
return null;
|
||||
}
|
||||
name=name.toUpperCase();
|
||||
if(name.equals("FORMATS")){
|
||||
return FORMAT;
|
||||
}
|
||||
for(AttributeItemType bagType:values()){
|
||||
if(name.equals(bagType.name())){
|
||||
return bagType;
|
||||
|
@ -15,10 +15,11 @@
|
||||
*/
|
||||
package com.reandroid.lib.arsc.value.attribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.reandroid.lib.arsc.value.ValueType;
|
||||
|
||||
public enum AttributeValueType {
|
||||
import java.util.*;
|
||||
|
||||
public enum AttributeValueType {
|
||||
REFERENCE((byte) 0x01),
|
||||
STRING((byte) 0x02),
|
||||
INTEGER((byte) 0x04),
|
||||
@ -129,4 +130,49 @@ public enum AttributeValueType {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Set<ValueType> toValueTypes(AttributeValueType[] types){
|
||||
Set<ValueType> results=new HashSet<>();
|
||||
if(types==null){
|
||||
return results;
|
||||
}
|
||||
for(AttributeValueType type:types){
|
||||
if(type==ANY){
|
||||
return new HashSet<>(Arrays.asList(ValueType.values()));
|
||||
}
|
||||
switch (type){
|
||||
case REFERENCE:
|
||||
results.add(ValueType.REFERENCE);
|
||||
results.add(ValueType.ATTRIBUTE);
|
||||
results.add(ValueType.DYNAMIC_REFERENCE);
|
||||
results.add(ValueType.DYNAMIC_ATTRIBUTE);
|
||||
break;
|
||||
case COLOR:
|
||||
results.add(ValueType.INT_COLOR_ARGB8);
|
||||
results.add(ValueType.INT_COLOR_ARGB4);
|
||||
results.add(ValueType.INT_COLOR_RGB8);
|
||||
results.add(ValueType.INT_COLOR_RGB4);
|
||||
break;
|
||||
case STRING:
|
||||
results.add(ValueType.STRING);
|
||||
break;
|
||||
case BOOL:
|
||||
results.add(ValueType.INT_BOOLEAN);
|
||||
break;
|
||||
case FLOAT:
|
||||
case FRACTION:
|
||||
results.add(ValueType.FLOAT);
|
||||
results.add(ValueType.FRACTION);
|
||||
break;
|
||||
case DIMENSION:
|
||||
results.add(ValueType.FRACTION);
|
||||
results.add(ValueType.DIMENSION);
|
||||
break;
|
||||
case INTEGER:
|
||||
results.add(ValueType.INT_DEC);
|
||||
results.add(ValueType.INT_HEX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public enum PluralsQuantity {
|
||||
if(name==null){
|
||||
return null;
|
||||
}
|
||||
name=name.toUpperCase();
|
||||
name=name.trim().toUpperCase();
|
||||
PluralsQuantity[] all=values();
|
||||
for(PluralsQuantity pq:all){
|
||||
if(name.equals(pq.name())){
|
||||
|
21
src/main/java/com/reandroid/lib/common/ResourceResolver.java
Normal file
21
src/main/java/com/reandroid/lib/common/ResourceResolver.java
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2022 github.com/REAndroid
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.reandroid.lib.common;
|
||||
|
||||
public interface ResourceResolver {
|
||||
int resolveResourceId(String packageName, String type, String name);
|
||||
int resolveResourceId(int packageId, String type, String name);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user