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   */
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: PUSH.html 1018313 2017-09-18 09:03:04Z britter $
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 }