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