    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.classfile;
    019
    020import java.io.DataInput;
    021import java.io.DataOutputStream;
    022import java.io.IOException;
    023
    024import org.apache.bcel.Const;
    025
    026/**
    027 * This class represents the type of a local variable or item on stack
    028 * used in the StackMap entries.
    029 *
    030 * @version $Id: StackMapType.java 1749603 2016-06-21 20:50:19Z ggregory $
    031 * @see     StackMapEntry
    032 * @see     StackMap
    033 * @see     Const
    034 */
    035public final class StackMapType implements Cloneable {
    036
    037    private byte type;
    038    private int index = -1; // Index to CONSTANT_Class or offset
    039    private ConstantPool constant_pool;
    040
    041
    042    /**
    043     * Construct object from file stream.
    044     * @param file Input stream
    045     * @throws IOException
    046     */
    047    StackMapType(final DataInput file, final ConstantPool constant_pool) throws IOException {
    048        this(file.readByte(), -1, constant_pool);
    049        if (hasIndex()) {
    050            this.index = file.readShort();
    051        }
    052        this.constant_pool = constant_pool;
    053    }
    054
    055
    056    /**
    057     * @param type type tag as defined in the Constants interface
    058     * @param index index to constant pool, or byte code offset
    059     */
    060    public StackMapType(final byte type, final int index, final ConstantPool constant_pool) {
    061        if ((type < Const.ITEM_Bogus) || (type > Const.ITEM_NewObject)) {
    062            throw new RuntimeException("Illegal type for StackMapType: " + type);
    063        }
    064        this.type = type;
    065        this.index = index;
    066        this.constant_pool = constant_pool;
    067    }
    068
    069
    070    public void setType( final byte t ) {
    071        if ((t < Const.ITEM_Bogus) || (t > Const.ITEM_NewObject)) {
    072            throw new RuntimeException("Illegal type for StackMapType: " + t);
    073        }
    074        type = t;
    075    }
    076
    077
    078    public byte getType() {
    079        return type;
    080    }
    081
    082
    083    public void setIndex( final int t ) {
    084        index = t;
    085    }
    086
    087
    088    /** @return index to constant pool if type == ITEM_Object, or offset
    089     * in byte code, if type == ITEM_NewObject, and -1 otherwise
    090     */
    091    public int getIndex() {
    092        return index;
    093    }
    094
    095
    096    /**
    097     * Dump type entries to file.
    098     *
    099     * @param file Output file stream
    100     * @throws IOException
    101     */
    102    public final void dump( final DataOutputStream file ) throws IOException {
    103        file.writeByte(type);
    104        if (hasIndex()) {
    105            file.writeShort(getIndex());
    106        }
    107    }
    108
    109
    110    /** @return true, if type is either ITEM_Object or ITEM_NewObject
    111     */
    112    public final boolean hasIndex() {
    113        return type == Const.ITEM_Object || type == Const.ITEM_NewObject;
    114    }
    115
    116
    117    private String printIndex() {
    118        if (type == Const.ITEM_Object) {
    119            if (index < 0) {
    120                return ", class=<unknown>";
    121            }
    122            return ", class=" + constant_pool.constantToString(index, Const.CONSTANT_Class);
    123        } else if (type == Const.ITEM_NewObject) {
    124            return ", offset=" + index;
    125        } else {
    126            return "";
    127        }
    128    }
    129
    130
    131    /**
    132     * @return String representation
    133     */
    134    @Override
    135    public final String toString() {
    136        return "(type=" + Const.getItemName(type) + printIndex() + ")";
    137    }
    138
    139
    140    /**
    141     * @return deep copy of this object
    142     */
    143    public StackMapType copy() {
    144        try {
    145            return (StackMapType) clone();
    146        } catch (final CloneNotSupportedException e) {
    147            // TODO should this throw?
    148        }
    149        return null;
    150    }
    151
    152
    153    /**
    154     * @return Constant pool used by this object.
    155     */
    156    public final ConstantPool getConstantPool() {
    157        return constant_pool;
    158    }
    159
    160
    161    /**
    162     * @param constant_pool Constant pool to be used for this object.
    163     */
    164    public final void setConstantPool( final ConstantPool constant_pool ) {
    165        this.constant_pool = constant_pool;
    166    }
    167}