OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / tools / external / asm / org / objectweb / asm / ClassReader.java
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;
33 import java.io.IOException;
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[] 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         int ll = items.length;
107         strings = new String[ll];
108         int max = 0;
109         int index = off + 10;
110         for (int i = 1; i < ll; ++i) {
111             items[i] = index + 1;
112             int tag = b[index];
113             int size;
114             switch (tag) {
115                 case ClassWriter.FIELD:
116                 case ClassWriter.METH:
117                 case ClassWriter.IMETH:
118                 case ClassWriter.INT:
119                 case ClassWriter.FLOAT:
120                 case ClassWriter.NAME_TYPE:
121                     size = 5;
122                     break;
123                 case ClassWriter.LONG:
124                 case ClassWriter.DOUBLE:
125                     size = 9;
126                     ++i;
127                     break;
128                 case ClassWriter.UTF8:
129                     size = 3 + readUnsignedShort(index + 1);
130                     if (size > max) {
131                         max = size;
132                     }
133                     break;
134                 // case ClassWriter.CLASS:
135                 // case ClassWriter.STR:
136                 default:
137                     size = 3;
138                     break;
139             }
140             index += size;
141         }
142         maxStringLength = max;
143         // the class header information starts just after the constant pool
144         header = index;
145     }
146
147     /**
148      * Copies the constant pool data into the given {@link ClassWriter}. Should
149      * be called before the {@link #accept(ClassVisitor,boolean)} method.
150      * 
151      * @param classWriter the {@link ClassWriter} to copy constant pool into.
152      */
153     void copyPool(final ClassWriter classWriter) {
154         char[] buf = new char[maxStringLength];
155         int ll = items.length;
156         Item[] items2 = new Item[ll];
157         for (int i = 1; i < ll; i++) {
158             int index = items[i];
159             int tag = b[index - 1];
160             Item item = new Item(i);
161             int nameType;
162             switch (tag) {
163                 case ClassWriter.FIELD:
164                 case ClassWriter.METH:
165                 case ClassWriter.IMETH:
166                     nameType = items[readUnsignedShort(index + 2)];
167                     item.set(tag,
168                             readClass(index, buf),
169                             readUTF8(nameType, buf),
170                             readUTF8(nameType + 2, buf));
171                     break;
172
173                 case ClassWriter.INT:
174                     item.set(readInt(index));
175                     break;
176
177                 case ClassWriter.FLOAT:
178                     item.set(Float.intBitsToFloat(readInt(index)));
179                     break;
180
181                 case ClassWriter.NAME_TYPE:
182                     item.set(tag,
183                             readUTF8(index, buf),
184                             readUTF8(index + 2, buf),
185                             null);
186                     break;
187
188                 case ClassWriter.LONG:
189                     item.set(readLong(index));
190                     ++i;
191                     break;
192
193                 case ClassWriter.DOUBLE:
194                     item.set(Double.longBitsToDouble(readLong(index)));
195                     ++i;
196                     break;
197
198                 case ClassWriter.UTF8: {
199                     String s = strings[i];
200                     if (s == null) {
201                         index = items[i];
202                         s = strings[i] = readUTF(index + 2,
203                                 readUnsignedShort(index),
204                                 buf);
205                     }
206                     item.set(tag, s, null, null);
207                 }
208                     break;
209
210                 // case ClassWriter.STR:
211                 // case ClassWriter.CLASS:
212                 default:
213                     item.set(tag, readUTF8(index, buf), null, null);
214                     break;
215             }
216
217             int index2 = item.hashCode % items2.length;
218             item.next = items2[index2];
219             items2[index2] = item;
220         }
221
222         int off = items[1] - 1;
223         classWriter.pool.putByteArray(b, off, header - off);
224         classWriter.items = items2;
225         classWriter.threshold = (int) (0.75d * ll);
226         classWriter.index = ll;
227     }
228
229     /**
230      * Constructs a new {@link ClassReader} object.
231      * 
232      * @param is an input stream from which to read the class.
233      * @throws IOException if a problem occurs during reading.
234      */
235     public ClassReader(final InputStream is) throws IOException {
236         this(readClass(is));
237     }
238
239     /**
240      * Constructs a new {@link ClassReader} object.
241      * 
242      * @param name the fully qualified name of the class to be read.
243      * @throws IOException if an exception occurs during reading.
244      */
245     public ClassReader(final String name) throws IOException {
246         this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
247                 + ".class"));
248     }
249
250     /**
251      * Reads the bytecode of a class.
252      * 
253      * @param is an input stream from which to read the class.
254      * @return the bytecode read from the given input stream.
255      * @throws IOException if a problem occurs during reading.
256      */
257     private static byte[] readClass(final InputStream is) throws IOException {
258         if (is == null) {
259             throw new IOException("Class not found");
260         }
261         byte[] b = new byte[is.available()];
262         int len = 0;
263         while (true) {
264             int n = is.read(b, len, b.length - len);
265             if (n == -1) {
266                 if (len < b.length) {
267                     byte[] c = new byte[len];
268                     System.arraycopy(b, 0, c, 0, len);
269                     b = c;
270                 }
271                 return b;
272             }
273             len += n;
274             if (len == b.length) {
275                 byte[] c = new byte[b.length + 1000];
276                 System.arraycopy(b, 0, c, 0, len);
277                 b = c;
278             }
279         }
280     }
281
282     // ------------------------------------------------------------------------
283     // Public methods
284     // ------------------------------------------------------------------------
285
286     /**
287      * Makes the given visitor visit the Java class of this {@link ClassReader}.
288      * This class is the one specified in the constructor (see
289      * {@link #ClassReader(byte[]) ClassReader}).
290      * 
291      * @param classVisitor the visitor that must visit this class.
292      * @param skipDebug <tt>true</tt> if the debug information of the class
293      *        must not be visited. In this case the
294      *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
295      *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
296      *        not be called.
297      */
298     public void accept(final ClassVisitor classVisitor, final boolean skipDebug)
299     {
300         accept(classVisitor, new Attribute[0], skipDebug);
301     }
302
303     /**
304      * Makes the given visitor visit the Java class of this {@link ClassReader}.
305      * This class is the one specified in the constructor (see
306      * {@link #ClassReader(byte[]) ClassReader}).
307      * 
308      * @param classVisitor the visitor that must visit this class.
309      * @param attrs prototypes of the attributes that must be parsed during the
310      *        visit of the class. Any attribute whose type is not equal to the
311      *        type of one the prototypes will be ignored.
312      * @param skipDebug <tt>true</tt> if the debug information of the class
313      *        must not be visited. In this case the
314      *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
315      *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
316      *        not be called.
317      */
318     public void accept(
319         final ClassVisitor classVisitor,
320         final Attribute[] attrs,
321         final boolean skipDebug)
322     {
323         byte[] b = this.b; // the bytecode array
324         char[] c = new char[maxStringLength]; // buffer used to read strings
325         int i, j, k; // loop variables
326         int u, v, w; // indexes in b
327         Attribute attr;
328
329         int access;
330         String name;
331         String desc;
332         String attrName;
333         String signature;
334         int anns = 0;
335         int ianns = 0;
336         Attribute cattrs = null;
337
338         // visits the header
339         u = header;
340         access = readUnsignedShort(u);
341         name = readClass(u + 2, c);
342         v = items[readUnsignedShort(u + 4)];
343         String superClassName = v == 0 ? null : readUTF8(v, c);
344         String[] implementedItfs = new String[readUnsignedShort(u + 6)];
345         w = 0;
346         u += 8;
347         for (i = 0; i < implementedItfs.length; ++i) {
348             implementedItfs[i] = readClass(u, c);
349             u += 2;
350         }
351
352         // skips fields and methods
353         v = u;
354         i = readUnsignedShort(v);
355         v += 2;
356         for (; i > 0; --i) {
357             j = readUnsignedShort(v + 6);
358             v += 8;
359             for (; j > 0; --j) {
360                 v += 6 + readInt(v + 2);
361             }
362         }
363         i = readUnsignedShort(v);
364         v += 2;
365         for (; i > 0; --i) {
366             j = readUnsignedShort(v + 6);
367             v += 8;
368             for (; j > 0; --j) {
369                 v += 6 + readInt(v + 2);
370             }
371         }
372         // reads the class's attributes
373         signature = null;
374         String sourceFile = null;
375         String sourceDebug = null;
376         String enclosingOwner = null;
377         String enclosingName = null;
378         String enclosingDesc = null;
379
380         i = readUnsignedShort(v);
381         v += 2;
382         for (; i > 0; --i) {
383             attrName = readUTF8(v, c);
384             if (attrName.equals("SourceFile")) {
385                 sourceFile = readUTF8(v + 6, c);
386             } else if (attrName.equals("Deprecated")) {
387                 access |= Opcodes.ACC_DEPRECATED;
388             } else if (attrName.equals("Synthetic")) {
389                 access |= Opcodes.ACC_SYNTHETIC;
390             } else if (attrName.equals("Annotation")) {
391                 access |= Opcodes.ACC_ANNOTATION;
392             } else if (attrName.equals("Enum")) {
393                 access |= Opcodes.ACC_ENUM;
394             } else if (attrName.equals("InnerClasses")) {
395                 w = v + 6;
396             } else if (attrName.equals("Signature")) {
397                 signature = readUTF8(v + 6, c);
398             } else if (attrName.equals("SourceDebugExtension")) {
399                 int len = readInt(v + 2);
400                 sourceDebug = readUTF(v + 6, len, new char[len]);
401             } else if (attrName.equals("EnclosingMethod")) {
402                 enclosingOwner = readClass(v + 6, c);
403                 int item = readUnsignedShort(v + 8);
404                 if (item != 0) {
405                     enclosingName = readUTF8(items[item], c);
406                     enclosingDesc = readUTF8(items[item] + 2, c);
407                 }
408             } else if (attrName.equals("RuntimeVisibleAnnotations")) {
409                 anns = v + 6;
410             } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
411                 ianns = v + 6;
412             } else {
413                 attr = readAttribute(attrs,
414                         attrName,
415                         v + 6,
416                         readInt(v + 2),
417                         c,
418                         -1,
419                         null);
420                 if (attr != null) {
421                     attr.next = cattrs;
422                     cattrs = attr;
423                 }
424             }
425             v += 6 + readInt(v + 2);
426         }
427         // calls the visit method
428         classVisitor.visit(readInt(4),
429                 access,
430                 name,
431                 signature,
432                 superClassName,
433                 implementedItfs);
434
435         // calls the visitSource method
436         if (sourceFile != null || sourceDebug != null) {
437             classVisitor.visitSource(sourceFile, sourceDebug);
438         }
439
440         // calls the visitOuterClass method
441         if (enclosingOwner != null) {
442             classVisitor.visitOuterClass(enclosingOwner,
443                     enclosingName,
444                     enclosingDesc);
445         }
446
447         // visits the class annotations
448         for (i = 1; i >= 0; --i) {
449             v = i == 0 ? ianns : anns;
450             if (v != 0) {
451                 j = readUnsignedShort(v);
452                 v += 2;
453                 for (; j > 0; --j) {
454                     desc = readUTF8(v, c);
455                     v += 2;
456                     v = readAnnotationValues(v,
457                             c,
458                             classVisitor.visitAnnotation(desc, i != 0));
459                 }
460             }
461         }
462
463         // visits the class attributes
464         while (cattrs != null) {
465             attr = cattrs.next;
466             cattrs.next = null;
467             classVisitor.visitAttribute(cattrs);
468             cattrs = attr;
469         }
470
471         // class the visitInnerClass method
472         if (w != 0) {
473             i = readUnsignedShort(w);
474             w += 2;
475             for (; i > 0; --i) {
476                 classVisitor.visitInnerClass(readUnsignedShort(w) == 0
477                         ? null
478                         : readClass(w, c), readUnsignedShort(w + 2) == 0
479                         ? null
480                         : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
481                         ? null
482                         : readUTF8(w + 4, c), readUnsignedShort(w + 6));
483                 w += 8;
484             }
485         }
486
487         // visits the fields
488         i = readUnsignedShort(u);
489         u += 2;
490         for (; i > 0; --i) {
491             access = readUnsignedShort(u);
492             name = readUTF8(u + 2, c);
493             desc = readUTF8(u + 4, c);
494             // visits the field's attributes and looks for a ConstantValue
495             // attribute
496             int fieldValueItem = 0;
497             signature = null;
498             anns = 0;
499             ianns = 0;
500             cattrs = null;
501
502             j = readUnsignedShort(u + 6);
503             u += 8;
504             for (; j > 0; --j) {
505                 attrName = readUTF8(u, c);
506                 if (attrName.equals("ConstantValue")) {
507                     fieldValueItem = readUnsignedShort(u + 6);
508                 } else if (attrName.equals("Synthetic")) {
509                     access |= Opcodes.ACC_SYNTHETIC;
510                 } else if (attrName.equals("Deprecated")) {
511                     access |= Opcodes.ACC_DEPRECATED;
512                 } else if (attrName.equals("Enum")) {
513                     access |= Opcodes.ACC_ENUM;
514                 } else if (attrName.equals("Signature")) {
515                     signature = readUTF8(u + 6, c);
516                 } else if (attrName.equals("RuntimeVisibleAnnotations")) {
517                     anns = u + 6;
518                 } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
519                     ianns = u + 6;
520                 } else {
521                     attr = readAttribute(attrs,
522                             attrName,
523                             u + 6,
524                             readInt(u + 2),
525                             c,
526                             -1,
527                             null);
528                     if (attr != null) {
529                         attr.next = cattrs;
530                         cattrs = attr;
531                     }
532                 }
533                 u += 6 + readInt(u + 2);
534             }
535             // reads the field's value, if any
536             Object value = (fieldValueItem == 0
537                     ? null
538                     : readConst(fieldValueItem, c));
539             // visits the field
540             FieldVisitor fv = classVisitor.visitField(access,
541                     name,
542                     desc,
543                     signature,
544                     value);
545             // visits the field annotations and attributes
546             if (fv != null) {
547                 for (j = 1; j >= 0; --j) {
548                     v = j == 0 ? ianns : anns;
549                     if (v != 0) {
550                         k = readUnsignedShort(v);
551                         v += 2;
552                         for (; k > 0; --k) {
553                             desc = readUTF8(v, c);
554                             v += 2;
555                             v = readAnnotationValues(v,
556                                     c,
557                                     fv.visitAnnotation(desc, j != 0));
558                         }
559                     }
560                 }
561                 while (cattrs != null) {
562                     attr = cattrs.next;
563                     cattrs.next = null;
564                     fv.visitAttribute(cattrs);
565                     cattrs = attr;
566                 }
567                 fv.visitEnd();
568             }
569         }
570
571         // visits the methods
572         i = readUnsignedShort(u);
573         u += 2;
574         for (; i > 0; --i) {
575             int u0 = u + 6;
576             access = readUnsignedShort(u);
577             name = readUTF8(u + 2, c);
578             desc = readUTF8(u + 4, c);
579             signature = null;
580             anns = 0;
581             ianns = 0;
582             int dann = 0;
583             int mpanns = 0;
584             int impanns = 0;
585             cattrs = null;
586             v = 0;
587             w = 0;
588
589             // looks for Code and Exceptions attributes
590             j = readUnsignedShort(u + 6);
591             u += 8;
592             for (; j > 0; --j) {
593                 attrName = readUTF8(u, c);
594                 u += 2;
595                 int attrSize = readInt(u);
596                 u += 4;
597                 if (attrName.equals("Code")) {
598                     v = u;
599                 } else if (attrName.equals("Exceptions")) {
600                     w = u;
601                 } else if (attrName.equals("Synthetic")) {
602                     access |= Opcodes.ACC_SYNTHETIC;
603                 } else if (attrName.equals("Varargs")) {
604                     access |= Opcodes.ACC_VARARGS;
605                 } else if (attrName.equals("Bridge")) {
606                     access |= Opcodes.ACC_BRIDGE;
607                 } else if (attrName.equals("Deprecated")) {
608                     access |= Opcodes.ACC_DEPRECATED;
609                 } else if (attrName.equals("Signature")) {
610                     signature = readUTF8(u, c);
611                 } else if (attrName.equals("AnnotationDefault")) {
612                     dann = u;
613                 } else if (attrName.equals("RuntimeVisibleAnnotations")) {
614                     anns = u;
615                 } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
616                     ianns = u;
617                 } else if (attrName.equals("RuntimeVisibleParameterAnnotations"))
618                 {
619                     mpanns = u;
620                 } else if (attrName.equals("RuntimeInvisibleParameterAnnotations"))
621                 {
622                     impanns = u;
623                 } else {
624                     attr = readAttribute(attrs,
625                             attrName,
626                             u,
627                             attrSize,
628                             c,
629                             -1,
630                             null);
631                     if (attr != null) {
632                         attr.next = cattrs;
633                         cattrs = attr;
634                     }
635                 }
636                 u += attrSize;
637             }
638             // reads declared exceptions
639             String[] exceptions;
640             if (w == 0) {
641                 exceptions = null;
642             } else {
643                 exceptions = new String[readUnsignedShort(w)];
644                 w += 2;
645                 for (j = 0; j < exceptions.length; ++j) {
646                     exceptions[j] = readClass(w, c);
647                     w += 2;
648                 }
649             }
650
651             // visits the method's code, if any
652             MethodVisitor mv = classVisitor.visitMethod(access,
653                     name,
654                     desc,
655                     signature,
656                     exceptions);
657
658             if (mv != null) {
659                 /*
660                  * if the returned MethodVisitor is in fact a MethodWriter, it
661                  * means there is no method adapter between the reader and the
662                  * writer. If, in addition, the writer's constant pool was
663                  * copied from this reader (mw.cw.cr == this), and the signature
664                  * and exceptions of the method have not been changed, then it
665                  * is possible to skip all visit events and just copy the
666                  * original code of the method to the writer (the access, name
667                  * and descriptor can have been changed, this is not important
668                  * since they are not copied as is from the reader).
669                  */
670                 if (mv instanceof MethodWriter) {
671                     MethodWriter mw = (MethodWriter) mv;
672                     if (mw.cw.cr == this) {
673                         if (signature == mw.signature) {
674                             boolean sameExceptions = false;
675                             if (exceptions == null) {
676                                 sameExceptions = mw.exceptionCount == 0;
677                             } else {
678                                 if (exceptions.length == mw.exceptionCount) {
679                                     sameExceptions = true;
680                                     for (j = exceptions.length - 1; j >= 0; --j)
681                                     {
682                                         w -= 2;
683                                         if (mw.exceptions[j] != readUnsignedShort(w))
684                                         {
685                                             sameExceptions = false;
686                                             break;
687                                         }
688                                     }
689                                 }
690                             }
691                             if (sameExceptions) {
692                                 /*
693                                  * we do not copy directly the code into
694                                  * MethodWriter to save a byte array copy
695                                  * operation. The real copy will be done in
696                                  * ClassWriter.toByteArray().
697                                  */
698                                 mw.classReaderOffset = u0;
699                                 mw.classReaderLength = u - u0;
700                                 continue;
701                             }
702                         }
703                     }
704                 }
705                 if (dann != 0) {
706                     AnnotationVisitor dv = mv.visitAnnotationDefault();
707                     readAnnotationValue(dann, c, null, dv);
708                     dv.visitEnd();
709                 }
710                 for (j = 1; j >= 0; --j) {
711                     w = j == 0 ? ianns : anns;
712                     if (w != 0) {
713                         k = readUnsignedShort(w);
714                         w += 2;
715                         for (; k > 0; --k) {
716                             desc = readUTF8(w, c);
717                             w += 2;
718                             w = readAnnotationValues(w,
719                                     c,
720                                     mv.visitAnnotation(desc, j != 0));
721                         }
722                     }
723                 }
724                 if (mpanns != 0) {
725                     readParameterAnnotations(mpanns, c, true, mv);
726                 }
727                 if (impanns != 0) {
728                     readParameterAnnotations(impanns, c, false, mv);
729                 }
730                 while (cattrs != null) {
731                     attr = cattrs.next;
732                     cattrs.next = null;
733                     mv.visitAttribute(cattrs);
734                     cattrs = attr;
735                 }
736             }
737
738             if (mv != null && v != 0) {
739                 int maxStack = readUnsignedShort(v);
740                 int maxLocals = readUnsignedShort(v + 2);
741                 int codeLength = readInt(v + 4);
742                 v += 8;
743
744                 int codeStart = v;
745                 int codeEnd = v + codeLength;
746
747                 mv.visitCode();
748
749                 // 1st phase: finds the labels
750                 int label;
751                 Label[] labels = new Label[codeLength + 1];
752                 while (v < codeEnd) {
753                     int opcode = b[v] & 0xFF;
754                     switch (ClassWriter.TYPE[opcode]) {
755                         case ClassWriter.NOARG_INSN:
756                         case ClassWriter.IMPLVAR_INSN:
757                             v += 1;
758                             break;
759                         case ClassWriter.LABEL_INSN:
760                             label = v - codeStart + readShort(v + 1);
761                             if (labels[label] == null) {
762                                 labels[label] = new Label();
763                             }
764                             v += 3;
765                             break;
766                         case ClassWriter.LABELW_INSN:
767                             label = v - codeStart + readInt(v + 1);
768                             if (labels[label] == null) {
769                                 labels[label] = new Label();
770                             }
771                             v += 5;
772                             break;
773                         case ClassWriter.WIDE_INSN:
774                             opcode = b[v + 1] & 0xFF;
775                             if (opcode == Opcodes.IINC) {
776                                 v += 6;
777                             } else {
778                                 v += 4;
779                             }
780                             break;
781                         case ClassWriter.TABL_INSN:
782                             // skips 0 to 3 padding bytes
783                             w = v - codeStart;
784                             v = v + 4 - (w & 3);
785                             // reads instruction
786                             label = w + readInt(v);
787                             v += 4;
788                             if (labels[label] == null) {
789                                 labels[label] = new Label();
790                             }
791                             j = readInt(v);
792                             v += 4;
793                             j = readInt(v) - j + 1;
794                             v += 4;
795                             for (; j > 0; --j) {
796                                 label = w + readInt(v);
797                                 v += 4;
798                                 if (labels[label] == null) {
799                                     labels[label] = new Label();
800                                 }
801                             }
802                             break;
803                         case ClassWriter.LOOK_INSN:
804                             // skips 0 to 3 padding bytes
805                             w = v - codeStart;
806                             v = v + 4 - (w & 3);
807                             // reads instruction
808                             label = w + readInt(v);
809                             v += 4;
810                             if (labels[label] == null) {
811                                 labels[label] = new Label();
812                             }
813                             j = readInt(v);
814                             v += 4;
815                             for (; j > 0; --j) {
816                                 v += 4; // skips key
817                                 label = w + readInt(v);
818                                 v += 4;
819                                 if (labels[label] == null) {
820                                     labels[label] = new Label();
821                                 }
822                             }
823                             break;
824                         case ClassWriter.VAR_INSN:
825                         case ClassWriter.SBYTE_INSN:
826                         case ClassWriter.LDC_INSN:
827                             v += 2;
828                             break;
829                         case ClassWriter.SHORT_INSN:
830                         case ClassWriter.LDCW_INSN:
831                         case ClassWriter.FIELDORMETH_INSN:
832                         case ClassWriter.TYPE_INSN:
833                         case ClassWriter.IINC_INSN:
834                             v += 3;
835                             break;
836                         case ClassWriter.ITFMETH_INSN:
837                             v += 5;
838                             break;
839                         // case MANA_INSN:
840                         default:
841                             v += 4;
842                             break;
843                     }
844                 }
845                 // parses the try catch entries
846                 j = readUnsignedShort(v);
847                 v += 2;
848                 for (; j > 0; --j) {
849                     label = readUnsignedShort(v);
850                     Label start = labels[label];
851                     if (start == null) {
852                         labels[label] = start = new Label();
853                     }
854                     label = readUnsignedShort(v + 2);
855                     Label end = labels[label];
856                     if (end == null) {
857                         labels[label] = end = new Label();
858                     }
859                     label = readUnsignedShort(v + 4);
860                     Label handler = labels[label];
861                     if (handler == null) {
862                         labels[label] = handler = new Label();
863                     }
864                     
865                     int type = readUnsignedShort(v + 6);
866                     if (type == 0) {
867                         mv.visitTryCatchBlock(start, end, handler, null);
868                     } else {
869                         mv.visitTryCatchBlock(start,
870                                 end,
871                                 handler,
872                                 readUTF8(items[type], c));
873                     }
874                     v += 8;
875                 }
876                 // parses the local variable, line number tables, and code
877                 // attributes
878                 int varTable = 0;
879                 int varTypeTable = 0;
880                 cattrs = null;
881                 j = readUnsignedShort(v);
882                 v += 2;
883                 for (; j > 0; --j) {
884                     attrName = readUTF8(v, c);
885                     if (attrName.equals("LocalVariableTable")) {
886                         if (!skipDebug) {
887                             varTable = v + 6;
888                             k = readUnsignedShort(v + 6);
889                             w = v + 8;
890                             for (; k > 0; --k) {
891                                 label = readUnsignedShort(w);
892                                 if (labels[label] == null) {
893                                     labels[label] = new Label();
894                                 }
895                                 label += readUnsignedShort(w + 2);
896                                 if (labels[label] == null) {
897                                     labels[label] = new Label();
898                                 }
899                                 w += 10;
900                             }
901                         }
902                     } else if (attrName.equals("LocalVariableTypeTable")) {
903                         varTypeTable = v + 6;
904                     } else if (attrName.equals("LineNumberTable")) {
905                         if (!skipDebug) {
906                             k = readUnsignedShort(v + 6);
907                             w = v + 8;
908                             for (; k > 0; --k) {
909                                 label = readUnsignedShort(w);
910                                 if (labels[label] == null) {
911                                     labels[label] = new Label();
912                                 }
913                                 labels[label].line = readUnsignedShort(w + 2);
914                                 w += 4;
915                             }
916                         }
917                     } else {
918                         for (k = 0; k < attrs.length; ++k) {
919                             if (attrs[k].type.equals(attrName)) {
920                                 attr = attrs[k].read(this,
921                                         v + 6,
922                                         readInt(v + 2),
923                                         c,
924                                         codeStart - 8,
925                                         labels);
926                                 if (attr != null) {
927                                     attr.next = cattrs;
928                                     cattrs = attr;
929                                 }
930                             }
931                         }
932                     }
933                     v += 6 + readInt(v + 2);
934                 }
935
936                 // 2nd phase: visits each instruction
937                 v = codeStart;
938                 Label l;
939                 while (v < codeEnd) {
940                     w = v - codeStart;
941                     l = labels[w];
942                     if (l != null) {
943                         mv.visitLabel(l);
944                         if (!skipDebug && l.line > 0) {
945                             mv.visitLineNumber(l.line, l);
946                         }
947                     }
948                     int opcode = b[v] & 0xFF;
949                     switch (ClassWriter.TYPE[opcode]) {
950                         case ClassWriter.NOARG_INSN:
951                             mv.visitInsn(opcode);
952                             v += 1;
953                             break;
954                         case ClassWriter.IMPLVAR_INSN:
955                             if (opcode > Opcodes.ISTORE) {
956                                 opcode -= 59; // ISTORE_0
957                                 mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
958                                         opcode & 0x3);
959                             } else {
960                                 opcode -= 26; // ILOAD_0
961                                 mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
962                                         opcode & 0x3);
963                             }
964                             v += 1;
965                             break;
966                         case ClassWriter.LABEL_INSN:
967                             mv.visitJumpInsn(opcode, labels[w
968                                     + readShort(v + 1)]);
969                             v += 3;
970                             break;
971                         case ClassWriter.LABELW_INSN:
972                             mv.visitJumpInsn(opcode - 33, labels[w
973                                     + readInt(v + 1)]);
974                             v += 5;
975                             break;
976                         case ClassWriter.WIDE_INSN:
977                             opcode = b[v + 1] & 0xFF;
978                             if (opcode == Opcodes.IINC) {
979                                 mv.visitIincInsn(readUnsignedShort(v + 2),
980                                         readShort(v + 4));
981                                 v += 6;
982                             } else {
983                                 mv.visitVarInsn(opcode,
984                                         readUnsignedShort(v + 2));
985                                 v += 4;
986                             }
987                             break;
988                         case ClassWriter.TABL_INSN:
989                             // skips 0 to 3 padding bytes
990                             v = v + 4 - (w & 3);
991                             // reads instruction
992                             label = w + readInt(v);
993                             v += 4;
994                             int min = readInt(v);
995                             v += 4;
996                             int max = readInt(v);
997                             v += 4;
998                             Label[] table = new Label[max - min + 1];
999                             for (j = 0; j < table.length; ++j) {
1000                                 table[j] = labels[w + readInt(v)];
1001                                 v += 4;
1002                             }
1003                             mv.visitTableSwitchInsn(min,
1004                                     max,
1005                                     labels[label],
1006                                     table);
1007                             break;
1008                         case ClassWriter.LOOK_INSN:
1009                             // skips 0 to 3 padding bytes
1010                             v = v + 4 - (w & 3);
1011                             // reads instruction
1012                             label = w + readInt(v);
1013                             v += 4;
1014                             j = readInt(v);
1015                             v += 4;
1016                             int[] keys = new int[j];
1017                             Label[] values = new Label[j];
1018                             for (j = 0; j < keys.length; ++j) {
1019                                 keys[j] = readInt(v);
1020                                 v += 4;
1021                                 values[j] = labels[w + readInt(v)];
1022                                 v += 4;
1023                             }
1024                             mv.visitLookupSwitchInsn(labels[label],
1025                                     keys,
1026                                     values);
1027                             break;
1028                         case ClassWriter.VAR_INSN:
1029                             mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
1030                             v += 2;
1031                             break;
1032                         case ClassWriter.SBYTE_INSN:
1033                             mv.visitIntInsn(opcode, b[v + 1]);
1034                             v += 2;
1035                             break;
1036                         case ClassWriter.SHORT_INSN:
1037                             mv.visitIntInsn(opcode, readShort(v + 1));
1038                             v += 3;
1039                             break;
1040                         case ClassWriter.LDC_INSN:
1041                             mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
1042                             v += 2;
1043                             break;
1044                         case ClassWriter.LDCW_INSN:
1045                             mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
1046                                     c));
1047                             v += 3;
1048                             break;
1049                         case ClassWriter.FIELDORMETH_INSN:
1050                         case ClassWriter.ITFMETH_INSN:
1051                             int cpIndex = items[readUnsignedShort(v + 1)];
1052                             String iowner = readClass(cpIndex, c);
1053                             cpIndex = items[readUnsignedShort(cpIndex + 2)];
1054                             String iname = readUTF8(cpIndex, c);
1055                             String idesc = readUTF8(cpIndex + 2, c);
1056                             if (opcode < Opcodes.INVOKEVIRTUAL) {
1057                                 mv.visitFieldInsn(opcode, iowner, iname, idesc);
1058                             } else {
1059                                 mv.visitMethodInsn(opcode, iowner, iname, idesc);
1060                             }
1061                             if (opcode == Opcodes.INVOKEINTERFACE) {
1062                                 v += 5;
1063                             } else {
1064                                 v += 3;
1065                             }
1066                             break;
1067                         case ClassWriter.TYPE_INSN:
1068                             mv.visitTypeInsn(opcode, readClass(v + 1, c));
1069                             v += 3;
1070                             break;
1071                         case ClassWriter.IINC_INSN:
1072                             mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
1073                             v += 3;
1074                             break;
1075                         // case MANA_INSN:
1076                         default:
1077                             mv.visitMultiANewArrayInsn(readClass(v + 1, c),
1078                                     b[v + 3] & 0xFF);
1079                             v += 4;
1080                             break;
1081                     }
1082                 }
1083                 l = labels[codeEnd - codeStart];
1084                 if (l != null) {
1085                     mv.visitLabel(l);
1086                 }
1087
1088                 // visits the local variable tables
1089                 if (!skipDebug && varTable != 0) {
1090                     int[] typeTable = null;
1091                     if (varTypeTable != 0) {
1092                         w = varTypeTable;
1093                         k = readUnsignedShort(w) * 3;
1094                         w += 2;
1095                         typeTable = new int[k];
1096                         while (k > 0) {
1097                             typeTable[--k] = w + 6; // signature
1098                             typeTable[--k] = readUnsignedShort(w + 8); // index
1099                             typeTable[--k] = readUnsignedShort(w); // start
1100                             w += 10;
1101                         }
1102                     }
1103                     w = varTable;
1104                     k = readUnsignedShort(w);
1105                     w += 2;
1106                     for (; k > 0; --k) {
1107                         int start = readUnsignedShort(w);
1108                         int length = readUnsignedShort(w + 2);
1109                         int index = readUnsignedShort(w + 8);
1110                         String vsignature = null;
1111                         if (typeTable != null) {
1112                             for (int a = 0; a < typeTable.length; a += 3) {
1113                                 if (typeTable[a] == start
1114                                         && typeTable[a + 1] == index)
1115                                 {
1116                                     vsignature = readUTF8(typeTable[a + 2], c);
1117                                     break;
1118                                 }
1119                             }
1120                         }
1121                         mv.visitLocalVariable(readUTF8(w + 4, c),
1122                                 readUTF8(w + 6, c),
1123                                 vsignature,
1124                                 labels[start],
1125                                 labels[start + length],
1126                                 index);
1127                         w += 10;
1128                     }
1129                 }
1130                 // visits the other attributes
1131                 while (cattrs != null) {
1132                     attr = cattrs.next;
1133                     cattrs.next = null;
1134                     mv.visitAttribute(cattrs);
1135                     cattrs = attr;
1136                 }
1137                 // visits the max stack and max locals values
1138                 mv.visitMaxs(maxStack, maxLocals);
1139             }
1140
1141             if (mv != null) {
1142                 mv.visitEnd();
1143             }
1144         }
1145
1146         // visits the end of the class
1147         classVisitor.visitEnd();
1148     }
1149
1150     /**
1151      * Reads parameter annotations and makes the given visitor visit them.
1152      * 
1153      * @param v start offset in {@link #b b} of the annotations to be read.
1154      * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1155      *        {@link #readClass(int,char[]) readClass} or
1156      *        {@link #readConst readConst}.
1157      * @param visible <tt>true</tt> if the annotations to be read are visible
1158      *        at runtime.
1159      * @param mv the visitor that must visit the annotations.
1160      */
1161     private void readParameterAnnotations(
1162         int v,
1163         final char[] buf,
1164         final boolean visible,
1165         final MethodVisitor mv)
1166     {
1167         int n = b[v++] & 0xFF;
1168         for (int i = 0; i < n; ++i) {
1169             int j = readUnsignedShort(v);
1170             v += 2;
1171             for (; j > 0; --j) {
1172                 String desc = readUTF8(v, buf);
1173                 v += 2;
1174                 AnnotationVisitor av = mv.visitParameterAnnotation(i,
1175                         desc,
1176                         visible);
1177                 v = readAnnotationValues(v, buf, av);
1178             }
1179         }
1180     }
1181
1182     /**
1183      * Reads the values of an annotation and makes the given visitor visit them.
1184      * 
1185      * @param v the start offset in {@link #b b} of the values to be read
1186      *        (including the unsigned short that gives the number of values).
1187      * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1188      *        {@link #readClass(int,char[]) readClass} or
1189      *        {@link #readConst readConst}.
1190      * @param av the visitor that must visit the values.
1191      * @return the end offset of the annotations values.
1192      */
1193     private int readAnnotationValues(
1194         int v,
1195         final char[] buf,
1196         final AnnotationVisitor av)
1197     {
1198         int i = readUnsignedShort(v);
1199         v += 2;
1200         for (; i > 0; --i) {
1201             String name = readUTF8(v, buf);
1202             v += 2;
1203             v = readAnnotationValue(v, buf, name, av);
1204         }
1205         av.visitEnd();
1206         return v;
1207     }
1208
1209     /**
1210      * Reads a value of an annotation and makes the given visitor visit it.
1211      * 
1212      * @param v the start offset in {@link #b b} of the value to be read (<i>not
1213      *        including the value name constant pool index</i>).
1214      * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1215      *        {@link #readClass(int,char[]) readClass} or
1216      *        {@link #readConst readConst}.
1217      * @param name the name of the value to be read.
1218      * @param av the visitor that must visit the value.
1219      * @return the end offset of the annotation value.
1220      */
1221     private int readAnnotationValue(
1222         int v,
1223         final char[] buf,
1224         final String name,
1225         final AnnotationVisitor av)
1226     {
1227         int i;
1228         switch (readByte(v++)) {
1229             case 'I': // pointer to CONSTANT_Integer
1230             case 'J': // pointer to CONSTANT_Long
1231             case 'F': // pointer to CONSTANT_Float
1232             case 'D': // pointer to CONSTANT_Double
1233                 av.visit(name, readConst(readUnsignedShort(v), buf));
1234                 v += 2;
1235                 break;
1236             case 'B': // pointer to CONSTANT_Byte
1237                 av.visit(name,
1238                         new Byte((byte) readInt(items[readUnsignedShort(v)])));
1239                 v += 2;
1240                 break;
1241             case 'Z': // pointer to CONSTANT_Boolean
1242                 boolean b = readInt(items[readUnsignedShort(v)]) == 0;
1243                 av.visit(name, b ? Boolean.FALSE : Boolean.TRUE);
1244                 v += 2;
1245                 break;
1246             case 'S': // pointer to CONSTANT_Short
1247                 av.visit(name,
1248                         new Short((short) readInt(items[readUnsignedShort(v)])));
1249                 v += 2;
1250                 break;
1251             case 'C': // pointer to CONSTANT_Char
1252                 av.visit(name,
1253                         new Character((char) readInt(items[readUnsignedShort(v)])));
1254                 v += 2;
1255                 break;
1256             case 's': // pointer to CONSTANT_Utf8
1257                 av.visit(name, readUTF8(v, buf));
1258                 v += 2;
1259                 break;
1260             case 'e': // enum_const_value
1261                 av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
1262                 v += 4;
1263                 break;
1264             case 'c': // class_info
1265                 av.visit(name, Type.getType(readUTF8(v, buf)));
1266                 v += 2;
1267                 break;
1268             case '@': // annotation_value
1269                 String desc = readUTF8(v, buf);
1270                 v += 2;
1271                 v = readAnnotationValues(v, buf, av.visitAnnotation(name, desc));
1272                 break;
1273             case '[': // array_value
1274                 int size = readUnsignedShort(v);
1275                 v += 2;
1276                 if (size == 0) {
1277                     av.visitArray(name).visitEnd();
1278                     return v;
1279                 }
1280                 switch (readByte(v++)) {
1281                     case 'B':
1282                         byte[] bv = new byte[size];
1283                         for (i = 0; i < size; i++) {
1284                             bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
1285                             v += 3;
1286                         }
1287                         av.visit(name, bv);
1288                         --v;
1289                         break;
1290                     case 'Z':
1291                         boolean[] zv = new boolean[size];
1292                         for (i = 0; i < size; i++) {
1293                             zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
1294                             v += 3;
1295                         }
1296                         av.visit(name, zv);
1297                         --v;
1298                         break;
1299                     case 'S':
1300                         short[] sv = new short[size];
1301                         for (i = 0; i < size; i++) {
1302                             sv[i] = (short) readInt(items[readUnsignedShort(v)]);
1303                             v += 3;
1304                         }
1305                         av.visit(name, sv);
1306                         --v;
1307                         break;
1308                     case 'C':
1309                         char[] cv = new char[size];
1310                         for (i = 0; i < size; i++) {
1311                             cv[i] = (char) readInt(items[readUnsignedShort(v)]);
1312                             v += 3;
1313                         }
1314                         av.visit(name, cv);
1315                         --v;
1316                         break;
1317                     case 'I':
1318                         int[] iv = new int[size];
1319                         for (i = 0; i < size; i++) {
1320                             iv[i] = readInt(items[readUnsignedShort(v)]);
1321                             v += 3;
1322                         }
1323                         av.visit(name, iv);
1324                         --v;
1325                         break;
1326                     case 'J':
1327                         long[] lv = new long[size];
1328                         for (i = 0; i < size; i++) {
1329                             lv[i] = readLong(items[readUnsignedShort(v)]);
1330                             v += 3;
1331                         }
1332                         av.visit(name, lv);
1333                         --v;
1334                         break;
1335                     case 'F':
1336                         float[] fv = new float[size];
1337                         for (i = 0; i < size; i++) {
1338                             fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
1339                             v += 3;
1340                         }
1341                         av.visit(name, fv);
1342                         --v;
1343                         break;
1344                     case 'D':
1345                         double[] dv = new double[size];
1346                         for (i = 0; i < size; i++) {
1347                             dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
1348                             v += 3;
1349                         }
1350                         av.visit(name, dv);
1351                         --v;
1352                         break;
1353                     default:
1354                         v--;
1355                         AnnotationVisitor aav = av.visitArray(name);
1356                         for (i = size; i > 0; --i) {
1357                             v = readAnnotationValue(v, buf, null, aav);
1358                         }
1359                         aav.visitEnd();
1360                 }
1361         }
1362         return v;
1363     }
1364
1365     /**
1366      * Reads an attribute in {@link #b b}.
1367      * 
1368      * @param attrs prototypes of the attributes that must be parsed during the
1369      *        visit of the class. Any attribute whose type is not equal to the
1370      *        type of one the prototypes is ignored (i.e. an empty
1371      *        {@link Attribute} instance is returned).
1372      * @param type the type of the attribute.
1373      * @param off index of the first byte of the attribute's content in
1374      *        {@link #b b}. The 6 attribute header bytes, containing the type
1375      *        and the length of the attribute, are not taken into account here
1376      *        (they have already been read).
1377      * @param len the length of the attribute's content.
1378      * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1379      *        {@link #readClass(int,char[]) readClass} or
1380      *        {@link #readConst readConst}.
1381      * @param codeOff index of the first byte of code's attribute content in
1382      *        {@link #b b}, or -1 if the attribute to be read is not a code
1383      *        attribute. The 6 attribute header bytes, containing the type and
1384      *        the length of the attribute, are not taken into account here.
1385      * @param labels the labels of the method's code, or <tt>null</tt> if the
1386      *        attribute to be read is not a code attribute.
1387      * @return the attribute that has been read, or <tt>null</tt> to skip this
1388      *         attribute.
1389      */
1390     private Attribute readAttribute(
1391         final Attribute[] attrs,
1392         final String type,
1393         final int off,
1394         final int len,
1395         final char[] buf,
1396         final int codeOff,
1397         final Label[] labels)
1398     {
1399         for (int i = 0; i < attrs.length; ++i) {
1400             if (attrs[i].type.equals(type)) {
1401                 return attrs[i].read(this, off, len, buf, codeOff, labels);
1402             }
1403         }
1404         return new Attribute(type).read(this, off, len, null, -1, null);
1405     }
1406
1407     // ------------------------------------------------------------------------
1408     // Utility methods: low level parsing
1409     // ------------------------------------------------------------------------
1410
1411     /**
1412      * Returns the start index of the constant pool item in {@link #b b}, plus
1413      * one. <i>This method is intended for {@link Attribute} sub classes, and is
1414      * normally not needed by class generators or adapters.</i>
1415      * 
1416      * @param item the index a constant pool item.
1417      * @return the start index of the constant pool item in {@link #b b}, plus
1418      *         one.
1419      */
1420     public int getItem(final int item) {
1421         return items[item];
1422     }
1423
1424     /**
1425      * Reads a byte value in {@link #b b}. <i>This method is intended for
1426      * {@link Attribute} sub classes, and is normally not needed by class
1427      * generators or adapters.</i>
1428      * 
1429      * @param index the start index of the value to be read in {@link #b b}.
1430      * @return the read value.
1431      */
1432     public int readByte(final int index) {
1433         return b[index] & 0xFF;
1434     }
1435
1436     /**
1437      * Reads an unsigned short value in {@link #b b}. <i>This method is
1438      * intended for {@link Attribute} sub classes, and is normally not needed by
1439      * class generators or adapters.</i>
1440      * 
1441      * @param index the start index of the value to be read in {@link #b b}.
1442      * @return the read value.
1443      */
1444     public int readUnsignedShort(final int index) {
1445         byte[] b = this.b;
1446         return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1447     }
1448
1449     /**
1450      * Reads a signed short value in {@link #b b}. <i>This method is intended
1451      * for {@link Attribute} sub classes, and is normally not needed by class
1452      * generators or adapters.</i>
1453      * 
1454      * @param index the start index of the value to be read in {@link #b b}.
1455      * @return the read value.
1456      */
1457     public short readShort(final int index) {
1458         byte[] b = this.b;
1459         return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1460     }
1461
1462     /**
1463      * Reads a signed int value in {@link #b b}. <i>This method is intended for
1464      * {@link Attribute} sub classes, and is normally not needed by class
1465      * generators or adapters.</i>
1466      * 
1467      * @param index the start index of the value to be read in {@link #b b}.
1468      * @return the read value.
1469      */
1470     public int readInt(final int index) {
1471         byte[] b = this.b;
1472         return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
1473                 | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1474     }
1475
1476     /**
1477      * Reads a signed long value in {@link #b b}. <i>This method is intended
1478      * for {@link Attribute} sub classes, and is normally not needed by class
1479      * generators or adapters.</i>
1480      * 
1481      * @param index the start index of the value to be read in {@link #b b}.
1482      * @return the read value.
1483      */
1484     public long readLong(final int index) {
1485         long l1 = readInt(index);
1486         long l0 = readInt(index + 4) & 0xFFFFFFFFL;
1487         return (l1 << 32) | l0;
1488     }
1489
1490     /**
1491      * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
1492      * is intended for {@link Attribute} sub classes, and is normally not needed
1493      * by class generators or adapters.</i>
1494      * 
1495      * @param index the start index of an unsigned short value in {@link #b b},
1496      *        whose value is the index of an UTF8 constant pool item.
1497      * @param buf buffer to be used to read the item. This buffer must be
1498      *        sufficiently large. It is not automatically resized.
1499      * @return the String corresponding to the specified UTF8 item.
1500      */
1501     public String readUTF8(int index, final char[] buf) {
1502         int item = readUnsignedShort(index);
1503         String s = strings[item];
1504         if (s != null) {
1505             return s;
1506         }
1507         index = items[item];
1508         return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
1509     }
1510
1511     /**
1512      * Reads UTF8 string in {@link #b b}.
1513      * 
1514      * @param index start offset of the UTF8 string to be read.
1515      * @param utfLen length of the UTF8 string to be read.
1516      * @param buf buffer to be used to read the string. This buffer must be
1517      *        sufficiently large. It is not automatically resized.
1518      * @return the String corresponding to the specified UTF8 string.
1519      */
1520     private String readUTF(int index, int utfLen, char[] buf) {
1521         int endIndex = index + utfLen;
1522         byte[] b = this.b;
1523         int strLen = 0;
1524         int c, d, e;
1525         while (index < endIndex) {
1526             c = b[index++] & 0xFF;
1527             switch (c >> 4) {
1528                 case 0:
1529                 case 1:
1530                 case 2:
1531                 case 3:
1532                 case 4:
1533                 case 5:
1534                 case 6:
1535                 case 7:
1536                     // 0xxxxxxx
1537                     buf[strLen++] = (char) c;
1538                     break;
1539                 case 12:
1540                 case 13:
1541                     // 110x xxxx 10xx xxxx
1542                     d = b[index++];
1543                     buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
1544                     break;
1545                 default:
1546                     // 1110 xxxx 10xx xxxx 10xx xxxx
1547                     d = b[index++];
1548                     e = b[index++];
1549                     buf[strLen++] = (char) (((c & 0x0F) << 12)
1550                             | ((d & 0x3F) << 6) | (e & 0x3F));
1551                     break;
1552             }
1553         }
1554         return new String(buf, 0, strLen);
1555     }
1556
1557     /**
1558      * Reads a class constant pool item in {@link #b b}. <i>This method is
1559      * intended for {@link Attribute} sub classes, and is normally not needed by
1560      * class generators or adapters.</i>
1561      * 
1562      * @param index the start index of an unsigned short value in {@link #b b},
1563      *        whose value is the index of a class constant pool item.
1564      * @param buf buffer to be used to read the item. This buffer must be
1565      *        sufficiently large. It is not automatically resized.
1566      * @return the String corresponding to the specified class item.
1567      */
1568     public String readClass(final int index, final char[] buf) {
1569         // computes the start index of the CONSTANT_Class item in b
1570         // and reads the CONSTANT_Utf8 item designated by
1571         // the first two bytes of this CONSTANT_Class item
1572         return readUTF8(items[readUnsignedShort(index)], buf);
1573     }
1574
1575     /**
1576      * Reads a numeric or string constant pool item in {@link #b b}. <i>This
1577      * method is intended for {@link Attribute} sub classes, and is normally not
1578      * needed by class generators or adapters.</i>
1579      * 
1580      * @param item the index of a constant pool item.
1581      * @param buf buffer to be used to read the item. This buffer must be
1582      *        sufficiently large. It is not automatically resized.
1583      * @return the {@link Integer}, {@link Float}, {@link Long},
1584      *         {@link Double}, {@link String} or {@link Type} corresponding to
1585      *         the given constant pool item.
1586      */
1587     public Object readConst(final int item, final char[] buf) {
1588         int index = items[item];
1589         switch (b[index - 1]) {
1590             case ClassWriter.INT:
1591                 return new Integer(readInt(index));
1592             case ClassWriter.FLOAT:
1593                 return new Float(Float.intBitsToFloat(readInt(index)));
1594             case ClassWriter.LONG:
1595                 return new Long(readLong(index));
1596             case ClassWriter.DOUBLE:
1597                 return new Double(Double.longBitsToDouble(readLong(index)));
1598             case ClassWriter.CLASS:
1599                 String s = readUTF8(index, buf);
1600                 return Type.getType(s.charAt(0) == '[' ? s : "L" + s + ";");
1601             // case ClassWriter.STR:
1602             default:
1603                 return readUTF8(index, buf);
1604         }
1605     }
1606 }