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;
023import java.util.Arrays;
024import java.util.Iterator;
025import java.util.stream.Stream;
026
027import org.apache.bcel.Const;
028
029// The new table is used when generic types are about...
030
031//LocalVariableTable_attribute {
032//       u2 attribute_name_index;
033//       u4 attribute_length;
034//       u2 local_variable_table_length;
035//       {  u2 start_pc;
036//          u2 length;
037//          u2 name_index;
038//          u2 descriptor_index;
039//          u2 index;
040//       } local_variable_table[local_variable_table_length];
041//     }
042
043//LocalVariableTypeTable_attribute {
044//    u2 attribute_name_index;
045//    u4 attribute_length;
046//    u2 local_variable_type_table_length;
047//    {
048//      u2 start_pc;
049//      u2 length;
050//      u2 name_index;
051//      u2 signature_index;
052//      u2 index;
053//    } localVariableTypeTable[local_variable_type_table_length];
054//  }
055// J5TODO: Needs some testing !
056
057/**
058 * @since 6.0
059 */
060public class LocalVariableTypeTable extends Attribute implements Iterable<LocalVariable> {
061
062    private LocalVariable[] localVariableTypeTable; // variables
063
064    LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException {
065        this(nameIdx, len, (LocalVariable[]) null, cpool);
066
067        final int localVariableTypeTableLength = input.readUnsignedShort();
068        localVariableTypeTable = new LocalVariable[localVariableTypeTableLength];
069
070        for (int i = 0; i < localVariableTypeTableLength; i++) {
071            localVariableTypeTable[i] = new LocalVariable(input, cpool);
072        }
073    }
074
075    public LocalVariableTypeTable(final int name_index, final int length, final LocalVariable[] local_variable_table, final ConstantPool constant_pool) {
076        super(Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool);
077        this.localVariableTypeTable = local_variable_table;
078    }
079
080    public LocalVariableTypeTable(final LocalVariableTypeTable c) {
081        this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), c.getConstantPool());
082    }
083
084    @Override
085    public void accept(final Visitor v) {
086        v.visitLocalVariableTypeTable(this);
087    }
088
089    /**
090     * @return deep copy of this attribute
091     */
092    @Override
093    public Attribute copy(final ConstantPool constant_pool) {
094        final LocalVariableTypeTable c = (LocalVariableTypeTable) clone();
095
096        c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length];
097        Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy());
098        c.setConstantPool(constant_pool);
099        return c;
100    }
101
102    @Override
103    public final void dump(final DataOutputStream file) throws IOException {
104        super.dump(file);
105        file.writeShort(localVariableTypeTable.length);
106        for (final LocalVariable variable : localVariableTypeTable) {
107            variable.dump(file);
108        }
109    }
110
111    public final LocalVariable getLocalVariable(final int index) {
112        for (final LocalVariable variable : localVariableTypeTable) {
113            if (variable.getIndex() == index) {
114                return variable;
115            }
116        }
117
118        return null;
119    }
120
121    public final LocalVariable[] getLocalVariableTypeTable() {
122        return localVariableTypeTable;
123    }
124
125    public final int getTableLength() {
126        return localVariableTypeTable == null ? 0 : localVariableTypeTable.length;
127    }
128
129    @Override
130    public Iterator<LocalVariable> iterator() {
131        return Stream.of(localVariableTypeTable).iterator();
132    }
133
134    public final void setLocalVariableTable(final LocalVariable[] local_variable_table) {
135        this.localVariableTypeTable = local_variable_table;
136    }
137
138    /**
139     * @return String representation.
140     */
141    @Override
142    public final String toString() {
143        final StringBuilder buf = new StringBuilder();
144
145        for (int i = 0; i < localVariableTypeTable.length; i++) {
146            buf.append(localVariableTypeTable[i].toStringShared(true));
147
148            if (i < localVariableTypeTable.length - 1) {
149                buf.append('\n');
150            }
151        }
152
153        return buf.toString();
154    }
155}