1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.classfile;
  23 
  24 import java.io.DataInput;
  25 import java.io.DataOutputStream;
  26 import java.io.IOException;
  27 
  28 import com.sun.org.apache.bcel.internal.Const;
  29 
  30 /**
  31  * This class represents a stack map attribute used for
  32  * preverification of Java classes for the <a
  33  * href="https://www.oracle.com/java/technologies/javameoverview.html">Java Platform, Micro Edition</a>
  34  * (Java ME). This attribute is used by the <a
  35  * href="https://www.oracle.com/technetwork/java/embedded/javame/java-mobile/kvmwp-150240.pdf">KVM</a> 
  36  * and contained within the Code attribute of a method. See CLDC specification
  37  * 5.3.1.2
  38  *
  39  * @see     Code
  40  * @see     StackMapEntry
  41  * @see     StackMapType
  42  */
  43 public final class StackMap extends Attribute {
  44 
  45     private StackMapEntry[] map; // Table of stack map entries
  46 
  47 
  48     /*
  49      * @param name_index Index of name
  50      * @param length Content length in bytes
  51      * @param map Table of stack map entries
  52      * @param constant_pool Array of constants
  53      */
  54     public StackMap(final int name_index, final int length, final StackMapEntry[] map, final ConstantPool constant_pool) {
  55         super(Const.ATTR_STACK_MAP, name_index, length, constant_pool);
  56         this.map = map;
  57     }
  58 
  59 
  60     /**
  61      * Construct object from input stream.
  62      *
  63      * @param name_index Index of name
  64      * @param length Content length in bytes
  65      * @param input Input stream
  66      * @param constant_pool Array of constants
  67      * @throws IOException
  68      */
  69     StackMap(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
  70         this(name_index, length, (StackMapEntry[]) null, constant_pool);
  71         final int map_length = input.readUnsignedShort();
  72         map = new StackMapEntry[map_length];
  73         for (int i = 0; i < map_length; i++) {
  74             map[i] = new StackMapEntry(input, constant_pool);
  75         }
  76     }
  77 
  78 
  79     /**
  80      * Dump stack map table attribute to file stream in binary format.
  81      *
  82      * @param file Output file stream
  83      * @throws IOException
  84      */
  85     @Override
  86     public void dump( final DataOutputStream file ) throws IOException {
  87         super.dump(file);
  88         file.writeShort(map.length);
  89         for (final StackMapEntry entry : map) {
  90             entry.dump(file);
  91         }
  92     }
  93 
  94 
  95     /**
  96      * @return Array of stack map entries
  97      */
  98     public StackMapEntry[] getStackMap() {
  99         return map;
 100     }
 101 
 102 
 103     /**
 104      * @param map Array of stack map entries
 105      */
 106     public void setStackMap( final StackMapEntry[] map ) {
 107         this.map = map;
 108         int len = 2; // Length of 'number_of_entries' field prior to the array of stack maps
 109         for (final StackMapEntry element : map) {
 110             len += element.getMapEntrySize();
 111         }
 112         setLength(len);
 113     }
 114 
 115 
 116     /**
 117      * @return String representation.
 118      */
 119     @Override
 120     public String toString() {
 121         final StringBuilder buf = new StringBuilder("StackMap(");
 122         for (int i = 0; i < map.length; i++) {
 123             buf.append(map[i]);
 124             if (i < map.length - 1) {
 125                 buf.append(", ");
 126             }
 127         }
 128         buf.append(')');
 129         return buf.toString();
 130     }
 131 
 132 
 133     /**
 134      * @return deep copy of this attribute
 135      */
 136     @Override
 137     public Attribute copy( final ConstantPool _constant_pool ) {
 138         final StackMap c = (StackMap) clone();
 139         c.map = new StackMapEntry[map.length];
 140         for (int i = 0; i < map.length; i++) {
 141             c.map[i] = map[i].copy();
 142         }
 143         c.setConstantPool(_constant_pool);
 144         return c;
 145     }
 146 
 147 
 148     /**
 149      * Called by objects that are traversing the nodes of the tree implicitely
 150      * defined by the contents of a Java class. I.e., the hierarchy of methods,
 151      * fields, attributes, etc. spawns a tree of objects.
 152      *
 153      * @param v Visitor object
 154      */
 155     @Override
 156     public void accept( final Visitor v ) {
 157         v.visitStackMap(this);
 158     }
 159 
 160 
 161     public int getMapLength() {
 162         return map == null ? 0 : map.length;
 163     }
 164 }