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

View File

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

View File

@ -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:@?/]+)$");

View File

@ -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;

View File

@ -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 {

View File

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

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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())){

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