From 04dbcc664ec59638c238cd47c725a35adb93ccd0 Mon Sep 17 00:00:00 2001 From: kamhung <22250530@qq.com> Date: Tue, 10 Nov 2015 11:03:58 +0800 Subject: [PATCH] --- .../convert/json/JsonByteBufferWriter.java | 147 ++++++++++++++---- 1 file changed, 119 insertions(+), 28 deletions(-) diff --git a/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java b/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java index fd2af56a6..864a28101 100644 --- a/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java +++ b/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java @@ -71,7 +71,7 @@ public final class JsonByteBufferWriter extends JsonWriter { return len; } - private void expand(final int byteLength) { + private int expand(final int byteLength) { if (this.buffers == null) { this.index = 0; this.buffers = new ByteBuffer[]{supplier.get()}; @@ -86,8 +86,8 @@ public final class JsonByteBufferWriter extends JsonWriter { this.buffers = bufs; this.index++; } - if (buffer.remaining() >= byteLength) return; int len = buffer.remaining(); + int size = 0; while (len < byteLength) { buffer = supplier.get(); ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; @@ -95,7 +95,9 @@ public final class JsonByteBufferWriter extends JsonWriter { bufs[this.buffers.length] = buffer; this.buffers = bufs; len += buffer.remaining(); + size++; } + return size; } @Override @@ -107,10 +109,10 @@ public final class JsonByteBufferWriter extends JsonWriter { @Override public void writeTo(final char[] chs, final int start, final int len) { - writeTo(false, chs, start, len); + writeTo(-1, false, chs, start, len); } - private void writeTo(final boolean quote, final char[] chs, final int start, final int len) { + private void writeTo(int expandsize, final boolean quote, final char[] chs, final int start, final int len) { int byteLength = quote ? 2 : 0; ByteBuffer bb = null; if (charset == null) { @@ -119,7 +121,33 @@ public final class JsonByteBufferWriter extends JsonWriter { bb = charset.encode(CharBuffer.wrap(chs, start, len)); byteLength += bb.remaining(); } - expand(byteLength); + if (expandsize < 0) expandsize = expand(byteLength); + if (expandsize == 0) { // 只需要一个buffer + final ByteBuffer buffer = this.buffers[index]; + if (quote) buffer.put((byte) '"'); + + if (charset == null) { //UTF-8 + final int limit = start + len; + for (int i = start; i < limit; i++) { + char c = chs[i]; + if (c < 0x80) { + buffer.put((byte) c); + } else if (c < 0x800) { + buffer.put((byte) (0xc0 | (c >> 6))); + buffer.put((byte) (0x80 | (c & 0x3f))); + } else { + buffer.put((byte) (0xe0 | ((c >> 12)))); + buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); + buffer.put((byte) (0x80 | (c & 0x3f))); + } + } + } else { + buffer.put(bb); + } + + if (quote) buffer.put((byte) '"'); + return; + } ByteBuffer buffer = this.buffers[index]; if (quote) { if (!buffer.hasRemaining()) buffer = nextByteBuffer(); @@ -132,8 +160,8 @@ public final class JsonByteBufferWriter extends JsonWriter { } } else { while (bb.hasRemaining()) { - buffer.put(bb.get()); if (!buffer.hasRemaining()) buffer = nextByteBuffer(); + buffer.put(bb.get()); } } if (quote) { @@ -179,6 +207,32 @@ public final class JsonByteBufferWriter extends JsonWriter { return size; } + private static int encodeEscapeUTF8Length(final char[] text, final int start, final int len) { + char c; + int size = 0; + final char[] chars = text; + final int limit = start + len; + for (int i = start; i < limit; i++) { + c = chars[i]; + switch (c) { + case '\n': size += 2; + break; + case '\r': size += 2; + break; + case '\t': size += 2; + break; + case '\\': size += 2; + break; + case '"': size += 2; + break; + default: + size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3)); + break; + } + } + return size; + } + /** * 注意: 该String值不能为null且不会进行转义, 只用于不含需要转义字符的字符串,例如enum、double、BigInteger转换的String * @@ -188,7 +242,7 @@ public final class JsonByteBufferWriter extends JsonWriter { @Override public void writeTo(final boolean quote, final String value) { char[] chs = Utility.charArray(value); - writeTo(quote, chs, 0, chs.length); + writeTo(-1, quote, chs, 0, chs.length); } @Override @@ -216,28 +270,65 @@ public final class JsonByteBufferWriter extends JsonWriter { } } if (len == chs.length) { - writeTo(true, chs, 0, len); - } else { - StringBuilder sb = new StringBuilder(len); - for (char ch : chs) { - switch (ch) { - case '\n': sb.append("\\n"); - break; - case '\r': sb.append("\\r"); - break; - case '\t': sb.append("\\t"); - break; - case '\\': sb.append("\\\\"); - break; - case '"': sb.append("\\\""); - break; - default: sb.append(ch); - break; - } - } - char[] cs = Utility.charArray(sb); - writeTo(true, cs, 0, sb.length()); + writeTo(-1, true, chs, 0, len); + return; } + int expandsize = -1; + if (this.charset == null) { //UTF-8 + final int byteLength = 2 + encodeEscapeUTF8Length(chs, 0, chs.length); + expandsize = expand(byteLength); + if (expandsize == 0) { // 只需要一个buffer + final ByteBuffer buffer = this.buffers[index]; + buffer.put((byte) '"'); + for (char c : chs) { + switch (c) { + case '\n': buffer.put((byte) '\\').put((byte) 'n'); + break; + case '\r': buffer.put((byte) '\\').put((byte) 'r'); + break; + case '\t': buffer.put((byte) '\\').put((byte) 't'); + break; + case '\\': buffer.put((byte) '\\').put((byte) '\\'); + break; + case '"': buffer.put((byte) '\\').put((byte) '"'); + break; + default: + if (c < 0x80) { + buffer.put((byte) c); + } else if (c < 0x800) { + buffer.put((byte) (0xc0 | (c >> 6))); + buffer.put((byte) (0x80 | (c & 0x3f))); + } else { + buffer.put((byte) (0xe0 | ((c >> 12)))); + buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); + buffer.put((byte) (0x80 | (c & 0x3f))); + } + break; + } + } + buffer.put((byte) '"'); + return; + } + } + StringBuilder sb = new StringBuilder(len); + for (char ch : chs) { + switch (ch) { + case '\n': sb.append("\\n"); + break; + case '\r': sb.append("\\r"); + break; + case '\t': sb.append("\\t"); + break; + case '\\': sb.append("\\\\"); + break; + case '"': sb.append("\\\""); + break; + default: sb.append(ch); + break; + } + } + char[] cs = Utility.charArray(sb); + writeTo(expandsize, true, cs, 0, sb.length()); } @Override