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 * Pushes an array type constant, for example {@code int[].class}, {@code String[].class}, and so on. 032 * 033 * @param cp generated constant pool. 034 * @param value to be pushed. 035 * @since 6.7.0 036 */ 037 public PUSH(final ConstantPoolGen cp, final ArrayType value) { 038 if (value == null) { 039 instruction = InstructionConst.ACONST_NULL; 040 } else { 041 instruction = new LDC(cp.addArrayClass(value)); 042 } 043 } 044 045 /** 046 * @param cp Constant pool 047 * @param value to be pushed 048 */ 049 public PUSH(final ConstantPoolGen cp, final boolean value) { 050 Objects.requireNonNull(cp, "cp"); 051 instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0)); 052 } 053 054 /** 055 * @param cp Constant pool 056 * @param value to be pushed 057 */ 058 public PUSH(final ConstantPoolGen cp, final Boolean value) { 059 this(cp, value.booleanValue()); 060 } 061 062 /** 063 * creates a push object from a Character value. Warning: Make sure not to attempt to allow autoboxing to create this 064 * value parameter, as an alternative constructor will be called 065 * 066 * @param cp Constant pool 067 * @param value to be pushed 068 */ 069 public PUSH(final ConstantPoolGen cp, final Character value) { 070 this(cp, value.charValue()); 071 } 072 073 /** 074 * @param cp Constant pool 075 * @param value to be pushed 076 */ 077 public PUSH(final ConstantPoolGen cp, final double value) { 078 if (value == 0.0) { 079 instruction = InstructionConst.DCONST_0; 080 } else if (value == 1.0) { 081 instruction = InstructionConst.DCONST_1; 082 } else { 083 instruction = new LDC2_W(cp.addDouble(value)); 084 } 085 } 086 087 /** 088 * @param cp Constant pool 089 * @param value to be pushed 090 */ 091 public PUSH(final ConstantPoolGen cp, final float value) { 092 if (value == 0.0) { 093 instruction = InstructionConst.FCONST_0; 094 } else if (value == 1.0) { 095 instruction = InstructionConst.FCONST_1; 096 } else if (value == 2.0) { 097 instruction = InstructionConst.FCONST_2; 098 } else { 099 instruction = new LDC(cp.addFloat(value)); 100 } 101 } 102 103 /** 104 * This constructor also applies for values of type short, char, byte 105 * 106 * @param cp Constant pool 107 * @param value to be pushed 108 */ 109 public PUSH(final ConstantPoolGen cp, final int value) { 110 if (value >= -1 && value <= 5) { 111 instruction = InstructionConst.getInstruction(Const.ICONST_0 + value); 112 } else if (Instruction.isValidByte(value)) { 113 instruction = new BIPUSH((byte) value); 114 } else if (Instruction.isValidShort(value)) { 115 instruction = new SIPUSH((short) value); 116 } else { 117 instruction = new LDC(cp.addInteger(value)); 118 } 119 } 120 121 /** 122 * @param cp Constant pool 123 * @param value to be pushed 124 */ 125 public PUSH(final ConstantPoolGen cp, final long value) { 126 if (value == 0) { 127 instruction = InstructionConst.LCONST_0; 128 } else if (value == 1) { 129 instruction = InstructionConst.LCONST_1; 130 } else { 131 instruction = new LDC2_W(cp.addLong(value)); 132 } 133 } 134 135 /** 136 * @param cp Constant pool 137 * @param value to be pushed 138 */ 139 public PUSH(final ConstantPoolGen cp, final Number value) { 140 if (value instanceof Integer || value instanceof Short || value instanceof Byte) { 141 instruction = new PUSH(cp, value.intValue()).instruction; 142 } else if (value instanceof Double) { 143 instruction = new PUSH(cp, value.doubleValue()).instruction; 144 } else if (value instanceof Float) { 145 instruction = new PUSH(cp, value.floatValue()).instruction; 146 } else if (value instanceof Long) { 147 instruction = new PUSH(cp, value.longValue()).instruction; 148 } else { 149 throw new ClassGenException("What's this: " + value); 150 } 151 } 152 153 /** 154 * 155 * @param cp 156 * @param value 157 * @since 6.0 158 */ 159 public PUSH(final ConstantPoolGen cp, final ObjectType value) { 160 if (value == null) { 161 instruction = InstructionConst.ACONST_NULL; 162 } else { 163 instruction = new LDC(cp.addClass(value)); 164 } 165 } 166 167 /** 168 * @param cp Constant pool 169 * @param value to be pushed 170 */ 171 public PUSH(final ConstantPoolGen cp, final String value) { 172 if (value == null) { 173 instruction = InstructionConst.ACONST_NULL; 174 } else { 175 instruction = new LDC(cp.addString(value)); 176 } 177 } 178 179 public Instruction getInstruction() { 180 return instruction; 181 } 182 183 @Override 184 public InstructionList getInstructionList() { 185 return new InstructionList(instruction); 186 } 187 188 /** 189 * @return mnemonic for instruction 190 */ 191 @Override 192 public String toString() { 193 return instruction + " (PUSH)"; 194 } 195}