view src/clojure/asm/AnnotationWriter.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line source
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 clojure.asm;
32 /**
33 * An {@link AnnotationVisitor} that generates annotations in bytecode form.
34 *
35 * @author Eric Bruneton
36 * @author Eugene Kuleshov
37 */
38 final class AnnotationWriter implements AnnotationVisitor{
40 /**
41 * The class writer to which this annotation must be added.
42 */
43 private final ClassWriter cw;
45 /**
46 * The number of values in this annotation.
47 */
48 private int size;
50 /**
51 * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
52 * writers used for annotation default and annotation arrays use unnamed
53 * values.
54 */
55 private final boolean named;
57 /**
58 * The annotation values in bytecode form. This byte vector only contains
59 * the values themselves, i.e. the number of values must be stored as a
60 * unsigned short just before these bytes.
61 */
62 private final ByteVector bv;
64 /**
65 * The byte vector to be used to store the number of values of this
66 * annotation. See {@link #bv}.
67 */
68 private final ByteVector parent;
70 /**
71 * Where the number of values of this annotation must be stored in
72 * {@link #parent}.
73 */
74 private final int offset;
76 /**
77 * Next annotation writer. This field is used to store annotation lists.
78 */
79 AnnotationWriter next;
81 /**
82 * Previous annotation writer. This field is used to store annotation lists.
83 */
84 AnnotationWriter prev;
86 // ------------------------------------------------------------------------
87 // Constructor
88 // ------------------------------------------------------------------------
90 /**
91 * Constructs a new {@link AnnotationWriter}.
92 *
93 * @param cw the class writer to which this annotation must be added.
94 * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
95 * @param bv where the annotation values must be stored.
96 * @param parent where the number of annotation values must be stored.
97 * @param offset where in <tt>parent</tt> the number of annotation values must
98 * be stored.
99 */
100 AnnotationWriter(
101 final ClassWriter cw,
102 final boolean named,
103 final ByteVector bv,
104 final ByteVector parent,
105 final int offset){
106 this.cw = cw;
107 this.named = named;
108 this.bv = bv;
109 this.parent = parent;
110 this.offset = offset;
111 }
113 // ------------------------------------------------------------------------
114 // Implementation of the AnnotationVisitor interface
115 // ------------------------------------------------------------------------
117 public void visit(final String name, final Object value){
118 ++size;
119 if(named)
120 {
121 bv.putShort(cw.newUTF8(name));
122 }
123 if(value instanceof String)
124 {
125 bv.put12('s', cw.newUTF8((String) value));
126 }
127 else if(value instanceof Byte)
128 {
129 bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
130 }
131 else if(value instanceof Boolean)
132 {
133 int v = ((Boolean) value).booleanValue() ? 1 : 0;
134 bv.put12('Z', cw.newInteger(v).index);
135 }
136 else if(value instanceof Character)
137 {
138 bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
139 }
140 else if(value instanceof Short)
141 {
142 bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
143 }
144 else if(value instanceof Type)
145 {
146 bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
147 }
148 else if(value instanceof byte[])
149 {
150 byte[] v = (byte[]) value;
151 bv.put12('[', v.length);
152 for(int i = 0; i < v.length; i++)
153 {
154 bv.put12('B', cw.newInteger(v[i]).index);
155 }
156 }
157 else if(value instanceof boolean[])
158 {
159 boolean[] v = (boolean[]) value;
160 bv.put12('[', v.length);
161 for(int i = 0; i < v.length; i++)
162 {
163 bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
164 }
165 }
166 else if(value instanceof short[])
167 {
168 short[] v = (short[]) value;
169 bv.put12('[', v.length);
170 for(int i = 0; i < v.length; i++)
171 {
172 bv.put12('S', cw.newInteger(v[i]).index);
173 }
174 }
175 else if(value instanceof char[])
176 {
177 char[] v = (char[]) value;
178 bv.put12('[', v.length);
179 for(int i = 0; i < v.length; i++)
180 {
181 bv.put12('C', cw.newInteger(v[i]).index);
182 }
183 }
184 else if(value instanceof int[])
185 {
186 int[] v = (int[]) value;
187 bv.put12('[', v.length);
188 for(int i = 0; i < v.length; i++)
189 {
190 bv.put12('I', cw.newInteger(v[i]).index);
191 }
192 }
193 else if(value instanceof long[])
194 {
195 long[] v = (long[]) value;
196 bv.put12('[', v.length);
197 for(int i = 0; i < v.length; i++)
198 {
199 bv.put12('J', cw.newLong(v[i]).index);
200 }
201 }
202 else if(value instanceof float[])
203 {
204 float[] v = (float[]) value;
205 bv.put12('[', v.length);
206 for(int i = 0; i < v.length; i++)
207 {
208 bv.put12('F', cw.newFloat(v[i]).index);
209 }
210 }
211 else if(value instanceof double[])
212 {
213 double[] v = (double[]) value;
214 bv.put12('[', v.length);
215 for(int i = 0; i < v.length; i++)
216 {
217 bv.put12('D', cw.newDouble(v[i]).index);
218 }
219 }
220 else
221 {
222 Item i = cw.newConstItem(value);
223 bv.put12(".s.IFJDCS".charAt(i.type), i.index);
224 }
225 }
227 public void visitEnum(
228 final String name,
229 final String desc,
230 final String value){
231 ++size;
232 if(named)
233 {
234 bv.putShort(cw.newUTF8(name));
235 }
236 bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
237 }
239 public AnnotationVisitor visitAnnotation(
240 final String name,
241 final String desc){
242 ++size;
243 if(named)
244 {
245 bv.putShort(cw.newUTF8(name));
246 }
247 // write tag and type, and reserve space for values count
248 bv.put12('@', cw.newUTF8(desc)).putShort(0);
249 return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
250 }
252 public AnnotationVisitor visitArray(final String name){
253 ++size;
254 if(named)
255 {
256 bv.putShort(cw.newUTF8(name));
257 }
258 // write tag, and reserve space for array size
259 bv.put12('[', 0);
260 return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
261 }
263 public void visitEnd(){
264 if(parent != null)
265 {
266 byte[] data = parent.data;
267 data[offset] = (byte) (size >>> 8);
268 data[offset + 1] = (byte) size;
269 }
270 }
272 // ------------------------------------------------------------------------
273 // Utility methods
274 // ------------------------------------------------------------------------
276 /**
277 * Returns the size of this annotation writer list.
278 *
279 * @return the size of this annotation writer list.
280 */
281 int getSize(){
282 int size = 0;
283 AnnotationWriter aw = this;
284 while(aw != null)
285 {
286 size += aw.bv.length;
287 aw = aw.next;
288 }
289 return size;
290 }
292 /**
293 * Puts the annotations of this annotation writer list into the given byte
294 * vector.
295 *
296 * @param out where the annotations must be put.
297 */
298 void put(final ByteVector out){
299 int n = 0;
300 int size = 2;
301 AnnotationWriter aw = this;
302 AnnotationWriter last = null;
303 while(aw != null)
304 {
305 ++n;
306 size += aw.bv.length;
307 aw.visitEnd(); // in case user forgot to call visitEnd
308 aw.prev = last;
309 last = aw;
310 aw = aw.next;
311 }
312 out.putInt(size);
313 out.putShort(n);
314 aw = last;
315 while(aw != null)
316 {
317 out.putByteArray(aw.bv.data, 0, aw.bv.length);
318 aw = aw.prev;
319 }
320 }
322 /**
323 * Puts the given annotation lists into the given byte vector.
324 *
325 * @param panns an array of annotation writer lists.
326 * @param out where the annotations must be put.
327 */
328 static void put(final AnnotationWriter[] panns, final ByteVector out){
329 int size = 1 + 2 * panns.length;
330 for(int i = 0; i < panns.length; ++i)
331 {
332 size += panns[i] == null ? 0 : panns[i].getSize();
333 }
334 out.putInt(size).putByte(panns.length);
335 for(int i = 0; i < panns.length; ++i)
336 {
337 AnnotationWriter aw = panns[i];
338 AnnotationWriter last = null;
339 int n = 0;
340 while(aw != null)
341 {
342 ++n;
343 aw.visitEnd(); // in case user forgot to call visitEnd
344 aw.prev = last;
345 last = aw;
346 aw = aw.next;
347 }
348 out.putShort(n);
349 aw = last;
350 while(aw != null)
351 {
352 out.putByteArray(aw.bv.data, 0, aw.bv.length);
353 aw = aw.prev;
354 }
355 }
356 }
357 }