package com.sun.tools.jdi;
import java.util.ArrayList;
import java.util.List;
public class JNITypeParser {
static final char SIGNATURE_ENDCLASS = ';';
static final char SIGNATURE_FUNC = '(';
static final char SIGNATURE_ENDFUNC = ')';
private String signature;
private List<String> typeNameList;
private List<String> signatureList;
private int currentIndex;
JNITypeParser(String signature) {
this.signature = signature;
}
static String typeNameToSignature(String signature) {
StringBuilder sb = new StringBuilder();
int firstIndex = signature.indexOf('[');
int index = firstIndex;
while (index != -1) {
sb.append('[');
index = signature.indexOf('[', index + 1);
}
if (firstIndex != -1) {
signature = signature.substring(0, firstIndex);
}
if (signature.equals("boolean")) {
sb.append('Z');
} else if (signature.equals("byte")) {
sb.append('B');
} else if (signature.equals("char")) {
sb.append('C');
} else if (signature.equals("short")) {
sb.append('S');
} else if (signature.equals("int")) {
sb.append('I');
} else if (signature.equals("long")) {
sb.append('J');
} else if (signature.equals("float")) {
sb.append('F');
} else if (signature.equals("double")) {
sb.append('D');
} else {
sb.append('L');
sb.append(signature.replace('.', '/'));
sb.append(';');
}
return sb.toString();
}
String typeName() {
return typeNameList().get(typeNameList().size()-1);
}
List<String> argumentTypeNames() {
return typeNameList().subList(0, typeNameList().size() - 1);
}
String signature() {
return signatureList().get(signatureList().size()-1);
}
List<String> argumentSignatures() {
return signatureList().subList(0, signatureList().size() - 1);
}
int dimensionCount() {
int count = 0;
String signature = signature();
while (signature.charAt(count) == '[') {
count++;
}
return count;
}
String componentSignature(int level) {
return signature().substring(level);
}
private synchronized List<String> signatureList() {
if (signatureList == null) {
signatureList = new ArrayList<>(10);
String elem;
currentIndex = 0;
while(currentIndex < signature.length()) {
elem = nextSignature();
signatureList.add(elem);
}
if (signatureList.size() == 0) {
throw new IllegalArgumentException("Invalid JNI signature '" +
signature + "'");
}
}
return signatureList;
}
private synchronized List<String> typeNameList() {
if (typeNameList == null) {
typeNameList = new ArrayList<>(10);
String elem;
currentIndex = 0;
while(currentIndex < signature.length()) {
elem = nextTypeName();
typeNameList.add(elem);
}
if (typeNameList.size() == 0) {
throw new IllegalArgumentException("Invalid JNI signature '" +
signature + "'");
}
}
return typeNameList;
}
private String nextSignature() {
char key = signature.charAt(currentIndex++);
switch(key) {
case (JDWP.Tag.ARRAY):
return key + nextSignature();
case (JDWP.Tag.OBJECT):
int endClass = signature.indexOf(SIGNATURE_ENDCLASS,
currentIndex);
String retVal = signature.substring(currentIndex - 1,
endClass + 1);
currentIndex = endClass + 1;
return retVal;
case (JDWP.Tag.VOID):
case (JDWP.Tag.BOOLEAN):
case (JDWP.Tag.BYTE):
case (JDWP.Tag.CHAR):
case (JDWP.Tag.SHORT):
case (JDWP.Tag.INT):
case (JDWP.Tag.LONG):
case (JDWP.Tag.FLOAT):
case (JDWP.Tag.DOUBLE):
return String.valueOf(key);
case SIGNATURE_ENDFUNC:
case SIGNATURE_FUNC:
return nextSignature();
default:
throw new IllegalArgumentException(
"Invalid JNI signature character '" + key + "'");
}
}
private String nextTypeName() {
char key = signature.charAt(currentIndex++);
switch(key) {
case (JDWP.Tag.ARRAY):
return nextTypeName() + "[]";
case (JDWP.Tag.BYTE):
return "byte";
case (JDWP.Tag.CHAR):
return "char";
case (JDWP.Tag.OBJECT):
int endClass = signature.indexOf(SIGNATURE_ENDCLASS,
currentIndex);
String retVal = signature.substring(currentIndex,
endClass);
retVal = retVal.replace('/','.');
currentIndex = endClass + 1;
return retVal;
case (JDWP.Tag.FLOAT):
return "float";
case (JDWP.Tag.DOUBLE):
return "double";
case (JDWP.Tag.INT):
return "int";
case (JDWP.Tag.LONG):
return "long";
case (JDWP.Tag.SHORT):
return "short";
case (JDWP.Tag.VOID):
return "void";
case (JDWP.Tag.BOOLEAN):
return "boolean";
case SIGNATURE_ENDFUNC:
case SIGNATURE_FUNC:
return nextTypeName();
default:
throw new IllegalArgumentException(
"Invalid JNI signature character '" + key + "'");
}
}
}