/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2007 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.zbus.common.json.asm; /** * A Java type. This class can be used to make it easier to manipulate type and method descriptors. * * @author Eric Bruneton * @author Chris Nokleberg */ public class Type { /** * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. */ public static final int VOID = 0; /** * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. */ public static final int BOOLEAN = 1; /** * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. */ public static final int CHAR = 2; /** * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. */ public static final int BYTE = 3; /** * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. */ public static final int SHORT = 4; /** * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. */ public static final int INT = 5; /** * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. */ public static final int FLOAT = 6; /** * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. */ public static final int LONG = 7; /** * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. */ public static final int DOUBLE = 8; /** * The sort of array reference types. See {@link #getSort getSort}. */ public static final int ARRAY = 9; /** * The sort of object reference type. See {@link #getSort getSort}. */ public static final int OBJECT = 10; /** * The <tt>void</tt> type. */ public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) | (5 << 16) | (0 << 8) | 0, 1); /** * The <tt>boolean</tt> type. */ public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) | (0 << 16) | (5 << 8) | 1, 1); /** * The <tt>char</tt> type. */ public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) | (0 << 16) | (6 << 8) | 1, 1); /** * The <tt>byte</tt> type. */ public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) | (0 << 16) | (5 << 8) | 1, 1); /** * The <tt>short</tt> type. */ public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) | (0 << 16) | (7 << 8) | 1, 1); /** * The <tt>int</tt> type. */ public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) | (0 << 16) | (0 << 8) | 1, 1); /** * The <tt>float</tt> type. */ public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) | (2 << 16) | (2 << 8) | 1, 1); /** * The <tt>long</tt> type. */ public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) | (1 << 16) | (1 << 8) | 2, 1); /** * The <tt>double</tt> type. */ public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) | (3 << 16) | (3 << 8) | 2, 1); // ------------------------------------------------------------------------ // Fields // ------------------------------------------------------------------------ /** * The sort of this Java type. */ private final int sort; /** * A buffer containing the internal name of this Java type. This field is only used for reference types. */ private final char[] buf; /** * The offset of the internal name of this Java type in {@link #buf buf} or, for primitive types, the size, * descriptor and getOpcode offsets for this type (byte 0 contains the size, byte 1 the descriptor, byte 2 the * offset for IALOAD or IASTORE, byte 3 the offset for all other instructions). */ private final int off; /** * The length of the internal name of this Java type. */ private final int len; // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ /** * Constructs a reference type. * * @param sort the sort of the reference type to be constructed. * @param buf a buffer containing the descriptor of the previous type. * @param off the offset of this descriptor in the previous buffer. * @param len the length of this descriptor. */ private Type(final int sort, final char[] buf, final int off, final int len){ this.sort = sort; this.buf = buf; this.off = off; this.len = len; } /** * Returns the Java type corresponding to the given type descriptor. * * @param typeDescriptor a type descriptor. * @return the Java type corresponding to the given type descriptor. */ public static Type getType(final String typeDescriptor) { return getType(typeDescriptor.toCharArray(), 0); } /** * Computes the size of the arguments and of the return value of a method. * * @param desc the descriptor of a method. * @return the size of the arguments of the method (plus one for the implicit this argument), argSize, and the size * of its return value, retSize, packed into a single int i = <tt>(argSize << 2) | retSize</tt> (argSize is * therefore equal to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). */ public static int getArgumentsAndReturnSizes(final String desc) { int n = 1; int c = 1; while (true) { char car = desc.charAt(c++); if (car == ')') { car = desc.charAt(c); return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); } else if (car == 'L') { while (desc.charAt(c++) != ';') { } n += 1; // } else if (car == '[') { // while ((car = desc.charAt(c)) == '[') { // ++c; // } // if (car == 'D' || car == 'J') { // n -= 1; // } } else if (car == 'D' || car == 'J') { n += 2; } else { n += 1; } } } /** * Returns the Java type corresponding to the given type descriptor. * * @param buf a buffer containing a type descriptor. * @param off the offset of this descriptor in the previous buffer. * @return the Java type corresponding to the given type descriptor. */ private static Type getType(final char[] buf, final int off) { int len; switch (buf[off]) { case 'V': return VOID_TYPE; case 'Z': return BOOLEAN_TYPE; case 'C': return CHAR_TYPE; case 'B': return BYTE_TYPE; case 'S': return SHORT_TYPE; case 'I': return INT_TYPE; case 'F': return FLOAT_TYPE; case 'J': return LONG_TYPE; case 'D': return DOUBLE_TYPE; case '[': len = 1; while (buf[off + len] == '[') { ++len; } if (buf[off + len] == 'L') { ++len; while (buf[off + len] != ';') { ++len; } } return new Type(ARRAY, buf, off, len + 1); // case 'L': default: len = 1; while (buf[off + len] != ';') { ++len; } return new Type(OBJECT, buf, off + 1, len - 1); } } // ------------------------------------------------------------------------ // Accessors // ------------------------------------------------------------------------ /** * Returns the sort of this Java type. * * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT * SHORT}, {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} * or {@link #OBJECT OBJECT}. */ public int getSort() { return sort; } /** * Returns the internal name of the class corresponding to this object or array type. The internal name of a class * is its fully qualified name (as returned by Class.getName(), where '.' are replaced by '/'. This method should * only be used for an object or array type. * * @return the internal name of the class corresponding to this object type. */ public String getInternalName() { return new String(buf, off, len); } // ------------------------------------------------------------------------ // Conversion to type descriptors // ------------------------------------------------------------------------ /** * Returns the descriptor corresponding to this Java type. * * @return the descriptor corresponding to this Java type. */ String getDescriptor() { return new String(this.buf, off, len); } }