• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2009 Eric Lafortune (eric@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      */
TableSwitchInstruction()42     public TableSwitchInstruction() {}
43 
44 
45     /**
46      * Creates a new TableSwitchInstruction with the given arguments.
47      */
TableSwitchInstruction(byte opcode, int defaultOffset, int lowCase, int highCase, int[] jumpOffsets)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      */
copy(TableSwitchInstruction tableSwitchInstruction)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 
shrink()81     public Instruction shrink()
82     {
83         // There aren't any ways to shrink this instruction.
84         return this;
85     }
86 
readInfo(byte[] code, int offset)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 
writeInfo(byte[] code, int offset)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 
length(int offset)129     public int length(int offset)
130     {
131         return 1 + (-(offset+1) & 3) + 12 + (highCase - lowCase + 1) * 4;
132     }
133 
134 
accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)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