• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dx.rop.cst;
18 
19 import com.android.dx.rop.type.Type;
20 
21 import java.util.HashMap;
22 
23 /**
24  * Constants that represent an arbitrary type (reference or primitive).
25  */
26 public final class CstType extends TypedConstant {
27     /** non-null; map of interned types */
28     private static final HashMap<Type, CstType> interns =
29         new HashMap<Type, CstType>(100);
30 
31     /** non-null; instance corresponding to the class <code>Object</code> */
32     public static final CstType OBJECT = intern(Type.OBJECT);
33 
34     /** non-null; instance corresponding to the class <code>Boolean</code> */
35     public static final CstType BOOLEAN = intern(Type.BOOLEAN_CLASS);
36 
37     /** non-null; instance corresponding to the class <code>Byte</code> */
38     public static final CstType BYTE = intern(Type.BYTE_CLASS);
39 
40     /** non-null; instance corresponding to the class <code>Character</code> */
41     public static final CstType CHARACTER = intern(Type.CHARACTER_CLASS);
42 
43     /** non-null; instance corresponding to the class <code>Double</code> */
44     public static final CstType DOUBLE = intern(Type.DOUBLE_CLASS);
45 
46     /** non-null; instance corresponding to the class <code>Float</code> */
47     public static final CstType FLOAT = intern(Type.FLOAT_CLASS);
48 
49     /** non-null; instance corresponding to the class <code>Long</code> */
50     public static final CstType LONG = intern(Type.LONG_CLASS);
51 
52     /** non-null; instance corresponding to the class <code>Integer</code> */
53     public static final CstType INTEGER = intern(Type.INTEGER_CLASS);
54 
55     /** non-null; instance corresponding to the class <code>Short</code> */
56     public static final CstType SHORT = intern(Type.SHORT_CLASS);
57 
58     /** non-null; instance corresponding to the class <code>Void</code> */
59     public static final CstType VOID = intern(Type.VOID_CLASS);
60 
61     /** non-null; instance corresponding to the type <code>boolean[]</code> */
62     public static final CstType BOOLEAN_ARRAY = intern(Type.BOOLEAN_ARRAY);
63 
64     /** non-null; instance corresponding to the type <code>byte[]</code> */
65     public static final CstType BYTE_ARRAY = intern(Type.BYTE_ARRAY);
66 
67     /** non-null; instance corresponding to the type <code>char[]</code> */
68     public static final CstType CHAR_ARRAY = intern(Type.CHAR_ARRAY);
69 
70     /** non-null; instance corresponding to the type <code>double[]</code> */
71     public static final CstType DOUBLE_ARRAY = intern(Type.DOUBLE_ARRAY);
72 
73     /** non-null; instance corresponding to the type <code>float[]</code> */
74     public static final CstType FLOAT_ARRAY = intern(Type.FLOAT_ARRAY);
75 
76     /** non-null; instance corresponding to the type <code>long[]</code> */
77     public static final CstType LONG_ARRAY = intern(Type.LONG_ARRAY);
78 
79     /** non-null; instance corresponding to the type <code>int[]</code> */
80     public static final CstType INT_ARRAY = intern(Type.INT_ARRAY);
81 
82     /** non-null; instance corresponding to the type <code>short[]</code> */
83     public static final CstType SHORT_ARRAY = intern(Type.SHORT_ARRAY);
84 
85     /** non-null; the underlying type */
86     private final Type type;
87 
88     /**
89      * null-ok; the type descriptor corresponding to this instance, if
90      * calculated
91      */
92     private CstUtf8 descriptor;
93 
94     /**
95      * Returns an instance of this class that represents the wrapper
96      * class corresponding to a given primitive type. For example, if
97      * given {@link Type#INT}, this method returns the class reference
98      * <code>java.lang.Integer</code>.
99      *
100      * @param primitiveType non-null; the primitive type
101      * @return non-null; the corresponding wrapper class
102      */
forBoxedPrimitiveType(Type primitiveType)103     public static CstType forBoxedPrimitiveType(Type primitiveType) {
104         switch (primitiveType.getBasicType()) {
105             case Type.BT_BOOLEAN: return BOOLEAN;
106             case Type.BT_BYTE:    return BYTE;
107             case Type.BT_CHAR:    return CHARACTER;
108             case Type.BT_DOUBLE:  return DOUBLE;
109             case Type.BT_FLOAT:   return FLOAT;
110             case Type.BT_INT:     return INTEGER;
111             case Type.BT_LONG:    return LONG;
112             case Type.BT_SHORT:   return SHORT;
113             case Type.BT_VOID:    return VOID;
114         }
115 
116         throw new IllegalArgumentException("not primitive: " + primitiveType);
117     }
118 
119     /**
120      * Returns an interned instance of this class for the given type.
121      *
122      * @param type non-null; the underlying type
123      * @return non-null; an appropriately-constructed instance
124      */
intern(Type type)125     public static CstType intern(Type type) {
126         CstType cst = interns.get(type);
127 
128         if (cst == null) {
129             cst = new CstType(type);
130             interns.put(type, cst);
131         }
132 
133         return cst;
134     }
135 
136     /**
137      * Constructs an instance.
138      *
139      * @param type non-null; the underlying type
140      */
CstType(Type type)141     public CstType(Type type) {
142         if (type == null) {
143             throw new NullPointerException("type == null");
144         }
145 
146         if (type == type.KNOWN_NULL) {
147             throw new UnsupportedOperationException(
148                     "KNOWN_NULL is not representable");
149         }
150 
151         this.type = type;
152         this.descriptor = null;
153     }
154 
155     /** {@inheritDoc} */
156     @Override
equals(Object other)157     public boolean equals(Object other) {
158         if (!(other instanceof CstType)) {
159             return false;
160         }
161 
162         return type == ((CstType) other).type;
163     }
164 
165     /** {@inheritDoc} */
166     @Override
hashCode()167     public int hashCode() {
168         return type.hashCode();
169     }
170 
171     /** {@inheritDoc} */
172     @Override
compareTo0(Constant other)173     protected int compareTo0(Constant other) {
174         String thisDescriptor = type.getDescriptor();
175         String otherDescriptor = ((CstType) other).type.getDescriptor();
176         return thisDescriptor.compareTo(otherDescriptor);
177     }
178 
179     /** {@inheritDoc} */
180     @Override
toString()181     public String toString() {
182         return "type{" + toHuman() + '}';
183     }
184 
185     /** {@inheritDoc} */
getType()186     public Type getType() {
187         return Type.CLASS;
188     }
189 
190     /** {@inheritDoc} */
191     @Override
typeName()192     public String typeName() {
193         return "type";
194     }
195 
196     /** {@inheritDoc} */
197     @Override
isCategory2()198     public boolean isCategory2() {
199         return false;
200     }
201 
202     /** {@inheritDoc} */
toHuman()203     public String toHuman() {
204         return type.toHuman();
205     }
206 
207     /**
208      * Gets the underlying type (as opposed to the type corresponding
209      * to this instance as a constant, which is always
210      * <code>Class</code>).
211      *
212      * @return non-null; the type corresponding to the name
213      */
getClassType()214     public Type getClassType() {
215         return type;
216     }
217 
218     /**
219      * Gets the type descriptor for this instance.
220      *
221      * @return non-null; the descriptor
222      */
getDescriptor()223     public CstUtf8 getDescriptor() {
224         if (descriptor == null) {
225             descriptor = new CstUtf8(type.getDescriptor());
226         }
227 
228         return descriptor;
229     }
230 }
231