JsonCharsWriter

This commit is contained in:
redkale
2024-09-23 17:49:48 +08:00
parent 7b03a9fffe
commit c098674ab8
3 changed files with 130 additions and 28 deletions

View File

@@ -446,7 +446,7 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
}
byte[] utf16s = Utility.byteUTF16Array(value);
if (utf16s != null) { // JDK9+
writeUTF16String(quote, utf16s);
writeEscapeUTF16String(quote, utf16s);
return;
}
int len = value.length();
@@ -513,7 +513,7 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
}
// see java.lang.StringCoding.encodeUTF8_UTF16 方法
private void writeUTF16String(final boolean quote, byte[] value) {
private void writeEscapeUTF16String(final boolean quote, byte[] value) {
int len = value.length;
byte[] bytes = expand(len * 4 + 2);
int curr = count;
@@ -591,14 +591,14 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
count = curr;
}
static final char MIN_LOW_SURROGATE = '\uDC00';
static final char MAX_LOW_SURROGATE = '\uDFFF';
static final char MIN_HIGH_SURROGATE = '\uD800';
static final char MAX_HIGH_SURROGATE = '\uDBFF';
static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
static final char MAX_LOW_SURROGATE_MORE = MAX_LOW_SURROGATE + 1;
static final char MAX_HIGH_SURROGATE_MORE = MAX_HIGH_SURROGATE + 1;
static final int MIN_SUPPLEMENTARY_CODE_POINT_MORE =
private static final char MIN_LOW_SURROGATE = '\uDC00';
private static final char MAX_LOW_SURROGATE = '\uDFFF';
private static final char MIN_HIGH_SURROGATE = '\uD800';
private static final char MAX_HIGH_SURROGATE = '\uDBFF';
private static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
private static final char MAX_LOW_SURROGATE_MORE = MAX_LOW_SURROGATE + 1;
private static final char MAX_HIGH_SURROGATE_MORE = MAX_HIGH_SURROGATE + 1;
private static final int MIN_SUPPLEMENTARY_CODE_POINT_MORE =
(MIN_SUPPLEMENTARY_CODE_POINT - (MIN_HIGH_SURROGATE << 10) - MIN_LOW_SURROGATE);
private void writeEscapeLatinString(final boolean quote, byte[] value) {
@@ -654,11 +654,8 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
writeTo(Utility.latin1ByteArray(value));
return;
}
byte[] utf16s = Utility.byteUTF16Array(value);
if (utf16s != null) { // JDK9+
writeUTF16String(false, utf16s);
return;
}
// 不能使用writeEscapeUTF16String
//
byte[] bytes = expand(value.length() * 4 + 2);
int curr = count;
int len = value.length();

View File

@@ -50,7 +50,7 @@ public class JsonCharsWriter extends JsonWriter {
}
public JsonCharsWriter(int size) {
this.content = new char[size > 1024 ? size : 1024];
this.content = new char[size > DEFAULT_SIZE ? size : DEFAULT_SIZE];
}
// -----------------------------------------------------------------------
@@ -66,7 +66,7 @@ public class JsonCharsWriter extends JsonWriter {
if (ncount <= content.length) {
return content;
}
char[] newdata = new char[Math.max(content.length * 3 / 2, ncount)];
char[] newdata = new char[Math.max(content.length * 2, ncount)];
System.arraycopy(content, 0, newdata, 0, count);
this.content = newdata;
return newdata;
@@ -369,8 +369,17 @@ public class JsonCharsWriter extends JsonWriter {
return;
}
final String str = value;
if (Utility.isLatin1(str)) {
writeEscapeLatinString(quote, Utility.latin1ByteArray(str));
return;
}
// byte[] utf16s = Utility.byteUTF16Array(value);
// if (utf16s != null) { // JDK9+
// writeEscapeUTF16String(quote, utf16s);
// return;
// }
final int len = str.length();
char[] chars = expand(len + 2);
char[] chars = expand(len * 2 + 2);
int curr = count;
if (quote) {
chars[curr++] = BYTE_DQUOTE;
@@ -417,6 +426,101 @@ public class JsonCharsWriter extends JsonWriter {
count = curr;
}
private void writeEscapeUTF16String(final boolean quote, byte[] value) {
byte[] bytes = value;
int len = bytes.length;
char[] chars = expand(len + 2);
int curr = count;
if (quote) {
chars[curr++] = BYTE_DQUOTE;
}
byte b1, b2;
for (int i = 0; i < len; i += 2) {
b1 = bytes[i];
b2 = bytes[i + 1];
char ch = (char) ((b2 == 0 && b1 >= 0) ? b1 : ((b1 & 0xff) | ((b2 & 0xff) << 8)));
switch (ch) {
case '\n':
chars[curr++] = '\\';
chars[curr++] = 'n';
break;
case '\r':
chars[curr++] = '\\';
chars[curr++] = 'r';
break;
case '\f':
chars[curr++] = '\\';
chars[curr++] = 'f';
break;
case '\b':
chars[curr++] = '\\';
chars[curr++] = 'b';
break;
case '\t':
chars[curr++] = '\\';
chars[curr++] = 't';
break;
case '\\':
chars[curr++] = '\\';
chars[curr++] = ch;
break;
case '"':
chars[curr++] = '\\';
chars[curr++] = ch;
break;
default:
chars[curr++] = ch;
break;
}
}
if (quote) {
chars[curr++] = BYTE_DQUOTE;
}
count = curr;
}
private void writeEscapeLatinString(final boolean quote, byte[] value) {
char[] chars = expand(value.length * 2 + 2);
int curr = count;
if (quote) {
chars[curr++] = BYTE_DQUOTE;
}
for (byte b : value) {
if (b == BYTE_DQUOTE) {
chars[curr++] = '\\';
chars[curr++] = BYTE_DQUOTE;
} else if (b == '\\') {
chars[curr++] = '\\';
chars[curr++] = '\\';
} else if (b < 32) {
if (b == '\n') {
chars[curr++] = '\\';
chars[curr++] = 'n';
} else if (b == '\r') {
chars[curr++] = '\\';
chars[curr++] = 'r';
} else if (b == '\f') {
chars[curr++] = '\\';
chars[curr++] = 'f';
} else if (b == '\b') {
chars[curr++] = '\\';
chars[curr++] = 'b';
} else if (b == '\t') {
chars[curr++] = '\\';
chars[curr++] = 't';
} else {
chars[curr++] = (char) b;
}
} else {
chars[curr++] = (char) b;
}
}
if (quote) {
chars[curr++] = BYTE_DQUOTE;
}
count = curr;
}
@Override
public String toString() {
return new String(content, 0, count);

View File

@@ -110,9 +110,9 @@ public final class Utility {
private static final Unsafe unsafeInstance;
// -------------------------------------------------------------------------------
private static final Function<Object, Object> strByteFunction;
private static final Function<String, byte[]> strByteFunction;
private static final Function<Object, Object> sbByteFunction;
private static final Function<StringBuilder, byte[]> sbByteFunction;
private static final Predicate<Object> strLatin1Function;
@@ -142,8 +142,8 @@ public final class Utility {
.setRemoveOnCancelPolicy(true);
Unsafe unsafe0 = null;
Function<Object, Object> strByteFunction0 = null;
Function<Object, Object> sbByteFunction0 = null;
Function<String, byte[]> strByteFunction0 = null;
Function<StringBuilder, byte[]> sbByteFunction0 = null;
Predicate<Object> strLatin1Function0 = null;
ToLongFunction<Object> bufferAddrFunction0 = null;
Consumer<Consumer<String>> signalShutdownConsumer0 = null;
@@ -315,10 +315,11 @@ public final class Utility {
final long fd3 = unsafe0.objectFieldOffset(String.class.getDeclaredField("coder"));
final long fd4 = unsafe0.objectFieldOffset(Buffer.class.getDeclaredField("address"));
Field cf = String.class.getDeclaredField("COMPACT_STRINGS");
strByteFunction0 = (String t) -> (byte[]) unsafe.getObject(t, fd1);
sbByteFunction0 = (StringBuilder t) -> (byte[]) unsafe.getObject(t, fd2);
final boolean compact = unsafe.getBoolean(String.class, unsafe0.staticFieldOffset(cf));
strByteFunction0 = (Object t) -> unsafe.getObject(t, fd1);
sbByteFunction0 = (Object t) -> unsafe.getObject(t, fd2);
strLatin1Function0 = (Object t) -> compact && unsafe.getByte(t, fd3) == 0; // LATIN1:0 UTF16:1
// LATIN1:0 UTF16:1
strLatin1Function0 = compact ? (Object t) -> unsafe.getByte(t, fd3) == 0 : (Object t) -> false;
bufferAddrFunction0 = (Object t) -> unsafe.getLong(t, fd4);
}
{ // signalShutdown
@@ -4915,7 +4916,7 @@ public final class Utility {
if (value == null || strByteFunction == null) {
return null;
}
return (byte[]) strByteFunction.apply(value);
return strByteFunction.apply(value);
}
public static char[] charArray(String value) {
@@ -4940,7 +4941,7 @@ public final class Utility {
if (strByteFunction == null) {
return latin1Value.getBytes();
}
return (byte[]) strByteFunction.apply(latin1Value);
return strByteFunction.apply(latin1Value);
}
// 只能是单字节字符串
@@ -4951,7 +4952,7 @@ public final class Utility {
if (sbByteFunction == null) {
return latin1Value.toString().getBytes();
}
return (byte[]) sbByteFunction.apply(latin1Value);
return sbByteFunction.apply(latin1Value);
}
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] array) {