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 17package com.android.dx.rop.cst; 18 19import com.android.dx.rop.type.Type; 20 21import java.util.HashMap; 22 23/** 24 * Constants that represent an arbitrary type (reference or primitive). 25 */ 26public final class CstType extends TypedConstant { 27 /** {@code non-null;} map of interned types */ 28 private static final HashMap<Type, CstType> interns = 29 new HashMap<Type, CstType>(100); 30 31 /** {@code non-null;} instance corresponding to the class {@code Object} */ 32 public static final CstType OBJECT = intern(Type.OBJECT); 33 34 /** {@code non-null;} instance corresponding to the class {@code Boolean} */ 35 public static final CstType BOOLEAN = intern(Type.BOOLEAN_CLASS); 36 37 /** {@code non-null;} instance corresponding to the class {@code Byte} */ 38 public static final CstType BYTE = intern(Type.BYTE_CLASS); 39 40 /** {@code non-null;} instance corresponding to the class {@code Character} */ 41 public static final CstType CHARACTER = intern(Type.CHARACTER_CLASS); 42 43 /** {@code non-null;} instance corresponding to the class {@code Double} */ 44 public static final CstType DOUBLE = intern(Type.DOUBLE_CLASS); 45 46 /** {@code non-null;} instance corresponding to the class {@code Float} */ 47 public static final CstType FLOAT = intern(Type.FLOAT_CLASS); 48 49 /** {@code non-null;} instance corresponding to the class {@code Long} */ 50 public static final CstType LONG = intern(Type.LONG_CLASS); 51 52 /** {@code non-null;} instance corresponding to the class {@code Integer} */ 53 public static final CstType INTEGER = intern(Type.INTEGER_CLASS); 54 55 /** {@code non-null;} instance corresponding to the class {@code Short} */ 56 public static final CstType SHORT = intern(Type.SHORT_CLASS); 57 58 /** {@code non-null;} instance corresponding to the class {@code Void} */ 59 public static final CstType VOID = intern(Type.VOID_CLASS); 60 61 /** {@code non-null;} instance corresponding to the type {@code boolean[]} */ 62 public static final CstType BOOLEAN_ARRAY = intern(Type.BOOLEAN_ARRAY); 63 64 /** {@code non-null;} instance corresponding to the type {@code byte[]} */ 65 public static final CstType BYTE_ARRAY = intern(Type.BYTE_ARRAY); 66 67 /** {@code non-null;} instance corresponding to the type {@code char[]} */ 68 public static final CstType CHAR_ARRAY = intern(Type.CHAR_ARRAY); 69 70 /** {@code non-null;} instance corresponding to the type {@code double[]} */ 71 public static final CstType DOUBLE_ARRAY = intern(Type.DOUBLE_ARRAY); 72 73 /** {@code non-null;} instance corresponding to the type {@code float[]} */ 74 public static final CstType FLOAT_ARRAY = intern(Type.FLOAT_ARRAY); 75 76 /** {@code non-null;} instance corresponding to the type {@code long[]} */ 77 public static final CstType LONG_ARRAY = intern(Type.LONG_ARRAY); 78 79 /** {@code non-null;} instance corresponding to the type {@code int[]} */ 80 public static final CstType INT_ARRAY = intern(Type.INT_ARRAY); 81 82 /** {@code non-null;} instance corresponding to the type {@code short[]} */ 83 public static final CstType SHORT_ARRAY = intern(Type.SHORT_ARRAY); 84 85 /** {@code non-null;} the underlying type */ 86 private final Type type; 87 88 /** 89 * {@code null-ok;} the type descriptor corresponding to this instance, if 90 * calculated 91 */ 92 private CstString 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}. 99 * 100 * @param primitiveType {@code non-null;} the primitive type 101 * @return {@code non-null;} the corresponding wrapper class 102 */ 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 {@code non-null;} the underlying type 123 * @return {@code non-null;} an appropriately-constructed instance 124 */ 125 public static CstType intern(Type type) { 126 synchronized (interns) { 127 CstType cst = interns.get(type); 128 129 if (cst == null) { 130 cst = new CstType(type); 131 interns.put(type, cst); 132 } 133 134 return cst; 135 } 136 } 137 138 /** 139 * Constructs an instance. 140 * 141 * @param type {@code non-null;} the underlying type 142 */ 143 public CstType(Type type) { 144 if (type == null) { 145 throw new NullPointerException("type == null"); 146 } 147 148 if (type == type.KNOWN_NULL) { 149 throw new UnsupportedOperationException( 150 "KNOWN_NULL is not representable"); 151 } 152 153 this.type = type; 154 this.descriptor = null; 155 } 156 157 /** {@inheritDoc} */ 158 @Override 159 public boolean equals(Object other) { 160 if (!(other instanceof CstType)) { 161 return false; 162 } 163 164 return type == ((CstType) other).type; 165 } 166 167 /** {@inheritDoc} */ 168 @Override 169 public int hashCode() { 170 return type.hashCode(); 171 } 172 173 /** {@inheritDoc} */ 174 @Override 175 protected int compareTo0(Constant other) { 176 String thisDescriptor = type.getDescriptor(); 177 String otherDescriptor = ((CstType) other).type.getDescriptor(); 178 return thisDescriptor.compareTo(otherDescriptor); 179 } 180 181 /** {@inheritDoc} */ 182 @Override 183 public String toString() { 184 return "type{" + toHuman() + '}'; 185 } 186 187 /** {@inheritDoc} */ 188 public Type getType() { 189 return Type.CLASS; 190 } 191 192 /** {@inheritDoc} */ 193 @Override 194 public String typeName() { 195 return "type"; 196 } 197 198 /** {@inheritDoc} */ 199 @Override 200 public boolean isCategory2() { 201 return false; 202 } 203 204 /** {@inheritDoc} */ 205 public String toHuman() { 206 return type.toHuman(); 207 } 208 209 /** 210 * Gets the underlying type (as opposed to the type corresponding 211 * to this instance as a constant, which is always 212 * {@code Class}). 213 * 214 * @return {@code non-null;} the type corresponding to the name 215 */ 216 public Type getClassType() { 217 return type; 218 } 219 220 /** 221 * Gets the type descriptor for this instance. 222 * 223 * @return {@code non-null;} the descriptor 224 */ 225 public CstString getDescriptor() { 226 if (descriptor == null) { 227 descriptor = new CstString(type.getDescriptor()); 228 } 229 230 return descriptor; 231 } 232} 233