9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.invoke.util;
27
28 public enum Wrapper {
29 // wrapperType primitiveType char zero emptyArray format
30 BOOLEAN( Boolean.class, boolean.class, 'Z', Boolean.FALSE, new boolean[0], Format.unsigned( 1)),
31 // These must be in the order defined for widening primitive conversions in JLS 5.1.2
32 // Avoid boxing integral types here to defer initialization of internal caches
33 BYTE ( Byte.class, byte.class, 'B', new Byte((byte)0), new byte[0], Format.signed( 8)),
34 SHORT ( Short.class, short.class, 'S', new Short((short)0), new short[0], Format.signed( 16)),
35 CHAR (Character.class, char.class, 'C', new Character((char)0), new char[0], Format.unsigned(16)),
36 INT ( Integer.class, int.class, 'I', new Integer(0), new int[0], Format.signed( 32)),
37 LONG ( Long.class, long.class, 'J', new Long(0), new long[0], Format.signed( 64)),
38 FLOAT ( Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)),
39 DOUBLE ( Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)),
40 OBJECT ( Object.class, Object.class, 'L', null, new Object[0], Format.other( 1)),
41 // VOID must be the last type, since it is "assignable" from any other type:
42 VOID ( Void.class, void.class, 'V', null, null, Format.other( 0)),
43 ;
44
45 private final Class<?> wrapperType;
46 private final Class<?> primitiveType;
47 private final char basicTypeChar;
48 private final Object zero;
49 private final Object emptyArray;
50 private final int format;
51 private final String wrapperSimpleName;
52 private final String primitiveSimpleName;
53
54 private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
55 this.wrapperType = wtype;
56 this.primitiveType = ptype;
57 this.basicTypeChar = tchar;
58 this.zero = zero;
59 this.emptyArray = emptyArray;
60 this.format = format;
61 this.wrapperSimpleName = wtype.getSimpleName();
62 this.primitiveSimpleName = ptype.getSimpleName();
63 }
64
65 /** For debugging, give the details of this wrapper. */
66 public String detailString() {
67 return wrapperSimpleName+
68 java.util.Arrays.asList(wrapperType, primitiveType,
69 basicTypeChar, zero,
70 "0x"+Integer.toHexString(format));
71 }
72
73 private abstract static class Format {
74 static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
75 static final int
76 SIGNED = (-1) << KIND_SHIFT,
77 UNSIGNED = 0 << KIND_SHIFT,
78 FLOATING = 1 << KIND_SHIFT;
79 static final int
80 SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
81 SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
82 static int format(int kind, int size, int slots) {
83 assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
84 assert((size & (size-1)) == 0); // power of two
85 assert((kind == SIGNED) ? (size > 0) :
86 (kind == UNSIGNED) ? (size > 0) :
87 (kind == FLOATING) ? (size == 32 || size == 64) :
88 false);
89 assert((slots == 2) ? (size == 64) :
206 else if (x.isFloating()) {
207 if (w.compareTo(x) < 0)
208 assert(!w.isConvertibleFrom(x));
209 else
210 assert(w.isConvertibleFrom(x));
211 }
212 }
213 }
214 }
215 return true; // i.e., assert(true)
216 }
217
218 /** Produce a zero value for the given wrapper type.
219 * This will be a numeric zero for a number or character,
220 * false for a boolean, and null for a reference or void.
221 * The common thread is that this is what is contained
222 * in a default-initialized variable of the given primitive
223 * type. (For void, it is what a reflective method returns
224 * instead of no value at all.)
225 */
226 public Object zero() { return zero; }
227
228 /** Produce a zero value for the given wrapper type T.
229 * The optional argument must a type compatible with this wrapper.
230 * Equivalent to {@code this.cast(this.zero(), type)}.
231 */
232 public <T> T zero(Class<T> type) { return convert(zero, type); }
233
234 /** Return the wrapper that wraps values of the given type.
235 * The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
236 * Otherwise, the type must be a primitive.
237 * @throws IllegalArgumentException for unexpected types
238 */
239 public static Wrapper forPrimitiveType(Class<?> type) {
240 Wrapper w = findPrimitiveType(type);
241 if (w != null) return w;
242 if (type.isPrimitive())
243 throw new InternalError(); // redo hash function
244 throw newIllegalArgumentException("not primitive: "+type);
245 }
246
247 static Wrapper findPrimitiveType(Class<?> type) {
248 Wrapper w = FROM_PRIM[hashPrim(type)];
249 if (w != null && w.primitiveType == type) {
250 return w;
251 }
252 return null;
457 // If the target type is a primitive, change it to a wrapper.
458 assert(!type.isPrimitive());
459 if (!type.isInterface())
460 type.cast(x);
461 @SuppressWarnings("unchecked")
462 T result = (T) x; // unchecked warning is expected here
463 return result;
464 }
465 Class<T> wtype = wrapperType(type);
466 if (wtype.isInstance(x)) {
467 return wtype.cast(x);
468 }
469 if (!isCast) {
470 Class<?> sourceType = x.getClass(); // throw NPE if x is null
471 Wrapper source = findWrapperType(sourceType);
472 if (source == null || !this.isConvertibleFrom(source)) {
473 throw newClassCastException(wtype, sourceType);
474 }
475 } else if (x == null) {
476 @SuppressWarnings("unchecked")
477 T z = (T) zero;
478 return z;
479 }
480 @SuppressWarnings("unchecked")
481 T result = (T) wrap(x); // unchecked warning is expected here
482 assert (result == null ? Void.class : result.getClass()) == wtype;
483 return result;
484 }
485
486 /** Cast a reference type to another reference type.
487 * If the target type is an interface, perform no runtime check.
488 * (This loophole is safe, and is allowed by the JVM verifier.)
489 * If the target type is a primitive, change it to a wrapper.
490 */
491 static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
492 boolean z = (type == exampleType ||
493 type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
494 exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
495 type == Object.class && !exampleType.isPrimitive());
496 if (!z)
497 System.out.println(type+" <= "+exampleType);
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.invoke.util;
27
28 public enum Wrapper {
29 // wrapperType primitiveType char emptyArray format
30 BOOLEAN( Boolean.class, boolean.class, 'Z', new boolean[0], Format.unsigned( 1)),
31 // These must be in the order defined for widening primitive conversions in JLS 5.1.2
32 // Avoid boxing integral types here to defer initialization of internal caches
33 BYTE ( Byte.class, byte.class, 'B', new byte[0], Format.signed( 8)),
34 SHORT ( Short.class, short.class, 'S', new short[0], Format.signed( 16)),
35 CHAR (Character.class, char.class, 'C', new char[0], Format.unsigned(16)),
36 INT ( Integer.class, int.class, 'I', new int[0], Format.signed( 32)),
37 LONG ( Long.class, long.class, 'J', new long[0], Format.signed( 64)),
38 FLOAT ( Float.class, float.class, 'F', new float[0], Format.floating(32)),
39 DOUBLE ( Double.class, double.class, 'D', new double[0], Format.floating(64)),
40 OBJECT ( Object.class, Object.class, 'L', new Object[0], Format.other( 1)),
41 // VOID must be the last type, since it is "assignable" from any other type:
42 VOID ( Void.class, void.class, 'V', null, Format.other( 0)),
43 ;
44
45 private final Class<?> wrapperType;
46 private final Class<?> primitiveType;
47 private final char basicTypeChar;
48 private final Object emptyArray;
49 private final int format;
50 private final String wrapperSimpleName;
51 private final String primitiveSimpleName;
52
53 private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object emptyArray, int format) {
54 this.wrapperType = wtype;
55 this.primitiveType = ptype;
56 this.basicTypeChar = tchar;
57 this.emptyArray = emptyArray;
58 this.format = format;
59 this.wrapperSimpleName = wtype.getSimpleName();
60 this.primitiveSimpleName = ptype.getSimpleName();
61 }
62
63 /** For debugging, give the details of this wrapper. */
64 public String detailString() {
65 return wrapperSimpleName+
66 java.util.Arrays.asList(wrapperType, primitiveType,
67 basicTypeChar, zero(),
68 "0x"+Integer.toHexString(format));
69 }
70
71 private abstract static class Format {
72 static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
73 static final int
74 SIGNED = (-1) << KIND_SHIFT,
75 UNSIGNED = 0 << KIND_SHIFT,
76 FLOATING = 1 << KIND_SHIFT;
77 static final int
78 SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
79 SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
80 static int format(int kind, int size, int slots) {
81 assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
82 assert((size & (size-1)) == 0); // power of two
83 assert((kind == SIGNED) ? (size > 0) :
84 (kind == UNSIGNED) ? (size > 0) :
85 (kind == FLOATING) ? (size == 32 || size == 64) :
86 false);
87 assert((slots == 2) ? (size == 64) :
204 else if (x.isFloating()) {
205 if (w.compareTo(x) < 0)
206 assert(!w.isConvertibleFrom(x));
207 else
208 assert(w.isConvertibleFrom(x));
209 }
210 }
211 }
212 }
213 return true; // i.e., assert(true)
214 }
215
216 /** Produce a zero value for the given wrapper type.
217 * This will be a numeric zero for a number or character,
218 * false for a boolean, and null for a reference or void.
219 * The common thread is that this is what is contained
220 * in a default-initialized variable of the given primitive
221 * type. (For void, it is what a reflective method returns
222 * instead of no value at all.)
223 */
224 public Object zero() {
225 switch (this) {
226 case BOOLEAN:
227 return Boolean.FALSE;
228 case INT:
229 return (Integer)0;
230 case BYTE:
231 return (Byte)(byte)0;
232 case CHAR:
233 return (Character)(char)0;
234 case SHORT:
235 return (Short)(short)0;
236 case LONG:
237 return (Long)(long)0;
238 case FLOAT:
239 return FLOAT_ZERO;
240 case DOUBLE:
241 return DOUBLE_ZERO;
242 case VOID:
243 case OBJECT:
244 default:
245 return null;
246 }
247 }
248
249 private static final Object DOUBLE_ZERO = (Double)(double)0;
250 private static final Object FLOAT_ZERO = (Float)(float)0;
251
252 /** Produce a zero value for the given wrapper type T.
253 * The optional argument must a type compatible with this wrapper.
254 * Equivalent to {@code this.cast(this.zero(), type)}.
255 */
256 public <T> T zero(Class<T> type) { return convert(zero(), type); }
257
258 /** Return the wrapper that wraps values of the given type.
259 * The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
260 * Otherwise, the type must be a primitive.
261 * @throws IllegalArgumentException for unexpected types
262 */
263 public static Wrapper forPrimitiveType(Class<?> type) {
264 Wrapper w = findPrimitiveType(type);
265 if (w != null) return w;
266 if (type.isPrimitive())
267 throw new InternalError(); // redo hash function
268 throw newIllegalArgumentException("not primitive: "+type);
269 }
270
271 static Wrapper findPrimitiveType(Class<?> type) {
272 Wrapper w = FROM_PRIM[hashPrim(type)];
273 if (w != null && w.primitiveType == type) {
274 return w;
275 }
276 return null;
481 // If the target type is a primitive, change it to a wrapper.
482 assert(!type.isPrimitive());
483 if (!type.isInterface())
484 type.cast(x);
485 @SuppressWarnings("unchecked")
486 T result = (T) x; // unchecked warning is expected here
487 return result;
488 }
489 Class<T> wtype = wrapperType(type);
490 if (wtype.isInstance(x)) {
491 return wtype.cast(x);
492 }
493 if (!isCast) {
494 Class<?> sourceType = x.getClass(); // throw NPE if x is null
495 Wrapper source = findWrapperType(sourceType);
496 if (source == null || !this.isConvertibleFrom(source)) {
497 throw newClassCastException(wtype, sourceType);
498 }
499 } else if (x == null) {
500 @SuppressWarnings("unchecked")
501 T z = (T) zero();
502 return z;
503 }
504 @SuppressWarnings("unchecked")
505 T result = (T) wrap(x); // unchecked warning is expected here
506 assert (result == null ? Void.class : result.getClass()) == wtype;
507 return result;
508 }
509
510 /** Cast a reference type to another reference type.
511 * If the target type is an interface, perform no runtime check.
512 * (This loophole is safe, and is allowed by the JVM verifier.)
513 * If the target type is a primitive, change it to a wrapper.
514 */
515 static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
516 boolean z = (type == exampleType ||
517 type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
518 exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
519 type == Object.class && !exampleType.isPrimitive());
520 if (!z)
521 System.out.println(type+" <= "+exampleType);
|