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       * Constructs an IINC instruction.
43       *
44       * @param n index of local variable.
45       * @param c increment factor.
46       */
47      public IINC(final int n, final int c) {
48          // Default behavior of LocalVariableInstruction causes error
49          super.setOpcode(Const.IINC);
50          super.setLength((short) 3);
51          setIndex(n); // May set wide as side effect
52          setIncrement(c);
53      }
54  
55      /**
56       * Calls corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call
57       * methods according to the class hierarchy in descending order, that is, the most specific visitXXX() call comes last.
58       *
59       * @param v Visitor object.
60       */
61      @Override
62      public void accept(final Visitor v) {
63          v.visitLocalVariableInstruction(this);
64          v.visitIINC(this);
65      }
66  
67      /**
68       * Dumps instruction as byte code to stream out.
69       *
70       * @param out Output stream.
71       */
72      @Override
73      public void dump(final DataOutputStream out) throws IOException {
74          if (wide) {
75              out.writeByte(Const.WIDE);
76          }
77          out.writeByte(super.getOpcode());
78          if (wide) {
79              out.writeShort(super.getIndex());
80              out.writeShort(c);
81          } else {
82              out.writeByte(super.getIndex());
83              out.writeByte(c);
84          }
85      }
86  
87      /**
88       * Gets the increment factor.
89       *
90       * @return increment factor.
91       */
92      public final int getIncrement() {
93          return c;
94      }
95  
96      /**
97       * Gets the int type.
98       *
99       * @return int type.
100      */
101     @Override
102     public Type getType(final ConstantPoolGen cp) {
103         return Type.INT;
104     }
105 
106     /**
107      * Reads needed data (for example index) from file.
108      */
109     @Override
110     protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
111         this.wide = wide;
112         if (wide) {
113             super.setLength(6);
114             super.setIndexOnly(bytes.readUnsignedShort());
115             c = bytes.readShort();
116         } else {
117             super.setLength(3);
118             super.setIndexOnly(bytes.readUnsignedByte());
119             c = bytes.readByte();
120         }
121     }
122 
123     /**
124      * Sets increment factor.
125      *
126      * @param c the increment factor.
127      */
128     public final void setIncrement(final int c) {
129         this.c = c;
130         setWide();
131     }
132 
133     /**
134      * Sets index of local variable.
135      */
136     @Override
137     public final void setIndex(final int n) {
138         if (n < 0) {
139             throw new ClassGenException("Negative index value: " + n);
140         }
141         super.setIndexOnly(n);
142         setWide();
143     }
144 
145     private void setWide() {
146         wide = super.getIndex() > Const.MAX_BYTE;
147         if (c > 0) {
148             wide = wide || c > Byte.MAX_VALUE;
149         } else {
150             wide = wide || c < Byte.MIN_VALUE;
151         }
152         if (wide) {
153             super.setLength(6); // wide byte included
154         } else {
155             super.setLength(3);
156         }
157     }
158 
159     /**
160      * Returns mnemonic for instruction.
161      *
162      * @return mnemonic for instruction.
163      */
164     @Override
165     public String toString(final boolean verbose) {
166         return super.toString(verbose) + " " + c;
167     }
168 }