All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.reandroid.dex.key.FieldKey Maven / Gradle / Ivy

/*
 *  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.dex.key;

import com.reandroid.dex.id.FieldId;
import com.reandroid.dex.smali.SmaliParseException;
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.StringsUtil;
import com.reandroid.utils.collection.CombiningIterator;
import com.reandroid.utils.collection.SingleIterator;

import java.io.IOException;
import java.util.Iterator;
import java.util.function.Function;


public class FieldKey implements Key {

    private final String declaring;
    private final String name;
    private final String type;

    public FieldKey(String declaring, String name, String type) {
        this.declaring = declaring;
        this.name = name;
        this.type = type;
    }

    @Deprecated
    public FieldKey changeDefining(TypeKey typeKey){
        return changeDeclaring(typeKey);
    }
    @Deprecated
    public FieldKey changeDefining(String defining){
        return changeDeclaring(defining);
    }
    public FieldKey changeDeclaring(TypeKey typeKey){
        return changeDeclaring(typeKey.getTypeName());
    }
    public FieldKey changeDeclaring(String defining){
        if(defining.equals(getDeclaringName())){
            return this;
        }
        return new FieldKey(defining, getName(), getTypeName());
    }
    public FieldKey changeName(String name){
        if(name.equals(getName())){
            return this;
        }
        return new FieldKey(getDeclaringName(), name, getTypeName());
    }
    public FieldKey changeType(TypeKey typeKey){
        return changeType(typeKey.getTypeName());
    }
    public FieldKey changeType(String type){
        if(type.equals(getTypeName())){
            return this;
        }
        return new FieldKey(getDeclaringName(), getName(), type);
    }

    @Override
    public TypeKey getDeclaring() {
        return new TypeKey(getDeclaringName());
    }
    @Override
    public Iterator mentionedKeys() {
        return CombiningIterator.singleThree(
                FieldKey.this,
                SingleIterator.of(getDeclaring()),
                SingleIterator.of(getNameKey()),
                SingleIterator.of(getType()));
    }

    public FieldKey replaceTypes(Function function) {

        FieldKey result = this;

        TypeKey typeKey = getDeclaring();
        typeKey = typeKey.changeTypeName(function.apply(typeKey));

        result = result.changeDeclaring(typeKey);

        typeKey = getType();
        typeKey = typeKey.changeTypeName(function.apply(typeKey));

        result = result.changeType(typeKey);

        return result;
    }
    @Override
    public Key replaceKey(Key search, Key replace) {
        FieldKey result = this;
        if(search.equals(result)){
            return replace;
        }
        if(search.equals(result.getDeclaring())){
            result = result.changeDeclaring((TypeKey) replace);
        }
        if(search.equals(result.getType())){
            result = result.changeType((TypeKey) replace);
        }
        return result;
    }

    public StringKey getNameKey() {
        return new StringKey(getName());
    }
    public TypeKey getType() {
        return new TypeKey(getTypeName());
    }

    public String getDeclaringName() {
        return declaring;
    }
    public String getName() {
        return name;
    }
    public String getTypeName() {
        return type;
    }

    @Override
    public void append(SmaliWriter writer) throws IOException {
        writer.appendOptional(getDeclaring());
        writer.append("->");
        writer.append(getName());
        writer.append(':');
        writer.appendOptional(getType());
    }

    @Override
    public int compareTo(Object obj) {
        return compareTo(obj, true);
    }
    public int compareTo(Object obj, boolean compareDefining) {
        if(obj == null){
            return -1;
        }
        FieldKey key = (FieldKey) obj;
        int i;
        if(compareDefining){
            i = CompareUtil.compare(getDeclaringName(), key.getDeclaringName());
            if(i != 0) {
                return i;
            }
        }
        i = CompareUtil.compare(getName(), key.getName());
        if(i != 0) {
            return i;
        }
        return CompareUtil.compare(getTypeName(), key.getTypeName());
    }

    @Override
    public int hashCode() {
        int hash = 1;
        String defining = getDeclaringName();
        if(defining != null){
            hash += defining.hashCode();
        }
        return hash * 31 + getName().hashCode();
    }

    public boolean equalsDeclaring(String declaring){
        if(declaring == null){
            return false;
        }
        return KeyUtil.matches(getDeclaringName(), declaring);
    }
    public boolean equalsDeclaring(TypeKey declaring){
        if(declaring == null){
            return false;
        }
        return KeyUtil.matches(getDeclaringName(), declaring.getTypeName());
    }
    public boolean equalsDeclaring(FieldKey other){
        if(other == null){
            return false;
        }
        if(other == this){
            return true;
        }
        return KeyUtil.matches(getDeclaringName(), other.getDeclaringName());
    }
    public boolean equalsIgnoreName(FieldKey other){
        if(other == null){
            return false;
        }
        if(other == this){
            return true;
        }
        if(!KeyUtil.matches(getDeclaringName(), other.getDeclaringName())){
            return false;
        }
        return KeyUtil.matches(getTypeName(), other.getTypeName());
    }
    public boolean equalsName(FieldKey other){
        if(other == null){
            return false;
        }
        if(other == this){
            return true;
        }
        return KeyUtil.matches(getName(), other.getName());
    }
    public boolean equalsName(String name){
        return KeyUtil.matches(getName(), name);
    }
    public boolean equalsType(String returnTypeName){
        return KeyUtil.matches(getTypeName(), returnTypeName);
    }
    public boolean equalsType(TypeKey returnType){
        if(returnType == null){
            return false;
        }
        return KeyUtil.matches(getTypeName(), returnType.getTypeName());
    }
    public boolean equalsType(FieldKey other){
        if(other == null){
            return false;
        }
        if(other == this){
            return true;
        }
        return KeyUtil.matches(getTypeName(), other.getTypeName());
    }
    @Override
    public boolean equals(Object obj) {
        return equals(obj, true, true);
    }
    public boolean equals(Object obj, boolean checkDefining, boolean checkType) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof FieldKey)) {
            return false;
        }
        FieldKey fieldKey = (FieldKey) obj;
        if(!KeyUtil.matches(getName(), fieldKey.getName())){
            return false;
        }
        if(checkDefining){
            if(!KeyUtil.matches(getDeclaringName(), fieldKey.getDeclaringName())){
                return false;
            }
        }
        if(checkType){
            return KeyUtil.matches(getTypeName(), fieldKey.getTypeName());
        }
        return true;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(getDeclaringName());
        builder.append("->");
        builder.append(getName());
        String type = getTypeName();
        if(type != null){
            builder.append(':');
            builder.append(getTypeName());
        }
        return builder.toString();
    }

    public static FieldKey parse(String text) {
        if(text == null){
            return null;
        }
        text = text.trim();
        if(text.length() < 6 || text.charAt(0) != 'L'){
            return null;
        }
        int i = text.indexOf(";->");
        if(i < 0){
            return null;
        }
        String defining = text.substring(0, i + 1);
        text = text.substring(i + 3);
        i = text.indexOf(':');
        if(i < 0){
            return null;
        }
        String name = text.substring(0, i);
        text = text.substring(i + 1);
        String type = null;
        if(!StringsUtil.isEmpty(text)){
            type = text;
        }
        return new FieldKey(defining, name, type);
    }
    public static FieldKey create(FieldId fieldId){
        TypeKey defining = fieldId.getDefining();
        if(defining == null){
            return null;
        }
        String name = fieldId.getName();
        if(name == null) {
            return null;
        }
        TypeKey fieldType = fieldId.getFieldType();
        if(fieldType == null){
            return null;
        }
        return new FieldKey(defining.getTypeName(), name, fieldType.getTypeName());
    }

    public static FieldKey read(SmaliReader reader) throws IOException {
        TypeKey declaring = TypeKey.read(reader);
        reader.skipWhitespacesOrComment();
        SmaliParseException.expect(reader, '-');
        SmaliParseException.expect(reader, '>');
        reader.skipWhitespacesOrComment();
        int i;
        int i1 = reader.indexOfBeforeLineEnd(':');
        int i2 = reader.indexOfWhiteSpaceOrComment();
        if(i1 < 0 && i2 < 0){
            throw new SmaliParseException("Expecting ':'", reader);
        }
        if(i1 < 0 || i2 >= 0 && i2 < i1){
            i = i2;
        }else {
            i = i1;
        }
        char stop = reader.getASCII(i);
        String name = reader.readEscapedString(stop);
        reader.skipWhitespacesOrComment();
        SmaliParseException.expect(reader, ':');
        TypeKey type = TypeKey.read(reader);
        return new FieldKey(declaring.getTypeName(), name, type.getTypeName());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy