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