summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/CheckCastIterator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/bytecode/CheckCastIterator.java')
-rw-r--r--src/cuchaz/enigma/bytecode/CheckCastIterator.java150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/bytecode/CheckCastIterator.java b/src/cuchaz/enigma/bytecode/CheckCastIterator.java
new file mode 100644
index 0000000..7ed5d7f
--- /dev/null
+++ b/src/cuchaz/enigma/bytecode/CheckCastIterator.java
@@ -0,0 +1,150 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import java.util.Iterator;
14
15import javassist.bytecode.BadBytecode;
16import javassist.bytecode.CodeAttribute;
17import javassist.bytecode.CodeIterator;
18import javassist.bytecode.ConstPool;
19import javassist.bytecode.Descriptor;
20import javassist.bytecode.Opcode;
21import cuchaz.enigma.bytecode.CheckCastIterator.CheckCast;
22import cuchaz.enigma.mapping.ClassEntry;
23import cuchaz.enigma.mapping.MethodEntry;
24
25public class CheckCastIterator implements Iterator<CheckCast>
26{
27 public static class CheckCast
28 {
29 public String className;
30 public MethodEntry prevMethodEntry;
31
32 public CheckCast( String className, MethodEntry prevMethodEntry )
33 {
34 this.className = className;
35 this.prevMethodEntry = prevMethodEntry;
36 }
37 }
38
39 private ConstPool m_constants;
40 private CodeAttribute m_attribute;
41 private CodeIterator m_iter;
42 private CheckCast m_next;
43
44 public CheckCastIterator( CodeAttribute codeAttribute )
45 throws BadBytecode
46 {
47 m_constants = codeAttribute.getConstPool();
48 m_attribute = codeAttribute;
49 m_iter = m_attribute.iterator();
50
51 m_next = getNext();
52 }
53
54 @Override
55 public boolean hasNext( )
56 {
57 return m_next != null;
58 }
59
60 @Override
61 public CheckCast next( )
62 {
63 CheckCast out = m_next;
64 try
65 {
66 m_next = getNext();
67 }
68 catch( BadBytecode ex )
69 {
70 throw new Error( ex );
71 }
72 return out;
73 }
74
75 @Override
76 public void remove( )
77 {
78 throw new UnsupportedOperationException();
79 }
80
81 private CheckCast getNext( )
82 throws BadBytecode
83 {
84 int prevPos = 0;
85 while( m_iter.hasNext() )
86 {
87 int pos = m_iter.next();
88 int opcode = m_iter.byteAt( pos );
89 switch( opcode )
90 {
91 case Opcode.CHECKCAST:
92
93 // get the type of this op code (next two bytes are a classinfo index)
94 MethodEntry prevMethodEntry = getMethodEntry( prevPos );
95 if( prevMethodEntry != null )
96 {
97 return new CheckCast(
98 m_constants.getClassInfo( m_iter.s16bitAt( pos + 1 ) ),
99 prevMethodEntry
100 );
101 }
102 break;
103 }
104 prevPos = pos;
105 }
106 return null;
107 }
108
109 private MethodEntry getMethodEntry( int pos )
110 {
111 switch( m_iter.byteAt( pos ) )
112 {
113 case Opcode.INVOKEVIRTUAL:
114 case Opcode.INVOKESTATIC:
115 case Opcode.INVOKEDYNAMIC:
116 case Opcode.INVOKESPECIAL:
117 {
118 int index = m_iter.s16bitAt( pos + 1 );
119 return new MethodEntry(
120 new ClassEntry( Descriptor.toJvmName( m_constants.getMethodrefClassName( index ) ) ),
121 m_constants.getMethodrefName( index ),
122 m_constants.getMethodrefType( index )
123 );
124 }
125
126 case Opcode.INVOKEINTERFACE:
127 {
128 int index = m_iter.s16bitAt( pos + 1 );
129 return new MethodEntry(
130 new ClassEntry( Descriptor.toJvmName( m_constants.getInterfaceMethodrefClassName( index ) ) ),
131 m_constants.getInterfaceMethodrefName( index ),
132 m_constants.getInterfaceMethodrefType( index )
133 );
134 }
135 }
136 return null;
137 }
138
139 public Iterable<CheckCast> casts( )
140 {
141 return new Iterable<CheckCast>( )
142 {
143 @Override
144 public Iterator<CheckCast> iterator( )
145 {
146 return CheckCastIterator.this;
147 }
148 };
149 }
150}