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