1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.generic; 19 20 import org.apache.bcel.Const; 21 22 /** 23 * Wrapper class for push operations, which are implemented either as BIPUSH, 24 * LDC or xCONST_n instructions. 25 * 26 * @version $Id$ 27 */ 28 public final class PUSH implements CompoundInstruction, VariableLengthInstruction, InstructionConstants { 29 30 private Instruction instruction; 31 32 33 /** 34 * This constructor also applies for values of type short, char, byte 35 * 36 * @param cp Constant pool 37 * @param value to be pushed 38 */ 39 public PUSH(final ConstantPoolGen cp, final int value) { 40 if ((value >= -1) && (value <= 5)) { 41 instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); 42 } else if (Instruction.isValidByte(value)) { 43 instruction = new BIPUSH((byte) value); 44 } else if (Instruction.isValidShort(value)) { 45 instruction = new SIPUSH((short) value); 46 } else { 47 instruction = new LDC(cp.addInteger(value)); 48 } 49 } 50 51 52 /** 53 * @param cp Constant pool 54 * @param value to be pushed 55 */ 56 public PUSH(final ConstantPoolGen cp, final boolean value) { 57 instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0)); 58 } 59 60 61 /** 62 * @param cp Constant pool 63 * @param value to be pushed 64 */ 65 public PUSH(final ConstantPoolGen cp, final float value) { 66 if (value == 0.0) { 67 instruction = InstructionConst.FCONST_0; 68 } else if (value == 1.0) { 69 instruction = InstructionConst.FCONST_1; 70 } else if (value == 2.0) { 71 instruction = InstructionConst.FCONST_2; 72 } else { 73 instruction = new LDC(cp.addFloat(value)); 74 } 75 } 76 77 78 /** 79 * @param cp Constant pool 80 * @param value to be pushed 81 */ 82 public PUSH(final ConstantPoolGen cp, final long value) { 83 if (value == 0) { 84 instruction = InstructionConst.LCONST_0; 85 } else if (value == 1) { 86 instruction = InstructionConst.LCONST_1; 87 } else { 88 instruction = new LDC2_W(cp.addLong(value)); 89 } 90 } 91 92 93 /** 94 * @param cp Constant pool 95 * @param value to be pushed 96 */ 97 public PUSH(final ConstantPoolGen cp, final double value) { 98 if (value == 0.0) { 99 instruction = InstructionConst.DCONST_0; 100 } else if (value == 1.0) { 101 instruction = InstructionConst.DCONST_1; 102 } else { 103 instruction = new LDC2_W(cp.addDouble(value)); 104 } 105 } 106 107 108 /** 109 * @param cp Constant pool 110 * @param value to be pushed 111 */ 112 public PUSH(final ConstantPoolGen cp, final String value) { 113 if (value == null) { 114 instruction = InstructionConst.ACONST_NULL; 115 } else { 116 instruction = new LDC(cp.addString(value)); 117 } 118 } 119 120 /** 121 * 122 * @param cp 123 * @param value 124 * @since 6.0 125 */ 126 public PUSH(final ConstantPoolGen cp, final ObjectType value) { 127 if (value == null) { 128 instruction = InstructionConst.ACONST_NULL; 129 } else { 130 instruction = new LDC(cp.addClass(value)); 131 } 132 } 133 134 /** 135 * @param cp Constant pool 136 * @param value to be pushed 137 */ 138 public PUSH(final ConstantPoolGen cp, final Number value) { 139 if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) { 140 instruction = new PUSH(cp, value.intValue()).instruction; 141 } else if (value instanceof Double) { 142 instruction = new PUSH(cp, value.doubleValue()).instruction; 143 } else if (value instanceof Float) { 144 instruction = new PUSH(cp, value.floatValue()).instruction; 145 } else if (value instanceof Long) { 146 instruction = new PUSH(cp, value.longValue()).instruction; 147 } else { 148 throw new ClassGenException("What's this: " + value); 149 } 150 } 151 152 153 /** 154 * creates a push object from a Character value. Warning: Make sure not to attempt to allow 155 * autoboxing to create this value parameter, as an alternative constructor will be called 156 * 157 * @param cp Constant pool 158 * @param value to be pushed 159 */ 160 public PUSH(final ConstantPoolGen cp, final Character value) { 161 this(cp, value.charValue()); 162 } 163 164 165 /** 166 * @param cp Constant pool 167 * @param value to be pushed 168 */ 169 public PUSH(final ConstantPoolGen cp, final Boolean value) { 170 this(cp, value.booleanValue()); 171 } 172 173 174 @Override 175 public final InstructionList getInstructionList() { 176 return new InstructionList(instruction); 177 } 178 179 180 public final Instruction getInstruction() { 181 return instruction; 182 } 183 184 185 /** 186 * @return mnemonic for instruction 187 */ 188 @Override 189 public String toString() { 190 return instruction + " (PUSH)"; 191 } 192 } 193