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