diff options
Diffstat (limited to 'plugin/src/main/java/ch/jodersky/sbt/jni/javah/Utils.java')
-rw-r--r-- | plugin/src/main/java/ch/jodersky/sbt/jni/javah/Utils.java | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/plugin/src/main/java/ch/jodersky/sbt/jni/javah/Utils.java b/plugin/src/main/java/ch/jodersky/sbt/jni/javah/Utils.java new file mode 100644 index 0000000..61e7a96 --- /dev/null +++ b/plugin/src/main/java/ch/jodersky/sbt/jni/javah/Utils.java @@ -0,0 +1,133 @@ +package ch.jodersky.sbt.jni.javah; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +class Utils { + public static final int MAX_SUPPORTED_VERSION = 13; + + public static final List<String> MULTI_RELEASE_VERSIONS = + IntStream.rangeClosed(9, MAX_SUPPORTED_VERSION).mapToObj(Integer::toString).collect(Collectors.toList()); + + public static final Pattern SIMPLE_NAME_PATTERN = Pattern.compile("[^.;\\[/]+"); + public static final Pattern FULL_NAME_PATTERN = + Pattern.compile("[^.;\\[/]+(\\.[^.;\\[/]+)*"); + + public static final Pattern METHOD_NAME_PATTERN = Pattern.compile("(<init>)|(<cinit>)|([^.;\\[/<>]+)"); + public static final Pattern METHOD_TYPE_PATTERN = + Pattern.compile("\\((?<args>(\\[*([BCDFIJSZ]|L[^.;\\[/]+(/[^.;\\\\\\[/]+)*;))*)\\)(?<ret>\\[*([BCDFIJSZV]|L[^.;\\[/]+(/[^.;\\[/]+)*;))"); + + public static final PrintWriter NOOP_WRITER = new PrintWriter(new Writer() { + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + } + + @Override + public void flush() throws IOException { + } + + @Override + public void close() throws IOException { + } + }); + + public static String mangleName(String name) { + StringBuilder builder = new StringBuilder(name.length() * 2); + int len = name.length(); + for (int i = 0; i < len; i++) { + char ch = name.charAt(i); + if (ch == '.') { + builder.append('_'); + } else if (ch == '_') { + builder.append("_1"); + } else if (ch == ';') { + builder.append("_2"); + } else if (ch == '[') { + builder.append("_3"); + } else if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && (ch <= 'Z'))) { + builder.append(ch); + } else { + builder.append(String.format("_0%04x", (int) ch)); + } + } + return builder.toString(); + } + + public static String escape(String unicode) { + Objects.requireNonNull(unicode); + int len = unicode.length(); + StringBuilder builder = new StringBuilder(len); + for (int i = 0; i < len; i++) { + char ch = unicode.charAt(i); + if (ch >= ' ' && ch <= '~') { + builder.append(ch); + } else { + builder.append(String.format("\\u%04x", (int) ch)); + } + } + return builder.toString(); + } + + public static Path classPathRoot(Path p) { + Objects.requireNonNull(p); + p = p.toAbsolutePath(); + + if (Files.notExists(p)) { + return null; + } + if (Files.isDirectory(p)) { + return p; + } + + try { + FileSystem fs = FileSystems.newFileSystem(p, (ClassLoader) null); + String name = p.getFileName().toString().toLowerCase(); + if (name.endsWith(".jar") || name.endsWith(".zip")) { + return fs.getPath("/"); + } + if (name.endsWith(".jmod")) { + return fs.getPath("/", "classes"); + } + + fs.close(); + } catch (IOException ignored) { + return null; + } + return null; + } + + public static ClassName superClassOf(ClassReader reader) { + Objects.requireNonNull(reader); + class V extends ClassVisitor { + V() { + super(Opcodes.ASM6); + } + + ClassName superName = null; + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + if (superName != null) { + this.superName = ClassName.of(superName.replace('/', '.')); + } + } + } + V v = new V(); + reader.accept(v, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); + return v.superName; + } +} |