Home | History | Annotate | Download | only in instruction
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.classfile.instruction;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.attribute.CodeAttribute;
     25 import proguard.classfile.instruction.visitor.InstructionVisitor;
     26 
     27 /**
     28  * This Instruction represents a simple instruction without variable arguments
     29  * or constant pool references.
     30  *
     31  * @author Eric Lafortune
     32  */
     33 public class TableSwitchInstruction extends SwitchInstruction
     34 {
     35     public int lowCase;
     36     public int highCase;
     37 
     38 
     39     /**
     40      * Creates an uninitialized TableSwitchInstruction.
     41      */
     42     public TableSwitchInstruction() {}
     43 
     44 
     45     /**
     46      * Creates a new TableSwitchInstruction with the given arguments.
     47      */
     48     public TableSwitchInstruction(byte  opcode,
     49                                   int   defaultOffset,
     50                                   int   lowCase,
     51                                   int   highCase,
     52                                   int[] jumpOffsets)
     53     {
     54         this.opcode        = opcode;
     55         this.defaultOffset = defaultOffset;
     56         this.lowCase       = lowCase;
     57         this.highCase      = highCase;
     58         this.jumpOffsets   = jumpOffsets;
     59     }
     60 
     61 
     62     /**
     63      * Copies the given instruction into this instruction.
     64      * @param tableSwitchInstruction the instruction to be copied.
     65      * @return this instruction.
     66      */
     67     public TableSwitchInstruction copy(TableSwitchInstruction tableSwitchInstruction)
     68     {
     69         this.opcode        = tableSwitchInstruction.opcode;
     70         this.defaultOffset = tableSwitchInstruction.defaultOffset;
     71         this.lowCase       = tableSwitchInstruction.lowCase;
     72         this.highCase      = tableSwitchInstruction.highCase;
     73         this.jumpOffsets   = tableSwitchInstruction.jumpOffsets;
     74 
     75         return this;
     76     }
     77 
     78 
     79     // Implementations for Instruction.
     80 
     81     public Instruction shrink()
     82     {
     83         // There aren't any ways to shrink this instruction.
     84         return this;
     85     }
     86 
     87     protected void readInfo(byte[] code, int offset)
     88     {
     89         // Skip up to three padding bytes.
     90         offset += -offset & 3;
     91 
     92         // Read the three 32-bit arguments.
     93         defaultOffset = readInt(code, offset); offset += 4;
     94         lowCase       = readInt(code, offset); offset += 4;
     95         highCase      = readInt(code, offset); offset += 4;
     96 
     97         // Read the jump offsets.
     98         jumpOffsets = new int[highCase - lowCase + 1];
     99 
    100         for (int index = 0; index < jumpOffsets.length; index++)
    101         {
    102             jumpOffsets[index] = readInt(code, offset); offset += 4;
    103         }
    104     }
    105 
    106 
    107     protected void writeInfo(byte[] code, int offset)
    108     {
    109         // Write up to three padding bytes.
    110         while ((offset & 3) != 0)
    111         {
    112             writeByte(code, offset++, 0);
    113         }
    114 
    115         // Write the three 32-bit arguments.
    116         writeInt(code, offset, defaultOffset); offset += 4;
    117         writeInt(code, offset, lowCase);       offset += 4;
    118         writeInt(code, offset, highCase);      offset += 4;
    119 
    120         // Write the jump offsets.
    121         int length = highCase - lowCase + 1;
    122         for (int index = 0; index < length; index++)
    123         {
    124             writeInt(code, offset, jumpOffsets[index]); offset += 4;
    125         }
    126     }
    127 
    128 
    129     public int length(int offset)
    130     {
    131         return 1 + (-(offset+1) & 3) + 12 + (highCase - lowCase + 1) * 4;
    132     }
    133 
    134 
    135     public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)
    136     {
    137         instructionVisitor.visitTableSwitchInstruction(clazz, method, codeAttribute, offset, this);
    138     }
    139 }
    140