
com.reandroid.dex.key.ProtoKey Maven / Gradle / Ivy
package com.reandroid.dex.key;
import com.reandroid.dex.id.ProtoId;
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.collection.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
public class ProtoKey implements Key{
private final String[] parameters;
private final String returnType;
private int mHash;
public ProtoKey(String[] parameters, String returnType){
this.parameters = parameters;
this.returnType = returnType;
}
public int getRegister(int index) {
int result = 0;
int size = getParametersCount();
if(index < size){
size = index;
}
for(int i = 0; i < size; i++){
TypeKey typeKey = getParameter(i);
result ++;
if(typeKey.isWide()){
result ++;
}
}
return result;
}
public int getParameterIndex(int register) {
int size = getParametersCount();
int registerCount = 0;
for(int i = 0; i < size; i++){
if(registerCount == register){
return i;
}
TypeKey typeKey = getParameter(i);
registerCount ++;
if(typeKey.isWide()){
registerCount ++;
}
}
return -1;
}
public ProtoKey removeParameter(int index){
TypeListKey typeListKey = getParameterListKey();
if(typeListKey != null){
typeListKey = typeListKey.remove(index);
}
return create(typeListKey, getReturnTypeName());
}
public ProtoKey changeReturnType(TypeKey typeKey){
return changeReturnType(typeKey.getTypeName());
}
public ProtoKey changeReturnType(String type){
if(type.equals(getReturnTypeName())){
return this;
}
return new ProtoKey(getParameterNames(), type);
}
public TypeListKey getParameterListKey() {
return TypeListKey.create(getParameterNames());
}
public TypeKey getReturnType() {
return new TypeKey(getReturnTypeName());
}
public String getReturnTypeName() {
return returnType;
}
public int getParametersCount() {
String[] parameters = getParameterNames();
if(parameters != null){
return parameters.length;
}
return 0;
}
public String[] getParameterNames() {
return parameters;
}
public String getParameterName(int i){
return getParameterNames()[i];
}
public TypeKey getParameter(int i){
return TypeKey.create(getParameterName(i));
}
public Iterator getParameters(){
return ComputeIterator.of(ArrayIterator.of(getParameterNames()), TypeKey::create);
}
public String getShorty(){
StringBuilder builder = new StringBuilder();
builder.append(toShorty(getReturnTypeName()));
String[] parameters = getParameterNames();
if(parameters != null){
for(String param : parameters){
builder.append(toShorty(param));
}
}
return builder.toString();
}
public int getParameterRegistersCount(){
int result = 0;
Iterator iterator = getParameters();
while (iterator.hasNext()){
TypeKey key = iterator.next();
result ++;
if(key.isWide()){
result ++;
}
}
return result;
}
@Override
public Iterator mentionedKeys() {
return CombiningIterator.singleThree(
ProtoKey.this,
SingleIterator.of(StringKey.create(getShorty())),
getParameters(),
SingleIterator.of(getReturnType()));
}
@Override
public Key replaceKey(Key search, Key replace) {
ProtoKey result = this;
if(search.equals(result)){
return replace;
}
if(search.equals(result.getReturnType())){
result = result.changeReturnType((TypeKey) replace);
}
String[] parameters = this.getParameterNames();
if(parameters != null && search instanceof TypeKey){
TypeKey searchType = (TypeKey) search;
String replaceType = ((TypeKey) replace).getTypeName();
int length = parameters.length;
for(int i = 0; i < length; i++){
if(searchType.equals(new TypeKey(parameters[i]))){
parameters[i] = replaceType;
}
}
}
return result;
}
@Override
public void append(SmaliWriter writer) throws IOException {
writer.append('(');
writer.appendAll(getParameters(), false);
writer.append(')');
getReturnType().append(writer);
}
@Override
public int compareTo(Object obj) {
if(obj == null){
return -1;
}
ProtoKey key = (ProtoKey) obj;
int i = CompareUtil.compare(getParameterNames(), key.getParameterNames());
if(i != 0) {
return i;
}
return CompareUtil.compare(getReturnTypeName(), key.getReturnTypeName());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ProtoKey)) {
return false;
}
ProtoKey protoKey = (ProtoKey) obj;
return Objects.equals(getReturnTypeName(), protoKey.getReturnTypeName()) &&
CompareUtil.compare(getParameterNames(), protoKey.getParameterNames()) == 0;
}
@Override
public int hashCode() {
int hash = mHash;
if(hash != 0){
return hash;
}
hash = 1;
String type = getReturnTypeName();
if(type != null){
hash += type.hashCode();
}
String[] parameters = getParameterNames();
if(parameters != null){
for(String param : parameters){
hash = hash * 31 + param.hashCode();
}
}
mHash = hash;
return hash;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append('(');
String[] parameters = getParameterNames();
if(parameters != null){
for (String parameter : parameters) {
builder.append(parameter);
}
}
builder.append(')');
String type = getReturnTypeName();
if(type != null){
builder.append(type);
}
return builder.toString();
}
public static ProtoKey create(ProtoId protoId){
TypeKey returnType = protoId.getReturnType();
if(returnType == null){
return null;
}
return new ProtoKey(protoId.getParameterNames(), returnType.getTypeName());
}
public static ProtoKey create(TypeListKey typeListKey, String returnType){
if(returnType == null){
return null;
}
String[] parameters = null;
if(typeListKey != null){
parameters = typeListKey.getParameterNames();
}
return new ProtoKey(parameters, returnType);
}
public static ProtoKey read(SmaliReader reader) throws IOException {
reader.skipWhitespacesOrComment();
SmaliParseException.expect(reader, '(');
reader.skipWhitespacesOrComment();
List parameterKeys = new ArrayCollection<>();
while (!reader.finished() && reader.get() != ')'){
parameterKeys.add(TypeKey.read(reader));
reader.skipWhitespacesOrComment();
}
SmaliParseException.expect(reader, ')');
TypeKey returnType = TypeKey.read(reader);
int size = parameterKeys.size();
String[] parameters;
if(size == 0){
parameters = null;
}else {
parameters = new String[size];
for(int i = 0; i < size; i++){
parameters[i] = parameterKeys.get(i).getTypeName();
}
}
return new ProtoKey(parameters, returnType.getTypeName());
}
private static char toShorty(String typeName) {
if(typeName.length() == 1){
return typeName.charAt(0);
}
if(typeName.length() == 0){
throw new RuntimeException();
}
return 'L';
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy