~ubuntu-branches/debian/sid/scala/sid

« back to all changes in this revision

Viewing changes to src/asm/scala/tools/asm/Type.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg, Mehdi Dogguy, Lucas Satabin, Frank S. Thomas, Emmanuel Bourg
  • Date: 2015-06-05 23:52:59 UTC
  • mfrom: (1.2.11)
  • Revision ID: package-import@ubuntu.com-20150605235259-wk00vgk83dh8o19g
Tags: 2.10.5-1
* Team upload.

[ Mehdi Dogguy ]
* New upstream release (Closes: #744278).

[ Lucas Satabin ]
* Update patches
* Update the clean target
* Update paths of elements to install
* Update watch file

[ Frank S. Thomas ]
* Remove myself from Uploaders.

[ Emmanuel Bourg ]
* The package has been adopted by the Java Team (Closes: #754935)
* Patched the build to avoid downloading libraries from the Internet
* Replaced the minified JavaScript files with unobfuscated ones
* No longer build scala-partest.jar until diffutils is packaged or replaced
* debian/watch: Fixed the versions matched (x.y.z instead of x.y.z..z)
* debian/rules:
  - Added the missing get-orig-source target (Closes: #724704)
  - Improved the clean target
* debian/control:
  - Build depend on scala (>= 2.10) and bnd
  - Use canonical URLs for the Vcs-* fields
  - Standards-Version updated to 3.9.6 (no changes)
* Switch to debhelper level 9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***
 
2
 * ASM: a very small and fast Java bytecode manipulation framework
 
3
 * Copyright (c) 2000-2011 INRIA, France Telecom
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 * 3. Neither the name of the copyright holders nor the names of its
 
15
 *    contributors may be used to endorse or promote products derived from
 
16
 *    this software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 
28
 * THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
package scala.tools.asm;
 
31
 
 
32
import java.lang.reflect.Constructor;
 
33
import java.lang.reflect.Method;
 
34
 
 
35
/**
 
36
 * A Java field or method type. This class can be used to make it easier to
 
37
 * manipulate type and method descriptors.
 
38
 *
 
39
 * @author Eric Bruneton
 
40
 * @author Chris Nokleberg
 
41
 */
 
42
public class Type {
 
43
 
 
44
    /**
 
45
     * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
 
46
     */
 
47
    public static final int VOID = 0;
 
48
 
 
49
    /**
 
50
     * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
 
51
     */
 
52
    public static final int BOOLEAN = 1;
 
53
 
 
54
    /**
 
55
     * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
 
56
     */
 
57
    public static final int CHAR = 2;
 
58
 
 
59
    /**
 
60
     * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
 
61
     */
 
62
    public static final int BYTE = 3;
 
63
 
 
64
    /**
 
65
     * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
 
66
     */
 
67
    public static final int SHORT = 4;
 
68
 
 
69
    /**
 
70
     * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
 
71
     */
 
72
    public static final int INT = 5;
 
73
 
 
74
    /**
 
75
     * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
 
76
     */
 
77
    public static final int FLOAT = 6;
 
78
 
 
79
    /**
 
80
     * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
 
81
     */
 
82
    public static final int LONG = 7;
 
83
 
 
84
    /**
 
85
     * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
 
86
     */
 
87
    public static final int DOUBLE = 8;
 
88
 
 
89
    /**
 
90
     * The sort of array reference types. See {@link #getSort getSort}.
 
91
     */
 
92
    public static final int ARRAY = 9;
 
93
 
 
94
    /**
 
95
     * The sort of object reference types. See {@link #getSort getSort}.
 
96
     */
 
97
    public static final int OBJECT = 10;
 
98
 
 
99
    /**
 
100
     * The sort of method types. See {@link #getSort getSort}.
 
101
     */
 
102
    public static final int METHOD = 11;
 
103
 
 
104
    /**
 
105
     * The <tt>void</tt> type.
 
106
     */
 
107
    public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
 
108
            | (5 << 16) | (0 << 8) | 0, 1);
 
109
 
 
110
    /**
 
111
     * The <tt>boolean</tt> type.
 
112
     */
 
113
    public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)
 
114
            | (0 << 16) | (5 << 8) | 1, 1);
 
115
 
 
116
    /**
 
117
     * The <tt>char</tt> type.
 
118
     */
 
119
    public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)
 
120
            | (0 << 16) | (6 << 8) | 1, 1);
 
121
 
 
122
    /**
 
123
     * The <tt>byte</tt> type.
 
124
     */
 
125
    public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)
 
126
            | (0 << 16) | (5 << 8) | 1, 1);
 
127
 
 
128
    /**
 
129
     * The <tt>short</tt> type.
 
130
     */
 
131
    public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)
 
132
            | (0 << 16) | (7 << 8) | 1, 1);
 
133
 
 
134
    /**
 
135
     * The <tt>int</tt> type.
 
136
     */
 
137
    public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)
 
138
            | (0 << 16) | (0 << 8) | 1, 1);
 
139
 
 
140
    /**
 
141
     * The <tt>float</tt> type.
 
142
     */
 
143
    public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)
 
144
            | (2 << 16) | (2 << 8) | 1, 1);
 
145
 
 
146
    /**
 
147
     * The <tt>long</tt> type.
 
148
     */
 
149
    public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)
 
150
            | (1 << 16) | (1 << 8) | 2, 1);
 
151
 
 
152
    /**
 
153
     * The <tt>double</tt> type.
 
154
     */
 
155
    public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)
 
156
            | (3 << 16) | (3 << 8) | 2, 1);
 
157
 
 
158
    // ------------------------------------------------------------------------
 
159
    // Fields
 
160
    // ------------------------------------------------------------------------
 
161
 
 
162
    /**
 
163
     * The sort of this Java type.
 
164
     */
 
165
    private final int sort;
 
166
 
 
167
    /**
 
168
     * A buffer containing the internal name of this Java type. This field is
 
169
     * only used for reference types.
 
170
     */
 
171
    private final char[] buf;
 
172
 
 
173
    /**
 
174
     * The offset of the internal name of this Java type in {@link #buf buf} or,
 
175
     * for primitive types, the size, descriptor and getOpcode offsets for this
 
176
     * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset
 
177
     * for IALOAD or IASTORE, byte 3 the offset for all other instructions).
 
178
     */
 
179
    private final int off;
 
180
 
 
181
    /**
 
182
     * The length of the internal name of this Java type.
 
183
     */
 
184
    private final int len;
 
185
 
 
186
    // ------------------------------------------------------------------------
 
187
    // Constructors
 
188
    // ------------------------------------------------------------------------
 
189
 
 
190
    /**
 
191
     * Constructs a reference type.
 
192
     *
 
193
     * @param sort the sort of the reference type to be constructed.
 
194
     * @param buf a buffer containing the descriptor of the previous type.
 
195
     * @param off the offset of this descriptor in the previous buffer.
 
196
     * @param len the length of this descriptor.
 
197
     */
 
198
    private Type(final int sort, final char[] buf, final int off, final int len)
 
199
    {
 
200
        this.sort = sort;
 
201
        this.buf = buf;
 
202
        this.off = off;
 
203
        this.len = len;
 
204
    }
 
205
 
 
206
    /**
 
207
     * Returns the Java type corresponding to the given type descriptor.
 
208
     *
 
209
     * @param typeDescriptor a field or method type descriptor.
 
210
     * @return the Java type corresponding to the given type descriptor.
 
211
     */
 
212
    public static Type getType(final String typeDescriptor) {
 
213
        return getType(typeDescriptor.toCharArray(), 0);
 
214
    }
 
215
 
 
216
    /**
 
217
     * Returns the Java type corresponding to the given internal name.
 
218
     *
 
219
     * @param internalName an internal name.
 
220
     * @return the Java type corresponding to the given internal name.
 
221
     */
 
222
    public static Type getObjectType(final String internalName) {
 
223
        char[] buf = internalName.toCharArray();
 
224
        return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
 
225
    }
 
226
 
 
227
    /**
 
228
     * Returns the Java type corresponding to the given method descriptor.
 
229
     * Equivalent to <code>Type.getType(methodDescriptor)</code>.
 
230
     *
 
231
     * @param methodDescriptor a method descriptor.
 
232
     * @return the Java type corresponding to the given method descriptor.
 
233
     */
 
234
    public static Type getMethodType(final String methodDescriptor) {
 
235
        return getType(methodDescriptor.toCharArray(), 0);
 
236
    }
 
237
 
 
238
    /**
 
239
     * Returns the Java method type corresponding to the given argument and
 
240
     * return types.
 
241
     *
 
242
     * @param returnType the return type of the method.
 
243
     * @param argumentTypes the argument types of the method.
 
244
     * @return the Java type corresponding to the given argument and return types.
 
245
     */
 
246
    public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
 
247
        return getType(getMethodDescriptor(returnType, argumentTypes));
 
248
    }
 
249
 
 
250
    /**
 
251
     * Returns the Java type corresponding to the given class.
 
252
     *
 
253
     * @param c a class.
 
254
     * @return the Java type corresponding to the given class.
 
255
     */
 
256
    public static Type getType(final Class<?> c) {
 
257
        if (c.isPrimitive()) {
 
258
            if (c == Integer.TYPE) {
 
259
                return INT_TYPE;
 
260
            } else if (c == Void.TYPE) {
 
261
                return VOID_TYPE;
 
262
            } else if (c == Boolean.TYPE) {
 
263
                return BOOLEAN_TYPE;
 
264
            } else if (c == Byte.TYPE) {
 
265
                return BYTE_TYPE;
 
266
            } else if (c == Character.TYPE) {
 
267
                return CHAR_TYPE;
 
268
            } else if (c == Short.TYPE) {
 
269
                return SHORT_TYPE;
 
270
            } else if (c == Double.TYPE) {
 
271
                return DOUBLE_TYPE;
 
272
            } else if (c == Float.TYPE) {
 
273
                return FLOAT_TYPE;
 
274
            } else /* if (c == Long.TYPE) */{
 
275
                return LONG_TYPE;
 
276
            }
 
277
        } else {
 
278
            return getType(getDescriptor(c));
 
279
        }
 
280
    }
 
281
 
 
282
    /**
 
283
     * Returns the Java method type corresponding to the given constructor.
 
284
     *
 
285
     * @param c a {@link Constructor Constructor} object.
 
286
     * @return the Java method type corresponding to the given constructor.
 
287
     */
 
288
    public static Type getType(final Constructor<?> c) {
 
289
        return getType(getConstructorDescriptor(c));
 
290
    }
 
291
 
 
292
    /**
 
293
     * Returns the Java method type corresponding to the given method.
 
294
     *
 
295
     * @param m a {@link Method Method} object.
 
296
     * @return the Java method type corresponding to the given method.
 
297
     */
 
298
    public static Type getType(final Method m) {
 
299
        return getType(getMethodDescriptor(m));
 
300
    }
 
301
 
 
302
    /**
 
303
     * Returns the Java types corresponding to the argument types of the given
 
304
     * method descriptor.
 
305
     *
 
306
     * @param methodDescriptor a method descriptor.
 
307
     * @return the Java types corresponding to the argument types of the given
 
308
     *         method descriptor.
 
309
     */
 
310
    public static Type[] getArgumentTypes(final String methodDescriptor) {
 
311
        char[] buf = methodDescriptor.toCharArray();
 
312
        int off = 1;
 
313
        int size = 0;
 
314
        while (true) {
 
315
            char car = buf[off++];
 
316
            if (car == ')') {
 
317
                break;
 
318
            } else if (car == 'L') {
 
319
                while (buf[off++] != ';') {
 
320
                }
 
321
                ++size;
 
322
            } else if (car != '[') {
 
323
                ++size;
 
324
            }
 
325
        }
 
326
        Type[] args = new Type[size];
 
327
        off = 1;
 
328
        size = 0;
 
329
        while (buf[off] != ')') {
 
330
            args[size] = getType(buf, off);
 
331
            off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
 
332
            size += 1;
 
333
        }
 
334
        return args;
 
335
    }
 
336
 
 
337
    /**
 
338
     * Returns the Java types corresponding to the argument types of the given
 
339
     * method.
 
340
     *
 
341
     * @param method a method.
 
342
     * @return the Java types corresponding to the argument types of the given
 
343
     *         method.
 
344
     */
 
345
    public static Type[] getArgumentTypes(final Method method) {
 
346
        Class<?>[] classes = method.getParameterTypes();
 
347
        Type[] types = new Type[classes.length];
 
348
        for (int i = classes.length - 1; i >= 0; --i) {
 
349
            types[i] = getType(classes[i]);
 
350
        }
 
351
        return types;
 
352
    }
 
353
 
 
354
    /**
 
355
     * Returns the Java type corresponding to the return type of the given
 
356
     * method descriptor.
 
357
     *
 
358
     * @param methodDescriptor a method descriptor.
 
359
     * @return the Java type corresponding to the return type of the given
 
360
     *         method descriptor.
 
361
     */
 
362
    public static Type getReturnType(final String methodDescriptor) {
 
363
        char[] buf = methodDescriptor.toCharArray();
 
364
        return getType(buf, methodDescriptor.indexOf(')') + 1);
 
365
    }
 
366
 
 
367
    /**
 
368
     * Returns the Java type corresponding to the return type of the given
 
369
     * method.
 
370
     *
 
371
     * @param method a method.
 
372
     * @return the Java type corresponding to the return type of the given
 
373
     *         method.
 
374
     */
 
375
    public static Type getReturnType(final Method method) {
 
376
        return getType(method.getReturnType());
 
377
    }
 
378
 
 
379
    /**
 
380
     * Computes the size of the arguments and of the return value of a method.
 
381
     *
 
382
     * @param desc the descriptor of a method.
 
383
     * @return the size of the arguments of the method (plus one for the
 
384
     *         implicit this argument), argSize, and the size of its return
 
385
     *         value, retSize, packed into a single int i =
 
386
     *         <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
 
387
     *         to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
 
388
     */
 
389
    public static int getArgumentsAndReturnSizes(final String desc) {
 
390
        int n = 1;
 
391
        int c = 1;
 
392
        while (true) {
 
393
            char car = desc.charAt(c++);
 
394
            if (car == ')') {
 
395
                car = desc.charAt(c);
 
396
                return n << 2
 
397
                        | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
 
398
            } else if (car == 'L') {
 
399
                while (desc.charAt(c++) != ';') {
 
400
                }
 
401
                n += 1;
 
402
            } else if (car == '[') {
 
403
                while ((car = desc.charAt(c)) == '[') {
 
404
                    ++c;
 
405
                }
 
406
                if (car == 'D' || car == 'J') {
 
407
                    n -= 1;
 
408
                }
 
409
            } else if (car == 'D' || car == 'J') {
 
410
                n += 2;
 
411
            } else {
 
412
                n += 1;
 
413
            }
 
414
        }
 
415
    }
 
416
 
 
417
    /**
 
418
     * Returns the Java type corresponding to the given type descriptor. For
 
419
     * method descriptors, buf is supposed to contain nothing more than the
 
420
     * descriptor itself.
 
421
     *
 
422
     * @param buf a buffer containing a type descriptor.
 
423
     * @param off the offset of this descriptor in the previous buffer.
 
424
     * @return the Java type corresponding to the given type descriptor.
 
425
     */
 
426
    private static Type getType(final char[] buf, final int off) {
 
427
        int len;
 
428
        switch (buf[off]) {
 
429
            case 'V':
 
430
                return VOID_TYPE;
 
431
            case 'Z':
 
432
                return BOOLEAN_TYPE;
 
433
            case 'C':
 
434
                return CHAR_TYPE;
 
435
            case 'B':
 
436
                return BYTE_TYPE;
 
437
            case 'S':
 
438
                return SHORT_TYPE;
 
439
            case 'I':
 
440
                return INT_TYPE;
 
441
            case 'F':
 
442
                return FLOAT_TYPE;
 
443
            case 'J':
 
444
                return LONG_TYPE;
 
445
            case 'D':
 
446
                return DOUBLE_TYPE;
 
447
            case '[':
 
448
                len = 1;
 
449
                while (buf[off + len] == '[') {
 
450
                    ++len;
 
451
                }
 
452
                if (buf[off + len] == 'L') {
 
453
                    ++len;
 
454
                    while (buf[off + len] != ';') {
 
455
                        ++len;
 
456
                    }
 
457
                }
 
458
                return new Type(ARRAY, buf, off, len + 1);
 
459
            case 'L':
 
460
                len = 1;
 
461
                while (buf[off + len] != ';') {
 
462
                    ++len;
 
463
                }
 
464
                return new Type(OBJECT, buf, off + 1, len - 1);
 
465
            // case '(':
 
466
            default:
 
467
                return new Type(METHOD, buf, 0, buf.length);
 
468
        }
 
469
    }
 
470
 
 
471
    // ------------------------------------------------------------------------
 
472
    // Accessors
 
473
    // ------------------------------------------------------------------------
 
474
 
 
475
    /**
 
476
     * Returns the sort of this Java type.
 
477
     *
 
478
     * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
 
479
     *         {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
 
480
     *         {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
 
481
     *         {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY},
 
482
     *         {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
 
483
     */
 
484
    public int getSort() {
 
485
        return sort;
 
486
    }
 
487
 
 
488
    /**
 
489
     * Returns the number of dimensions of this array type. This method should
 
490
     * only be used for an array type.
 
491
     *
 
492
     * @return the number of dimensions of this array type.
 
493
     */
 
494
    public int getDimensions() {
 
495
        int i = 1;
 
496
        while (buf[off + i] == '[') {
 
497
            ++i;
 
498
        }
 
499
        return i;
 
500
    }
 
501
 
 
502
    /**
 
503
     * Returns the type of the elements of this array type. This method should
 
504
     * only be used for an array type.
 
505
     *
 
506
     * @return Returns the type of the elements of this array type.
 
507
     */
 
508
    public Type getElementType() {
 
509
        return getType(buf, off + getDimensions());
 
510
    }
 
511
 
 
512
    /**
 
513
     * Returns the binary name of the class corresponding to this type. This
 
514
     * method must not be used on method types.
 
515
     *
 
516
     * @return the binary name of the class corresponding to this type.
 
517
     */
 
518
    public String getClassName() {
 
519
        switch (sort) {
 
520
            case VOID:
 
521
                return "void";
 
522
            case BOOLEAN:
 
523
                return "boolean";
 
524
            case CHAR:
 
525
                return "char";
 
526
            case BYTE:
 
527
                return "byte";
 
528
            case SHORT:
 
529
                return "short";
 
530
            case INT:
 
531
                return "int";
 
532
            case FLOAT:
 
533
                return "float";
 
534
            case LONG:
 
535
                return "long";
 
536
            case DOUBLE:
 
537
                return "double";
 
538
            case ARRAY:
 
539
                StringBuffer b = new StringBuffer(getElementType().getClassName());
 
540
                for (int i = getDimensions(); i > 0; --i) {
 
541
                    b.append("[]");
 
542
                }
 
543
                return b.toString();
 
544
            case OBJECT:
 
545
                return new String(buf, off, len).replace('/', '.');
 
546
            default:
 
547
                return null;
 
548
        }
 
549
    }
 
550
 
 
551
    /**
 
552
     * Returns the internal name of the class corresponding to this object or
 
553
     * array type. The internal name of a class is its fully qualified name (as
 
554
     * returned by Class.getName(), where '.' are replaced by '/'. This method
 
555
     * should only be used for an object or array type.
 
556
     *
 
557
     * @return the internal name of the class corresponding to this object type.
 
558
     */
 
559
    public String getInternalName() {
 
560
        return new String(buf, off, len);
 
561
    }
 
562
 
 
563
    /**
 
564
     * Returns the argument types of methods of this type. This method should
 
565
     * only be used for method types.
 
566
     *
 
567
     * @return the argument types of methods of this type.
 
568
     */
 
569
    public Type[] getArgumentTypes() {
 
570
        return getArgumentTypes(getDescriptor());
 
571
    }
 
572
 
 
573
    /**
 
574
     * Returns the return type of methods of this type. This method should only
 
575
     * be used for method types.
 
576
     *
 
577
     * @return the return type of methods of this type.
 
578
     */
 
579
    public Type getReturnType() {
 
580
        return getReturnType(getDescriptor());
 
581
    }
 
582
 
 
583
    /**
 
584
     * Returns the size of the arguments and of the return value of methods of
 
585
     * this type. This method should only be used for method types.
 
586
     *
 
587
     * @return the size of the arguments (plus one for the implicit this
 
588
     *         argument), argSize, and the size of the return value, retSize,
 
589
     *         packed into a single int i = <tt>(argSize << 2) | retSize</tt>
 
590
     *         (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
 
591
     *         <tt>i & 0x03</tt>).
 
592
     */
 
593
    public int getArgumentsAndReturnSizes() {
 
594
        return getArgumentsAndReturnSizes(getDescriptor());
 
595
    }
 
596
 
 
597
    // ------------------------------------------------------------------------
 
598
    // Conversion to type descriptors
 
599
    // ------------------------------------------------------------------------
 
600
 
 
601
    /**
 
602
     * Returns the descriptor corresponding to this Java type.
 
603
     *
 
604
     * @return the descriptor corresponding to this Java type.
 
605
     */
 
606
    public String getDescriptor() {
 
607
        StringBuffer buf = new StringBuffer();
 
608
        getDescriptor(buf);
 
609
        return buf.toString();
 
610
    }
 
611
 
 
612
    /**
 
613
     * Returns the descriptor corresponding to the given argument and return
 
614
     * types.
 
615
     *
 
616
     * @param returnType the return type of the method.
 
617
     * @param argumentTypes the argument types of the method.
 
618
     * @return the descriptor corresponding to the given argument and return
 
619
     *         types.
 
620
     */
 
621
    public static String getMethodDescriptor(
 
622
        final Type returnType,
 
623
        final Type... argumentTypes)
 
624
    {
 
625
        StringBuffer buf = new StringBuffer();
 
626
        buf.append('(');
 
627
        for (int i = 0; i < argumentTypes.length; ++i) {
 
628
            argumentTypes[i].getDescriptor(buf);
 
629
        }
 
630
        buf.append(')');
 
631
        returnType.getDescriptor(buf);
 
632
        return buf.toString();
 
633
    }
 
634
 
 
635
    /**
 
636
     * Appends the descriptor corresponding to this Java type to the given
 
637
     * string buffer.
 
638
     *
 
639
     * @param buf the string buffer to which the descriptor must be appended.
 
640
     */
 
641
    private void getDescriptor(final StringBuffer buf) {
 
642
        if (this.buf == null) {
 
643
            // descriptor is in byte 3 of 'off' for primitive types (buf == null)
 
644
            buf.append((char) ((off & 0xFF000000) >>> 24));
 
645
        } else if (sort == OBJECT) {
 
646
            buf.append('L');
 
647
            buf.append(this.buf, off, len);
 
648
            buf.append(';');
 
649
        } else { // sort == ARRAY || sort == METHOD
 
650
            buf.append(this.buf, off, len);
 
651
        }
 
652
    }
 
653
 
 
654
    // ------------------------------------------------------------------------
 
655
    // Direct conversion from classes to type descriptors,
 
656
    // without intermediate Type objects
 
657
    // ------------------------------------------------------------------------
 
658
 
 
659
    /**
 
660
     * Returns the internal name of the given class. The internal name of a
 
661
     * class is its fully qualified name, as returned by Class.getName(), where
 
662
     * '.' are replaced by '/'.
 
663
     *
 
664
     * @param c an object or array class.
 
665
     * @return the internal name of the given class.
 
666
     */
 
667
    public static String getInternalName(final Class<?> c) {
 
668
        return c.getName().replace('.', '/');
 
669
    }
 
670
 
 
671
    /**
 
672
     * Returns the descriptor corresponding to the given Java type.
 
673
     *
 
674
     * @param c an object class, a primitive class or an array class.
 
675
     * @return the descriptor corresponding to the given class.
 
676
     */
 
677
    public static String getDescriptor(final Class<?> c) {
 
678
        StringBuffer buf = new StringBuffer();
 
679
        getDescriptor(buf, c);
 
680
        return buf.toString();
 
681
    }
 
682
 
 
683
    /**
 
684
     * Returns the descriptor corresponding to the given constructor.
 
685
     *
 
686
     * @param c a {@link Constructor Constructor} object.
 
687
     * @return the descriptor of the given constructor.
 
688
     */
 
689
    public static String getConstructorDescriptor(final Constructor<?> c) {
 
690
        Class<?>[] parameters = c.getParameterTypes();
 
691
        StringBuffer buf = new StringBuffer();
 
692
        buf.append('(');
 
693
        for (int i = 0; i < parameters.length; ++i) {
 
694
            getDescriptor(buf, parameters[i]);
 
695
        }
 
696
        return buf.append(")V").toString();
 
697
    }
 
698
 
 
699
    /**
 
700
     * Returns the descriptor corresponding to the given method.
 
701
     *
 
702
     * @param m a {@link Method Method} object.
 
703
     * @return the descriptor of the given method.
 
704
     */
 
705
    public static String getMethodDescriptor(final Method m) {
 
706
        Class<?>[] parameters = m.getParameterTypes();
 
707
        StringBuffer buf = new StringBuffer();
 
708
        buf.append('(');
 
709
        for (int i = 0; i < parameters.length; ++i) {
 
710
            getDescriptor(buf, parameters[i]);
 
711
        }
 
712
        buf.append(')');
 
713
        getDescriptor(buf, m.getReturnType());
 
714
        return buf.toString();
 
715
    }
 
716
 
 
717
    /**
 
718
     * Appends the descriptor of the given class to the given string buffer.
 
719
     *
 
720
     * @param buf the string buffer to which the descriptor must be appended.
 
721
     * @param c the class whose descriptor must be computed.
 
722
     */
 
723
    private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
 
724
        Class<?> d = c;
 
725
        while (true) {
 
726
            if (d.isPrimitive()) {
 
727
                char car;
 
728
                if (d == Integer.TYPE) {
 
729
                    car = 'I';
 
730
                } else if (d == Void.TYPE) {
 
731
                    car = 'V';
 
732
                } else if (d == Boolean.TYPE) {
 
733
                    car = 'Z';
 
734
                } else if (d == Byte.TYPE) {
 
735
                    car = 'B';
 
736
                } else if (d == Character.TYPE) {
 
737
                    car = 'C';
 
738
                } else if (d == Short.TYPE) {
 
739
                    car = 'S';
 
740
                } else if (d == Double.TYPE) {
 
741
                    car = 'D';
 
742
                } else if (d == Float.TYPE) {
 
743
                    car = 'F';
 
744
                } else /* if (d == Long.TYPE) */{
 
745
                    car = 'J';
 
746
                }
 
747
                buf.append(car);
 
748
                return;
 
749
            } else if (d.isArray()) {
 
750
                buf.append('[');
 
751
                d = d.getComponentType();
 
752
            } else {
 
753
                buf.append('L');
 
754
                String name = d.getName();
 
755
                int len = name.length();
 
756
                for (int i = 0; i < len; ++i) {
 
757
                    char car = name.charAt(i);
 
758
                    buf.append(car == '.' ? '/' : car);
 
759
                }
 
760
                buf.append(';');
 
761
                return;
 
762
            }
 
763
        }
 
764
    }
 
765
 
 
766
    // ------------------------------------------------------------------------
 
767
    // Corresponding size and opcodes
 
768
    // ------------------------------------------------------------------------
 
769
 
 
770
    /**
 
771
     * Returns the size of values of this type. This method must not be used for
 
772
     * method types.
 
773
     *
 
774
     * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
 
775
     *         <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
 
776
     */
 
777
    public int getSize() {
 
778
        // the size is in byte 0 of 'off' for primitive types (buf == null)
 
779
        return buf == null ? (off & 0xFF) : 1;
 
780
    }
 
781
 
 
782
    /**
 
783
     * Returns a JVM instruction opcode adapted to this Java type. This method
 
784
     * must not be used for method types.
 
785
     *
 
786
     * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
 
787
     *        ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
 
788
     *        ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
 
789
     * @return an opcode that is similar to the given opcode, but adapted to
 
790
     *         this Java type. For example, if this type is <tt>float</tt> and
 
791
     *         <tt>opcode</tt> is IRETURN, this method returns FRETURN.
 
792
     */
 
793
    public int getOpcode(final int opcode) {
 
794
        if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
 
795
            // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
 
796
            // primitive types (buf == null)
 
797
            return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
 
798
        } else {
 
799
            // the offset for other instructions is in byte 2 of 'off' for
 
800
            // primitive types (buf == null)
 
801
            return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
 
802
        }
 
803
    }
 
804
 
 
805
    // ------------------------------------------------------------------------
 
806
    // Equals, hashCode and toString
 
807
    // ------------------------------------------------------------------------
 
808
 
 
809
    /**
 
810
     * Tests if the given object is equal to this type.
 
811
     *
 
812
     * @param o the object to be compared to this type.
 
813
     * @return <tt>true</tt> if the given object is equal to this type.
 
814
     */
 
815
    @Override
 
816
    public boolean equals(final Object o) {
 
817
        if (this == o) {
 
818
            return true;
 
819
        }
 
820
        if (!(o instanceof Type)) {
 
821
            return false;
 
822
        }
 
823
        Type t = (Type) o;
 
824
        if (sort != t.sort) {
 
825
            return false;
 
826
        }
 
827
        if (sort >= ARRAY) {
 
828
            if (len != t.len) {
 
829
                return false;
 
830
            }
 
831
            for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
 
832
                if (buf[i] != t.buf[j]) {
 
833
                    return false;
 
834
                }
 
835
            }
 
836
        }
 
837
        return true;
 
838
    }
 
839
 
 
840
    /**
 
841
     * Returns a hash code value for this type.
 
842
     *
 
843
     * @return a hash code value for this type.
 
844
     */
 
845
    @Override
 
846
    public int hashCode() {
 
847
        int hc = 13 * sort;
 
848
        if (sort >= ARRAY) {
 
849
            for (int i = off, end = i + len; i < end; i++) {
 
850
                hc = 17 * (hc + buf[i]);
 
851
            }
 
852
        }
 
853
        return hc;
 
854
    }
 
855
 
 
856
    /**
 
857
     * Returns a string representation of this type.
 
858
     *
 
859
     * @return the descriptor of this type.
 
860
     */
 
861
    @Override
 
862
    public String toString() {
 
863
        return getDescriptor();
 
864
    }
 
865
}