21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.internal.jimage;
27
28 import java.io.UTFDataFormatException;
29 import java.nio.ByteBuffer;
30 import java.util.Objects;
31
32 /**
33 * @implNote This class needs to maintain JDK 8 source compatibility.
34 *
35 * It is used internally in the JDK to implement jimage/jrtfs access,
36 * but also compiled and delivered as part of the jrtfs.jar to support access
37 * to the jimage file provided by the shipped JDK by tools running on JDK 8.
38 */
39 public class ImageStringsReader implements ImageStrings {
40 public static final int HASH_MULTIPLIER = 0x01000193;
41 private final BasicImageReader reader;
42
43 ImageStringsReader(BasicImageReader reader) {
44 this.reader = Objects.requireNonNull(reader);
45 }
46
47 @Override
48 public String get(int offset) {
49 return reader.getString(offset);
50 }
51
52 @Override
53 public int add(final String string) {
54 throw new InternalError("Can not add strings at runtime");
55 }
56
57 private static int hashCode(byte[] bytes, int offset, int count, int seed) {
58 Objects.requireNonNull(bytes);
59
60 if (offset < 0 || count < 0 || offset > bytes.length - count) {
61 throw new IndexOutOfBoundsException("offset=" + offset + ", count=" + count);
62 }
63
64 int limit = offset + count;
65
66 if (limit < 0 || limit > bytes.length) {
67 throw new IndexOutOfBoundsException("limit=" + limit);
68 }
69
70 for (int i = offset; i < limit; i++) {
71 seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
72 }
73
74 return seed & 0x7FFFFFFF;
75 }
76
77 public static int hashCode(byte[] bytes, int seed) {
78 return hashCode(bytes, 0, bytes.length, seed);
79 }
80
81 public static int hashCode(byte[] bytes) {
82 return hashCode(bytes, 0, bytes.length, HASH_MULTIPLIER);
83 }
84
85 public static int hashCode(String string, int seed) {
86 return hashCode(mutf8FromString(string), seed);
87 }
88
89 public static int hashCode(String string) {
90 return hashCode(mutf8FromString(string), HASH_MULTIPLIER);
91 }
92
93 static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
94 int length = 0;
95
96 for (int i = offset; i < offset + count; i++) {
97 byte ch = bytes[i];
98
99 if (ch == 0) {
100 break;
101 }
102
103 if ((ch & 0xC0) != 0x80) {
104 length++;
105 }
106 }
107
108 return length;
109 }
110
162 }
163
164 static int charsFromByteBufferLength(ByteBuffer buffer) {
165 int length = 0;
166
167 while(buffer.hasRemaining()) {
168 byte ch = buffer.get();
169
170 if (ch == 0) {
171 return length;
172 }
173
174 if ((ch & 0xC0) != 0x80) {
175 length++;
176 }
177 }
178
179 throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
180 }
181
182 static void charsFromByteBuffer(char chars[], ByteBuffer buffer) {
183 int j = 0;
184
185 while(buffer.hasRemaining()) {
186 byte ch = buffer.get();
187
188 if (ch == 0) {
189 return;
190 }
191
192 boolean is_unicode = (ch & 0x80) != 0;
193 int uch = ch & 0x7F;
194
195 if (is_unicode) {
196 int mask = 0x40;
197
198 while ((uch & mask) != 0) {
199 ch = buffer.get();
200
201 if ((ch & 0xC0) != 0x80) {
202 throw new InternalError("Bad continuation in " +
211 if ((uch & 0xFFFF) != uch) {
212 throw new InternalError("UTF-32 char in modified UTF-8 " +
213 "byte sequence: " + uch);
214 }
215
216 chars[j++] = (char)uch;
217 }
218
219 throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
220 }
221
222 public static String stringFromByteBuffer(ByteBuffer buffer) {
223 int length = charsFromByteBufferLength(buffer);
224 buffer.rewind();
225 char[] chars = new char[length];
226 charsFromByteBuffer(chars, buffer);
227
228 return new String(chars);
229 }
230
231 static int mutf8FromCharsLength(char chars[]) {
232 int length = 0;
233
234 for (char ch : chars) {
235 int uch = ch & 0xFFFF;
236
237 if ((uch & ~0x7F) != 0) {
238 int mask = ~0x3F;
239 int n = 0;
240
241 do {
242 n++;
243 uch >>= 6;
244 mask >>= 1;
245 } while ((uch & mask) != 0);
246
247 length += n + 1;
248 } else if (uch == 0) {
249 length += 2;
250 } else {
251 length++;
252 }
253 }
254
255 return length;
256 }
257
258 static void mutf8FromChars(byte[] bytes, int offset, char chars[]) {
259 int j = offset;
260 byte[] buffer = new byte[8];
261
262 for (char ch : chars) {
263 int uch = ch & 0xFFFF;
264
265 if ((uch & ~0x7F) != 0) {
266 int mask = ~0x3F;
267 int n = 0;
268
269 do {
270 buffer[n++] = (byte)(0x80 | (uch & 0x3F));
271 uch >>= 6;
272 mask >>= 1;
273 } while ((uch & mask) != 0);
274
275 buffer[n] = (byte)((mask << 1) | uch);
276
277 do {
278 bytes[j++] = buffer[n--];
279 } while (0 <= n);
280 } else if (uch == 0) {
281 bytes[j++] = (byte)0xC0;
282 bytes[j++] = (byte)0x80;
283 } else {
284 bytes[j++] = (byte)uch;
285 }
286 }
287 }
288
289 public static byte[] mutf8FromString(String string) {
290 char[] chars = string.toCharArray();
291 int length = mutf8FromCharsLength(chars);
292 byte[] bytes = new byte[length];
293 mutf8FromChars(bytes, 0, chars);
294
295 return bytes;
296 }
297 }
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.internal.jimage;
27
28 import java.io.UTFDataFormatException;
29 import java.nio.ByteBuffer;
30 import java.util.Objects;
31
32 /**
33 * @implNote This class needs to maintain JDK 8 source compatibility.
34 *
35 * It is used internally in the JDK to implement jimage/jrtfs access,
36 * but also compiled and delivered as part of the jrtfs.jar to support access
37 * to the jimage file provided by the shipped JDK by tools running on JDK 8.
38 */
39 public class ImageStringsReader implements ImageStrings {
40 public static final int HASH_MULTIPLIER = 0x01000193;
41 public static final int POSITIVE_MASK = 0x7FFFFFFF;
42
43 private final BasicImageReader reader;
44
45 ImageStringsReader(BasicImageReader reader) {
46 this.reader = Objects.requireNonNull(reader);
47 }
48
49 @Override
50 public String get(int offset) {
51 return reader.getString(offset);
52 }
53
54 @Override
55 public int add(final String string) {
56 throw new InternalError("Can not add strings at runtime");
57 }
58
59 public static int hashCode(String string) {
60 return hashCode(string, HASH_MULTIPLIER);
61 }
62
63 public static int hashCode(String string, int seed) {
64 return unmaskedHashCode(string, seed) & POSITIVE_MASK;
65 }
66
67 public static int hashCode(String module, String string) {
68 return hashCode(module, string, HASH_MULTIPLIER);
69 }
70
71 public static int hashCode(String module, String string, int seed) {
72 seed = unmaskedHashCode("/", seed);
73 seed = unmaskedHashCode(module, seed);
74 seed = unmaskedHashCode("/", seed);
75 seed = unmaskedHashCode(string, seed);
76 return seed & POSITIVE_MASK;
77 }
78
79 public static int unmaskedHashCode(String string, int seed) {
80 int slen = string.length();
81 byte[] buffer = null;
82
83 for (int i = 0; i < slen; i++) {
84 char ch = string.charAt(i);
85 int uch = ch & 0xFFFF;
86
87 if ((uch & ~0x7F) != 0) {
88 if (buffer == null) {
89 buffer = new byte[8];
90 }
91 int mask = ~0x3F;
92 int n = 0;
93
94 do {
95 buffer[n++] = (byte)(0x80 | (uch & 0x3F));
96 uch >>= 6;
97 mask >>= 1;
98 } while ((uch & mask) != 0);
99
100 buffer[n] = (byte)((mask << 1) | uch);
101
102 do {
103 seed = (seed * HASH_MULTIPLIER) ^ (buffer[n--] & 0xFF);
104 } while (0 <= n);
105 } else if (uch == 0) {
106 seed = (seed * HASH_MULTIPLIER) ^ (0xC0);
107 seed = (seed * HASH_MULTIPLIER) ^ (0x80);
108 } else {
109 seed = (seed * HASH_MULTIPLIER) ^ (uch);
110 }
111 }
112 return seed;
113 }
114
115 static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
116 int length = 0;
117
118 for (int i = offset; i < offset + count; i++) {
119 byte ch = bytes[i];
120
121 if (ch == 0) {
122 break;
123 }
124
125 if ((ch & 0xC0) != 0x80) {
126 length++;
127 }
128 }
129
130 return length;
131 }
132
184 }
185
186 static int charsFromByteBufferLength(ByteBuffer buffer) {
187 int length = 0;
188
189 while(buffer.hasRemaining()) {
190 byte ch = buffer.get();
191
192 if (ch == 0) {
193 return length;
194 }
195
196 if ((ch & 0xC0) != 0x80) {
197 length++;
198 }
199 }
200
201 throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
202 }
203
204 static void charsFromByteBuffer(char[] chars, ByteBuffer buffer) {
205 int j = 0;
206
207 while(buffer.hasRemaining()) {
208 byte ch = buffer.get();
209
210 if (ch == 0) {
211 return;
212 }
213
214 boolean is_unicode = (ch & 0x80) != 0;
215 int uch = ch & 0x7F;
216
217 if (is_unicode) {
218 int mask = 0x40;
219
220 while ((uch & mask) != 0) {
221 ch = buffer.get();
222
223 if ((ch & 0xC0) != 0x80) {
224 throw new InternalError("Bad continuation in " +
233 if ((uch & 0xFFFF) != uch) {
234 throw new InternalError("UTF-32 char in modified UTF-8 " +
235 "byte sequence: " + uch);
236 }
237
238 chars[j++] = (char)uch;
239 }
240
241 throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
242 }
243
244 public static String stringFromByteBuffer(ByteBuffer buffer) {
245 int length = charsFromByteBufferLength(buffer);
246 buffer.rewind();
247 char[] chars = new char[length];
248 charsFromByteBuffer(chars, buffer);
249
250 return new String(chars);
251 }
252
253 static int mutf8FromStringLength(String s) {
254 int length = 0;
255 int slen = s.length();
256
257 for (int i = 0; i < slen; i++) {
258 char ch = s.charAt(i);
259 int uch = ch & 0xFFFF;
260
261 if ((uch & ~0x7F) != 0) {
262 int mask = ~0x3F;
263 int n = 0;
264
265 do {
266 n++;
267 uch >>= 6;
268 mask >>= 1;
269 } while ((uch & mask) != 0);
270
271 length += n + 1;
272 } else if (uch == 0) {
273 length += 2;
274 } else {
275 length++;
276 }
277 }
278
279 return length;
280 }
281
282 static void mutf8FromString(byte[] bytes, int offset, String s) {
283 int j = offset;
284 byte[] buffer = null;
285 int slen = s.length();
286
287 for (int i = 0; i < slen; i++) {
288 char ch = s.charAt(i);
289 int uch = ch & 0xFFFF;
290
291 if ((uch & ~0x7F) != 0) {
292 if (buffer == null) {
293 buffer = new byte[8];
294 }
295 int mask = ~0x3F;
296 int n = 0;
297
298 do {
299 buffer[n++] = (byte)(0x80 | (uch & 0x3F));
300 uch >>= 6;
301 mask >>= 1;
302 } while ((uch & mask) != 0);
303
304 buffer[n] = (byte)((mask << 1) | uch);
305
306 do {
307 bytes[j++] = buffer[n--];
308 } while (0 <= n);
309 } else if (uch == 0) {
310 bytes[j++] = (byte)0xC0;
311 bytes[j++] = (byte)0x80;
312 } else {
313 bytes[j++] = (byte)uch;
314 }
315 }
316 }
317
318 public static byte[] mutf8FromString(String string) {
319 int length = mutf8FromStringLength(string);
320 byte[] bytes = new byte[length];
321 mutf8FromString(bytes, 0, string);
322
323 return bytes;
324 }
325 }
|