KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > asm > signature > SignatureReader


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 com.sleepycat.asm.signature;
31
32 /**
33  * A type signature parser to make a signature visitor visit an existing
34  * signature.
35  *
36  * @author Thomas Hallgren
37  * @author Eric Bruneton
38  */

39 public class SignatureReader {
40
41     /**
42      * The signature to be read.
43      */

44     private final String JavaDoc signature;
45
46     /**
47      * Constructs a {@link SignatureReader} for the given signature.
48      *
49      * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
50      * or <i>FieldTypeSignature</i>.
51      */

52     public SignatureReader(final String JavaDoc signature) {
53         this.signature = signature;
54     }
55
56     /**
57      * Makes the given visitor visit the signature of this
58      * {@link SignatureReader}. This signature is the one specified in the
59      * constructor (see {@link #SignatureReader(String) SignatureReader}). This
60      * method is intended to be called on a {@link SignatureReader} that was
61      * created using a <i>ClassSignature</i> (such as the
62      * <code>signature</code> parameter of the
63      * {@link com.sleepycat.asm.ClassVisitor#visit ClassVisitor.visit} method)
64      * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
65      * parameter of the
66      * {@link com.sleepycat.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
67      * method).
68      *
69      * @param v the visitor that must visit this signature.
70      */

71     public void accept(final SignatureVisitor v) {
72         String JavaDoc signature = this.signature;
73         int len = signature.length();
74         int pos;
75         char c;
76
77         if (signature.charAt(0) == '<') {
78             pos = 2;
79             do {
80                 int end = signature.indexOf(':', pos);
81                 v.visitFormalTypeParameter(signature.substring(pos - 1, end));
82                 pos = end + 1;
83
84                 c = signature.charAt(pos);
85                 if (c == 'L' || c == '[' || c == 'T') {
86                     pos = parseType(signature, pos, v.visitClassBound());
87                 }
88
89                 for (;;) {
90                     if ((c = signature.charAt(pos++)) == ':') {
91                         pos = parseType(signature, pos, v.visitInterfaceBound());
92                     } else {
93                         break;
94                     }
95                 }
96             } while (c != '>');
97         } else {
98             pos = 0;
99         }
100
101         if (signature.charAt(pos) == '(') {
102             pos = pos + 1;
103             while (signature.charAt(pos) != ')') {
104                 pos = parseType(signature, pos, v.visitParameterType());
105             }
106             pos = parseType(signature, pos + 1, v.visitReturnType());
107             while (pos < len) {
108                 pos = parseType(signature, pos + 1, v.visitExceptionType());
109             }
110         } else {
111             pos = parseType(signature, pos, v.visitSuperclass());
112             while (pos < len) {
113                 pos = parseType(signature, pos, v.visitInterface());
114             }
115         }
116     }
117
118     /**
119      * Makes the given visitor visit the signature of this
120      * {@link SignatureReader}. This signature is the one specified in the
121      * constructor (see {@link #SignatureReader(String) SignatureReader}). This
122      * method is intended to be called on a {@link SignatureReader} that was
123      * created using a <i>FieldTypeSignature</i>, such as the
124      * <code>signature</code> parameter of the
125      * {@link com.sleepycat.asm.ClassVisitor#visitField
126      * ClassVisitor.visitField} or {@link
127      * com.sleepycat.asm.MethodVisitor#visitLocalVariable
128      * MethodVisitor.visitLocalVariable} methods.
129      *
130      * @param v the visitor that must visit this signature.
131      */

132     public void acceptType(final SignatureVisitor v) {
133         parseType(this.signature, 0, v);
134     }
135
136     /**
137      * Parses a field type signature and makes the given visitor visit it.
138      *
139      * @param signature a string containing the signature that must be parsed.
140      * @param pos index of the first character of the signature to parsed.
141      * @param v the visitor that must visit this signature.
142      * @return the index of the first character after the parsed signature.
143      */

144     private static int parseType(
145         final String JavaDoc signature,
146         int pos,
147         final SignatureVisitor v)
148     {
149         char c;
150         int start, end;
151         boolean visited, inner;
152         String JavaDoc name;
153
154         switch (c = signature.charAt(pos++)) {
155             case 'Z':
156             case 'C':
157             case 'B':
158             case 'S':
159             case 'I':
160             case 'F':
161             case 'J':
162             case 'D':
163             case 'V':
164                 v.visitBaseType(c);
165                 return pos;
166
167             case '[':
168                 return parseType(signature, pos, v.visitArrayType());
169
170             case 'T':
171                 end = signature.indexOf(';', pos);
172                 v.visitTypeVariable(signature.substring(pos, end));
173                 return end + 1;
174
175             default: // case 'L':
176
start = pos;
177                 visited = false;
178                 inner = false;
179                 for (;;) {
180                     switch (c = signature.charAt(pos++)) {
181                         case '.':
182                         case ';':
183                             if (!visited) {
184                                 name = signature.substring(start, pos - 1);
185                                 if (inner) {
186                                     v.visitInnerClassType(name);
187                                 } else {
188                                     v.visitClassType(name);
189                                 }
190                             }
191                             if (c == ';') {
192                                 v.visitEnd();
193                                 return pos;
194                             }
195                             start = pos;
196                             visited = false;
197                             inner = true;
198                             break;
199
200                         case '<':
201                             name = signature.substring(start, pos - 1);
202                             if (inner) {
203                                 v.visitInnerClassType(name);
204                             } else {
205                                 v.visitClassType(name);
206                             }
207                             visited = true;
208                             top: for (;;) {
209                                 switch (c = signature.charAt(pos)) {
210                                     case '>':
211                                         break top;
212                                     case '*':
213                                         ++pos;
214                                         v.visitTypeArgument();
215                                         break;
216                                     case '+':
217                                     case '-':
218                                         pos = parseType(signature,
219                                                 pos + 1,
220                                                 v.visitTypeArgument(c));
221                                         break;
222                                     default:
223                                         pos = parseType(signature,
224                                                 pos,
225                                                 v.visitTypeArgument('='));
226                                         break;
227                                 }
228                             }
229                     }
230                 }
231         }
232     }
233 }
234
Popular Tags