prepare for XMLEncode

This commit is contained in:
REAndroid 2023-01-02 09:59:28 -05:00
parent d8065f0b9e
commit a7424bbf96
11 changed files with 276 additions and 29 deletions

View File

@ -24,7 +24,6 @@ import com.reandroid.lib.json.JSONObject;
import com.reandroid.xml.*; import com.reandroid.xml.*;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
public class ResourceIds { public class ResourceIds {
@ -248,6 +247,21 @@ import java.util.*;
this.id = id; this.id = id;
this.typeMap = new HashMap<>(); 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(){ public int getIdInt(){
return 0xff & id; return 0xff & id;
} }
@ -443,6 +457,14 @@ import java.util.*;
this.id = id; this.id = id;
this.entryMap = new HashMap<>(); 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(){ public int getIdInt(){
return 0xff & id; return 0xff & id;
} }

View File

@ -322,10 +322,6 @@ import java.util.Set;
} }
public void setValueAsInteger(int val){ public void setValueAsInteger(int val){
setValueType(ValueType.INT_DEC); setValueType(ValueType.INT_DEC);
ResXmlAttributeArray array=getParentResXmlAttributeArray();
if(array!=null && array.getFirstIntAttribute()==this){
setValueType(ValueType.FIRST_INT);
}
setRawValue(val); setRawValue(val);
setValueStringReference(-1); setValueStringReference(-1);
} }

View File

@ -31,6 +31,49 @@ import java.util.regex.Pattern;
public class ValueDecoder { 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){ public static boolean isReference(String txt){
if(txt==null){ if(txt==null){
return false; return false;
@ -49,33 +92,94 @@ import java.util.regex.Pattern;
} }
return false; return false;
} }
public static int encodeFloatOrDimension(String dimensionString){ public static EncodeResult encodeColor(String value){
if(dimensionString==null){ if(value==null){
return 0; return null;
} }
Matcher matcher=PATTERN_DIMEN.matcher(dimensionString); Matcher matcher = PATTERN_COLOR.matcher(value);
if(!matcher.find()){ 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 sign = matcher.group(1);
String number = matcher.group(2); String number = matcher.group(2);
String unit = matcher.group(3); String unit = matcher.group(3);
float value = Float.parseFloat(number); float fraction = Float.parseFloat(number);
if("-".equals(sign)){ 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)){ if(unit==null||"".equals(unit)){
return Float.floatToIntBits(val); return new EncodeResult(ValueType.FLOAT,
Float.floatToIntBits(val));
} }
ValueType valueType = ValueType.DIMENSION;
int index=0; int index=0;
if("%".equals(unit)||"%p".equals(unit)){ if("%".equals(unit)||"%p".equals(unit)){
val=val/100.0f; val=val/100.0f;
if("%p".equals(unit)){ if("%p".equals(unit)){
index=1; index=1;
} }
valueType = ValueType.FRACTION;
}else { }else {
index=ValueDecoder.getDimensionIndex(unit); index=ValueDecoder.getDimensionIndex(unit);
} }
@ -93,10 +197,10 @@ import java.util.regex.Pattern;
} }
} }
} }
shift=shift<<4; shift = shift<<4;
result= result | shift; result = result | shift;
result= result | index; result = result | index;
return result; return new EncodeResult(valueType, result);
} }
public static String decodeAttributeName(EntryStore store, PackageBlock currentPackage, int resourceId){ 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 // Should not happen the string could be in ResXmlBlock, but if you are lazy here it goes
return decodeString(entryStore, currentPackageId, rawVal); 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); result=decodeAttribute(entryStore, nameResourceId, rawVal);
if(result!=null){ if(result!=null){
return result; return result;
@ -683,6 +787,18 @@ import java.util.regex.Pattern;
str=str.trim(); str=str.trim();
return str.length()==0; 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 String[] DIMENSION_UNIT_STRS = new String[] { "px", "dip", "sp", "pt", "in", "mm" };
private static final float MANTISSA_MULT = 1.0f / (1 << 8); 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 * MANTISSA_MULT, 1.0f / (1 << 7) * MANTISSA_MULT,
1.0f / (1 << 15) * MANTISSA_MULT, 1.0f / (1 << 23) * 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})$"); public 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_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_INTEGER = Pattern.compile("^(-?)([0-9]+)$");
private static final Pattern PATTERN_HEX = Pattern.compile("^0x[0-9a-fA-F]+$"); private static final Pattern PATTERN_HEX = Pattern.compile("^0x[0-9a-fA-F]+$");
public static final Pattern PATTERN_REFERENCE = Pattern.compile("^([?@])(([^\\s:@?/]+:)?)([^\\s:@?/]+)/([^\\s:@?/]+)$"); public static final Pattern PATTERN_REFERENCE = Pattern.compile("^([?@])(([^\\s:@?/]+:)?)([^\\s:@?/]+)/([^\\s:@?/]+)$");

View File

@ -285,6 +285,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
return mSpecReference.get(); return mSpecReference.get();
} }
public void setSpecReference(int ref){ public void setSpecReference(int ref){
if(mSpecReference==null){
return;
}
int old=mSpecReference.get(); int old=mSpecReference.get();
if(ref==old){ if(ref==old){
return; return;
@ -294,8 +297,10 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
} }
public void setSpecReference(SpecString specString){ public void setSpecReference(SpecString specString){
removeSpecRef(); removeSpecRef();
if(mSpecReference!=null){
mSpecReference.set(specString.getIndex()); mSpecReference.set(specString.getIndex());
} }
}
public BaseResValue getResValue(){ public BaseResValue getResValue(){
return mResValue; return mResValue;
} }
@ -639,6 +644,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
} }
} }
private void removeSpecRef(){ private void removeSpecRef(){
if(mSpecReference==null){
return;
}
TypeBlock typeBlock=getTypeBlock(); TypeBlock typeBlock=getTypeBlock();
if(typeBlock==null){ if(typeBlock==null){
return; return;

View File

@ -80,6 +80,7 @@ public class ResValueBag extends BaseResValue {
count=0; count=0;
} }
mCount.set(count); mCount.set(count);
mResValueBagItemArray.setChildesCount(count);
} }
@Override @Override
@ -121,7 +122,7 @@ public class ResValueBag extends BaseResValue {
} }
private void refreshCount(){ private void refreshCount(){
setCount(getResValueBagItemArray().childesCount()); mCount.set(getResValueBagItemArray().childesCount());
} }
@Override @Override
protected int onWriteBytes(OutputStream writer) throws IOException { protected int onWriteBytes(OutputStream writer) throws IOException {

View File

@ -171,7 +171,7 @@ public class ResValueBagItem extends BaseResValueItem{
return; return;
} }
beforeDataValueChanged(); beforeDataValueChanged();
setShort(OFFSET_DATA+2, val); setShort(OFFSET_DATA, val);
afterDataValueChanged(); afterDataValueChanged();
} }
@Override @Override

View File

@ -15,8 +15,10 @@
*/ */
package com.reandroid.lib.arsc.value.attribute; 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.EntryBlock;
import com.reandroid.lib.arsc.value.ResValueBag; import com.reandroid.lib.arsc.value.ResValueBag;
import com.reandroid.lib.arsc.value.ValueType;
import com.reandroid.lib.common.EntryStore; import com.reandroid.lib.common.EntryStore;
@ -25,6 +27,26 @@ public class AttributeBag {
public AttributeBag(AttributeBagItem[] bagItems){ public AttributeBag(AttributeBagItem[] bagItems){
this.mBagItems=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){ public String decodeAttributeValue(EntryStore entryStore, int attrValue){
AttributeBagItem[] bagItems=searchValue(attrValue); AttributeBagItem[] bagItems=searchValue(attrValue);
return AttributeBagItem.toString(entryStore, bagItems); return AttributeBagItem.toString(entryStore, bagItems);
@ -32,6 +54,18 @@ public class AttributeBag {
public String decodeValueType(){ public String decodeValueType(){
return AttributeValueType.toString(getValueTypes()); 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){ public AttributeBagItem[] searchValue(int attrValue){
if(isFlag()){ if(isFlag()){
return searchFlagValue(attrValue); return searchFlagValue(attrValue);

View File

@ -45,6 +45,9 @@ public enum AttributeItemType {
return null; return null;
} }
name=name.toUpperCase(); name=name.toUpperCase();
if(name.equals("FORMATS")){
return FORMAT;
}
for(AttributeItemType bagType:values()){ for(AttributeItemType bagType:values()){
if(name.equals(bagType.name())){ if(name.equals(bagType.name())){
return bagType; return bagType;

View File

@ -15,10 +15,11 @@
*/ */
package com.reandroid.lib.arsc.value.attribute; package com.reandroid.lib.arsc.value.attribute;
import java.util.ArrayList; import com.reandroid.lib.arsc.value.ValueType;
import java.util.List;
public enum AttributeValueType { import java.util.*;
public enum AttributeValueType {
REFERENCE((byte) 0x01), REFERENCE((byte) 0x01),
STRING((byte) 0x02), STRING((byte) 0x02),
INTEGER((byte) 0x04), INTEGER((byte) 0x04),
@ -129,4 +130,49 @@ public enum AttributeValueType {
} }
return null; 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;
}
} }

View File

@ -48,7 +48,7 @@ public enum PluralsQuantity {
if(name==null){ if(name==null){
return null; return null;
} }
name=name.toUpperCase(); name=name.trim().toUpperCase();
PluralsQuantity[] all=values(); PluralsQuantity[] all=values();
for(PluralsQuantity pq:all){ for(PluralsQuantity pq:all){
if(name.equals(pq.name())){ if(name.equals(pq.name())){

View 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);
}