blob: 70ebce7549a966242fb7c3700f2d6f263747e55c [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24package ilib;
25
26class ClassReaderWriter implements RuntimeConstants {
27
28 int codeAttributeIndex;
29 int lineNumberAttributeIndex;
30 int localVarAttributeIndex;
31
32 private final byte[] orig;
33 private final byte[] gen;
34 private final int sectionLength;
35
36 private static final int GROWTH_FACTOR = 2;
37 private static final int SECTIONS = 2;
38 private static final String codeAttributeName = "Code";
39 private static final String lineNumberAttributeName = "LineNumberTable";
40 private static final String localVarAttributeName = "LocalVariableTable";
41
42 private int[] genSectionPos = new int[SECTIONS];
43
44 private int inputPos = 0;
45 private int genPos = 0;
46 private int markPos = 0;
47 private int currentSection = 0;
48
49 private String[] constantPool;
50
51 ClassReaderWriter(byte[] orig) {
52 this.orig = orig;
53 sectionLength = orig.length * GROWTH_FACTOR;
54 gen = new byte[sectionLength * SECTIONS];
55 for (int section = 0; section < SECTIONS; ++section) {
56 genSectionPos[section] = section * sectionLength;
57 }
58 }
59
60 int setSection(int section) {
61 int prevSection = currentSection;
62 genSectionPos[prevSection] = genPos;
63 genPos = genSectionPos[section];
64 currentSection = section;
65 return prevSection;
66 }
67
68 byte[] result() {
69 int section;
70 int totalLength = 0;
71
72 setSection(0); // save current section
73
74 for (section = 0; section < SECTIONS; ++section) {
75 int sectionStart = section * sectionLength;
76 int sectionGenLength = genSectionPos[section] - sectionStart;
77 totalLength += sectionGenLength;
78 }
79
80 byte[] newcf = new byte[totalLength];
81 int written = 0;
82 for (section = 0; section < SECTIONS; ++section) {
83 int sectionStart = section * sectionLength;
84 int sectionGenLength = genSectionPos[section] - sectionStart;
85 System.arraycopy(gen, sectionStart, newcf, written, sectionGenLength);
86 written += sectionGenLength;
87 }
88
89 return newcf;
90 }
91
92 int readU1() {
93 return ((int)orig[inputPos++]) & 0xFF;
94 }
95
96 int readU2() {
97 int res = readU1();
98 return (res << 8) + readU1();
99 }
100
101 short readS2() {
102 int res = readU1();
103 return (short)((res << 8) + readU1());
104 }
105
106 int readU4() {
107 int res = readU2();
108 return (res << 16) + readU2();
109 }
110
111 void writeU1(int val) {
112 gen[genPos++] = (byte)val;
113 }
114
115 void writeU2(int val) {
116 writeU1(val >> 8);
117 writeU1(val & 0xFF);
118 }
119
120 void writeU4(int val) {
121 writeU2(val >> 16);
122 writeU2(val & 0xFFFF);
123 }
124
125 int copyU1() {
126 int value = readU1();
127 writeU1(value);
128 return value;
129 }
130
131 int copyU2() {
132 int value = readU2();
133 writeU2(value);
134 return value;
135 }
136
137 int copyU4() {
138 int value = readU4();
139 writeU4(value);
140 return value;
141 }
142
143 void copy(int count) {
144 for (int i = 0; i < count; ++i) {
145 gen[genPos++] = orig[inputPos++];
146 }
147 }
148
149 void skip(int count) {
150 inputPos += count;
151 }
152
153 byte[] readBytes(int count) {
154 byte[] bytes = new byte[count];
155 for (int i = 0; i < count; ++i) {
156 bytes[i] = orig[inputPos++];
157 }
158 return bytes;
159 }
160
161 void writeBytes(byte[] bytes) {
162 for (int i = 0; i < bytes.length; ++i) {
163 gen[genPos++] = bytes[i];
164 }
165 }
166
167 byte[] inputBytes() {
168 return orig;
169 }
170
171 int inputPosition() {
172 return inputPos;
173 }
174
175 void setInputPosition(int pos) {
176 inputPos = pos;
177 }
178
179 void markLocalPositionStart() {
180 markPos = inputPos;
181 }
182
183 int localPosition() {
184 return inputPos - markPos;
185 }
186
187 void rewind() {
188 setInputPosition(markPos);
189 }
190
191 int generatedPosition() {
192 return genPos;
193 }
194
195 void randomAccessWriteU2(int pos, int val) {
196 int savePos = genPos;
197 genPos = pos;
198 writeU2(val);
199 genPos = savePos;
200 }
201
202 void randomAccessWriteU4(int pos, int val) {
203 int savePos = genPos;
204 genPos = pos;
205 writeU4(val);
206 genPos = savePos;
207 }
208
209 String constantPoolString(int index) {
210 return constantPool[index];
211 }
212
213 void copyConstantPool(int constantPoolCount){
214 // copy const pool
215 constantPool = new String[constantPoolCount];
216 // index zero not in class file
217 for (int i = 1; i < constantPoolCount; ++i) {
218 int tag = readU1();
219 writeU1(tag);
220 switch (tag) {
221 case CONSTANT_CLASS:
222 case CONSTANT_STRING:
223 copy(2);
224 break;
225 case CONSTANT_FIELD:
226 case CONSTANT_METHOD:
227 case CONSTANT_INTERFACEMETHOD:
228 case CONSTANT_INTEGER:
229 case CONSTANT_FLOAT:
230 case CONSTANT_NAMEANDTYPE:
231 copy(4);
232 break;
233 case CONSTANT_LONG:
234 case CONSTANT_DOUBLE:
235 copy(8);
236 ++i; // these take two CP entries - duh!
237 break;
238 case CONSTANT_UTF8:
239 int len = copyU2();
240 byte[] utf8 = readBytes(len);
241 String str = null; // null to shut the compiler up
242 try {
243 str = new String(utf8, "UTF-8");
244 } catch (Exception exc) {
245 throw new Error("CP exception: " + exc);
246 }
247 constantPool[i] = str;
248 if (str.equals(codeAttributeName)) {
249 codeAttributeIndex = i;
250 } else if (str.equals(lineNumberAttributeName)) {
251 lineNumberAttributeIndex = i;
252 } else if (str.equals(localVarAttributeName)) {
253 localVarAttributeIndex = i;
254 }
255 writeBytes(utf8);
256 break;
257 default:
258 throw new Error(i + " unexpected CP tag: " + tag);
259 }
260 }
261 }
262
263}