001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.generic; 019 020import java.io.DataOutputStream; 021import java.io.IOException; 022 023import org.apache.bcel.Const; 024import org.apache.bcel.util.ByteSequence; 025 026/** 027 * IINC - Increment local variable by constant 028 */ 029public class IINC extends LocalVariableInstruction { 030 031 private boolean wide; 032 private int c; 033 034 /** 035 * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise. 036 */ 037 IINC() { 038 } 039 040 /** 041 * @param n index of local variable 042 * @param c increment factor 043 */ 044 public IINC(final int n, final int c) { 045 // Default behavior of LocalVariableInstruction causes error 046 super.setOpcode(Const.IINC); 047 super.setLength((short) 3); 048 setIndex(n); // May set wide as side effect 049 setIncrement(c); 050 } 051 052 /** 053 * Calls corresponding visitor method(s). The order is: Call visitor methods of implemented interfaces first, then call 054 * methods according to the class hierarchy in descending order, i.e., the most specific visitXXX() call comes last. 055 * 056 * @param v Visitor object 057 */ 058 @Override 059 public void accept(final Visitor v) { 060 v.visitLocalVariableInstruction(this); 061 v.visitIINC(this); 062 } 063 064 /** 065 * Dumps instruction as byte code to stream out. 066 * 067 * @param out Output stream 068 */ 069 @Override 070 public void dump(final DataOutputStream out) throws IOException { 071 if (wide) { 072 out.writeByte(Const.WIDE); 073 } 074 out.writeByte(super.getOpcode()); 075 if (wide) { 076 out.writeShort(super.getIndex()); 077 out.writeShort(c); 078 } else { 079 out.writeByte(super.getIndex()); 080 out.writeByte(c); 081 } 082 } 083 084 /** 085 * @return increment factor 086 */ 087 public final int getIncrement() { 088 return c; 089 } 090 091 /** 092 * @return int type 093 */ 094 @Override 095 public Type getType(final ConstantPoolGen cp) { 096 return Type.INT; 097 } 098 099 /** 100 * Reads needed data (e.g. index) from file. 101 */ 102 @Override 103 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException { 104 this.wide = wide; 105 if (wide) { 106 super.setLength(6); 107 super.setIndexOnly(bytes.readUnsignedShort()); 108 c = bytes.readShort(); 109 } else { 110 super.setLength(3); 111 super.setIndexOnly(bytes.readUnsignedByte()); 112 c = bytes.readByte(); 113 } 114 } 115 116 /** 117 * Sets increment factor. 118 */ 119 public final void setIncrement(final int c) { 120 this.c = c; 121 setWide(); 122 } 123 124 /** 125 * Sets index of local variable. 126 */ 127 @Override 128 public final void setIndex(final int n) { 129 if (n < 0) { 130 throw new ClassGenException("Negative index value: " + n); 131 } 132 super.setIndexOnly(n); 133 setWide(); 134 } 135 136 private void setWide() { 137 wide = super.getIndex() > Const.MAX_BYTE; 138 if (c > 0) { 139 wide = wide || c > Byte.MAX_VALUE; 140 } else { 141 wide = wide || c < Byte.MIN_VALUE; 142 } 143 if (wide) { 144 super.setLength(6); // wide byte included 145 } else { 146 super.setLength(3); 147 } 148 } 149 150 /** 151 * Returns mnemonic for instruction. 152 * 153 * @return mnemonic for instruction. 154 */ 155 @Override 156 public String toString(final boolean verbose) { 157 return super.toString(verbose) + " " + c; 158 } 159}