Mercurial > lasercutter
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/asm/AnnotationWriter.java Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,357 @@ 1.4 +/*** 1.5 + * ASM: a very small and fast Java bytecode manipulation framework 1.6 + * Copyright (c) 2000-2005 INRIA, France Telecom 1.7 + * All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions 1.11 + * are met: 1.12 + * 1. Redistributions of source code must retain the above copyright 1.13 + * notice, this list of conditions and the following disclaimer. 1.14 + * 2. Redistributions in binary form must reproduce the above copyright 1.15 + * notice, this list of conditions and the following disclaimer in the 1.16 + * documentation and/or other materials provided with the distribution. 1.17 + * 3. Neither the name of the copyright holders nor the names of its 1.18 + * contributors may be used to endorse or promote products derived from 1.19 + * this software without specific prior written permission. 1.20 + * 1.21 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.22 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1.25 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.26 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.27 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.28 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.29 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.30 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 1.31 + * THE POSSIBILITY OF SUCH DAMAGE. 1.32 + */ 1.33 +package clojure.asm; 1.34 + 1.35 +/** 1.36 + * An {@link AnnotationVisitor} that generates annotations in bytecode form. 1.37 + * 1.38 + * @author Eric Bruneton 1.39 + * @author Eugene Kuleshov 1.40 + */ 1.41 +final class AnnotationWriter implements AnnotationVisitor{ 1.42 + 1.43 +/** 1.44 + * The class writer to which this annotation must be added. 1.45 + */ 1.46 +private final ClassWriter cw; 1.47 + 1.48 +/** 1.49 + * The number of values in this annotation. 1.50 + */ 1.51 +private int size; 1.52 + 1.53 +/** 1.54 + * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation 1.55 + * writers used for annotation default and annotation arrays use unnamed 1.56 + * values. 1.57 + */ 1.58 +private final boolean named; 1.59 + 1.60 +/** 1.61 + * The annotation values in bytecode form. This byte vector only contains 1.62 + * the values themselves, i.e. the number of values must be stored as a 1.63 + * unsigned short just before these bytes. 1.64 + */ 1.65 +private final ByteVector bv; 1.66 + 1.67 +/** 1.68 + * The byte vector to be used to store the number of values of this 1.69 + * annotation. See {@link #bv}. 1.70 + */ 1.71 +private final ByteVector parent; 1.72 + 1.73 +/** 1.74 + * Where the number of values of this annotation must be stored in 1.75 + * {@link #parent}. 1.76 + */ 1.77 +private final int offset; 1.78 + 1.79 +/** 1.80 + * Next annotation writer. This field is used to store annotation lists. 1.81 + */ 1.82 +AnnotationWriter next; 1.83 + 1.84 +/** 1.85 + * Previous annotation writer. This field is used to store annotation lists. 1.86 + */ 1.87 +AnnotationWriter prev; 1.88 + 1.89 +// ------------------------------------------------------------------------ 1.90 +// Constructor 1.91 +// ------------------------------------------------------------------------ 1.92 + 1.93 +/** 1.94 + * Constructs a new {@link AnnotationWriter}. 1.95 + * 1.96 + * @param cw the class writer to which this annotation must be added. 1.97 + * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise. 1.98 + * @param bv where the annotation values must be stored. 1.99 + * @param parent where the number of annotation values must be stored. 1.100 + * @param offset where in <tt>parent</tt> the number of annotation values must 1.101 + * be stored. 1.102 + */ 1.103 +AnnotationWriter( 1.104 + final ClassWriter cw, 1.105 + final boolean named, 1.106 + final ByteVector bv, 1.107 + final ByteVector parent, 1.108 + final int offset){ 1.109 + this.cw = cw; 1.110 + this.named = named; 1.111 + this.bv = bv; 1.112 + this.parent = parent; 1.113 + this.offset = offset; 1.114 +} 1.115 + 1.116 +// ------------------------------------------------------------------------ 1.117 +// Implementation of the AnnotationVisitor interface 1.118 +// ------------------------------------------------------------------------ 1.119 + 1.120 +public void visit(final String name, final Object value){ 1.121 + ++size; 1.122 + if(named) 1.123 + { 1.124 + bv.putShort(cw.newUTF8(name)); 1.125 + } 1.126 + if(value instanceof String) 1.127 + { 1.128 + bv.put12('s', cw.newUTF8((String) value)); 1.129 + } 1.130 + else if(value instanceof Byte) 1.131 + { 1.132 + bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); 1.133 + } 1.134 + else if(value instanceof Boolean) 1.135 + { 1.136 + int v = ((Boolean) value).booleanValue() ? 1 : 0; 1.137 + bv.put12('Z', cw.newInteger(v).index); 1.138 + } 1.139 + else if(value instanceof Character) 1.140 + { 1.141 + bv.put12('C', cw.newInteger(((Character) value).charValue()).index); 1.142 + } 1.143 + else if(value instanceof Short) 1.144 + { 1.145 + bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); 1.146 + } 1.147 + else if(value instanceof Type) 1.148 + { 1.149 + bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); 1.150 + } 1.151 + else if(value instanceof byte[]) 1.152 + { 1.153 + byte[] v = (byte[]) value; 1.154 + bv.put12('[', v.length); 1.155 + for(int i = 0; i < v.length; i++) 1.156 + { 1.157 + bv.put12('B', cw.newInteger(v[i]).index); 1.158 + } 1.159 + } 1.160 + else if(value instanceof boolean[]) 1.161 + { 1.162 + boolean[] v = (boolean[]) value; 1.163 + bv.put12('[', v.length); 1.164 + for(int i = 0; i < v.length; i++) 1.165 + { 1.166 + bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); 1.167 + } 1.168 + } 1.169 + else if(value instanceof short[]) 1.170 + { 1.171 + short[] v = (short[]) value; 1.172 + bv.put12('[', v.length); 1.173 + for(int i = 0; i < v.length; i++) 1.174 + { 1.175 + bv.put12('S', cw.newInteger(v[i]).index); 1.176 + } 1.177 + } 1.178 + else if(value instanceof char[]) 1.179 + { 1.180 + char[] v = (char[]) value; 1.181 + bv.put12('[', v.length); 1.182 + for(int i = 0; i < v.length; i++) 1.183 + { 1.184 + bv.put12('C', cw.newInteger(v[i]).index); 1.185 + } 1.186 + } 1.187 + else if(value instanceof int[]) 1.188 + { 1.189 + int[] v = (int[]) value; 1.190 + bv.put12('[', v.length); 1.191 + for(int i = 0; i < v.length; i++) 1.192 + { 1.193 + bv.put12('I', cw.newInteger(v[i]).index); 1.194 + } 1.195 + } 1.196 + else if(value instanceof long[]) 1.197 + { 1.198 + long[] v = (long[]) value; 1.199 + bv.put12('[', v.length); 1.200 + for(int i = 0; i < v.length; i++) 1.201 + { 1.202 + bv.put12('J', cw.newLong(v[i]).index); 1.203 + } 1.204 + } 1.205 + else if(value instanceof float[]) 1.206 + { 1.207 + float[] v = (float[]) value; 1.208 + bv.put12('[', v.length); 1.209 + for(int i = 0; i < v.length; i++) 1.210 + { 1.211 + bv.put12('F', cw.newFloat(v[i]).index); 1.212 + } 1.213 + } 1.214 + else if(value instanceof double[]) 1.215 + { 1.216 + double[] v = (double[]) value; 1.217 + bv.put12('[', v.length); 1.218 + for(int i = 0; i < v.length; i++) 1.219 + { 1.220 + bv.put12('D', cw.newDouble(v[i]).index); 1.221 + } 1.222 + } 1.223 + else 1.224 + { 1.225 + Item i = cw.newConstItem(value); 1.226 + bv.put12(".s.IFJDCS".charAt(i.type), i.index); 1.227 + } 1.228 +} 1.229 + 1.230 +public void visitEnum( 1.231 + final String name, 1.232 + final String desc, 1.233 + final String value){ 1.234 + ++size; 1.235 + if(named) 1.236 + { 1.237 + bv.putShort(cw.newUTF8(name)); 1.238 + } 1.239 + bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); 1.240 +} 1.241 + 1.242 +public AnnotationVisitor visitAnnotation( 1.243 + final String name, 1.244 + final String desc){ 1.245 + ++size; 1.246 + if(named) 1.247 + { 1.248 + bv.putShort(cw.newUTF8(name)); 1.249 + } 1.250 + // write tag and type, and reserve space for values count 1.251 + bv.put12('@', cw.newUTF8(desc)).putShort(0); 1.252 + return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); 1.253 +} 1.254 + 1.255 +public AnnotationVisitor visitArray(final String name){ 1.256 + ++size; 1.257 + if(named) 1.258 + { 1.259 + bv.putShort(cw.newUTF8(name)); 1.260 + } 1.261 + // write tag, and reserve space for array size 1.262 + bv.put12('[', 0); 1.263 + return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); 1.264 +} 1.265 + 1.266 +public void visitEnd(){ 1.267 + if(parent != null) 1.268 + { 1.269 + byte[] data = parent.data; 1.270 + data[offset] = (byte) (size >>> 8); 1.271 + data[offset + 1] = (byte) size; 1.272 + } 1.273 +} 1.274 + 1.275 +// ------------------------------------------------------------------------ 1.276 +// Utility methods 1.277 +// ------------------------------------------------------------------------ 1.278 + 1.279 +/** 1.280 + * Returns the size of this annotation writer list. 1.281 + * 1.282 + * @return the size of this annotation writer list. 1.283 + */ 1.284 +int getSize(){ 1.285 + int size = 0; 1.286 + AnnotationWriter aw = this; 1.287 + while(aw != null) 1.288 + { 1.289 + size += aw.bv.length; 1.290 + aw = aw.next; 1.291 + } 1.292 + return size; 1.293 +} 1.294 + 1.295 +/** 1.296 + * Puts the annotations of this annotation writer list into the given byte 1.297 + * vector. 1.298 + * 1.299 + * @param out where the annotations must be put. 1.300 + */ 1.301 +void put(final ByteVector out){ 1.302 + int n = 0; 1.303 + int size = 2; 1.304 + AnnotationWriter aw = this; 1.305 + AnnotationWriter last = null; 1.306 + while(aw != null) 1.307 + { 1.308 + ++n; 1.309 + size += aw.bv.length; 1.310 + aw.visitEnd(); // in case user forgot to call visitEnd 1.311 + aw.prev = last; 1.312 + last = aw; 1.313 + aw = aw.next; 1.314 + } 1.315 + out.putInt(size); 1.316 + out.putShort(n); 1.317 + aw = last; 1.318 + while(aw != null) 1.319 + { 1.320 + out.putByteArray(aw.bv.data, 0, aw.bv.length); 1.321 + aw = aw.prev; 1.322 + } 1.323 +} 1.324 + 1.325 +/** 1.326 + * Puts the given annotation lists into the given byte vector. 1.327 + * 1.328 + * @param panns an array of annotation writer lists. 1.329 + * @param out where the annotations must be put. 1.330 + */ 1.331 +static void put(final AnnotationWriter[] panns, final ByteVector out){ 1.332 + int size = 1 + 2 * panns.length; 1.333 + for(int i = 0; i < panns.length; ++i) 1.334 + { 1.335 + size += panns[i] == null ? 0 : panns[i].getSize(); 1.336 + } 1.337 + out.putInt(size).putByte(panns.length); 1.338 + for(int i = 0; i < panns.length; ++i) 1.339 + { 1.340 + AnnotationWriter aw = panns[i]; 1.341 + AnnotationWriter last = null; 1.342 + int n = 0; 1.343 + while(aw != null) 1.344 + { 1.345 + ++n; 1.346 + aw.visitEnd(); // in case user forgot to call visitEnd 1.347 + aw.prev = last; 1.348 + last = aw; 1.349 + aw = aw.next; 1.350 + } 1.351 + out.putShort(n); 1.352 + aw = last; 1.353 + while(aw != null) 1.354 + { 1.355 + out.putByteArray(aw.bv.data, 0, aw.bv.length); 1.356 + aw = aw.prev; 1.357 + } 1.358 + } 1.359 +} 1.360 +}