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 */
018 package org.apache.bcel.classfile;
019
020 import java.io.DataInputStream;
021 import java.io.DataOutputStream;
022 import java.io.IOException;
023 import java.io.Serializable;
024
025 /**
026 * This class represents a stack map entry recording the types of
027 * local variables and the the of stack items at a given byte code offset.
028 * See CLDC specification �5.3.1.2
029 *
030 * @version $Id: StackMapEntry.java 1152077 2011-07-29 02:29:42Z dbrosius $
031 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
032 * @see StackMap
033 * @see StackMapType
034 */
035 public final class StackMapEntry implements Cloneable, Serializable {
036
037 private static final long serialVersionUID = 1L;
038
039 private int byte_code_offset;
040 private int number_of_locals;
041 private StackMapType[] types_of_locals;
042 private int number_of_stack_items;
043 private StackMapType[] types_of_stack_items;
044 private ConstantPool constant_pool;
045
046
047 /**
048 * Construct object from file stream.
049 * @param file Input stream
050 * @throws IOException
051 */
052 StackMapEntry(DataInputStream file, ConstantPool constant_pool) throws IOException {
053 this(file.readShort(), file.readShort(), null, -1, null, constant_pool);
054 types_of_locals = new StackMapType[number_of_locals];
055 for (int i = 0; i < number_of_locals; i++) {
056 types_of_locals[i] = new StackMapType(file, constant_pool);
057 }
058 number_of_stack_items = file.readShort();
059 types_of_stack_items = new StackMapType[number_of_stack_items];
060 for (int i = 0; i < number_of_stack_items; i++) {
061 types_of_stack_items[i] = new StackMapType(file, constant_pool);
062 }
063 }
064
065
066 public StackMapEntry(int byte_code_offset, int number_of_locals,
067 StackMapType[] types_of_locals, int number_of_stack_items,
068 StackMapType[] types_of_stack_items, ConstantPool constant_pool) {
069 this.byte_code_offset = byte_code_offset;
070 this.number_of_locals = number_of_locals;
071 this.types_of_locals = types_of_locals;
072 this.number_of_stack_items = number_of_stack_items;
073 this.types_of_stack_items = types_of_stack_items;
074 this.constant_pool = constant_pool;
075 }
076
077
078 /**
079 * Dump stack map entry
080 *
081 * @param file Output file stream
082 * @throws IOException
083 */
084 public final void dump( DataOutputStream file ) throws IOException {
085 file.writeShort(byte_code_offset);
086 file.writeShort(number_of_locals);
087 for (int i = 0; i < number_of_locals; i++) {
088 types_of_locals[i].dump(file);
089 }
090 file.writeShort(number_of_stack_items);
091 for (int i = 0; i < number_of_stack_items; i++) {
092 types_of_stack_items[i].dump(file);
093 }
094 }
095
096
097 /**
098 * @return String representation.
099 */
100 @Override
101 public final String toString() {
102 StringBuilder buf = new StringBuilder(64);
103 buf.append("(offset=").append(byte_code_offset);
104 if (number_of_locals > 0) {
105 buf.append(", locals={");
106 for (int i = 0; i < number_of_locals; i++) {
107 buf.append(types_of_locals[i]);
108 if (i < number_of_locals - 1) {
109 buf.append(", ");
110 }
111 }
112 buf.append("}");
113 }
114 if (number_of_stack_items > 0) {
115 buf.append(", stack items={");
116 for (int i = 0; i < number_of_stack_items; i++) {
117 buf.append(types_of_stack_items[i]);
118 if (i < number_of_stack_items - 1) {
119 buf.append(", ");
120 }
121 }
122 buf.append("}");
123 }
124 buf.append(")");
125 return buf.toString();
126 }
127
128
129 public void setByteCodeOffset( int b ) {
130 byte_code_offset = b;
131 }
132
133
134 public int getByteCodeOffset() {
135 return byte_code_offset;
136 }
137
138
139 public void setNumberOfLocals( int n ) {
140 number_of_locals = n;
141 }
142
143
144 public int getNumberOfLocals() {
145 return number_of_locals;
146 }
147
148
149 public void setTypesOfLocals( StackMapType[] t ) {
150 types_of_locals = t;
151 }
152
153
154 public StackMapType[] getTypesOfLocals() {
155 return types_of_locals;
156 }
157
158
159 public void setNumberOfStackItems( int n ) {
160 number_of_stack_items = n;
161 }
162
163
164 public int getNumberOfStackItems() {
165 return number_of_stack_items;
166 }
167
168
169 public void setTypesOfStackItems( StackMapType[] t ) {
170 types_of_stack_items = t;
171 }
172
173
174 public StackMapType[] getTypesOfStackItems() {
175 return types_of_stack_items;
176 }
177
178
179 /**
180 * @return deep copy of this object
181 */
182 public StackMapEntry copy() {
183 try {
184 return (StackMapEntry) clone();
185 } catch (CloneNotSupportedException e) {
186 }
187 return null;
188 }
189
190
191 /**
192 * Called by objects that are traversing the nodes of the tree implicitely
193 * defined by the contents of a Java class. I.e., the hierarchy of methods,
194 * fields, attributes, etc. spawns a tree of objects.
195 *
196 * @param v Visitor object
197 */
198 public void accept( Visitor v ) {
199 v.visitStackMapEntry(this);
200 }
201
202
203 /**
204 * @return Constant pool used by this object.
205 */
206 public final ConstantPool getConstantPool() {
207 return constant_pool;
208 }
209
210
211 /**
212 * @param constant_pool Constant pool to be used for this object.
213 */
214 public final void setConstantPool( ConstantPool constant_pool ) {
215 this.constant_pool = constant_pool;
216 }
217 }