    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 */
    018package org.apache.bcel.generic;
    019
    020import org.apache.bcel.Const;
    021
    022/**
    023 * Wrapper class for push operations, which are implemented either as BIPUSH,
    024 * LDC or xCONST_n instructions.
    025 *
    026 */
    027public final class PUSH implements CompoundInstruction, VariableLengthInstruction, InstructionConstants {
    028
    029    private Instruction instruction;
    030
    031
    032    /**
    033     * This constructor also applies for values of type short, char, byte
    034     *
    035     * @param cp Constant pool
    036     * @param value to be pushed
    037     */
    038    public PUSH(final ConstantPoolGen cp, final int value) {
    039        if ((value >= -1) && (value <= 5)) {
    040            instruction = InstructionConst.getInstruction(Const.ICONST_0 + value);
    041        } else if (Instruction.isValidByte(value)) {
    042            instruction = new BIPUSH((byte) value);
    043        } else if (Instruction.isValidShort(value)) {
    044            instruction = new SIPUSH((short) value);
    045        } else {
    046            instruction = new LDC(cp.addInteger(value));
    047        }
    048    }
    049
    050
    051    /**
    052     * @param cp Constant pool
    053     * @param value to be pushed
    054     */
    055    public PUSH(final ConstantPoolGen cp, final boolean value) {
    056        instruction = InstructionConst.getInstruction(Const.ICONST_0 + (value ? 1 : 0));
    057    }
    058
    059
    060    /**
    061     * @param cp Constant pool
    062     * @param value to be pushed
    063     */
    064    public PUSH(final ConstantPoolGen cp, final float value) {
    065        if (value == 0.0) {
    066            instruction = InstructionConst.FCONST_0;
    067        } else if (value == 1.0) {
    068            instruction = InstructionConst.FCONST_1;
    069        } else if (value == 2.0) {
    070            instruction = InstructionConst.FCONST_2;
    071        } else {
    072            instruction = new LDC(cp.addFloat(value));
    073        }
    074    }
    075
    076
    077    /**
    078     * @param cp Constant pool
    079     * @param value to be pushed
    080     */
    081    public PUSH(final ConstantPoolGen cp, final long value) {
    082        if (value == 0) {
    083            instruction = InstructionConst.LCONST_0;
    084        } else if (value == 1) {
    085            instruction = InstructionConst.LCONST_1;
    086        } else {
    087            instruction = new LDC2_W(cp.addLong(value));
    088        }
    089    }
    090
    091
    092    /**
    093     * @param cp Constant pool
    094     * @param value to be pushed
    095     */
    096    public PUSH(final ConstantPoolGen cp, final double value) {
    097        if (value == 0.0) {
    098            instruction = InstructionConst.DCONST_0;
    099        } else if (value == 1.0) {
    100            instruction = InstructionConst.DCONST_1;
    101        } else {
    102            instruction = new LDC2_W(cp.addDouble(value));
    103        }
    104    }
    105
    106
    107    /**
    108     * @param cp Constant pool
    109     * @param value to be pushed
    110     */
    111    public PUSH(final ConstantPoolGen cp, final String value) {
    112        if (value == null) {
    113            instruction = InstructionConst.ACONST_NULL;
    114        } else {
    115            instruction = new LDC(cp.addString(value));
    116        }
    117    }
    118
    119    /**
    120     *
    121     * @param cp
    122     * @param value
    123     * @since 6.0
    124     */
    125    public PUSH(final ConstantPoolGen cp, final ObjectType value) {
    126        if (value == null) {
    127            instruction = InstructionConst.ACONST_NULL;
    128        } else {
    129            instruction = new LDC(cp.addClass(value));
    130        }
    131    }
    132
    133    /**
    134     * @param cp Constant pool
    135     * @param value to be pushed
    136     */
    137    public PUSH(final ConstantPoolGen cp, final Number value) {
    138        if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
    139            instruction = new PUSH(cp, value.intValue()).instruction;
    140        } else if (value instanceof Double) {
    141            instruction = new PUSH(cp, value.doubleValue()).instruction;
    142        } else if (value instanceof Float) {
    143            instruction = new PUSH(cp, value.floatValue()).instruction;
    144        } else if (value instanceof Long) {
    145            instruction = new PUSH(cp, value.longValue()).instruction;
    146        } else {
    147            throw new ClassGenException("What's this: " + value);
    148        }
    149    }
    150
    151
    152    /**
    153     * creates a push object from a Character value. Warning: Make sure not to attempt to allow
    154     * autoboxing to create this value parameter, as an alternative constructor will be called
    155     *
    156     * @param cp Constant pool
    157     * @param value to be pushed
    158     */
    159    public PUSH(final ConstantPoolGen cp, final Character value) {
    160        this(cp, value.charValue());
    161    }
    162
    163
    164    /**
    165     * @param cp Constant pool
    166     * @param value to be pushed
    167     */
    168    public PUSH(final ConstantPoolGen cp, final Boolean value) {
    169        this(cp, value.booleanValue());
    170    }
    171
    172
    173    @Override
    174    public InstructionList getInstructionList() {
    175        return new InstructionList(instruction);
    176    }
    177
    178
    179    public Instruction getInstruction() {
    180        return instruction;
    181    }
    182
    183
    184    /**
    185     * @return mnemonic for instruction
    186     */
    187    @Override
    188    public String toString() {
    189        return instruction + " (PUSH)";
    190    }
    191}