KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > asm > ClassReader


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 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 org.objectweb.asm;
31
32 import java.io.InputStream JavaDoc;
33 import java.io.IOException JavaDoc;
34
35 /**
36  * A Java class parser to make a {@link ClassVisitor} visit an existing class.
37  * This class parses a byte array conforming to the Java class file format and
38  * calls the appropriate visit methods of a given class visitor for each field,
39  * method and bytecode instruction encountered.
40  *
41  * @author Eric Bruneton
42  * @author Eugene Kuleshov
43  */

44 public class ClassReader {
45
46     /**
47      * The class to be parsed. <i>The content of this array must not be
48      * modified. This field is intended for {@link Attribute} sub classes, and
49      * is normally not needed by class generators or adapters.</i>
50      */

51     public final byte[] b;
52
53     /**
54      * The start index of each constant pool item in {@link #b b}, plus one.
55      * The one byte offset skips the constant pool item tag that indicates its
56      * type.
57      */

58     private int[] items;
59
60     /**
61      * The String objects corresponding to the CONSTANT_Utf8 items. This cache
62      * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
63      * which GREATLY improves performances (by a factor 2 to 3). This caching
64      * strategy could be extended to all constant pool items, but its benefit
65      * would not be so great for these items (because they are much less
66      * expensive to parse than CONSTANT_Utf8 items).
67      */

68     private String JavaDoc[] strings;
69
70     /**
71      * Maximum length of the strings contained in the constant pool of the
72      * class.
73      */

74     private int maxStringLength;
75
76     /**
77      * Start index of the class header information (access, name...) in
78      * {@link #b b}.
79      */

80     public final int header;
81
82     // ------------------------------------------------------------------------
83
// Constructors
84
// ------------------------------------------------------------------------
85

86     /**
87      * Constructs a new {@link ClassReader} object.
88      *
89      * @param b the bytecode of the class to be read.
90      */

91     public ClassReader(final byte[] b) {
92         this(b, 0, b.length);
93     }
94
95     /**
96      * Constructs a new {@link ClassReader} object.
97      *
98      * @param b the bytecode of the class to be read.
99      * @param off the start offset of the class data.
100      * @param len the length of the class data.
101      */

102     public ClassReader(final byte[] b, final int off, final int len) {
103         this.b = b;
104         // parses the constant pool
105
items = new int[readUnsignedShort(off + 8)];
106         strings = new String JavaDoc[items.length];
107         int max = 0;
108         int index = off + 10;
109         for (int i = 1; i < items.length; ++i) {
110             items[i] = index + 1;
111             int tag = b[index];
112             int size;
113             switch (tag) {
114                 case ClassWriter.FIELD:
115                 case ClassWriter.METH:
116                 case ClassWriter.IMETH:
117                 case ClassWriter.INT:
118                 case ClassWriter.FLOAT:
119                 case ClassWriter.NAME_TYPE:
120                     size = 5;
121                     break;
122                 case ClassWriter.LONG:
123                 case ClassWriter.DOUBLE:
124                     size = 9;
125                     ++i;
126                     break;
127                 case ClassWriter.UTF8:
128                     size = 3 + readUnsignedShort(index + 1);
129                     if (size > max) {
130                         max = size;
131                     }
132                     break;
133                 // case ClassWriter.CLASS:
134
// case ClassWriter.STR:
135
default:
136                     size = 3;
137                     break;
138             }
139             index += size;
140         }
141         maxStringLength = max;
142         // the class header information starts just after the constant pool
143
header = index;
144     }
145
146     /**
147      * Constructs a new {@link ClassReader} object.
148      *
149      * @param is an input stream from which to read the class.
150      * @throws IOException if a problem occurs during reading.
151      */

152     public ClassReader(final InputStream JavaDoc is) throws IOException JavaDoc {
153         this(readClass(is));
154     }
155
156     /**
157      * Constructs a new {@link ClassReader} object.
158      *
159      * @param name the fully qualified name of the class to be read.
160      * @throws IOException if an exception occurs during reading.
161      */

162     public ClassReader(final String JavaDoc name) throws IOException JavaDoc {
163         this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
164                 + ".class"));
165     }
166
167     /**
168      * Reads the bytecode of a class.
169      *
170      * @param is an input stream from which to read the class.
171      * @return the bytecode read from the given input stream.
172      * @throws IOException if a problem occurs during reading.
173      */

174     private static byte[] readClass(final InputStream JavaDoc is) throws IOException JavaDoc {
175         if (is == null) {
176             throw new IOException JavaDoc("Class not found");
177         }
178         byte[] b = new byte[is.available()];
179         int len = 0;
180         while (true) {
181             int n = is.read(b, len, b.length - len);
182             if (n == -1) {
183                 if (len < b.length) {
184                     byte[] c = new byte[len];
185                     System.arraycopy(b, 0, c, 0, len);
186                     b = c;
187                 }
188                 return b;
189             }
190             len += n;
191             if (len == b.length) {
192                 byte[] c = new byte[b.length + 1000];
193                 System.arraycopy(b, 0, c, 0, len);
194                 b = c;
195             }
196         }
197     }
198
199     // ------------------------------------------------------------------------
200
// Public methods
201
// ------------------------------------------------------------------------
202

203     /**
204      * Makes the given visitor visit the Java class of this {@link ClassReader}.
205      * This class is the one specified in the constructor (see
206      * {@link #ClassReader(byte[]) ClassReader}).
207      *
208      * @param classVisitor the visitor that must visit this class.
209      * @param skipDebug <tt>true</tt> if the debug information of the class
210      * must not be visited. In this case the
211      * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
212      * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
213      * not be called.
214      */

215     public void accept(final ClassVisitor classVisitor, final boolean skipDebug)
216     {
217         accept(classVisitor, new Attribute[0], skipDebug);
218     }
219
220     /**
221      * Makes the given visitor visit the Java class of this {@link ClassReader}.
222      * This class is the one specified in the constructor (see
223      * {@link #ClassReader(byte[]) ClassReader}).
224      *
225      * @param classVisitor the visitor that must visit this class.
226      * @param attrs prototypes of the attributes that must be parsed during the
227      * visit of the class. Any attribute whose type is not equal to the
228      * type of one the prototypes will be ignored.
229      * @param skipDebug <tt>true</tt> if the debug information of the class
230      * must not be visited. In this case the
231      * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
232      * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
233      * not be called.
234      */

235     public void accept(
236         final ClassVisitor classVisitor,
237         final Attribute[] attrs,
238         final boolean skipDebug)
239     {
240         byte[] b = this.b; // the bytecode array
241
char[] c = new char[maxStringLength]; // buffer used to read strings
242
int i, j, k; // loop variables
243
int u, v, w; // indexes in b
244
Attribute attr;
245
246         int access;
247         String JavaDoc name;
248         String JavaDoc desc;
249         String JavaDoc attrName;
250         String JavaDoc signature;
251         int anns = 0;
252         int ianns = 0;
253         Attribute cattrs = null;
254
255         // visits the header
256
u = header;
257         access = readUnsignedShort(u);
258         name = readClass(u + 2, c);
259         v = items[readUnsignedShort(u + 4)];
260         String JavaDoc superClassName = v == 0 ? null : readUTF8(v, c);
261         String JavaDoc[] implementedItfs = new String JavaDoc[readUnsignedShort(u + 6)];
262         w = 0;
263         u += 8;
264         for (i = 0; i < implementedItfs.length; ++i) {
265             implementedItfs[i] = readClass(u, c);
266             u += 2;
267         }
268
269         // skips fields and methods
270
v = u;
271         i = readUnsignedShort(v);
272         v += 2;
273         for (; i > 0; --i) {
274             j = readUnsignedShort(v + 6);
275             v += 8;
276             for (; j > 0; --j) {
277                 v += 6 + readInt(v + 2);
278             }
279         }
280         i = readUnsignedShort(v);
281         v += 2;
282         for (; i > 0; --i) {
283             j = readUnsignedShort(v + 6);
284             v += 8;
285             for (; j > 0; --j) {
286                 v += 6 + readInt(v + 2);
287             }
288         }
289         // reads the class's attributes
290
signature = null;
291         String JavaDoc sourceFile = null;
292         String JavaDoc sourceDebug = null;
293         String JavaDoc enclosingOwner = null;
294         String JavaDoc enclosingName = null;
295         String JavaDoc enclosingDesc = null;
296
297         i = readUnsignedShort(v);
298         v += 2;
299         for (; i > 0; --i) {
300             attrName = readUTF8(v, c);
301             if (attrName.equals("SourceFile")) {
302                 sourceFile = readUTF8(v + 6, c);
303             } else if (attrName.equals("Deprecated")) {
304                 access |= Opcodes.ACC_DEPRECATED;
305             } else if (attrName.equals("Synthetic")) {
306                 access |= Opcodes.ACC_SYNTHETIC;
307             } else if (attrName.equals("Annotation")) {
308                 access |= Opcodes.ACC_ANNOTATION;
309             } else if (attrName.equals("Enum")) {
310                 access |= Opcodes.ACC_ENUM;
311             } else if (attrName.equals("InnerClasses")) {
312                 w = v + 6;
313             } else if (attrName.equals("Signature")) {
314                 signature = readUTF8(v + 6, c);
315             } else if (attrName.equals("SourceDebugExtension")) {
316                 int len = readInt(v + 2);
317                 sourceDebug = readUTF(v + 6, len, new char[len]);
318             } else if (attrName.equals("EnclosingMethod")) {
319                 enclosingOwner = readClass(v + 6, c);
320                 int item = readUnsignedShort(v + 8);
321                 if (item != 0) {
322                     enclosingName = readUTF8(items[item], c);
323                     enclosingDesc = readUTF8(items[item] + 2, c);
324                 }
325             } else if (attrName.equals("RuntimeVisibleAnnotations")) {
326                 anns = v + 6;
327             } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
328                 ianns = v + 6;
329             } else {
330                 attr = readAttribute(attrs,
331                         attrName,
332                         v + 6,
333                         readInt(v + 2),
334                         c,
335                         -1,
336                         null);
337                 if (attr != null) {
338                     attr.next = cattrs;
339                     cattrs = attr;
340                 }
341             }
342             v += 6 + readInt(v + 2);
343         }
344         // calls the visit method
345
classVisitor.visit(readInt(4),
346                 access,
347                 name,
348                 signature,
349                 superClassName,
350                 implementedItfs);
351
352         // calls the visitSource method
353
if (sourceFile != null || sourceDebug != null) {
354             classVisitor.visitSource(sourceFile, sourceDebug);
355         }
356
357         // calls the visitOuterClass method
358
if (enclosingOwner != null) {
359             classVisitor.visitOuterClass(enclosingOwner,
360                     enclosingName,
361                     enclosingDesc);
362         }
363
364         // visits the class annotations
365
for (i = 1; i >= 0; --i) {
366             v = i == 0 ? ianns : anns;
367             if (v != 0) {
368                 j = readUnsignedShort(v);
369                 v += 2;
370                 for (; j > 0; --j) {
371                     desc = readUTF8(v, c);
372                     v += 2;
373                     v = readAnnotationValues(v,
374                             c,
375                             classVisitor.visitAnnotation(desc, i != 0));
376                 }
377             }
378         }
379
380         // visits the class attributes
381
while (cattrs != null) {
382             attr = cattrs.next;
383             cattrs.next = null;
384             classVisitor.visitAttribute(cattrs);
385             cattrs = attr;
386         }
387
388         // class the visitInnerClass method
389
if (w != 0) {
390             i = readUnsignedShort(w);
391             w += 2;
392             for (; i > 0; --i) {
393                 classVisitor.visitInnerClass(readUnsignedShort(w) == 0
394                         ? null
395                         : readClass(w, c), readUnsignedShort(w + 2) == 0
396                         ? null
397                         : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
398                         ? null
399                         : readUTF8(w + 4, c), readUnsignedShort(w + 6));
400                 w += 8;
401             }
402         }
403
404         // visits the fields
405
i = readUnsignedShort(u);
406         u += 2;
407         for (; i > 0; --i) {
408             access = readUnsignedShort(u);
409             name = readUTF8(u + 2, c);
410             desc = readUTF8(u + 4, c);
411             // visits the field's attributes and looks for a ConstantValue
412
// attribute
413
int fieldValueItem = 0;
414             signature = null;
415             anns = 0;
416             ianns = 0;
417             cattrs = null;
418
419             j = readUnsignedShort(u + 6);
420             u += 8;
421             for (; j > 0; --j) {
422                 attrName = readUTF8(u, c);
423                 if (attrName.equals("ConstantValue")) {
424                     fieldValueItem = readUnsignedShort(u + 6);
425                 } else if (attrName.equals("Synthetic")) {
426                     access |= Opcodes.ACC_SYNTHETIC;
427                 } else if (attrName.equals("Deprecated")) {
428                     access |= Opcodes.ACC_DEPRECATED;
429                 } else if (attrName.equals("Enum")) {
430                     access |= Opcodes.ACC_ENUM;
431                 } else if (attrName.equals("Signature")) {
432                     signature = readUTF8(u + 6, c);
433                 } else if (attrName.equals("RuntimeVisibleAnnotations")) {
434                     anns = u + 6;
435                 } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
436                     ianns = u + 6;
437                 } else {
438                     attr = readAttribute(attrs,
439                             attrName,
440                             u + 6,
441                             readInt(u + 2),
442                             c,
443                             -1,
444                             null);
445                     if (attr != null) {
446                         attr.next = cattrs;
447                         cattrs = attr;
448                     }
449                 }
450                 u += 6 + readInt(u + 2);
451             }
452             // reads the field's value, if any
453
Object JavaDoc value = (fieldValueItem == 0
454                     ? null
455                     : readConst(fieldValueItem, c));
456             // visits the field
457
FieldVisitor fv = classVisitor.visitField(access,
458                     name,
459                     desc,
460                     signature,
461                     value);
462             // visits the field annotations and attributes
463
if (fv != null) {
464                 for (j = 1; j >= 0; --j) {
465                     v = j == 0 ? ianns : anns;
466                     if (v != 0) {
467                         k = readUnsignedShort(v);
468                         v += 2;
469                         for (; k > 0; --k) {
470                             desc = readUTF8(v, c);
471                             v += 2;
472                             v = readAnnotationValues(v,
473                                     c,
474                                     fv.visitAnnotation(desc, j != 0));
475                         }
476                     }
477                 }
478                 while (cattrs != null) {
479                     attr = cattrs.next;
480                     cattrs.next = null;
481                     fv.visitAttribute(cattrs);
482                     cattrs = attr;
483                 }
484                 fv.visitEnd();
485             }
486         }
487
488         // visits the methods
489
i = readUnsignedShort(u);
490         u += 2;
491         for (; i > 0; --i) {
492             access = readUnsignedShort(u);
493             name = readUTF8(u + 2, c);
494             desc = readUTF8(u + 4, c);
495             signature = null;
496             anns = 0;
497             ianns = 0;
498             int dann = 0;
499             int mpanns = 0;
500             int impanns = 0;
501             cattrs = null;
502             v = 0;
503             w = 0;
504
505             // looks for Code and Exceptions attributes
506
j = readUnsignedShort(u + 6);
507             u += 8;
508             for (; j > 0; --j) {
509                 attrName = readUTF8(u, c);
510                 u += 2;
511                 int attrSize = readInt(u);
512                 u += 4;
513                 if (attrName.equals("Code")) {
514                     v = u;
515                 } else if (attrName.equals("Exceptions")) {
516                     w = u;
517                 } else if (attrName.equals("Synthetic")) {
518                     access |= Opcodes.ACC_SYNTHETIC;
519                 } else if (attrName.equals("Varargs")) {
520                     access |= Opcodes.ACC_VARARGS;
521                 } else if (attrName.equals("Bridge")) {
522                     access |= Opcodes.ACC_BRIDGE;
523                 } else if (attrName.equals("Deprecated")) {
524                     access |= Opcodes.ACC_DEPRECATED;
525                 } else if (attrName.equals("Signature")) {
526                     signature = readUTF8(u, c);
527                 } else if (attrName.equals("AnnotationDefault")) {
528                     dann = u;
529                 } else if (attrName.equals("RuntimeVisibleAnnotations")) {
530                     anns = u;
531                 } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
532                     ianns = u;
533                 } else if (attrName.equals("RuntimeVisibleParameterAnnotations"))
534                 {
535                     mpanns = u;
536                 } else if (attrName.equals("RuntimeInvisibleParameterAnnotations"))
537                 {
538                     impanns = u;
539                 } else {
540                     attr = readAttribute(attrs,
541                             attrName,
542                             u,
543                             attrSize,
544                             c,
545                             -1,
546                             null);
547                     if (attr != null) {
548                         attr.next = cattrs;
549                         cattrs = attr;
550                     }
551                 }
552                 u += attrSize;
553             }
554             // reads declared exceptions
555
String JavaDoc[] exceptions;
556             if (w == 0) {
557                 exceptions = null;
558             } else {
559                 exceptions = new String JavaDoc[readUnsignedShort(w)];
560                 w += 2;
561                 for (j = 0; j < exceptions.length; ++j) {
562                     exceptions[j] = readClass(w, c);
563                     w += 2;
564                 }
565             }
566
567             // visits the method's code, if any
568
MethodVisitor mv = classVisitor.visitMethod(access,
569                     name,
570                     desc,
571                     signature,
572                     exceptions);
573
574             if (mv != null) {
575                 if (dann != 0) {
576                     AnnotationVisitor dv = mv.visitAnnotationDefault();
577                     readAnnotationValue(dann, c, null, dv);
578                     dv.visitEnd();
579                 }
580                 for (j = 1; j >= 0; --j) {
581                     w = j == 0 ? ianns : anns;
582                     if (w != 0) {
583                         k = readUnsignedShort(w);
584                         w += 2;
585                         for (; k > 0; --k) {
586                             desc = readUTF8(w, c);
587                             w += 2;
588                             w = readAnnotationValues(w,
589                                     c,
590                                     mv.visitAnnotation(desc, j != 0));
591                         }
592                     }
593                 }
594                 if (mpanns != 0) {
595                     readParameterAnnotations(mpanns, c, true, mv);
596                 }
597                 if (impanns != 0) {
598                     readParameterAnnotations(impanns, c, false, mv);
599                 }
600                 while (cattrs != null) {
601                     attr = cattrs.next;
602                     cattrs.next = null;
603                     mv.visitAttribute(cattrs);
604                     cattrs = attr;
605                 }
606             }
607
608             if (mv != null && v != 0) {
609                 int maxStack = readUnsignedShort(v);
610                 int maxLocals = readUnsignedShort(v + 2);
611                 int codeLength = readInt(v + 4);
612                 v += 8;
613
614                 int codeStart = v;
615                 int codeEnd = v + codeLength;
616
617                 // 1st phase: finds the labels
618
int label;
619                 Label[] labels = new Label[codeLength + 1];
620                 while (v < codeEnd) {
621                     int opcode = b[v] & 0xFF;
622                     switch (ClassWriter.TYPE[opcode]) {
623                         case ClassWriter.NOARG_INSN:
624                         case ClassWriter.IMPLVAR_INSN:
625                             v += 1;
626                             break;
627                         case ClassWriter.LABEL_INSN:
628                             label = v - codeStart + readShort(v + 1);
629                             if (labels[label] == null) {
630                                 labels[label] = new Label();
631                             }
632                             v += 3;
633                             break;
634                         case ClassWriter.LABELW_INSN:
635                             label = v - codeStart + readInt(v + 1);
636                             if (labels[label] == null) {
637                                 labels[label] = new Label();
638                             }
639                             v += 5;
640                             break;
641                         case ClassWriter.WIDE_INSN:
642                             opcode = b[v + 1] & 0xFF;
643                             if (opcode == Opcodes.IINC) {
644                                 v += 6;
645                             } else {
646                                 v += 4;
647                             }
648                             break;
649                         case ClassWriter.TABL_INSN:
650                             // skips 0 to 3 padding bytes
651
w = v - codeStart;
652                             v = v + 4 - (w & 3);
653                             // reads instruction
654
label = w + readInt(v);
655                             v += 4;
656                             if (labels[label] == null) {
657                                 labels[label] = new Label();
658                             }
659                             j = readInt(v);
660                             v += 4;
661                             j = readInt(v) - j + 1;
662                             v += 4;
663                             for (; j > 0; --j) {
664                                 label = w + readInt(v);
665                                 v += 4;
666                                 if (labels[label] == null) {
667                                     labels[label] = new Label();
668                                 }
669                             }
670                             break;
671                         case ClassWriter.LOOK_INSN:
672                             // skips 0 to 3 padding bytes
673
w = v - codeStart;
674                             v = v + 4 - (w & 3);
675                             // reads instruction
676
label = w + readInt(v);
677                             v += 4;
678                             if (labels[label] == null) {
679                                 labels[label] = new Label();
680                             }
681                             j = readInt(v);
682                             v += 4;
683                             for (; j > 0; --j) {
684                                 v += 4; // skips key
685
label = w + readInt(v);
686                                 v += 4;
687                                 if (labels[label] == null) {
688                                     labels[label] = new Label();
689                                 }
690                             }
691                             break;
692                         case ClassWriter.VAR_INSN:
693                         case ClassWriter.SBYTE_INSN:
694                         case ClassWriter.LDC_INSN:
695                             v += 2;
696                             break;
697                         case ClassWriter.SHORT_INSN:
698                         case ClassWriter.LDCW_INSN:
699                         case ClassWriter.FIELDORMETH_INSN:
700                         case ClassWriter.TYPE_INSN:
701                         case ClassWriter.IINC_INSN:
702                             v += 3;
703                             break;
704                         case ClassWriter.ITFMETH_INSN:
705                             v += 5;
706                             break;
707                         // case MANA_INSN:
708
default:
709                             v += 4;
710                             break;
711                     }
712                 }
713                 // parses the try catch entries
714
j = readUnsignedShort(v);
715                 v += 2;
716                 for (; j > 0; --j) {
717                     label = readUnsignedShort(v);
718                     if (labels[label] == null) {
719                         labels[label] = new Label();
720                     }
721                     label = readUnsignedShort(v + 2);
722                     if (labels[label] == null) {
723                         labels[label] = new Label();
724                     }
725                     label = readUnsignedShort(v + 4);
726                     if (labels[label] == null) {
727                         labels[label] = new Label();
728                     }
729                     v += 8;
730                 }
731                 // parses the local variable, line number tables, and code
732
// attributes
733
int varTable = 0;
734                 int varTypeTable = 0;
735                 cattrs = null;
736                 j = readUnsignedShort(v);
737                 v += 2;
738                 for (; j > 0; --j) {
739                     attrName = readUTF8(v, c);
740                     if (attrName.equals("LocalVariableTable")) {
741                         if (!skipDebug) {
742                             varTable = v + 6;
743                             k = readUnsignedShort(v + 6);
744                             w = v + 8;
745                             for (; k > 0; --k) {
746                                 label = readUnsignedShort(w);
747                                 if (labels[label] == null) {
748                                     labels[label] = new Label();
749                                 }
750                                 label += readUnsignedShort(w + 2);
751                                 if (labels[label] == null) {
752                                     labels[label] = new Label();
753                                 }
754                                 w += 10;
755                             }
756                         }
757                     } else if (attrName.equals("LocalVariableTypeTable")) {
758                         varTypeTable = v + 6;
759                     } else if (attrName.equals("LineNumberTable")) {
760                         if (!skipDebug) {
761                             k = readUnsignedShort(v + 6);
762                             w = v + 8;
763                             for (; k > 0; --k) {
764                                 label = readUnsignedShort(w);
765                                 if (labels[label] == null) {
766                                     labels[label] = new Label();
767                                 }
768                                 labels[label].line = readUnsignedShort(w + 2);
769                                 w += 4;
770                             }
771                         }
772                     } else {
773                         for (k = 0; k < attrs.length; ++k) {
774                             if (attrs[k].type.equals(attrName)) {
775                                 attr = attrs[k].read(this,
776                                         v + 6,
777                                         readInt(v + 2),
778                                         c,
779                                         codeStart - 8,
780                                         labels);
781                                 if (attr != null) {
782                                     attr.next = cattrs;
783                                     cattrs = attr;
784                                 }
785                             }
786                         }
787                     }
788                     v += 6 + readInt(v + 2);
789                 }
790
791                 // 2nd phase: visits each instruction
792
mv.visitCode();
793                 v = codeStart;
794                 Label l;
795                 while (v < codeEnd) {
796                     w = v - codeStart;
797                     l = labels[w];
798                     if (l != null) {
799                         mv.visitLabel(l);
800                         if (!skipDebug && l.line > 0) {
801                             mv.visitLineNumber(l.line, l);
802                         }
803                     }
804                     int opcode = b[v] & 0xFF;
805                     switch (ClassWriter.TYPE[opcode]) {
806                         case ClassWriter.NOARG_INSN:
807                             mv.visitInsn(opcode);
808                             v += 1;
809                             break;
810                         case ClassWriter.IMPLVAR_INSN:
811                             if (opcode > Opcodes.ISTORE) {
812                                 opcode -= 59; // ISTORE_0
813
mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
814                                         opcode & 0x3);
815                             } else {
816                                 opcode -= 26; // ILOAD_0
817
mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
818                                         opcode & 0x3);
819                             }
820                             v += 1;
821                             break;
822                         case ClassWriter.LABEL_INSN:
823                             mv.visitJumpInsn(opcode, labels[w
824                                     + readShort(v + 1)]);
825                             v += 3;
826                             break;
827                         case ClassWriter.LABELW_INSN:
828                             mv.visitJumpInsn(opcode - 33, labels[w
829                                     + readInt(v + 1)]);
830                             v += 5;
831                             break;
832                         case ClassWriter.WIDE_INSN:
833                             opcode = b[v + 1] & 0xFF;
834                             if (opcode == Opcodes.IINC) {
835                                 mv.visitIincInsn(readUnsignedShort(v + 2),
836                                         readShort(v + 4));
837                                 v += 6;
838                             } else {
839                                 mv.visitVarInsn(opcode,
840                                         readUnsignedShort(v + 2));
841                                 v += 4;
842                             }
843                             break;
844                         case ClassWriter.TABL_INSN:
845                             // skips 0 to 3 padding bytes
846
v = v + 4 - (w & 3);
847                             // reads instruction
848
label = w + readInt(v);
849                             v += 4;
850                             int min = readInt(v);
851                             v += 4;
852                             int max = readInt(v);
853                             v += 4;
854                             Label[] table = new Label[max - min + 1];
855                             for (j = 0; j < table.length; ++j) {
856                                 table[j] = labels[w + readInt(v)];
857                                 v += 4;
858                             }
859                             mv.visitTableSwitchInsn(min,
860                                     max,
861                                     labels[label],
862                                     table);
863                             break;
864                         case ClassWriter.LOOK_INSN:
865                             // skips 0 to 3 padding bytes
866
v = v + 4 - (w & 3);
867                             // reads instruction
868
label = w + readInt(v);
869                             v += 4;
870                             j = readInt(v);
871                             v += 4;
872                             int[] keys = new int[j];
873                             Label[] values = new Label[j];
874                             for (j = 0; j < keys.length; ++j) {
875                                 keys[j] = readInt(v);
876                                 v += 4;
877                                 values[j] = labels[w + readInt(v)];
878                                 v += 4;
879                             }
880                             mv.visitLookupSwitchInsn(labels[label],
881                                     keys,
882                                     values);
883                             break;
884                         case ClassWriter.VAR_INSN:
885                             mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
886                             v += 2;
887                             break;
888                         case ClassWriter.SBYTE_INSN:
889                             mv.visitIntInsn(opcode, b[v + 1]);
890                             v += 2;
891                             break;
892                         case ClassWriter.SHORT_INSN:
893                             mv.visitIntInsn(opcode, readShort(v + 1));
894                             v += 3;
895                             break;
896                         case ClassWriter.LDC_INSN:
897                             mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
898                             v += 2;
899                             break;
900                         case ClassWriter.LDCW_INSN:
901                             mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
902                                     c));
903                             v += 3;
904                             break;
905                         case ClassWriter.FIELDORMETH_INSN:
906                         case ClassWriter.ITFMETH_INSN:
907                             int cpIndex = items[readUnsignedShort(v + 1)];
908                             String JavaDoc iowner = readClass(cpIndex, c);
909                             cpIndex = items[readUnsignedShort(cpIndex + 2)];
910                             String JavaDoc iname = readUTF8(cpIndex, c);
911                             String JavaDoc idesc = readUTF8(cpIndex + 2, c);
912                             if (opcode < Opcodes.INVOKEVIRTUAL) {
913                                 mv.visitFieldInsn(opcode, iowner, iname, idesc);
914                             } else {
915                                 mv.visitMethodInsn(opcode, iowner, iname, idesc);
916                             }
917                             if (opcode == Opcodes.INVOKEINTERFACE) {
918                                 v += 5;
919                             } else {
920                                 v += 3;
921                             }
922                             break;
923                         case ClassWriter.TYPE_INSN:
924                             mv.visitTypeInsn(opcode, readClass(v + 1, c));
925                             v += 3;
926                             break;
927                         case ClassWriter.IINC_INSN:
928                             mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
929                             v += 3;
930                             break;
931                         // case MANA_INSN:
932
default:
933                             mv.visitMultiANewArrayInsn(readClass(v + 1, c),
934                                     b[v + 3] & 0xFF);
935                             v += 4;
936                             break;
937                     }
938                 }
939                 l = labels[codeEnd - codeStart];
940                 if (l != null) {
941                     mv.visitLabel(l);
942                 }
943                 // visits the try catch entries
944
j = readUnsignedShort(v);
945                 v += 2;
946                 for (; j > 0; --j) {
947                     Label start = labels[readUnsignedShort(v)];
948                     Label end = labels[readUnsignedShort(v + 2)];
949                     Label handler = labels[readUnsignedShort(v + 4)];
950                     int type = readUnsignedShort(v + 6);
951                     if (type == 0) {
952                         mv.visitTryCatchBlock(start, end, handler, null);
953                     } else {
954                         mv.visitTryCatchBlock(start,
955                                 end,
956                                 handler,
957                                 readUTF8(items[type], c));
958                     }
959                     v += 8;
960                 }
961                 // visits the local variable tables
962
if (!skipDebug && varTable != 0) {
963                     int[] typeTable = null;
964                     if (varTypeTable != 0) {
965                         w = varTypeTable;
966                         k = readUnsignedShort(w) * 3;
967                         w += 2;
968                         typeTable = new int[k];
969                         while (k > 0) {
970                             typeTable[--k] = w + 6; // signature
971
typeTable[--k] = readUnsignedShort(w + 8); // index
972
typeTable[--k] = readUnsignedShort(w); // start
973
w += 10;
974                         }
975                     }
976                     w = varTable;
977                     k = readUnsignedShort(w);
978                     w += 2;
979                     for (; k > 0; --k) {
980                         int start = readUnsignedShort(w);
981                         int length = readUnsignedShort(w + 2);
982                         int index = readUnsignedShort(w + 8);
983                         String JavaDoc vsignature = null;
984                         if (typeTable != null) {
985                             for (int a = 0; a < typeTable.length; a += 3) {
986                                 if (typeTable[a] == start
987                                         && typeTable[a + 1] == index)
988                                 {
989                                     vsignature = readUTF8(typeTable[a + 2], c);
990                                     break;
991                                 }
992                             }
993                         }
994                         mv.visitLocalVariable(readUTF8(w + 4, c),
995                                 readUTF8(w + 6, c),
996                                 vsignature,
997                                 labels[start],
998                                 labels[start + length],
999                                 index);
1000                        w += 10;
1001                    }
1002                }
1003                // visits the other attributes
1004
while (cattrs != null) {
1005                    attr = cattrs.next;
1006                    cattrs.next = null;
1007                    mv.visitAttribute(cattrs);
1008                    cattrs = attr;
1009                }
1010                // visits the max stack and max locals values
1011
mv.visitMaxs(maxStack, maxLocals);
1012            }
1013
1014            if (mv != null) {
1015                mv.visitEnd();
1016            }
1017        }
1018
1019        // visits the end of the class
1020
classVisitor.visitEnd();
1021    }
1022
1023    /**
1024     * Reads parameter annotations and makes the given visitor visit them.
1025     *
1026     * @param v start offset in {@link #b b} of the annotations to be read.
1027     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1028     * {@link #readClass(int,char[]) readClass} or
1029     * {@link #readConst readConst}.
1030     * @param visible <tt>true</tt> if the annotations to be read are visible
1031     * at runtime.
1032     * @param mv the visitor that must visit the annotations.
1033     */

1034    private void readParameterAnnotations(
1035        int v,
1036        final char[] buf,
1037        final boolean visible,
1038        final MethodVisitor mv)
1039    {
1040        int n = b[v++] & 0xFF;
1041        for (int i = 0; i < n; ++i) {
1042            int j = readUnsignedShort(v);
1043            v += 2;
1044            for (; j > 0; --j) {
1045                String JavaDoc desc = readUTF8(v, buf);
1046                v += 2;
1047                AnnotationVisitor av = mv.visitParameterAnnotation(i,
1048                        desc,
1049                        visible);
1050                v = readAnnotationValues(v, buf, av);
1051            }
1052        }
1053    }
1054
1055    /**
1056     * Reads the values of an annotation and makes the given visitor visit them.
1057     *
1058     * @param v the start offset in {@link #b b} of the values to be read
1059     * (including the unsigned short that gives the number of values).
1060     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1061     * {@link #readClass(int,char[]) readClass} or
1062     * {@link #readConst readConst}.
1063     * @param av the visitor that must visit the values.
1064     * @return the end offset of the annotations values.
1065     */

1066    private int readAnnotationValues(
1067        int v,
1068        final char[] buf,
1069        final AnnotationVisitor av)
1070    {
1071        int i = readUnsignedShort(v);
1072        v += 2;
1073        for (; i > 0; --i) {
1074            String JavaDoc name = readUTF8(v, buf);
1075            v += 2;
1076            v = readAnnotationValue(v, buf, name, av);
1077        }
1078        av.visitEnd();
1079        return v;
1080    }
1081
1082    /**
1083     * Reads a value of an annotation and makes the given visitor visit it.
1084     *
1085     * @param v the start offset in {@link #b b} of the value to be read (<i>not
1086     * including the value name constant pool index</i>).
1087     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1088     * {@link #readClass(int,char[]) readClass} or
1089     * {@link #readConst readConst}.
1090     * @param name the name of the value to be read.
1091     * @param av the visitor that must visit the value.
1092     * @return the end offset of the annotation value.
1093     */

1094    private int readAnnotationValue(
1095        int v,
1096        final char[] buf,
1097        final String JavaDoc name,
1098        final AnnotationVisitor av)
1099    {
1100        int i;
1101        switch (readByte(v++)) {
1102            case 'I': // pointer to CONSTANT_Integer
1103
case 'J': // pointer to CONSTANT_Long
1104
case 'F': // pointer to CONSTANT_Float
1105
case 'D': // pointer to CONSTANT_Double
1106
av.visit(name, readConst(readUnsignedShort(v), buf));
1107                v += 2;
1108                break;
1109            case 'B': // pointer to CONSTANT_Byte
1110
av.visit(name,
1111                        new Byte JavaDoc((byte) readInt(items[readUnsignedShort(v)])));
1112                v += 2;
1113                break;
1114            case 'Z': // pointer to CONSTANT_Boolean
1115
boolean b = readInt(items[readUnsignedShort(v)]) == 0;
1116                av.visit(name, b ? Boolean.FALSE : Boolean.TRUE);
1117                v += 2;
1118                break;
1119            case 'S': // pointer to CONSTANT_Short
1120
av.visit(name,
1121                        new Short JavaDoc((short) readInt(items[readUnsignedShort(v)])));
1122                v += 2;
1123                break;
1124            case 'C': // pointer to CONSTANT_Char
1125
av.visit(name,
1126                        new Character JavaDoc((char) readInt(items[readUnsignedShort(v)])));
1127                v += 2;
1128                break;
1129            case 's': // pointer to CONSTANT_Utf8
1130
av.visit(name, readUTF8(v, buf));
1131                v += 2;
1132                break;
1133            case 'e': // enum_const_value
1134
av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
1135                v += 4;
1136                break;
1137            case 'c': // class_info
1138
av.visit(name, Type.getType(readUTF8(v, buf)));
1139                v += 2;
1140                break;
1141            case '@': // annotation_value
1142
String JavaDoc desc = readUTF8(v, buf);
1143                v += 2;
1144                v = readAnnotationValues(v, buf, av.visitAnnotation(name, desc));
1145                break;
1146            case '[': // array_value
1147
int size = readUnsignedShort(v);
1148                v += 2;
1149                switch (readByte(v++)) {
1150                    case 'B':
1151                        byte[] bv = new byte[size];
1152                        for (i = 0; i < size; i++) {
1153                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
1154                            v += 3;
1155                        }
1156                        av.visit(name, bv);
1157                        --v;
1158                        break;
1159                    case 'Z':
1160                        boolean[] zv = new boolean[size];
1161                        for (i = 0; i < size; i++) {
1162                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
1163                            v += 3;
1164                        }
1165                        av.visit(name, zv);
1166                        --v;
1167                        break;
1168                    case 'S':
1169                        short[] sv = new short[size];
1170                        for (i = 0; i < size; i++) {
1171                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
1172                            v += 3;
1173                        }
1174                        av.visit(name, sv);
1175                        --v;
1176                        break;
1177                    case 'C':
1178                        char[] cv = new char[size];
1179                        for (i = 0; i < size; i++) {
1180                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
1181                            v += 3;
1182                        }
1183                        av.visit(name, cv);
1184                        --v;
1185                        break;
1186                    case 'I':
1187                        int[] iv = new int[size];
1188                        for (i = 0; i < size; i++) {
1189                            iv[i] = readInt(items[readUnsignedShort(v)]);
1190                            v += 3;
1191                        }
1192                        av.visit(name, iv);
1193                        --v;
1194                        break;
1195                    case 'J':
1196                        long[] lv = new long[size];
1197                        for (i = 0; i < size; i++) {
1198                            lv[i] = readLong(items[readUnsignedShort(v)]);
1199                            v += 3;
1200                        }
1201                        av.visit(name, lv);
1202                        --v;
1203                        break;
1204                    case 'F':
1205                        float[] fv = new float[size];
1206                        for (i = 0; i < size; i++) {
1207                            fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
1208                            v += 3;
1209                        }
1210                        av.visit(name, fv);
1211                        --v;
1212                        break;
1213                    case 'D':
1214                        double[] dv = new double[size];
1215                        for (i = 0; i < size; i++) {
1216                            dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
1217                            v += 3;
1218                        }
1219                        av.visit(name, dv);
1220                        --v;
1221                        break;
1222                    default:
1223                        v--;
1224                        AnnotationVisitor aav = av.visitArray(name);
1225                        for (i = size; i > 0; --i) {
1226                            v = readAnnotationValue(v, buf, null, aav);
1227                        }
1228                        aav.visitEnd();
1229                }
1230        }
1231        return v;
1232    }
1233
1234    /**
1235     * Reads an attribute in {@link #b b}.
1236     *
1237     * @param attrs prototypes of the attributes that must be parsed during the
1238     * visit of the class. Any attribute whose type is not equal to the
1239     * type of one the prototypes is ignored (i.e. an empty
1240     * {@link Attribute} instance is returned).
1241     * @param type the type of the attribute.
1242     * @param off index of the first byte of the attribute's content in
1243     * {@link #b b}. The 6 attribute header bytes, containing the type
1244     * and the length of the attribute, are not taken into account here
1245     * (they have already been read).
1246     * @param len the length of the attribute's content.
1247     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1248     * {@link #readClass(int,char[]) readClass} or
1249     * {@link #readConst readConst}.
1250     * @param codeOff index of the first byte of code's attribute content in
1251     * {@link #b b}, or -1 if the attribute to be read is not a code
1252     * attribute. The 6 attribute header bytes, containing the type and
1253     * the length of the attribute, are not taken into account here.
1254     * @param labels the labels of the method's code, or <tt>null</tt> if the
1255     * attribute to be read is not a code attribute.
1256     * @return the attribute that has been read, or <tt>null</tt> to skip this
1257     * attribute.
1258     */

1259    private Attribute readAttribute(
1260        final Attribute[] attrs,
1261        final String JavaDoc type,
1262        final int off,
1263        final int len,
1264        final char[] buf,
1265        final int codeOff,
1266        final Label[] labels)
1267    {
1268        for (int i = 0; i < attrs.length; ++i) {
1269            if (attrs[i].type.equals(type)) {
1270                return attrs[i].read(this, off, len, buf, codeOff, labels);
1271            }
1272        }
1273        return new Attribute(type);
1274    }
1275
1276    // ------------------------------------------------------------------------
1277
// Utility methods: low level parsing
1278
// ------------------------------------------------------------------------
1279

1280    /**
1281     * Returns the start index of the constant pool item in {@link #b b}, plus
1282     * one. <i>This method is intended for {@link Attribute} sub classes, and is
1283     * normally not needed by class generators or adapters.</i>
1284     *
1285     * @param item the index a constant pool item.
1286     * @return the start index of the constant pool item in {@link #b b}, plus
1287     * one.
1288     */

1289    public int getItem(final int item) {
1290        return items[item];
1291    }
1292
1293    /**
1294     * Reads a byte value in {@link #b b}. <i>This method is intended for
1295     * {@link Attribute} sub classes, and is normally not needed by class
1296     * generators or adapters.</i>
1297     *
1298     * @param index the start index of the value to be read in {@link #b b}.
1299     * @return the read value.
1300     */

1301    public int readByte(final int index) {
1302        return b[index] & 0xFF;
1303    }
1304
1305    /**
1306     * Reads an unsigned short value in {@link #b b}. <i>This method is
1307     * intended for {@link Attribute} sub classes, and is normally not needed by
1308     * class generators or adapters.</i>
1309     *
1310     * @param index the start index of the value to be read in {@link #b b}.
1311     * @return the read value.
1312     */

1313    public int readUnsignedShort(final int index) {
1314        byte[] b = this.b;
1315        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1316    }
1317
1318    /**
1319     * Reads a signed short value in {@link #b b}. <i>This method is intended
1320     * for {@link Attribute} sub classes, and is normally not needed by class
1321     * generators or adapters.</i>
1322     *
1323     * @param index the start index of the value to be read in {@link #b b}.
1324     * @return the read value.
1325     */

1326    public short readShort(final int index) {
1327        byte[] b = this.b;
1328        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1329    }
1330
1331    /**
1332     * Reads a signed int value in {@link #b b}. <i>This method is intended for
1333     * {@link Attribute} sub classes, and is normally not needed by class
1334     * generators or adapters.</i>
1335     *
1336     * @param index the start index of the value to be read in {@link #b b}.
1337     * @return the read value.
1338     */

1339    public int readInt(final int index) {
1340        byte[] b = this.b;
1341        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
1342                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1343    }
1344
1345    /**
1346     * Reads a signed long value in {@link #b b}. <i>This method is intended
1347     * for {@link Attribute} sub classes, and is normally not needed by class
1348     * generators or adapters.</i>
1349     *
1350     * @param index the start index of the value to be read in {@link #b b}.
1351     * @return the read value.
1352     */

1353    public long readLong(final int index) {
1354        long l1 = readInt(index);
1355        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
1356        return (l1 << 32) | l0;
1357    }
1358
1359    /**
1360     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
1361     * is intended for {@link Attribute} sub classes, and is normally not needed
1362     * by class generators or adapters.</i>
1363     *
1364     * @param index the start index of an unsigned short value in {@link #b b},
1365     * whose value is the index of an UTF8 constant pool item.
1366     * @param buf buffer to be used to read the item. This buffer must be
1367     * sufficiently large. It is not automatically resized.
1368     * @return the String corresponding to the specified UTF8 item.
1369     */

1370    public String JavaDoc readUTF8(int index, final char[] buf) {
1371        int item = readUnsignedShort(index);
1372        String JavaDoc s = strings[item];
1373        if (s != null) {
1374            return s;
1375        }
1376        index = items[item];
1377        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
1378    }
1379
1380    /**
1381     * Reads UTF8 string in {@link #b b}.
1382     *
1383     * @param index start offset of the UTF8 string to be read.
1384     * @param utfLen length of the UTF8 string to be read.
1385     * @param buf buffer to be used to read the string. This buffer must be
1386     * sufficiently large. It is not automatically resized.
1387     * @return the String corresponding to the specified UTF8 string.
1388     */

1389    private String JavaDoc readUTF(int index, int utfLen, char[] buf) {
1390        int endIndex = index + utfLen;
1391        byte[] b = this.b;
1392        int strLen = 0;
1393        int c, d, e;
1394        while (index < endIndex) {
1395            c = b[index++] & 0xFF;
1396            switch (c >> 4) {
1397                case 0:
1398                case 1:
1399                case 2:
1400                case 3:
1401                case 4:
1402                case 5:
1403                case 6:
1404                case 7:
1405                    // 0xxxxxxx
1406
buf[strLen++] = (char) c;
1407                    break;
1408                case 12:
1409                case 13:
1410                    // 110x xxxx 10xx xxxx
1411
d = b[index++];
1412                    buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
1413                    break;
1414                default:
1415                    // 1110 xxxx 10xx xxxx 10xx xxxx
1416
d = b[index++];
1417                    e = b[index++];
1418                    buf[strLen++] = (char) (((c & 0x0F) << 12)
1419                            | ((d & 0x3F) << 6) | (e & 0x3F));
1420                    break;
1421            }
1422        }
1423        return new String JavaDoc(buf, 0, strLen);
1424    }
1425
1426    /**
1427     * Reads a class constant pool item in {@link #b b}. <i>This method is
1428     * intended for {@link Attribute} sub classes, and is normally not needed by
1429     * class generators or adapters.</i>
1430     *
1431     * @param index the start index of an unsigned short value in {@link #b b},
1432     * whose value is the index of a class constant pool item.
1433     * @param buf buffer to be used to read the item. This buffer must be
1434     * sufficiently large. It is not automatically resized.
1435     * @return the String corresponding to the specified class item.
1436     */

1437    public String JavaDoc readClass(final int index, final char[] buf) {
1438        // computes the start index of the CONSTANT_Class item in b
1439
// and reads the CONSTANT_Utf8 item designated by
1440
// the first two bytes of this CONSTANT_Class item
1441
return readUTF8(items[readUnsignedShort(index)], buf);
1442    }
1443
1444    /**
1445     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
1446     * method is intended for {@link Attribute} sub classes, and is normally not
1447     * needed by class generators or adapters.</i>
1448     *
1449     * @param item the index of a constant pool item.
1450     * @param buf buffer to be used to read the item. This buffer must be
1451     * sufficiently large. It is not automatically resized.
1452     * @return the {@link Integer}, {@link Float}, {@link Long},
1453     * {@link Double}, {@link String} or {@link Type} corresponding to
1454     * the given constant pool item.
1455     */

1456    public Object JavaDoc readConst(final int item, final char[] buf) {
1457        int index = items[item];
1458        switch (b[index - 1]) {
1459            case ClassWriter.INT:
1460                return new Integer JavaDoc(readInt(index));
1461            case ClassWriter.FLOAT:
1462                return new Float JavaDoc(Float.intBitsToFloat(readInt(index)));
1463            case ClassWriter.LONG:
1464                return new Long JavaDoc(readLong(index));
1465            case ClassWriter.DOUBLE:
1466                return new Double JavaDoc(Double.longBitsToDouble(readLong(index)));
1467            case ClassWriter.CLASS:
1468                String JavaDoc s = readUTF8(index, buf);
1469                return Type.getType(s.charAt(0) == '[' ? s : "L" + s + ";");
1470            // case ClassWriter.STR:
1471
default:
1472                return readUTF8(index, buf);
1473        }
1474    }
1475}
1476
Popular Tags