View Javadoc
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  package org.apache.bcel.generic;
18  
19  import java.util.Objects;
20  
21  import org.apache.bcel.Const;
22  
23  /**
24   * Wrapper class for push operations, which are implemented either as BIPUSH, LDC or xCONST_n instructions.
25   */
26  public final class PUSH implements CompoundInstruction, VariableLengthInstruction, InstructionConstants {
27  
28      private final Instruction instruction;
29  
30      /**
31       * Pushes an array type constant, for example {@code int[].class}, {@code String[].class}, and so on.
32       *
33       * @param cp generated constant pool.
34       * @param value to be pushed.
35       * @since 6.7.0
36       */
37      public PUSH(final ConstantPoolGen cp, final ArrayType value) {
38          if (value == null) {
39              instruction = InstructionConst.ACONST_NULL;
40          } else {
41              instruction = new LDC(cp.addArrayClass(value));
42          }
43      }
44  
45     /**
46       * @param cp Constant pool
47       * @param value to be pushed
48       */
49      public PUSH(final ConstantPoolGen cp, final boolean value) {
50          Objects.requireNonNull(cp, "cp");
51          instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0));
52      }
53  
54      /**
55       * @param cp Constant pool
56       * @param value to be pushed
57       */
58      public PUSH(final ConstantPoolGen cp, final Boolean value) {
59          this(cp, value.booleanValue());
60      }
61  
62      /**
63       * creates a push object from a Character value. Warning: Make sure not to attempt to allow autoboxing to create this
64       * value parameter, as an alternative constructor will be called
65       *
66       * @param cp Constant pool
67       * @param value to be pushed
68       */
69      public PUSH(final ConstantPoolGen cp, final Character value) {
70          this(cp, value.charValue());
71      }
72  
73      /**
74       * @param cp Constant pool
75       * @param value to be pushed
76       */
77      public PUSH(final ConstantPoolGen cp, final double value) {
78          if (value == 0.0) {
79              instruction = InstructionConst.DCONST_0;
80          } else if (value == 1.0) {
81              instruction = InstructionConst.DCONST_1;
82          } else {
83              instruction = new LDC2_W(cp.addDouble(value));
84          }
85      }
86  
87      /**
88       * @param cp Constant pool
89       * @param value to be pushed
90       */
91      public PUSH(final ConstantPoolGen cp, final float value) {
92          if (value == 0.0) {
93              instruction = InstructionConst.FCONST_0;
94          } else if (value == 1.0) {
95              instruction = InstructionConst.FCONST_1;
96          } else if (value == 2.0) {
97              instruction = InstructionConst.FCONST_2;
98          } else {
99              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 }