Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java
41159 views
1
/*
2
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
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.nio.charset.StandardCharsets;
31
import java.util.Objects;
32
33
/**
34
* @implNote This class needs to maintain JDK 8 source compatibility.
35
*
36
* It is used internally in the JDK to implement jimage/jrtfs access,
37
* but also compiled and delivered as part of the jrtfs.jar to support access
38
* to the jimage file provided by the shipped JDK by tools running on JDK 8.
39
*/
40
public class ImageStringsReader implements ImageStrings {
41
public static final int HASH_MULTIPLIER = 0x01000193;
42
public static final int POSITIVE_MASK = 0x7FFFFFFF;
43
44
private final BasicImageReader reader;
45
46
ImageStringsReader(BasicImageReader reader) {
47
this.reader = Objects.requireNonNull(reader);
48
}
49
50
@Override
51
public String get(int offset) {
52
return reader.getString(offset);
53
}
54
55
@Override
56
public int match(int offset, String string, int stringOffset) {
57
return reader.match(offset, string, stringOffset);
58
}
59
60
@Override
61
public int add(final String string) {
62
throw new InternalError("Can not add strings at runtime");
63
}
64
65
public static int hashCode(String s) {
66
return hashCode(s, HASH_MULTIPLIER);
67
}
68
69
public static int hashCode(String s, int seed) {
70
return unmaskedHashCode(s, seed) & POSITIVE_MASK;
71
}
72
73
public static int hashCode(String module, String name) {
74
return hashCode(module, name, HASH_MULTIPLIER);
75
}
76
77
public static int hashCode(String module, String name, int seed) {
78
seed = (seed * HASH_MULTIPLIER) ^ ('/');
79
seed = unmaskedHashCode(module, seed);
80
seed = (seed * HASH_MULTIPLIER) ^ ('/');
81
seed = unmaskedHashCode(name, seed);
82
return seed & POSITIVE_MASK;
83
}
84
85
public static int unmaskedHashCode(String s, int seed) {
86
int slen = s.length();
87
byte[] buffer = null;
88
89
for (int i = 0; i < slen; i++) {
90
int uch = s.charAt(i);
91
92
if ((uch & ~0x7F) != 0) {
93
if (buffer == null) {
94
buffer = new byte[8];
95
}
96
int mask = ~0x3F;
97
int n = 0;
98
99
do {
100
buffer[n++] = (byte)(0x80 | (uch & 0x3F));
101
uch >>= 6;
102
mask >>= 1;
103
} while ((uch & mask) != 0);
104
105
buffer[n] = (byte)((mask << 1) | uch);
106
107
do {
108
seed = (seed * HASH_MULTIPLIER) ^ (buffer[n--] & 0xFF);
109
} while (0 <= n);
110
} else if (uch == 0) {
111
seed = (seed * HASH_MULTIPLIER) ^ (0xC0);
112
seed = (seed * HASH_MULTIPLIER) ^ (0x80);
113
} else {
114
seed = (seed * HASH_MULTIPLIER) ^ (uch);
115
}
116
}
117
return seed;
118
}
119
120
static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
121
int length = 0;
122
123
for (int i = offset; i < offset + count; i++) {
124
byte ch = bytes[i];
125
126
if (ch == 0) {
127
break;
128
}
129
130
if ((ch & 0xC0) != 0x80) {
131
length++;
132
}
133
}
134
135
return length;
136
}
137
138
static void charsFromMUTF8(char[] chars, byte[] bytes, int offset, int count) throws UTFDataFormatException {
139
int j = 0;
140
141
for (int i = offset; i < offset + count; i++) {
142
byte ch = bytes[i];
143
144
if (ch == 0) {
145
break;
146
}
147
148
boolean is_unicode = (ch & 0x80) != 0;
149
int uch = ch & 0x7F;
150
151
if (is_unicode) {
152
int mask = 0x40;
153
154
while ((uch & mask) != 0) {
155
ch = bytes[++i];
156
157
if ((ch & 0xC0) != 0x80) {
158
throw new UTFDataFormatException("bad continuation 0x" + Integer.toHexString(ch));
159
}
160
161
uch = ((uch & ~mask) << 6) | (ch & 0x3F);
162
mask <<= 6 - 1;
163
}
164
165
if ((uch & 0xFFFF) != uch) {
166
throw new UTFDataFormatException("character out of range \\u" + Integer.toHexString(uch));
167
}
168
}
169
170
chars[j++] = (char)uch;
171
}
172
}
173
174
public static String stringFromMUTF8(byte[] bytes, int offset, int count) {
175
int length = charsFromMUTF8Length(bytes, offset, count);
176
char[] chars = new char[length];
177
178
try {
179
charsFromMUTF8(chars, bytes, offset, count);
180
} catch (UTFDataFormatException ex) {
181
throw new InternalError("Attempt to convert non modified UTF-8 byte sequence", ex);
182
}
183
184
return new String(chars);
185
}
186
187
public static String stringFromMUTF8(byte[] bytes) {
188
return stringFromMUTF8(bytes, 0, bytes.length);
189
}
190
191
/**
192
* Calculates the number of characters in the String present at the
193
* specified offset. As an optimization, the length returned will
194
* be positive if the characters are all ASCII, and negative otherwise.
195
*/
196
private static int charsFromByteBufferLength(ByteBuffer buffer, int offset) {
197
int length = 0;
198
199
int limit = buffer.limit();
200
boolean asciiOnly = true;
201
while (offset < limit) {
202
byte ch = buffer.get(offset++);
203
204
if (ch < 0) {
205
asciiOnly = false;
206
} else if (ch == 0) {
207
return asciiOnly ? length : -length;
208
}
209
210
if ((ch & 0xC0) != 0x80) {
211
length++;
212
}
213
}
214
throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
215
}
216
217
private static void charsFromByteBuffer(char[] chars, ByteBuffer buffer, int offset) {
218
int j = 0;
219
220
int limit = buffer.limit();
221
while (offset < limit) {
222
byte ch = buffer.get(offset++);
223
224
if (ch == 0) {
225
return;
226
}
227
228
boolean is_unicode = (ch & 0x80) != 0;
229
int uch = ch & 0x7F;
230
231
if (is_unicode) {
232
int mask = 0x40;
233
234
while ((uch & mask) != 0) {
235
ch = buffer.get(offset++);
236
237
if ((ch & 0xC0) != 0x80) {
238
throw new InternalError("Bad continuation in " +
239
"modified UTF-8 byte sequence: " + ch);
240
}
241
242
uch = ((uch & ~mask) << 6) | (ch & 0x3F);
243
mask <<= 6 - 1;
244
}
245
}
246
247
if ((uch & 0xFFFF) != uch) {
248
throw new InternalError("UTF-32 char in modified UTF-8 " +
249
"byte sequence: " + uch);
250
}
251
252
chars[j++] = (char)uch;
253
}
254
255
throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
256
}
257
258
public static String stringFromByteBuffer(ByteBuffer buffer) {
259
return stringFromByteBuffer(buffer, 0);
260
}
261
262
/* package-private */
263
static String stringFromByteBuffer(ByteBuffer buffer, int offset) {
264
int length = charsFromByteBufferLength(buffer, offset);
265
if (length > 0) {
266
byte[] asciiBytes = new byte[length];
267
// Ideally we could use buffer.get(offset, asciiBytes, 0, length)
268
// here, but that was introduced in JDK 13
269
for (int i = 0; i < length; i++) {
270
asciiBytes[i] = buffer.get(offset++);
271
}
272
return new String(asciiBytes, StandardCharsets.US_ASCII);
273
}
274
char[] chars = new char[-length];
275
charsFromByteBuffer(chars, buffer, offset);
276
return new String(chars);
277
}
278
279
/* package-private */
280
static int stringFromByteBufferMatches(ByteBuffer buffer, int offset, String string, int stringOffset) {
281
// ASCII fast-path
282
int limit = buffer.limit();
283
int current = offset;
284
int slen = string.length();
285
while (current < limit) {
286
byte ch = buffer.get(current);
287
if (ch <= 0) {
288
if (ch == 0) {
289
// Match
290
return current - offset;
291
}
292
// non-ASCII byte, run slow-path from current offset
293
break;
294
}
295
if (slen <= stringOffset || string.charAt(stringOffset) != (char)ch) {
296
// No match
297
return -1;
298
}
299
stringOffset++;
300
current++;
301
}
302
// invariant: remainder of the string starting at current is non-ASCII,
303
// so return value from charsFromByteBufferLength will be negative
304
int length = -charsFromByteBufferLength(buffer, current);
305
char[] chars = new char[length];
306
charsFromByteBuffer(chars, buffer, current);
307
for (int i = 0; i < length; i++) {
308
if (string.charAt(stringOffset++) != chars[i]) {
309
return -1;
310
}
311
}
312
return length;
313
}
314
315
static int mutf8FromStringLength(String s) {
316
int length = 0;
317
int slen = s.length();
318
319
for (int i = 0; i < slen; i++) {
320
char ch = s.charAt(i);
321
int uch = ch & 0xFFFF;
322
323
if ((uch & ~0x7F) != 0) {
324
int mask = ~0x3F;
325
int n = 0;
326
327
do {
328
n++;
329
uch >>= 6;
330
mask >>= 1;
331
} while ((uch & mask) != 0);
332
333
length += n + 1;
334
} else if (uch == 0) {
335
length += 2;
336
} else {
337
length++;
338
}
339
}
340
341
return length;
342
}
343
344
static void mutf8FromString(byte[] bytes, int offset, String s) {
345
int j = offset;
346
byte[] buffer = null;
347
int slen = s.length();
348
349
for (int i = 0; i < slen; i++) {
350
char ch = s.charAt(i);
351
int uch = ch & 0xFFFF;
352
353
if ((uch & ~0x7F) != 0) {
354
if (buffer == null) {
355
buffer = new byte[8];
356
}
357
int mask = ~0x3F;
358
int n = 0;
359
360
do {
361
buffer[n++] = (byte)(0x80 | (uch & 0x3F));
362
uch >>= 6;
363
mask >>= 1;
364
} while ((uch & mask) != 0);
365
366
buffer[n] = (byte)((mask << 1) | uch);
367
368
do {
369
bytes[j++] = buffer[n--];
370
} while (0 <= n);
371
} else if (uch == 0) {
372
bytes[j++] = (byte)0xC0;
373
bytes[j++] = (byte)0x80;
374
} else {
375
bytes[j++] = (byte)uch;
376
}
377
}
378
}
379
380
public static byte[] mutf8FromString(String string) {
381
int length = mutf8FromStringLength(string);
382
byte[] bytes = new byte[length];
383
mutf8FromString(bytes, 0, string);
384
385
return bytes;
386
}
387
}
388
389