View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  
24  import org.apache.bcel.Const;
25  import org.apache.bcel.util.ByteSequence;
26  
27  /**
28   * IINC - Increment local variable by constant
29   */
30  public class IINC extends LocalVariableInstruction {
31  
32      private boolean wide;
33      private int c;
34  
35      /**
36       * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
37       */
38      IINC() {
39      }
40  
41      /**
42       * @param n index of local variable
43       * @param c increment factor
44       */
45      public IINC(final int n, final int c) {
46          // Default behavior of LocalVariableInstruction causes error
47          super.setOpcode(Const.IINC);
48          super.setLength((short) 3);
49          setIndex(n); // May set wide as side effect
50          setIncrement(c);
51      }
52  
53      /**
54       * Calls corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
55       * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last.
56       *
57       * @param v Visitor object
58       */
59      @Override
60      public void accept(final Visitor v) {
61          v.visitLocalVariableInstruction(this);
62          v.visitIINC(this);
63      }
64  
65      /**
66       * Dumps instruction as byte code to stream out.
67       *
68       * @param out Output stream
69       */
70      @Override
71      public void dump(final DataOutputStream out) throws IOException {
72          if (wide) {
73              out.writeByte(Const.WIDE);
74          }
75          out.writeByte(super.getOpcode());
76          if (wide) {
77              out.writeShort(super.getIndex());
78              out.writeShort(c);
79          } else {
80              out.writeByte(super.getIndex());
81              out.writeByte(c);
82          }
83      }
84  
85      /**
86       * @return increment factor
87       */
88      public final int getIncrement() {
89          return c;
90      }
91  
92      /**
93       * @return int type
94       */
95      @Override
96      public Type getType(final ConstantPoolGen cp) {
97          return Type.INT;
98      }
99  
100     /**
101      * Reads needed data (for example index) from file.
102      */
103     @Override
104     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
105         this.wide = wide;
106         if (wide) {
107             super.setLength(6);
108             super.setIndexOnly(bytes.readUnsignedShort());
109             c = bytes.readShort();
110         } else {
111             super.setLength(3);
112             super.setIndexOnly(bytes.readUnsignedByte());
113             c = bytes.readByte();
114         }
115     }
116 
117     /**
118      * Sets increment factor.
119      */
120     public final void setIncrement(final int c) {
121         this.c = c;
122         setWide();
123     }
124 
125     /**
126      * Sets index of local variable.
127      */
128     @Override
129     public final void setIndex(final int n) {
130         if (n < 0) {
131             throw new ClassGenException("Negative index value: " + n);
132         }
133         super.setIndexOnly(n);
134         setWide();
135     }
136 
137     private void setWide() {
138         wide = super.getIndex() > Const.MAX_BYTE;
139         if (c > 0) {
140             wide = wide || c > Byte.MAX_VALUE;
141         } else {
142             wide = wide || c < Byte.MIN_VALUE;
143         }
144         if (wide) {
145             super.setLength(6); // wide byte included
146         } else {
147             super.setLength(3);
148         }
149     }
150 
151     /**
152      * Returns mnemonic for instruction.
153      *
154      * @return mnemonic for instruction.
155      */
156     @Override
157     public String toString(final boolean verbose) {
158         return super.toString(verbose) + " " + c;
159     }
160 }