diff --git a/src/main/java/org/redkale/convert/json/JsonBytesWriter.java b/src/main/java/org/redkale/convert/json/JsonBytesWriter.java index 59a69506f..6689287fc 100644 --- a/src/main/java/org/redkale/convert/json/JsonBytesWriter.java +++ b/src/main/java/org/redkale/convert/json/JsonBytesWriter.java @@ -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(); diff --git a/src/main/java/org/redkale/convert/json/JsonCharsWriter.java b/src/main/java/org/redkale/convert/json/JsonCharsWriter.java index 5bac10679..5d2849b6a 100644 --- a/src/main/java/org/redkale/convert/json/JsonCharsWriter.java +++ b/src/main/java/org/redkale/convert/json/JsonCharsWriter.java @@ -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); diff --git a/src/main/java/org/redkale/util/Utility.java b/src/main/java/org/redkale/util/Utility.java index 903178b16..bbe141337 100644 --- a/src/main/java/org/redkale/util/Utility.java +++ b/src/main/java/org/redkale/util/Utility.java @@ -110,9 +110,9 @@ public final class Utility { private static final Unsafe unsafeInstance; // ------------------------------------------------------------------------------- - private static final Function strByteFunction; + private static final Function strByteFunction; - private static final Function sbByteFunction; + private static final Function sbByteFunction; private static final Predicate strLatin1Function; @@ -142,8 +142,8 @@ public final class Utility { .setRemoveOnCancelPolicy(true); Unsafe unsafe0 = null; - Function strByteFunction0 = null; - Function sbByteFunction0 = null; + Function strByteFunction0 = null; + Function sbByteFunction0 = null; Predicate strLatin1Function0 = null; ToLongFunction bufferAddrFunction0 = null; Consumer> 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) {