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