FileDocCategorySizeDatePackage
Prototype.javaAPI DocAndroid 5.1 API12090Thu Mar 12 22:18:30 GMT 2015com.android.dexgen.rop.type

Prototype

public final class Prototype extends Object implements Comparable
Representation of a method decriptor. Instances of this class are generally interned and may be usefully compared with each other using {@code ==}.

Fields Summary
private static final HashMap
internTable
{@code non-null;} intern table mapping string descriptors to instances
private final String
descriptor
{@code non-null;} method descriptor
private final Type
returnType
{@code non-null;} return type
private final StdTypeList
parameterTypes
{@code non-null;} list of parameter types
private StdTypeList
parameterFrameTypes
{@code null-ok;} list of parameter frame types, if calculated
Constructors Summary
private Prototype(String descriptor, Type returnType, StdTypeList parameterTypes)
Constructs an instance. This is a private constructor; use one of the public static methods to get instances.

param
descriptor {@code non-null;} the descriptor string

        if (descriptor == null) {
            throw new NullPointerException("descriptor == null");
        }

        if (returnType == null) {
            throw new NullPointerException("returnType == null");
        }

        if (parameterTypes == null) {
            throw new NullPointerException("parameterTypes == null");
        }

        this.descriptor = descriptor;
        this.returnType = returnType;
        this.parameterTypes = parameterTypes;
        this.parameterFrameTypes = null;
    
Methods Summary
public intcompareTo(com.android.dexgen.rop.type.Prototype other)
{@inheritDoc}

        if (this == other) {
            return 0;
        }

        /*
         * The return type is the major order, and then args in order,
         * and then the shorter list comes first (similar to string
         * sorting).
         */

        int result = returnType.compareTo(other.returnType);

        if (result != 0) {
            return result;
        }

        int thisSize = parameterTypes.size();
        int otherSize = other.parameterTypes.size();
        int size = Math.min(thisSize, otherSize);

        for (int i = 0; i < size; i++) {
            Type thisType = parameterTypes.get(i);
            Type otherType = other.parameterTypes.get(i);

            result = thisType.compareTo(otherType);

            if (result != 0) {
                return result;
            }
        }

        if (thisSize < otherSize) {
            return -1;
        } else if (thisSize > otherSize) {
            return 1;
        } else {
            return 0;
        }
    
public booleanequals(java.lang.Object other)
{@inheritDoc}

        if (this == other) {
            /*
             * Since externally-visible instances are interned, this
             * check helps weed out some easy cases.
             */
            return true;
        }

        if (!(other instanceof Prototype)) {
            return false;
        }

        return descriptor.equals(((Prototype) other).descriptor);
    
public java.lang.StringgetDescriptor()
Gets the descriptor string.

return
{@code non-null;} the descriptor

        return descriptor;
    
public StdTypeListgetParameterFrameTypes()
Gets the list of frame types corresponding to the list of parameter types. The difference between the two lists (if any) is that all "intlike" types (see {@link Type#isIntlike}) are replaced by {@link Type#INT}.

return
{@code non-null;} the list of parameter frame types

        if (parameterFrameTypes == null) {
            int sz = parameterTypes.size();
            StdTypeList list = new StdTypeList(sz);
            boolean any = false;
            for (int i = 0; i < sz; i++) {
                Type one = parameterTypes.get(i);
                if (one.isIntlike()) {
                    any = true;
                    one = Type.INT;
                }
                list.set(i, one);
            }
            parameterFrameTypes = any ? list : parameterTypes;
        }

        return parameterFrameTypes;
    
public StdTypeListgetParameterTypes()
Gets the list of parameter types.

return
{@code non-null;} the list of parameter types

        return parameterTypes;
    
public TypegetReturnType()
Gets the return type.

return
{@code non-null;} the return type

        return returnType;
    
public inthashCode()
{@inheritDoc}

        return descriptor.hashCode();
    
public static com.android.dexgen.rop.type.Prototypeintern(java.lang.String descriptor)
Returns the unique instance corresponding to the given method descriptor. See vmspec-2 sec4.3.3 for details on the field descriptor syntax.

param
descriptor {@code non-null;} the descriptor
return
{@code non-null;} the corresponding instance
throws
IllegalArgumentException thrown if the descriptor has invalid syntax


                                                  
         
        if (descriptor == null) {
            throw new NullPointerException("descriptor == null");
        }     
        Prototype result = internTable.get(descriptor);
        if (result != null) {
            return result;
        }

        Type[] params = makeParameterArray(descriptor);
        int paramCount = 0;
        int at = 1;

        for (;;) {
            int startAt = at;
            char c = descriptor.charAt(at);
            if (c == ')") {
                at++;
                break;
            }

            // Skip array markers.
            while (c == '[") {
                at++;
                c = descriptor.charAt(at);
            }

            if (c == 'L") {
                // It looks like the start of a class name; find the end.
                int endAt = descriptor.indexOf(';", at);
                if (endAt == -1) {
                    throw new IllegalArgumentException("bad descriptor");
                }
                at = endAt + 1;
            } else {
                at++;
            }

            params[paramCount] =
                Type.intern(descriptor.substring(startAt, at));
            paramCount++;
        }

        Type returnType = Type.internReturnType(descriptor.substring(at));
        StdTypeList parameterTypes = new StdTypeList(paramCount);

        for (int i = 0; i < paramCount; i++) {
            parameterTypes.set(i, params[i]);
        }

        result = new Prototype(descriptor, returnType, parameterTypes);
        return putIntern(result);
    
public static com.android.dexgen.rop.type.Prototypeintern(java.lang.String descriptor, Type definer, boolean isStatic, boolean isInit)
Interns an instance, adding to the descriptor as necessary based on the given definer, name, and flags. For example, an init method has an uninitialized object of type {@code definer} as its first argument.

param
descriptor {@code non-null;} the descriptor string
param
definer {@code non-null;} class the method is defined on
param
isStatic whether this is a static method
param
isInit whether this is an init method
return
{@code non-null;} the interned instance

        Prototype base = intern(descriptor);

        if (isStatic) {
            return base;
        }

        if (isInit) {
            definer = definer.asUninitialized(Integer.MAX_VALUE);
        }

        return base.withFirstParameter(definer);
    
public static com.android.dexgen.rop.type.PrototypeinternInts(Type returnType, int count)
Interns an instance which consists of the given number of {@code int}s along with the given return type

param
returnType {@code non-null;} the return type
param
count {@code > 0;} the number of elements in the prototype
return
{@code non-null;} the interned instance

        // Make the descriptor...

        StringBuffer sb = new StringBuffer(100);

        sb.append('(");

        for (int i = 0; i < count; i++) {
            sb.append('I");
        }

        sb.append(')");
        sb.append(returnType.getDescriptor());

        // ...and intern it.
        return intern(sb.toString());
    
private static Type[]makeParameterArray(java.lang.String descriptor)
Helper for {@link #intern} which returns an empty array to populate with parsed parameter types, and which also ensures that there is a '(' at the start of the descriptor and a single ')' somewhere before the end.

param
descriptor {@code non-null;} the descriptor string
return
{@code non-null;} array large enough to hold all parsed parameter types, but which is likely actually larger than needed

        int length = descriptor.length();

        if (descriptor.charAt(0) != '(") {
            throw new IllegalArgumentException("bad descriptor");
        }

        /*
         * This is a cheesy way to establish an upper bound on the
         * number of parameters: Just count capital letters.
         */
        int closeAt = 0;
        int maxParams = 0;
        for (int i = 1; i < length; i++) {
            char c = descriptor.charAt(i);
            if (c == ')") {
                closeAt = i;
                break;
            }
            if ((c >= 'A") && (c <= 'Z")) {
                maxParams++;
            }
        }

        if ((closeAt == 0) || (closeAt == (length - 1))) {
            throw new IllegalArgumentException("bad descriptor");
        }

        if (descriptor.indexOf(')", closeAt + 1) != -1) {
            throw new IllegalArgumentException("bad descriptor");
        }

        return new Type[maxParams];
    
private static com.android.dexgen.rop.type.PrototypeputIntern(com.android.dexgen.rop.type.Prototype desc)
Puts the given instance in the intern table if it's not already there. If a conflicting value is already in the table, then leave it. Return the interned value.

param
desc {@code non-null;} instance to make interned
return
{@code non-null;} the actual interned object

        synchronized (internTable) {
            String descriptor = desc.getDescriptor();
            Prototype already = internTable.get(descriptor);
            if (already != null) {
                return already;
            }
            internTable.put(descriptor, desc);
            return desc;
        }
    
public java.lang.StringtoString()
{@inheritDoc}

        return descriptor;
    
public com.android.dexgen.rop.type.PrototypewithFirstParameter(Type param)
Returns a new interned instance, which is the same as this instance, except that it has an additional parameter prepended to the original's argument list.

param
param {@code non-null;} the new first parameter
return
{@code non-null;} an appropriately-constructed instance

        String newDesc = "(" + param.getDescriptor() + descriptor.substring(1);
        StdTypeList newParams = parameterTypes.withFirst(param);

        newParams.setImmutable();

        Prototype result =
            new Prototype(newDesc, returnType, newParams);

        return putIntern(result);