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