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     *
017     */
018    package org.apache.bcel.generic;
019    
020    import org.apache.bcel.Constants;
021    
022    /** 
023     * Wrapper class for push operations, which are implemented either as BIPUSH,
024     * LDC or xCONST_n instructions.
025     *
026     * @version $Id: PUSH.java 1152072 2011-07-29 01:54:05Z dbrosius $
027     * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
028     */
029    public final class PUSH implements CompoundInstruction, VariableLengthInstruction,
030            InstructionConstants {
031    
032        private Instruction instruction;
033    
034    
035        /**
036         * This constructor also applies for values of type short, char, byte 
037         *
038         * @param cp Constant pool
039         * @param value to be pushed 
040         */
041        public PUSH(ConstantPoolGen cp, int value) {
042            if ((value >= -1) && (value <= 5)) {
043                instruction = INSTRUCTIONS[Constants.ICONST_0 + value];
044            } else if ((value >= -128) && (value <= 127)) {
045                instruction = new BIPUSH((byte) value);
046            } else if ((value >= -32768) && (value <= 32767)) {
047                instruction = new SIPUSH((short) value);
048            } else {
049                instruction = new LDC(cp.addInteger(value));
050            }
051        }
052    
053    
054        /**
055         * @param cp Constant pool
056         * @param value to be pushed 
057         */
058        public PUSH(ConstantPoolGen cp, boolean value) {
059            instruction = INSTRUCTIONS[Constants.ICONST_0 + (value ? 1 : 0)];
060        }
061    
062    
063        /**
064         * @param cp Constant pool
065         * @param value to be pushed 
066         */
067        public PUSH(ConstantPoolGen cp, float value) {
068            if (value == 0.0) {
069                instruction = FCONST_0;
070            } else if (value == 1.0) {
071                instruction = FCONST_1;
072            } else if (value == 2.0) {
073                instruction = FCONST_2;
074            } else {
075                instruction = new LDC(cp.addFloat(value));
076            }
077        }
078    
079    
080        /**
081         * @param cp Constant pool
082         * @param value to be pushed 
083         */
084        public PUSH(ConstantPoolGen cp, long value) {
085            if (value == 0) {
086                instruction = LCONST_0;
087            } else if (value == 1) {
088                instruction = LCONST_1;
089            } else {
090                instruction = new LDC2_W(cp.addLong(value));
091            }
092        }
093    
094    
095        /**
096         * @param cp Constant pool
097         * @param value to be pushed 
098         */
099        public PUSH(ConstantPoolGen cp, double value) {
100            if (value == 0.0) {
101                instruction = DCONST_0;
102            } else if (value == 1.0) {
103                instruction = DCONST_1;
104            } else {
105                instruction = new LDC2_W(cp.addDouble(value));
106            }
107        }
108    
109    
110        /**
111         * @param cp Constant pool
112         * @param value to be pushed 
113         */
114        public PUSH(ConstantPoolGen cp, String value) {
115            if (value == null) {
116                instruction = ACONST_NULL;
117            } else {
118                instruction = new LDC(cp.addString(value));
119            }
120        }
121    
122        /**
123         * 
124         * @param cp
125         * @param value
126         */
127        public PUSH(ConstantPoolGen cp, ObjectType value) {
128            if (value == null) {
129                instruction = ACONST_NULL;
130            } else {
131                instruction = new LDC(cp.addClass(value));
132            }
133        }
134        
135        /**
136         * @param cp Constant pool
137         * @param value to be pushed 
138         */
139        public PUSH(ConstantPoolGen cp, 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         * creates a push object from a Character value. Warning: Make sure not to attempt to allow
156         * autoboxing to create this value parameter, as an alternative constructor will be called
157         * 
158         * @param cp Constant pool
159         * @param value to be pushed 
160         */
161        public PUSH(ConstantPoolGen cp, Character value) {
162            this(cp, value.charValue());
163        }
164    
165    
166        /**
167         * @param cp Constant pool
168         * @param value to be pushed 
169         */
170        public PUSH(ConstantPoolGen cp, Boolean value) {
171            this(cp, value.booleanValue());
172        }
173    
174    
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.toString() + " (PUSH)";
191        }
192    }