-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFastStringFactory.java
66 lines (56 loc) · 2.23 KB
/
FastStringFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.komanov.stringformat;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FastStringFactory {
private static final MethodHandle stringBuilderValueGetter = getFieldHandler(getValueField());
private static final MethodHandle stringBuilderCoderGetter = getFieldHandler(getCoderField());
private static final MethodHandle newString = getNewStringHandler();
public static String fastNewString(StringBuilder sb) throws Throwable {
if (sb.capacity() != sb.length()) {
throw new IllegalArgumentException("Expected filled StringBuilder!");
}
return fastNewString(
(byte[]) stringBuilderValueGetter.invoke(sb),
(byte) stringBuilderCoderGetter.invoke(sb)
);
}
public static String fastNewString(byte[] value, byte coder) throws Throwable {
return (String) newString.invokeExact(value, coder);
}
private static MethodHandle getFieldHandler(Field field) {
try {
return MethodHandles.lookup().unreflectGetter(field);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Field getValueField() {
try {
Field field = StringBuilder.class.getSuperclass().getDeclaredField("value");
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
private static Field getCoderField() {
try {
Field field = StringBuilder.class.getSuperclass().getDeclaredField("coder");
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
private static MethodHandle getNewStringHandler() {
try {
Constructor<String> constructor = String.class.getDeclaredConstructor(byte[].class, byte.class);
constructor.setAccessible(true);
return MethodHandles.lookup().unreflectConstructor(constructor);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}