1 package serp.bytecode.lowlevel;
2
3 import java.io.*;
4
5
6
7
8
9
10
11
12 public class ConstantPoolTable {
13 private byte[] _bytecode = null;
14 private int[] _table = null;
15 private int _idx = 0;
16
17
18
19
20 public ConstantPoolTable(byte[] b) {
21 _bytecode = b;
22 _table = new int[readUnsignedShort(b, 8)];
23 _idx = parse(b, _table);
24 }
25
26
27
28
29 public ConstantPoolTable(InputStream in) throws IOException {
30 this(toByteArray(in));
31 }
32
33
34
35
36
37 public static int getEndIndex(byte[] b) {
38 return parse(b, null);
39 }
40
41
42
43
44 private static int parse(byte[] b, int[] table) {
45
46
47 int entries = (table == null) ? readUnsignedShort(b, 8) : table.length;
48 int idx = 10;
49 for (int i = 1; i < entries; i++) {
50 if (table != null)
51 table[i] = idx + 1;
52
53 switch (b[idx]) {
54 case 1:
55 idx += (3 + readUnsignedShort(b, idx + 1));
56 break;
57 case 3:
58 case 4:
59 case 9:
60 case 10:
61 case 11:
62 case 12:
63 idx += 5;
64 break;
65 case 5:
66 case 6:
67 idx += 9;
68 i++;
69 break;
70 default:
71 idx += 3;
72 }
73 }
74 return idx;
75 }
76
77
78
79
80 public static int readByte(byte[] b, int idx) {
81 return b[idx] & 0xFF;
82 }
83
84
85
86
87 public static int readUnsignedShort(byte[] b, int idx) {
88 return (readByte(b, idx) << 8) | readByte(b, idx + 1);
89 }
90
91
92
93
94 public static int readInt(byte[] b, int idx) {
95 return (readByte(b, idx) << 24) | (readByte(b, idx + 1) << 16)
96 | (readByte(b, idx + 2) << 8) | readByte(b, idx + 3);
97 }
98
99
100
101
102 public static long readLong(byte[] b, int idx) {
103 return (readInt(b, idx) << 32) | readInt(b, idx + 4);
104 }
105
106
107
108
109 public static String readString(byte[] b, int idx) {
110 int len = readUnsignedShort(b, idx);
111 try {
112 return new String(b, idx + 2, len, "UTF-8");
113 } catch (UnsupportedEncodingException uee) {
114 throw new ClassFormatError(uee.toString());
115 }
116 }
117
118
119
120
121 private static byte[] toByteArray(InputStream in) throws IOException {
122 ByteArrayOutputStream bout = new ByteArrayOutputStream();
123 byte[] buf = new byte[1024];
124 for (int r; (r = in.read(buf)) != -1; bout.write(buf, 0, r));
125 return bout.toByteArray();
126 }
127
128
129
130
131 public int getEndIndex() {
132 return _idx;
133 }
134
135
136
137
138 public int get(int idx) {
139 return _table[idx];
140 }
141
142
143
144
145 public int readByte(int idx) {
146 return readByte(_bytecode, idx);
147 }
148
149
150
151
152 public int readUnsignedShort(int idx) {
153 return readUnsignedShort(_bytecode, idx);
154 }
155
156
157
158
159 public int readInt(int idx) {
160 return readInt(_bytecode, idx);
161 }
162
163
164
165
166 public long readLong(int idx) {
167 return readLong(_bytecode, idx);
168 }
169
170
171
172
173 public String readString(int idx) {
174 return readString(_bytecode, idx);
175 }
176 }