PageRenderTime 96ms CodeModel.GetById 73ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/bsh/org/objectweb/asm/Type.java

#
Java | 693 lines | 303 code | 104 blank | 286 comment | 95 complexity | 93f78ab683f33c2a34d1fde7c3b77a0d MD5 | raw file
  1/***
  2 * ASM: a very small and fast Java bytecode manipulation framework
  3 * Copyright (C) 2000 INRIA, France Telecom
  4 * Copyright (C) 2002 France Telecom
  5 *
  6 * This library is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU Lesser General Public
  8 * License as published by the Free Software Foundation; either
  9 * version 2 of the License, or (at your option) any later version.
 10 *
 11 * This library is distributed in the hope that it will be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14 * Lesser General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU Lesser General Public
 17 * License along with this library; if not, write to the Free Software
 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19 *
 20 * Contact: Eric.Bruneton@rd.francetelecom.com
 21 *
 22 * Author: Eric Bruneton
 23 */
 24
 25package org.gjt.sp.jedit.bsh.org.objectweb.asm;
 26
 27import java.lang.reflect.Method;
 28
 29/**
 30 * A Java type. This class can be used to make it easier to manipulate type
 31 * and method descriptors.
 32 */
 33
 34public class Type {
 35
 36  /**
 37   * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
 38   */
 39
 40  public final static int VOID = 0;
 41
 42  /**
 43   * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
 44   */
 45
 46  public final static int BOOLEAN = 1;
 47
 48  /**
 49   * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
 50   */
 51
 52  public final static int CHAR = 2;
 53
 54  /**
 55   * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
 56   */
 57
 58  public final static int BYTE = 3;
 59
 60  /**
 61   * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
 62   */
 63
 64  public final static int SHORT = 4;
 65
 66  /**
 67   * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
 68   */
 69
 70  public final static int INT = 5;
 71
 72  /**
 73   * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
 74   */
 75
 76  public final static int FLOAT = 6;
 77
 78  /**
 79   * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
 80   */
 81
 82  public final static int LONG = 7;
 83
 84  /**
 85   * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
 86   */
 87
 88  public final static int DOUBLE = 8;
 89
 90  /**
 91   * The sort of array reference types. See {@link #getSort getSort}.
 92   */
 93
 94  public final static int ARRAY = 9;
 95
 96  /**
 97   * The sort of object reference type. See {@link #getSort getSort}.
 98   */
 99
100  public final static int OBJECT = 10;
101
102  /**
103   * The <tt>void</tt> type.
104   */
105
106  public final static Type VOID_TYPE = new Type(VOID);
107
108  /**
109   * The <tt>boolean</tt> type.
110   */
111
112  public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
113
114  /**
115   * The <tt>char</tt> type.
116   */
117
118  public final static Type CHAR_TYPE = new Type(CHAR);
119
120  /**
121   * The <tt>byte</tt> type.
122   */
123
124  public final static Type BYTE_TYPE = new Type(BYTE);
125
126  /**
127   * The <tt>short</tt> type.
128   */
129
130  public final static Type SHORT_TYPE = new Type(SHORT);
131
132  /**
133   * The <tt>int</tt> type.
134   */
135
136  public final static Type INT_TYPE = new Type(INT);
137
138  /**
139   * The <tt>float</tt> type.
140   */
141
142  public final static Type FLOAT_TYPE = new Type(FLOAT);
143
144  /**
145   * The <tt>long</tt> type.
146   */
147
148  public final static Type LONG_TYPE = new Type(LONG);
149
150  /**
151   * The <tt>double</tt> type.
152   */
153
154  public final static Type DOUBLE_TYPE = new Type(DOUBLE);
155
156  // --------------------------------------------------------------------------
157  // Fields
158  // --------------------------------------------------------------------------
159
160  /**
161   * The sort of this Java type.
162   */
163
164  private final int sort;
165
166  /**
167   * A buffer containing the descriptor of this Java type.
168   * This field is only used for reference types.
169   */
170
171  private char[] buf;
172
173  /**
174   * The offset of the descriptor of this Java type in {@link #buf buf}.
175   * This field is only used for reference types.
176   */
177
178  private int off;
179
180  /**
181   * The length of the descriptor of this Java type.
182   */
183
184  private int len;
185
186  // --------------------------------------------------------------------------
187  // Constructors
188  // --------------------------------------------------------------------------
189
190  /**
191   * Constructs a primitive type.
192   *
193   * @param sort the sort of the primitive type to be constructed.
194   */
195
196  private Type (final int sort) {
197    this.sort = sort;
198    this.len = 1;
199  }
200
201  /**
202   * Constructs a reference type.
203   *
204   * @param sort the sort of the reference type to be constructed.
205   * @param buf a buffer containing the descriptor of the previous type.
206   * @param off the offset of this descriptor in the previous buffer.
207   * @param len the length of this descriptor.
208   */
209
210  private Type (
211    final int sort,
212    final char[] buf,
213    final int off,
214    final int len)
215  {
216    this.sort = sort;
217    this.buf = buf;
218    this.off = off;
219    this.len = len;
220  }
221
222  /**
223   * Returns the Java type corresponding to the given type descriptor.
224   *
225   * @param typeDescriptor a type descriptor.
226   * @return the Java type corresponding to the given type descriptor.
227   */
228
229  public static Type getType (final String typeDescriptor) {
230    return getType(typeDescriptor.toCharArray(), 0);
231  }
232
233  /**
234   * Returns the Java type corresponding to the given class.
235   *
236   * @param c a class.
237   * @return the Java type corresponding to the given class.
238   */
239
240  public static Type getType (final Class c) {
241    if (c.isPrimitive()) {
242      if (c == Integer.TYPE) {
243        return INT_TYPE;
244      } else if (c == Void.TYPE) {
245        return VOID_TYPE;
246      } else if (c == Boolean.TYPE) {
247        return BOOLEAN_TYPE;
248      } else if (c == Byte.TYPE) {
249        return BYTE_TYPE;
250      } else if (c == Character.TYPE) {
251        return CHAR_TYPE;
252      } else if (c == Short.TYPE) {
253        return SHORT_TYPE;
254      } else if (c == Double.TYPE) {
255        return DOUBLE_TYPE;
256      } else if (c == Float.TYPE) {
257        return FLOAT_TYPE;
258      } else /*if (c == Long.TYPE)*/ {
259        return LONG_TYPE;
260      }
261    } else {
262      return getType(getDescriptor(c));
263    }
264  }
265
266  /**
267   * Returns the Java types corresponding to the argument types of the given
268   * method descriptor.
269   *
270   * @param methodDescriptor a method descriptor.
271   * @return the Java types corresponding to the argument types of the given
272   *      method descriptor.
273   */
274
275  public static Type[] getArgumentTypes (final String methodDescriptor) {
276    char[] buf = methodDescriptor.toCharArray();
277    int off = 1;
278    int size = 0;
279    while (true) {
280      char car = buf[off++];
281      if (car == ')') {
282        break;
283      } else if (car == 'L') {
284        while (buf[off++] != ';') {
285        }
286        ++size;
287      } else if (car != '[') {
288        ++size;
289      }
290    }
291    Type[] args = new Type[size];
292    off = 1;
293    size = 0;
294    while (buf[off] != ')') {
295      args[size] = getType(buf, off);
296      off += args[size].len;
297      size += 1;
298    }
299    return args;
300  }
301
302  /**
303   * Returns the Java types corresponding to the argument types of the given
304   * method.
305   *
306   * @param method a method.
307   * @return the Java types corresponding to the argument types of the given
308   *      method.
309   */
310
311  public static Type[] getArgumentTypes (final Method method) {
312    Class[] classes = method.getParameterTypes();
313    Type[] types = new Type[classes.length];
314    for (int i = classes.length - 1; i >= 0; --i) {
315      types[i] = getType(classes[i]);
316    }
317    return types;
318  }
319
320  /**
321   * Returns the Java type corresponding to the return type of the given
322   * method descriptor.
323   *
324   * @param methodDescriptor a method descriptor.
325   * @return the Java type corresponding to the return type of the given
326   *      method descriptor.
327   */
328
329  public static Type getReturnType (final String methodDescriptor) {
330    char[] buf = methodDescriptor.toCharArray();
331    return getType(buf, methodDescriptor.indexOf(')') + 1);
332  }
333
334  /**
335   * Returns the Java type corresponding to the return type of the given
336   * method.
337   *
338   * @param method a method.
339   * @return the Java type corresponding to the return type of the given
340   *      method.
341   */
342
343  public static Type getReturnType (final Method method) {
344    return getType(method.getReturnType());
345  }
346
347  /**
348   * Returns the Java type corresponding to the given type descriptor.
349   *
350   * @param buf a buffer containing a type descriptor.
351   * @param off the offset of this descriptor in the previous buffer.
352   * @return the Java type corresponding to the given type descriptor.
353   */
354
355  private static Type getType (final char[] buf, final int off) {
356    int len;
357    switch (buf[off]) {
358      case 'V': return VOID_TYPE;
359      case 'Z': return BOOLEAN_TYPE;
360      case 'C': return CHAR_TYPE;
361      case 'B': return BYTE_TYPE;
362      case 'S': return SHORT_TYPE;
363      case 'I': return INT_TYPE;
364      case 'F': return FLOAT_TYPE;
365      case 'J': return LONG_TYPE;
366      case 'D': return DOUBLE_TYPE;
367      case '[':
368        len = 1;
369        while (buf[off + len] == '[') {
370          ++len;
371        }
372        if (buf[off + len] == 'L') {
373          ++len;
374          while (buf[off + len] != ';') {
375            ++len;
376          }
377        }
378        return new Type(ARRAY, buf, off, len + 1);
379      //case 'L':
380      default:
381        len = 1;
382        while (buf[off + len] != ';') {
383          ++len;
384        }
385        return new Type(OBJECT, buf, off, len + 1);
386    }
387  }
388
389  // --------------------------------------------------------------------------
390  // Accessors
391  // --------------------------------------------------------------------------
392
393  /**
394   * Returns the sort of this Java type.
395   *
396   * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
397   *      {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, {@link
398   *      #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, {@link
399   *      #ARRAY ARRAY} or {@link #OBJECT OBJECT}.
400   */
401
402  public int getSort () {
403    return sort;
404  }
405
406  /**
407   * Returns the number of dimensions of this array type.
408   * This method should only be used for an array type.
409   *
410   * @return the number of dimensions of this array type.
411   */
412
413  public int getDimensions () {
414    int i = 1;
415    while (buf[off + i] == '[') {
416      ++i;
417    }
418    return i;
419  }
420
421  /**
422   * Returns the type of the elements of this array type.
423   * This method should only be used for an array type.
424   *
425   * @return Returns the type of the elements of this array type.
426   */
427
428  public Type getElementType () {
429    return getType(buf, off + getDimensions());
430  }
431
432  /**
433   * Returns the name of the class corresponding to this object type.
434   * This method should only be used for an object type.
435   *
436   * @return the fully qualified name of the class corresponding to this object
437   *      type.
438   */
439
440  public String getClassName () {
441    return new String(buf, off + 1, len - 2).replace('/', '.');
442  }
443
444  /**
445   * Returns the internal name of the class corresponding to this object type.
446   * The internal name of a class is its fully qualified name, where '.' are
447   * replaced by '/'.   * This method should only be used for an object type.
448   *
449   * @return the internal name of the class corresponding to this object type.
450   */
451
452  public String getInternalName () {
453    return new String(buf, off + 1, len - 2);
454  }
455
456  // --------------------------------------------------------------------------
457  // Conversion to type descriptors
458  // --------------------------------------------------------------------------
459
460  /**
461   * Returns the descriptor corresponding to this Java type.
462   *
463   * @return the descriptor corresponding to this Java type.
464   */
465
466  public String getDescriptor () {
467    StringBuilder buf = new StringBuilder();
468    getDescriptor(buf);
469    return buf.toString();
470  }
471
472  /**
473   * Returns the descriptor corresponding to the given argument and return
474   * types.
475   *
476   * @param returnType the return type of the method.
477   * @param argumentTypes the argument types of the method.
478   * @return the descriptor corresponding to the given argument and return
479   *      types.
480   */
481
482  public static String getMethodDescriptor (
483    final Type returnType,
484    final Type[] argumentTypes)
485  {
486    StringBuilder buf = new StringBuilder();
487    buf.append('(');
488    for (int i = 0; i < argumentTypes.length; ++i) {
489      argumentTypes[i].getDescriptor(buf);
490    }
491    buf.append(')');
492    returnType.getDescriptor(buf);
493    return buf.toString();
494  }
495
496  /**
497   * Appends the descriptor corresponding to this Java type to the given string
498   * buffer.
499   *
500   * @param buf the string buffer to which the descriptor must be appended.
501   */
502
503  private void getDescriptor(final StringBuilder buf) {
504    switch (sort) {
505      case VOID:    buf.append('V'); return;
506      case BOOLEAN: buf.append('Z'); return;
507      case CHAR:    buf.append('C'); return;
508      case BYTE:    buf.append('B'); return;
509      case SHORT:   buf.append('S'); return;
510      case INT:     buf.append('I'); return;
511      case FLOAT:   buf.append('F'); return;
512      case LONG:    buf.append('J'); return;
513      case DOUBLE:  buf.append('D'); return;
514      //case ARRAY:
515      //case OBJECT:
516      default:      buf.append(this.buf, off, len);
517    }
518  }
519
520  // --------------------------------------------------------------------------
521  // Direct conversion from classes to type descriptors,
522  // without intermediate Type objects
523  // --------------------------------------------------------------------------
524
525  /**
526   * Returns the internal name of the given class. The internal name of a class
527   * is its fully qualified name, where '.' are replaced by '/'.
528   *
529   * @param c an object class.
530   * @return the internal name of the given class.
531   */
532
533  public static String getInternalName (final Class c) {
534    return c.getName().replace('.', '/');
535  }
536
537  /**
538   * Returns the descriptor corresponding to the given Java type.
539   *
540   * @param c an object class, a primitive class or an array class.
541   * @return the descriptor corresponding to the given class.
542   */
543
544  public static String getDescriptor (final Class c) {
545    StringBuilder buf = new StringBuilder();
546    getDescriptor(buf, c);
547    return buf.toString();
548  }
549
550  /**
551   * Returns the descriptor corresponding to the given method.
552   *
553   * @param m a {@link Method Method} object.
554   * @return the descriptor of the given method.
555   */
556
557  public static String getMethodDescriptor (final Method m) {
558    Class[] parameters = m.getParameterTypes();
559    StringBuilder buf = new StringBuilder();
560    buf.append('(');
561    for (int i = 0; i < parameters.length; ++i) {
562      getDescriptor(buf, parameters[i]);
563    }
564    buf.append(')');
565    getDescriptor(buf, m.getReturnType());
566    return buf.toString();
567  }
568
569  /**
570   * Appends the descriptor of the given class to the given string buffer.
571   *
572   * @param buf the string buffer to which the descriptor must be appended.
573   * @param c the class whose descriptor must be computed.
574   */
575
576  private static void getDescriptor (final StringBuilder buf, final Class c) {
577    Class d = c;
578    while (true) {
579      if (d.isPrimitive()) {
580        char car;
581        if (d == Integer.TYPE) {
582          car = 'I';
583        } else if (d == Void.TYPE) {
584          car = 'V';
585        } else if (d == Boolean.TYPE) {
586          car = 'Z';
587        } else if (d == Byte.TYPE) {
588          car = 'B';
589        } else if (d == Character.TYPE) {
590          car = 'C';
591        } else if (d == Short.TYPE) {
592          car = 'S';
593        } else if (d == Double.TYPE) {
594          car = 'D';
595        } else if (d == Float.TYPE) {
596          car = 'F';
597        } else /*if (d == Long.TYPE)*/ {
598          car = 'J';
599        }
600        buf.append(car);
601        return;
602      } else if (d.isArray()) {
603        buf.append('[');
604        d = d.getComponentType();
605      } else {
606        buf.append('L');
607        String name = d.getName();
608        int len = name.length();
609        for (int i = 0; i < len; ++i) {
610          char car = name.charAt(i);
611          buf.append(car == '.' ? '/' : car);
612        }
613        buf.append(';');
614        return;
615      }
616    }
617  }
618
619  // --------------------------------------------------------------------------
620  // Corresponding size and opcodes
621  // --------------------------------------------------------------------------
622
623  /**
624   * Returns the size of values of this type.
625   *
626   * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
627   *      <tt>double</tt>, and 1 otherwise.
628   */
629
630  public int getSize () {
631    return (sort == LONG || sort == DOUBLE ? 2 : 1);
632  }
633
634  /**
635   * Returns a JVM instruction opcode adapted to this Java type.
636   *
637   * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
638   *      ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
639   *      ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
640   * @return an opcode that is similar to the given opcode, but adapted to this
641   *      Java type. For example, if this type is <tt>float</tt> and
642   *      <tt>opcode</tt> is IRETURN, this method returns FRETURN.
643   */
644
645  public int getOpcode (final int opcode) {
646    if (opcode == Constants.IALOAD || opcode == Constants.IASTORE) {
647      switch (sort) {
648        case VOID:
649          return opcode + 5;
650        case BOOLEAN:
651        case BYTE:
652          return opcode + 6;
653        case CHAR:
654          return opcode + 7;
655        case SHORT:
656          return opcode + 8;
657        case INT:
658          return opcode;
659        case FLOAT:
660          return opcode + 2;
661        case LONG:
662          return opcode + 1;
663        case DOUBLE:
664          return opcode + 3;
665        //case ARRAY:
666        //case OBJECT:
667        default:
668          return opcode + 4;
669      }
670    } else {
671      switch (sort) {
672        case VOID:
673          return opcode + 5;
674        case BOOLEAN:
675        case CHAR:
676        case BYTE:
677        case SHORT:
678        case INT:
679          return opcode;
680        case FLOAT:
681          return opcode + 2;
682        case LONG:
683          return opcode + 1;
684        case DOUBLE:
685          return opcode + 3;
686        //case ARRAY:
687        //case OBJECT:
688        default:
689          return opcode + 4;
690      }
691    }
692  }
693}