package org.coldswap.util;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import java.util.logging.Logger;
/**
* (C) Copyright 2013 Faur Ioan-Aurel.
* <p/>
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p/>
* Contributors:
* faur
* <p/>
* Created at:
* 5:06 PM 5/14/13
*/
/**
* Instructions for boxing and unboxing the primitives.
*/
public class AutoBoxing {
private static final Logger logger = Logger.getLogger(AutoBoxing.class.getName());
static {
logger.setLevel(ClassUtil.logLevel);
}
public static String getBoxClassName(Type type) {
String t = type.getDescriptor();
if (t.length() > 1) {
return null;
} else if ("Z".equals(t)) {
return "java/lang/Boolean";
} else if ("B".equals(t)) {
return "java/lang/Byte";
} else if ("C".equals(t)) {
return "java/lang/Character";
} else if ("S".equals(t)) {
return "java/lang/Short";
} else if ("I".equals(t)) {
return "java/lang/Integer";
} else if ("J".equals(t)) {
return "java/lang/Long";
} else if ("F".equals(t)) {
return "java/lang/Float";
} else if ("D".equals(t)) {
return "java/lang/Double";
}
return null;
}
public static String getUnBoxInvoke(Type type) {
String t = type.getDescriptor();
if (t.length() > 1) {
return null;
} else if ("Z".equals(t)) {
return "java/lang/Boolean.booleanValue";
} else if ("B".equals(t)) {
return "java/lang/Number.byteVale";
} else if ("C".equals(t)) {
return "java/lang/Character.charValue";
} else if ("S".equals(t)) {
return "java/lang/Number.shortValue";
} else if ("I".equals(t)) {
return "java/lang/Number.intValue";
} else if ("J".equals(t)) {
return "java/lang/Number.longValue";
} else if ("F".equals(t)) {
return "java/lang/Number.floatValue";
} else if ("D".equals(t)) {
return "java/lang/Number.doubleValue";
}
return null;
}
public static InsnList box(char type) {
switch (type) {
case 'Z':
return boxBoolean();
case 'B':
return boxByte();
case 'C':
return boxChar();
case 'S':
return boxShort();
case 'I':
return boxInt();
case 'J':
return boxLong();
case 'F':
return boxFloat();
case 'D':
return boxDouble();
default:
logger.severe("Could not identify type:" + type + " while trying to box!");
return null;
}
}
public static InsnList box(Type type) {
String t = type.getDescriptor();
if (t.length() > 1) {
return null;
} else if ("Z".equals(t)) {
return box('Z');
} else if ("B".equals(t)) {
return box('B');
} else if ("C".equals(t)) {
return box('C');
} else if ("S".equals(t)) {
return box('S');
} else if ("I".equals(t)) {
return box('I');
} else if ("J".equals(t)) {
return box('J');
} else if ("F".equals(t)) {
return box('F');
} else if ("D".equals(t)) {
return box('D');
}
return null;
}
public static InsnList unbox(char type) {
switch (type) {
case 'Z':
return unboxBoolean();
case 'B':
return unboxByte();
case 'C':
return unboxChar();
case 'S':
return unboxShort();
case 'I':
return unboxInt();
case 'J':
return unboxLong();
case 'F':
return unboxFloat();
case 'D':
return unboxDouble();
default:
logger.severe("Could not identify type:" + type + " while trying to unbox!");
return null;
}
}
public static InsnList unbox(Type type) {
String t = type.getDescriptor();
if (t.length() > 1) {
return null;
} else if ("Z".equals(t)) {
return unbox('Z');
} else if ("B".equals(t)) {
return unbox('B');
} else if ("C".equals(t)) {
return unbox('C');
} else if ("S".equals(t)) {
return unbox('S');
} else if ("I".equals(t)) {
return unbox('I');
} else if ("J".equals(t)) {
return unbox('J');
} else if ("F".equals(t)) {
return unbox('F');
} else if ("D".equals(t)) {
return unbox('D');
}
return null;
}
public static boolean isPrimitive(String type) {
if (type.length() > 1) {
return false;
} else if ("Z".equals(type)) {
return true;
} else if ("B".equals(type)) {
return true;
} else if ("C".equals(type)) {
return true;
} else if ("S".equals(type)) {
return true;
} else if ("I".equals(type)) {
return true;
} else if ("J".equals(type)) {
return true;
} else if ("F".equals(type)) {
return true;
} else if ("D".equals(type)) {
return true;
}
return false;
}
private static InsnList boxBoolean() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"));
return il;
}
private static InsnList unboxBoolean() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"));
return il;
}
private static InsnList boxByte() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"));
return il;
}
private static InsnList unboxByte() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Number"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "byteValue", "()B"));
return il;
}
private static InsnList boxChar() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"));
return il;
}
private static InsnList unboxChar() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C"));
return il;
}
private static InsnList boxShort() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"));
return il;
}
private static InsnList unboxShort() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Number"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "shortValue", "()S"));
return il;
}
private static InsnList boxInt() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"));
return il;
}
private static InsnList unboxInt() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Number"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I"));
return il;
}
private static InsnList boxLong() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"));
return il;
}
private static InsnList unboxLong() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Number"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "longValue", "()J"));
return il;
}
private static InsnList boxFloat() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"));
return il;
}
private static InsnList unboxFloat() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Number"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "floatValue", "()F"));
return il;
}
private static InsnList boxDouble() {
InsnList il = new InsnList();
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"));
return il;
}
private static InsnList unboxDouble() {
InsnList il = new InsnList();
il.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Number"));
il.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Number", "doubleValue", "()D"));
return il;
}
}