1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2013 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 31 package org.objectweb.asm; 32 33 /** 34 * The path to a type argument, wildcard bound, array element type, or static 35 * inner type within an enclosing type. 36 * 37 * @author Eric Bruneton 38 */ 39 public class TypePath { 40 41 /** 42 * A type path step that steps into the element type of an array type. See 43 * {@link #getStep getStep}. 44 */ 45 public final static int ARRAY_ELEMENT = 0; 46 47 /** 48 * A type path step that steps into the nested type of a class type. See 49 * {@link #getStep getStep}. 50 */ 51 public final static int INNER_TYPE = 1; 52 53 /** 54 * A type path step that steps into the bound of a wildcard type. See 55 * {@link #getStep getStep}. 56 */ 57 public final static int WILDCARD_BOUND = 2; 58 59 /** 60 * A type path step that steps into a type argument of a generic type. See 61 * {@link #getStep getStep}. 62 */ 63 public final static int TYPE_ARGUMENT = 3; 64 65 /** 66 * The byte array where the path is stored, in Java class file format. 67 */ 68 byte[] b; 69 70 /** 71 * The offset of the first byte of the type path in 'b'. 72 */ 73 int offset; 74 75 /** 76 * Creates a new type path. 77 * 78 * @param b 79 * the byte array containing the type path in Java class file 80 * format. 81 * @param offset 82 * the offset of the first byte of the type path in 'b'. 83 */ TypePath(byte[] b, int offset)84 TypePath(byte[] b, int offset) { 85 this.b = b; 86 this.offset = offset; 87 } 88 89 /** 90 * Returns the length of this path. 91 * 92 * @return the length of this path. 93 */ getLength()94 public int getLength() { 95 return b[offset]; 96 } 97 98 /** 99 * Returns the value of the given step of this path. 100 * 101 * @param index 102 * an index between 0 and {@link #getLength()}, exclusive. 103 * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE 104 * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or 105 * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. 106 */ getStep(int index)107 public int getStep(int index) { 108 return b[offset + 2 * index + 1]; 109 } 110 111 /** 112 * Returns the index of the type argument that the given step is stepping 113 * into. This method should only be used for steps whose value is 114 * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. 115 * 116 * @param index 117 * an index between 0 and {@link #getLength()}, exclusive. 118 * @return the index of the type argument that the given step is stepping 119 * into. 120 */ getStepArgument(int index)121 public int getStepArgument(int index) { 122 return b[offset + 2 * index + 2]; 123 } 124 125 /** 126 * Converts a type path in string form, in the format used by 127 * {@link #toString()}, into a TypePath object. 128 * 129 * @param typePath 130 * a type path in string form, in the format used by 131 * {@link #toString()}. May be null or empty. 132 * @return the corresponding TypePath object, or null if the path is empty. 133 */ fromString(final String typePath)134 public static TypePath fromString(final String typePath) { 135 if (typePath == null || typePath.length() == 0) { 136 return null; 137 } 138 int n = typePath.length(); 139 ByteVector out = new ByteVector(n); 140 out.putByte(0); 141 for (int i = 0; i < n;) { 142 char c = typePath.charAt(i++); 143 if (c == '[') { 144 out.put11(ARRAY_ELEMENT, 0); 145 } else if (c == '.') { 146 out.put11(INNER_TYPE, 0); 147 } else if (c == '*') { 148 out.put11(WILDCARD_BOUND, 0); 149 } else if (c >= '0' && c <= '9') { 150 int typeArg = c - '0'; 151 while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') { 152 typeArg = typeArg * 10 + c - '0'; 153 i += 1; 154 } 155 if (i < n && typePath.charAt(i) == ';') { 156 i += 1; 157 } 158 out.put11(TYPE_ARGUMENT, typeArg); 159 } 160 } 161 out.data[0] = (byte) (out.length / 2); 162 return new TypePath(out.data, 0); 163 } 164 165 /** 166 * Returns a string representation of this type path. {@link #ARRAY_ELEMENT 167 * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE 168 * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps 169 * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type 170 * argument index in decimal form followed by ';'. 171 */ 172 @Override toString()173 public String toString() { 174 int length = getLength(); 175 StringBuilder result = new StringBuilder(length * 2); 176 for (int i = 0; i < length; ++i) { 177 switch (getStep(i)) { 178 case ARRAY_ELEMENT: 179 result.append('['); 180 break; 181 case INNER_TYPE: 182 result.append('.'); 183 break; 184 case WILDCARD_BOUND: 185 result.append('*'); 186 break; 187 case TYPE_ARGUMENT: 188 result.append(getStepArgument(i)).append(';'); 189 break; 190 default: 191 result.append('_'); 192 } 193 } 194 return result.toString(); 195 } 196 } 197