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