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.util.ByteSequence; 024 025/** 026 * IINC - Increment local variable by constant 027 * 028 * @version $Id: IINC.java 1812166 2017-10-13 23:48:11Z ggregory $ 029 */ 030public class IINC extends LocalVariableInstruction { 031 032 private boolean wide; 033 private int c; 034 035 036 /** 037 * Empty constructor needed for Instruction.readInstruction. 038 * Not to be used otherwise. 039 */ 040 IINC() { 041 } 042 043 044 /** 045 * @param n index of local variable 046 * @param c increment factor 047 */ 048 public IINC(final int n, final int c) { 049 super(); // Default behaviour of LocalVariableInstruction causes error 050 super.setOpcode(org.apache.bcel.Const.IINC); 051 super.setLength((short) 3); 052 setIndex(n); // May set wide as side effect 053 setIncrement(c); 054 } 055 056 057 /** 058 * Dump instruction as byte code to stream out. 059 * @param out Output stream 060 */ 061 @Override 062 public void dump( final DataOutputStream out ) throws IOException { 063 if (wide) { 064 out.writeByte(org.apache.bcel.Const.WIDE); 065 } 066 out.writeByte(super.getOpcode()); 067 if (wide) { 068 out.writeShort(super.getIndex()); 069 out.writeShort(c); 070 } else { 071 out.writeByte(super.getIndex()); 072 out.writeByte(c); 073 } 074 } 075 076 077 private void setWide() { 078 wide = super.getIndex() > org.apache.bcel.Const.MAX_BYTE; 079 if (c > 0) { 080 wide = wide || (c > Byte.MAX_VALUE); 081 } else { 082 wide = wide || (c < Byte.MIN_VALUE); 083 } 084 if (wide) { 085 super.setLength(6); // wide byte included 086 } else { 087 super.setLength(3); 088 } 089 } 090 091 092 /** 093 * Read needed data (e.g. index) from file. 094 */ 095 @Override 096 protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { 097 this.wide = wide; 098 if (wide) { 099 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 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 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 */ 135 public final int getIncrement() { 136 return c; 137 } 138 139 140 /** 141 * Set increment factor. 142 */ 143 public final void setIncrement( final int c ) { 144 this.c = c; 145 setWide(); 146 } 147 148 149 /** @return int type 150 */ 151 @Override 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 166 public void accept( final Visitor v ) { 167 v.visitLocalVariableInstruction(this); 168 v.visitIINC(this); 169 } 170}