Mercurial > lasercutter
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 framework3 * Copyright (c) 2000-2005 INRIA, France Telecom4 * All rights reserved.5 *6 * Redistribution and use in source and binary forms, with or without7 * modification, are permitted provided that the following conditions8 * are met:9 * 1. Redistributions of source code must retain the above copyright10 * notice, this list of conditions and the following disclaimer.11 * 2. Redistributions in binary form must reproduce the above copyright12 * notice, this list of conditions and the following disclaimer in the13 * documentation and/or other materials provided with the distribution.14 * 3. Neither the name of the copyright holders nor the names of its15 * contributors may be used to endorse or promote products derived from16 * 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, THE20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF28 * 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 Bruneton36 * @author Eugene Kuleshov37 */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. Annotation52 * writers used for annotation default and annotation arrays use unnamed53 * values.54 */55 private final boolean named;57 /**58 * The annotation values in bytecode form. This byte vector only contains59 * the values themselves, i.e. the number of values must be stored as a60 * 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 this66 * annotation. See {@link #bv}.67 */68 private final ByteVector parent;70 /**71 * Where the number of values of this annotation must be stored in72 * {@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 // Constructor88 // ------------------------------------------------------------------------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 must98 * 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 interface115 // ------------------------------------------------------------------------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 else221 {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 count248 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 size259 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 methods274 // ------------------------------------------------------------------------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 byte294 * 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 visitEnd308 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 visitEnd344 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 }