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