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) {
86 return hashCode(string, HASH_MULTIPLIER);
87 }
88
89 public static int hashCode(String string, int seed) {
90
91 int slen = string.length();
92 byte[] buffer = null;
93
94 for (int i = 0; i < slen; i++) {
95 char ch = string.charAt(i);
96 int uch = ch & 0xFFFF;
97
98 if ((uch & ~0x7F) != 0) {
99 if (buffer == null) {
100 buffer = new byte[8];
101 }
102 int mask = ~0x3F;
103 int n = 0;
104
105 do {
106 buffer[n++] = (byte)(0x80 | (uch & 0x3F));
107 uch >>= 6;
108 mask >>= 1;
109 } while ((uch & mask) != 0);
110
111 buffer[n] = (byte)((mask << 1) | uch);
112
113 do {
114 seed = (seed * HASH_MULTIPLIER) ^ (buffer[n--] & 0xFF);
115 } while (0 <= n);
116 } else if (uch == 0) {
117 seed = (seed * HASH_MULTIPLIER) ^ (0xC0);
118 seed = (seed * HASH_MULTIPLIER) ^ (0x80);
119 } else {
120 seed = (seed * HASH_MULTIPLIER) ^ (uch);
121 }
122 }
123
124 return seed & 0x7FFFFFFF;
125 }
126
127 static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
128 int length = 0;
129
130 for (int i = offset; i < offset + count; i++) {
131 byte ch = bytes[i];
132
133 if (ch == 0) {
134 break;
135 }
136
137 if ((ch & 0xC0) != 0x80) {
138 length++;
139 }
140 }
141
142 return length;
143 }
144
248 }
249
250 chars[j++] = (char)uch;
251 }
252
253 throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence");
254 }
255
256 public static String stringFromByteBuffer(ByteBuffer buffer) {
257 int length = charsFromByteBufferLength(buffer);
258 buffer.rewind();
259 char[] chars = new char[length];
260 charsFromByteBuffer(chars, buffer);
261
262 return new String(chars);
263 }
264
265 static int mutf8FromStringLength(String s) {
266 int length = 0;
267 int slen = s.length();
268 for (int i = 0; i < slen; i++) {
269 char ch = s.charAt(i);
270 int uch = ch & 0xFFFF;
271
272 if ((uch & ~0x7F) != 0) {
273 int mask = ~0x3F;
274 int n = 0;
275
276 do {
277 n++;
278 uch >>= 6;
279 mask >>= 1;
280 } while ((uch & mask) != 0);
281
282 length += n + 1;
283 } else if (uch == 0) {
284 length += 2;
285 } else {
286 length++;
287 }
|
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
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 }
|