Java tutorial
/** * Copyright (c) 2015 Kyle Friz * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.friz.instruction.utility; import static org.objectweb.asm.Opcodes.ACONST_NULL; import static org.objectweb.asm.Opcodes.BIPUSH; import static org.objectweb.asm.Opcodes.DCONST_0; import static org.objectweb.asm.Opcodes.DCONST_1; import static org.objectweb.asm.Opcodes.FCONST_0; import static org.objectweb.asm.Opcodes.FCONST_1; import static org.objectweb.asm.Opcodes.FCONST_2; import static org.objectweb.asm.Opcodes.ICONST_0; import static org.objectweb.asm.Opcodes.ICONST_1; import static org.objectweb.asm.Opcodes.ICONST_2; import static org.objectweb.asm.Opcodes.ICONST_3; import static org.objectweb.asm.Opcodes.ICONST_4; import static org.objectweb.asm.Opcodes.ICONST_5; import static org.objectweb.asm.Opcodes.ICONST_M1; import static org.objectweb.asm.Opcodes.LCONST_0; import static org.objectweb.asm.Opcodes.LCONST_1; import static org.objectweb.asm.Opcodes.LDC; import static org.objectweb.asm.Opcodes.SIPUSH; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.IntInsnNode; import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.util.Printer; /** * @author Kyle Friz * @since Feb 29, 2016 */ public class InstructionUtil { /** * Creates a numeric push instruction. * * @param num * The number to push. * @return The instruction node. */ public static AbstractInsnNode createNumericPush(Number num) { if (num instanceof Integer) { int value = num.intValue(); if (value == -1) { return new InsnNode(ICONST_M1); } else if (value == 0) { return new InsnNode(ICONST_0); } else if (value == 1) { return new InsnNode(ICONST_1); } else if (value == 2) { return new InsnNode(ICONST_2); } else if (value == 3) { return new InsnNode(ICONST_3); } else if (value == 4) { return new InsnNode(ICONST_4); } else if (value == 5) { return new InsnNode(ICONST_5); } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { return new IntInsnNode(BIPUSH, value); } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { return new IntInsnNode(SIPUSH, value); } else if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) { return new LdcInsnNode(value); } else { return new LdcInsnNode(value); } } else if (num instanceof Long) { long value = num.longValue(); if (value == 0) { return new InsnNode(LCONST_0); } else if (value == 1) { return new InsnNode(LCONST_1); } else { return new LdcInsnNode(value); } } else if (num instanceof Float) { float value = num.floatValue(); if (value == 0.0F) { return new InsnNode(FCONST_0); } else if (value == 1.0F) { return new InsnNode(FCONST_1); } else if (value == 2.0F) { return new InsnNode(FCONST_2); } else { return new LdcInsnNode(value); } } else if (num instanceof Double) { double value = num.doubleValue(); if (value == 0.0D) { return new InsnNode(DCONST_0); } else if (value == 1.0D) { return new InsnNode(DCONST_1); } else { return new LdcInsnNode(value); } } else throw new AssertionError(num.getClass()); } /** * Reads the value of a numeric push instruction (which can be an * {@code ICONST_*} instruction, an {@code BIPUSH} instruction, an * {@code SIPUSH} instruction or a {@code LDC_*} instruction. * * @param push * The instruction node. * @return The numeric value. */ public static Number getNumericPush(AbstractInsnNode push) { if (push instanceof InsnNode) { switch (push.getOpcode()) { case ICONST_M1: return -1; case ICONST_0: return 0; case LCONST_0: return 0L; case FCONST_0: return 0.0F; case DCONST_0: return 0.0D; case ICONST_1: return 1; case LCONST_1: return 1L; case FCONST_1: return 1.0F; case DCONST_1: return 1.0D; case ICONST_2: return 2; case FCONST_2: return 2.0F; case ICONST_3: return 3; case ICONST_4: return 4; case ICONST_5: return 5; default: throw new AssertionError(Printer.OPCODES[push.getOpcode()]); } } else if (push instanceof IntInsnNode) { return ((IntInsnNode) push).operand; } else { return ((Number) ((LdcInsnNode) push).cst); } } public static boolean isStaticPush(AbstractInsnNode node) { return node.getOpcode() == ACONST_NULL || node.getOpcode() == ICONST_M1 || node.getOpcode() == ICONST_0 || node.getOpcode() == ICONST_1 || node.getOpcode() == ICONST_2 || node.getOpcode() == ICONST_3 || node.getOpcode() == ICONST_4 || node.getOpcode() == ICONST_5 || node.getOpcode() == LCONST_0 || node.getOpcode() == LCONST_1 || node.getOpcode() == FCONST_0 || node.getOpcode() == FCONST_1 || node.getOpcode() == FCONST_2 || node.getOpcode() == DCONST_0 || node.getOpcode() == DCONST_1 || node.getOpcode() == BIPUSH || node.getOpcode() == SIPUSH || node.getOpcode() == LDC; } public static boolean isDynamicPush(AbstractInsnNode node) { return !isStaticPush(node); } /** * Finds the next non-psuedo node following the specified node. * * @param node * The node. * @return The next non-psuedo node, or {@code null} if the end of the * instruction list is reached. */ public static AbstractInsnNode nextNonPsuedoNode(AbstractInsnNode node) { while ((node = node.getNext()) != null && node.getOpcode() == -1) ; return node; } /** * Finds the previous non-psuedo node following the specified node. * * @param node * The node. * @return The previous non-psuedo node, or {@code null} if the start of the * instruction list is reached. */ public static AbstractInsnNode previousNonPsuedoNode(AbstractInsnNode node) { while ((node = node.getPrevious()) != null && node.getOpcode() == -1) ; return node; } /** * Finds the previous non-psuedo node following the specified node. * * @param node * The node. * @return The previous non-psuedo node, or {@code null} if the start of the * instruction list is reached. */ public static AbstractInsnNode previousNonPsuedoNode(AbstractInsnNode node, int opcode) { while ((node = node.getPrevious()) != null && node.getOpcode() == opcode) ; return node; } /** * Finds the next psuedo node following the specified node. * * @param node * The node. * @return The next psuedo node, or {@code null} if the end of the * instruction list is reached. */ public static AbstractInsnNode nextPsuedoNode(AbstractInsnNode node) { while ((node = node.getNext()) != null && node.getOpcode() != -1) ; return node; } /** * Finds the previous psuedo node following the specified node. * * @param node * The node. * @return The previous psuedo node, or {@code null} if the start of the * instruction list is reached. */ public static AbstractInsnNode previousPsuedoNode(AbstractInsnNode node) { while ((node = node.getPrevious()) != null && node.getOpcode() != -1) ; return node; } /** * Finds the previous psuedo node following the specified node. * * @param node * The node. * @return The previous psuedo node, or {@code null} if the start of the * instruction list is reached. */ public static AbstractInsnNode previousPsuedoNode(AbstractInsnNode node, int opcode) { while ((node = node.getPrevious()) != null && node.getOpcode() != opcode) ; return node; } /** * Default private constructor to prevent instantiation. */ private InstructionUtil() { } }