001    /*
002     *                    BioJava development code
003     *
004     * This code may be freely distributed and modified under the
005     * terms of the GNU Lesser General Public Licence.  This should
006     * be distributed with the code.  If you do not have a copy,
007     * see:
008     *
009     *      http://www.gnu.org/copyleft/lesser.html
010     *
011     * Copyright for this code is held jointly by the individual
012     * authors.  These should be listed in @author doc comments.
013     *
014     * For more information on the BioJava project and its aims,
015     * or to join the biojava-l mailing list, visit the home page
016     * at:
017     *
018     *      http://www.biojava.org/
019     *
020     */
021    package org.biojava.utils.bytecode;
022    
023    /**
024     * Utility code for things you will frequently need.
025     *
026     * <p>
027     * This class provides common constants representing access modifiers and
028     * types. There are also some utility methods for munging data.
029     * </p>
030     *
031     * @author Thomas Down
032     * @author Matthew Pocock
033     */
034    public class CodeUtils {
035      public static final int ACC_PUBLIC       = 0x0001;
036      public static final int ACC_PRIVATE      = 0x0002;
037      public static final int ACC_PROTECTED    = 0x0004;
038      public static final int ACC_STATIC       = 0x0008;
039      public static final int ACC_FINAL        = 0x0010;
040      public static final int ACC_SUPER        = 0x0020;
041      public static final int ACC_SYNCHRONIZED = 0x0020;
042      public static final int ACC_VOLATILE     = 0x0040;
043      public static final int ACC_TRANSIENT    = 0x0080;
044      public static final int ACC_NATIVE       = 0x0100;
045      public static final int ACC_INTERFACE    = 0x0200;
046      public static final int ACC_ABSTRACT     = 0x0400;
047      public static final int ACC_STRICT       = 0x0800;
048      
049      public static final CodeClass TYPE_VOID;
050      public static final CodeClass TYPE_INT;
051      public static final CodeClass TYPE_FLOAT;
052      public static final CodeClass TYPE_DOUBLE;
053      public static final CodeClass TYPE_LONG;
054      public static final CodeClass TYPE_BYTE;
055      public static final CodeClass TYPE_SHORT;
056      public static final CodeClass TYPE_CHAR;
057      public static final CodeClass TYPE_BOOLEAN;
058      public static final CodeClass TYPE_OBJECT;
059      public static final CodeClass[] EMPTY_LIST;
060      public static final CodeGenerator DO_NOTHING;
061      
062      static {
063        TYPE_VOID = IntrospectedCodeClass.forClass(Void.TYPE);
064        TYPE_BYTE = IntrospectedCodeClass.forClass(Byte.TYPE);
065        TYPE_INT = IntrospectedCodeClass.forClass(Integer.TYPE);
066        TYPE_FLOAT = IntrospectedCodeClass.forClass(Float.TYPE);
067        TYPE_DOUBLE = IntrospectedCodeClass.forClass(Double.TYPE);
068        TYPE_LONG = IntrospectedCodeClass.forClass(Long.TYPE);
069        TYPE_SHORT = IntrospectedCodeClass.forClass(Short.TYPE);
070        TYPE_CHAR = IntrospectedCodeClass.forClass(Character.TYPE);
071        TYPE_BOOLEAN = IntrospectedCodeClass.forClass(Boolean.TYPE);
072        TYPE_OBJECT = IntrospectedCodeClass.forClass(Object.class);
073        
074        EMPTY_LIST = new CodeClass[0];
075        
076        DO_NOTHING = new CodeGenerator() {
077          public void writeCode(CodeContext cxt) { return; }
078          public int stackDepth() { return 0; }
079          public int stackDelta() { return 0; }
080        };
081      }
082      
083      /**
084       * Format an array of classes as a comma-seperated list.
085       *
086       * <p>
087       * The names of each class in classes will be seperated by a comma and a space
088       * and will use CodeClass.getName() to produce strings for each one. Their
089       * names will be present in the return value in the same order they are found
090       * in the classes array
091       * </p>
092       *
093       * @param classes  the array of classes to format
094       * @return a String containing the list of class names
095       */
096      public static String classListToString(CodeClass[] classes) {
097        StringBuffer sb = new StringBuffer();
098        if(classes.length > 0) {
099          sb.append(classes[0].getName());
100        }
101        
102        for(int a = 1; a < classes.length; a++) {
103          sb.append(", ");
104          sb.append(classes[a].getName());
105        }
106        
107        return sb.toString();
108      }
109      
110      /**
111       * Number of words needed for local variables of this type.
112       *
113       * <p>Longs and doubles require 2 words (64 bits), where as everything
114       * else needs 1 word (32 bits). Void needs no words.
115       * This just hides that knowledge.</p>
116       *
117       * @param cc the CodeClass to check word size for
118       * @return number of words needed for this type
119       */
120      public static int wordsForType(CodeClass cc) {
121        if(
122          (cc == TYPE_DOUBLE) ||
123          (cc == TYPE_LONG)
124        ) {
125          return 2;
126        } else if(cc == TYPE_VOID) {
127          return 0;
128        } else {
129          return 1;
130        }
131      }
132    
133      /**
134       * Returns true if the class is a floating point number.
135       *
136       * <p>
137       * Double and Float are floating point numbers. All other classes are not.
138       * </p>
139       *
140       * @param cc  the class to check
141       * @return  true if the class can be used to represent floating point numbers
142       */
143      public static boolean isFloatType(CodeClass cc) {
144        return
145          cc == TYPE_DOUBLE ||
146          cc == TYPE_FLOAT;
147      }
148    
149      /**
150       * Returns true if the class is an integer number.
151       *
152       * <p>
153       * All numeric types are integer (whole number) types, except for the floating
154       * point types. All other classes are not integer types.
155       * </p>
156       *
157       * @param cc  the class to check
158       * @return  true if the class can be used to represent integer numbers
159       */
160      public static boolean isIntegerType(CodeClass cc) {
161        return
162          cc == TYPE_LONG ||
163          cc == TYPE_BOOLEAN ||
164          cc == TYPE_BYTE ||
165          cc == TYPE_CHAR ||
166          cc == TYPE_LONG ||
167          cc == TYPE_SHORT;
168      }
169    }