Home | History | Annotate | Download | only in generic
      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$
     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 }
    193