aboutsummaryrefslogblamecommitdiff
path: root/src/main/java/org/glavo/javah/Utils.java
blob: cb1ceef8b5d4508b8d15094db998c007934b1c1c (plain) (tree)
1
2
3
4
5
6
7
8
9

                        


                                      
 
                           

                           



                                 





                                   

             
                                                       
 

                                                                                                                     
 


                                                                                    
 


                                                                                                                                                     
 


                                                                                
         
 

                                                
         
 



                                                
 
















                                                                                                            

             
                                  

     









                                                                   

             

                                  
 


                                              
 

                                 
         

                                   
         
 
             







                                                                             
 
                       
                                       
                        
         
                    

     




                                                              
             
 
                                       
 




                                                                                                                              

             


                                                                                                   

     
package org.glavo.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.Collections;
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.ASM7);
            }

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