001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.generic; 018 019import java.util.Objects; 020 021import org.apache.bcel.Const; 022 023/** 024 * Wrapper class for push operations, which are implemented either as BIPUSH, LDC or xCONST_n instructions. 025 */ 026public final class PUSH implements CompoundInstruction, VariableLengthInstruction, InstructionConstants { 027 028 private final Instruction instruction; 029 030 /** 031 * @param cp Constant pool 032 * @param value to be pushed 033 */ 034 public PUSH(final ConstantPoolGen cp, final boolean value) { 035 Objects.requireNonNull(cp, "cp"); 036 instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0)); 037 } 038 039 /** 040 * @param cp Constant pool 041 * @param value to be pushed 042 */ 043 public PUSH(final ConstantPoolGen cp, final Boolean value) { 044 this(cp, value.booleanValue()); 045 } 046 047 /** 048 * creates a push object from a Character value. Warning: Make sure not to attempt to allow autoboxing to create this 049 * value parameter, as an alternative constructor will be called 050 * 051 * @param cp Constant pool 052 * @param value to be pushed 053 */ 054 public PUSH(final ConstantPoolGen cp, final Character value) { 055 this(cp, value.charValue()); 056 } 057 058 /** 059 * @param cp Constant pool 060 * @param value to be pushed 061 */ 062 public PUSH(final ConstantPoolGen cp, final double value) { 063 if (value == 0.0) { 064 instruction = InstructionConst.DCONST_0; 065 } else if (value == 1.0) { 066 instruction = InstructionConst.DCONST_1; 067 } else { 068 instruction = new LDC2_W(cp.addDouble(value)); 069 } 070 } 071 072 /** 073 * @param cp Constant pool 074 * @param value to be pushed 075 */ 076 public PUSH(final ConstantPoolGen cp, final float value) { 077 if (value == 0.0) { 078 instruction = InstructionConst.FCONST_0; 079 } else if (value == 1.0) { 080 instruction = InstructionConst.FCONST_1; 081 } else if (value == 2.0) { 082 instruction = InstructionConst.FCONST_2; 083 } else { 084 instruction = new LDC(cp.addFloat(value)); 085 } 086 } 087 088 /** 089 * This constructor also applies for values of type short, char, byte 090 * 091 * @param cp Constant pool 092 * @param value to be pushed 093 */ 094 public PUSH(final ConstantPoolGen cp, final int value) { 095 if (value >= -1 && value <= 5) { 096 instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); 097 } else if (Instruction.isValidByte(value)) { 098 instruction = new BIPUSH((byte) value); 099 } else if (Instruction.isValidShort(value)) { 100 instruction = new SIPUSH((short) value); 101 } else { 102 instruction = new LDC(cp.addInteger(value)); 103 } 104 } 105 106 /** 107 * @param cp Constant pool 108 * @param value to be pushed 109 */ 110 public PUSH(final ConstantPoolGen cp, final long value) { 111 if (value == 0) { 112 instruction = InstructionConst.LCONST_0; 113 } else if (value == 1) { 114 instruction = InstructionConst.LCONST_1; 115 } else { 116 instruction = new LDC2_W(cp.addLong(value)); 117 } 118 } 119 120 /** 121 * @param cp Constant pool 122 * @param value to be pushed 123 */ 124 public PUSH(final ConstantPoolGen cp, final Number value) { 125 if (value instanceof Integer || value instanceof Short || value instanceof Byte) { 126 instruction = new PUSH(cp, value.intValue()).instruction; 127 } else if (value instanceof Double) { 128 instruction = new PUSH(cp, value.doubleValue()).instruction; 129 } else if (value instanceof Float) { 130 instruction = new PUSH(cp, value.floatValue()).instruction; 131 } else if (value instanceof Long) { 132 instruction = new PUSH(cp, value.longValue()).instruction; 133 } else { 134 throw new ClassGenException("What's this: " + value); 135 } 136 } 137 138 /** 139 * 140 * @param cp 141 * @param value 142 * @since 6.0 143 */ 144 public PUSH(final ConstantPoolGen cp, final ObjectType value) { 145 if (value == null) { 146 instruction = InstructionConst.ACONST_NULL; 147 } else { 148 instruction = new LDC(cp.addClass(value)); 149 } 150 } 151 152 /** 153 * @param cp Constant pool 154 * @param value to be pushed 155 */ 156 public PUSH(final ConstantPoolGen cp, final String value) { 157 if (value == null) { 158 instruction = InstructionConst.ACONST_NULL; 159 } else { 160 instruction = new LDC(cp.addString(value)); 161 } 162 } 163 164 public Instruction getInstruction() { 165 return instruction; 166 } 167 168 @Override 169 public InstructionList getInstructionList() { 170 return new InstructionList(instruction); 171 } 172 173 /** 174 * @return mnemonic for instruction 175 */ 176 @Override 177 public String toString() { 178 return instruction + " (PUSH)"; 179 } 180}