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}