Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Type.java

00001 package de.fub.bytecode.generic;
00002 
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.classfile.*;
00005 import java.io.*;
00006 import java.util.Vector;
00007 
00008 /** 
00009  * Abstract super class for all possible java types, namely basic types
00010  * such as int, object types like String and array types, e.g. int[]
00011  *
00012  * @version $Id: Type.java,v 1.1.1.1 2002/01/24 03:41:42 pserver Exp $
00013  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00014  */
00015 public abstract class Type {
00016   protected byte   type;
00017   protected String signature; // signature for the type
00018 
00019   /** Predefined constants
00020    */
00021   public static final BasicType     VOID         = new BasicType(Constants.T_VOID);
00022   public static final BasicType     BOOLEAN      = new BasicType(Constants.T_BOOLEAN);
00023   public static final BasicType     INT          = new BasicType(Constants.T_INT);
00024   public static final BasicType     SHORT        = new BasicType(Constants.T_SHORT);
00025   public static final BasicType     BYTE         = new BasicType(Constants.T_BYTE);
00026   public static final BasicType     LONG         = new BasicType(Constants.T_LONG);
00027   public static final BasicType     DOUBLE       = new BasicType(Constants.T_DOUBLE);
00028   public static final BasicType     FLOAT        = new BasicType(Constants.T_FLOAT);
00029   public static final BasicType     CHAR         = new BasicType(Constants.T_CHAR);
00030   public static final ObjectType    OBJECT       = new ObjectType("java.lang.Object");
00031   public static final ObjectType    STRING       = new ObjectType("java.lang.String");
00032   public static final ObjectType    STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
00033   public static final Type[]        NO_ARGS      = new Type[0];
00034   public static final ReferenceType NULL         = new ReferenceType();
00035   public static final Type          UNKNOWN      = new Type(Constants.T_UNKNOWN,
00036                                 "<unknown object>"){};
00037   public static final Type          ADDRESS      = new Type(Constants.T_ADDRESS,
00038                                 "<address>"){};
00039 
00040   private static int consumed_chars=0; // Remember position in string, see getArgumentTypes
00041 
00042   protected Type(byte t, String s) {
00043     type      = t;
00044     signature = s;
00045   }  
00046   /**
00047    * Convert arguments of a method (signature) to an array of Type objects.
00048    * @param signature signature string such as (Ljava/lang/String;)V
00049    * @return array of argument types
00050    */
00051   public static synchronized Type[] getArgumentTypes(String signature) {
00052     Vector vec = new Vector();
00053     int    index;
00054     Type[] types;
00055 
00056     try { // Read all declarations between for `(' and `)'
00057       if(signature.charAt(0) != '(')
00058     throw new ClassFormatError("Invalid method signature: " + signature);
00059 
00060       index = 1; // current string position
00061 
00062       while(signature.charAt(index) != ')') {
00063     vec.addElement(getType(signature.substring(index)));
00064     index += consumed_chars; // update position
00065       }
00066     } catch(StringIndexOutOfBoundsException e) { // Should never occur
00067       throw new ClassFormatError("Invalid method signature: " + signature);
00068     }
00069     
00070     types = new Type[vec.size()];
00071     vec.copyInto(types);
00072     return types;
00073   }  
00074   /**
00075    * Convert type to Java method signature, e.g. int[] f(java.lang.String x)
00076    * becomes (Ljava/lang/String;)[I
00077    *
00078    * @param return_type what the method returns
00079    * @param arg_types what are the argument types
00080    * @return method signature for given type(s).
00081    */
00082   public static String getMethodSignature(Type return_type, Type[] arg_types) { 
00083     StringBuffer buf = new StringBuffer("(");
00084     int length = (arg_types == null)? 0 : arg_types.length;
00085 
00086     for(int i=0; i < length; i++)
00087       buf.append(arg_types[i].getSignature());
00088 
00089     buf.append(')');
00090     buf.append(return_type.getSignature());
00091 
00092     return buf.toString();
00093   }  
00094   /**
00095    * Convert arguments of a method (signature) to a Type object.
00096    * @param signature signature string such as (Ljava/lang/String;)V
00097    * @return return type
00098    */
00099   public static Type getReturnType(String signature) {
00100     try {
00101       // Read return type after `)'
00102       int index = signature.lastIndexOf(')') + 1;
00103       return getType(signature.substring(index));
00104     } catch(StringIndexOutOfBoundsException e) { // Should never occur
00105       throw new ClassFormatError("Invalid method signature: " + signature);
00106     }
00107   }  
00108   /**
00109    * @return signature for given type.
00110    */
00111   public String getSignature() { return signature; }  
00112   /**
00113    * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
00114    */
00115   public int getSize() {
00116     switch(type) {
00117     case Constants.T_DOUBLE:
00118     case Constants.T_LONG: return 2;
00119     case Constants.T_VOID: return 0;
00120     default:     return 1;
00121     }
00122   }  
00123   /**
00124    * @return type as defined in Constants
00125    */
00126   public byte getType() { return type; }  
00127   /**
00128    * Convert signature to a Type object.
00129    * @param signature signature string such as Ljava/lang/String;
00130    * @return type object
00131    */
00132   public static synchronized final Type getType(String signature)
00133     throws StringIndexOutOfBoundsException
00134   {
00135     byte type = Utility.typeOfSignature(signature);
00136 
00137     if(type <= Constants.T_VOID) {
00138       consumed_chars = 1;
00139       return BasicType.getType(type);
00140     }
00141     else if(type == Constants.T_ARRAY) {
00142       int dim=0;
00143       do { // Count dimensions
00144     dim++;
00145       } while(signature.charAt(dim) == '[');
00146 
00147       // Recurse, but just once, if the signature is ok
00148       Type t = getType(signature.substring(dim));
00149 
00150       consumed_chars += dim; // update counter
00151 
00152       return new ArrayType(t, dim);
00153     }
00154     else { // type == T_REFERENCE
00155       int index = signature.indexOf(';'); // Look for closing `;'
00156 
00157       if(index < 0)
00158     throw new ClassFormatError("Invalid signature: " + signature);
00159     
00160       consumed_chars = index + 1; // "Lblabla;" `L' and `;' are removed
00161 
00162       return new ObjectType(signature.substring(1, index).replace('/', '.'));
00163     }
00164   }  
00165   /**
00166    * @return Type string, e.g. `int[]'
00167    */
00168   public String toString() {
00169     return (type >= Constants.T_UNKNOWN)? signature :
00170       Utility.signatureToString(signature, false);
00171   }  
00172 }

Generated at Thu Feb 7 06:58:38 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001