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 */
021package 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 */
034public 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}