From a7cddab9fb5634bb3f385d9862d9b7b439411124 Mon Sep 17 00:00:00 2001 From: redkale Date: Tue, 17 Sep 2024 10:34:35 +0800 Subject: [PATCH] CharArray --- .../redkale/convert/json/JsonCharsWriter.java | 4 + .../org/redkale/convert/json/JsonReader.java | 231 +++++++++++++----- .../org/redkale/test/convert/Json5Test.java | 25 +- 3 files changed, 194 insertions(+), 66 deletions(-) diff --git a/src/main/java/org/redkale/convert/json/JsonCharsWriter.java b/src/main/java/org/redkale/convert/json/JsonCharsWriter.java index 224102275..5bac10679 100644 --- a/src/main/java/org/redkale/convert/json/JsonCharsWriter.java +++ b/src/main/java/org/redkale/convert/json/JsonCharsWriter.java @@ -123,6 +123,10 @@ public class JsonCharsWriter extends JsonWriter { */ @Override public void writeLatin1To(final boolean quote, final String value) { + if (value == null) { + writeNull(); + return; + } int len = value.length(); if (quote) { expand(len + 2); diff --git a/src/main/java/org/redkale/convert/json/JsonReader.java b/src/main/java/org/redkale/convert/json/JsonReader.java index 085664b02..6b9130666 100644 --- a/src/main/java/org/redkale/convert/json/JsonReader.java +++ b/src/main/java/org/redkale/convert/json/JsonReader.java @@ -6,6 +6,7 @@ package org.redkale.convert.json; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Map; import org.redkale.convert.*; import static org.redkale.convert.Reader.*; @@ -27,6 +28,8 @@ public class JsonReader extends Reader { private int limit; + private CharArray array; + // public static ObjectPool createPool(int max) { // return new ObjectPool<>(max, (Object... params) -> new JsonReader(), null, JsonReader::recycle); // } @@ -69,9 +72,23 @@ public class JsonReader extends Reader { this.position = -1; this.limit = -1; this.text = null; + if (this.array != null) { + if (this.array.content.length > 102400) { + this.array = null; + } else { + this.array.clear(); + } + } return true; } + protected CharArray array() { + if (array == null) { + array = new CharArray(); + } + return array.clear(); + } + public void close() { this.recycle(); } @@ -369,59 +386,6 @@ public class JsonReader extends Reader { return null; } - @Override - public String readSmallString() { - final int eof = this.limit; - if (this.position == eof) { - return null; - } - char ch = nextGoodChar(true); // 需要跳过注释 - final char[] text0 = this.text; - int currpos = this.position; - if (ch == '"' || ch == '\'') { - final char quote = ch; - final int start = currpos + 1; - for (; ; ) { - ch = text0[++currpos]; - if (ch == '\\') { - this.position = currpos - 1; - return readEscapeValue(quote, start); - } else if (ch == quote) { - break; - } - } - this.position = currpos; - char[] chs = new char[currpos - start]; - System.arraycopy(text0, start, chs, 0, chs.length); - return new String(chs); - } else { - int start = currpos; - for (; ; ) { - if (currpos == eof) { - break; - } - ch = text0[++currpos]; - if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') { - break; - } - } - int len = currpos - start; - if (len < 1) { - this.position = currpos; - return String.valueOf(ch); - } - this.position = currpos - 1; - if (len == 4 - && text0[start] == 'n' - && text0[start + 1] == 'u' - && text0[start + 2] == 'l' - && text0[start + 3] == 'l') { - return null; - } - return new String(text0, start, len == eof ? (len + 1) : len); - } - } - /** * 读取一个int值 * @@ -835,6 +799,57 @@ public class JsonReader extends Reader { } } + @Override + public String readSmallString() { + final int eof = this.limit; + if (this.position == eof) { + return null; + } + char ch = nextGoodChar(true); // 需要跳过注释 + final char[] text0 = this.text; + int currpos = this.position; + if (ch == '"' || ch == '\'') { + final char quote = ch; + final int start = currpos + 1; + for (; ; ) { + ch = text0[++currpos]; + if (ch == '\\') { + this.position = currpos - 1; + return readEscapeValue(quote, start); + } else if (ch == quote) { + break; + } + } + this.position = currpos; + return new String(text0, start, currpos - start); + } else { + int start = currpos; + for (; ; ) { + if (currpos == eof) { + break; + } + ch = text0[++currpos]; + if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') { + break; + } + } + int len = currpos - start; + if (len < 1) { + this.position = currpos; + return String.valueOf(ch); + } + this.position = currpos - 1; + if (len == 4 + && text0[start] == 'n' + && text0[start + 1] == 'u' + && text0[start + 2] == 'l' + && text0[start + 3] == 'l') { + return null; + } + return new String(text0, start, len == eof ? (len + 1) : len); + } + } + /** * 读取字符串, 必须是"或者'包围的字符串值 * @@ -909,22 +924,63 @@ public class JsonReader extends Reader { + position + ") in (" + new String(this.text) + ")"); } final int start = ++currpos; + CharArray array = null; + char c; for (; ; ) { char ch = text0[currpos]; if (ch == expected) { break; } else if (ch == '\\') { - this.position = currpos - 1; - return readEscapeValue(expected, start); + if (array == null) { + array = array(); + array.append(text0, start, currpos - start); + } + c = text0[++currpos]; + switch (c) { + case '"': + case '\'': + case '\\': + case '/': + array.append(c); + break; + case 'n': + array.append('\n'); + break; + case 'r': + array.append('\r'); + break; + case 'u': + array.append((char) Integer.parseInt( + new String(new char[] { + text0[++currpos], text0[++currpos], text0[++currpos], text0[++currpos] + }), + 16)); + break; + case 't': + array.append('\t'); + break; + case 'b': + array.append('\b'); + break; + case 'f': + array.append('\f'); + break; + default: + this.position = currpos; + throw new ConvertException("illegal escape(" + c + ") (position = " + this.position + ") in (" + + new String(this.text) + ")"); + } + } else if (array != null) { + array.append(ch); } currpos++; } this.position = currpos; - return new String(text0, start, currpos - start); + return array != null ? array.toStringThenClear() : new String(text0, start, currpos - start); } private String readEscapeValue(final char expected, int start) { - StringBuilder array = new StringBuilder(); + CharArray array = this.array(); final char[] text0 = this.text; int pos = this.position; array.append(text0, start, pos + 1 - start); @@ -933,7 +989,7 @@ public class JsonReader extends Reader { c = text0[++pos]; if (c == expected) { this.position = pos; - return array.toString(); + return array.toStringThenClear(); } else if (c == '\\') { c = text0[++pos]; switch (c) { @@ -992,4 +1048,63 @@ public class JsonReader extends Reader { digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = -3; // -3可能跳过 digits[','] = digits['}'] = digits[']'] = digits[':'] = -4; // -4退出 } + + protected static class CharArray { + + private int count; + + private char[] content = new char[1024]; + + private char[] expand(int len) { + int newcount = count + len; + if (newcount <= content.length) { + return content; + } + char[] newdata = new char[Math.max(content.length * 2, newcount)]; + System.arraycopy(content, 0, newdata, 0, count); + this.content = newdata; + return newdata; + } + + public CharArray append(char[] str, int offset, int len) { + char[] chs = expand(len); + System.arraycopy(str, offset, chs, count, len); + count += len; + return this; + } + + public CharArray append(char ch) { + char[] chs = expand(1); + chs[count++] = ch; + return this; + } + + public CharArray clear() { + this.count = 0; + return this; + } + + public char[] content() { + return content; + } + + public int length() { + return count; + } + + public char[] getChars() { + return Arrays.copyOfRange(content, 0, count); + } + + public String toStringThenClear() { + String s = toString(); + this.count = 0; + return s; + } + + @Override + public String toString() { + return new String(content, 0, count); + } + } } diff --git a/src/test/java/org/redkale/test/convert/Json5Test.java b/src/test/java/org/redkale/test/convert/Json5Test.java index eac05a9e3..3f45e10a9 100644 --- a/src/test/java/org/redkale/test/convert/Json5Test.java +++ b/src/test/java/org/redkale/test/convert/Json5Test.java @@ -8,16 +8,14 @@ package org.redkale.test.convert; import java.util.*; import org.junit.jupiter.api.*; import org.redkale.convert.Convert; +import org.redkale.convert.ConvertSmallString; import org.redkale.convert.json.*; /** @author zhangjx */ public class Json5Test { - private boolean main; - public static void main(String[] args) throws Throwable { Json5Test test = new Json5Test(); - test.main = true; test.run1(); test.run2(); } @@ -36,14 +34,16 @@ public class Json5Test { JsonConvert convert = JsonConvert.root(); Json5Bean bean = new Json5Bean(); bean.id = 500; + bean.idx = 600; bean.decmails = 3.2f; bean.value = 44444; - bean.name = "haha"; - String json = "{/*多行\r\n注释**/\"decmails\":3.2,//单行注释\r\n\"id\":0x1F4,\"name\":\"haha\",\"value\":44444,}"; + bean.name = "ha\t\"ha"; + bean.desc = "normal"; + String json = + "{/*多行\r\n注释**/\"decmails\":3.2,//单行注释\r\n\"id\":0x1F4,\"idx\":600,\"name\":\"ha\\t\\\"ha\",\"desc\":\"normal\",\"value\":44444,}"; Json5Bean bean2 = convert.convertFrom(Json5Bean.class, json); - if (!main) { - Assertions.assertTrue(bean.equals(bean2)); - } + System.out.println(bean2.name); + Assertions.assertTrue(bean.equals(bean2)); System.out.println(convert.convertTo(bean2)); String arrayJson = "[" + json + "," + json + "," + "]"; @@ -59,16 +59,22 @@ public class Json5Test { public int id; + public int idx; + public float decmails; public long value; public String name; + @ConvertSmallString + public String desc; + @Override public int hashCode() { int hash = 7; hash = 47 * hash + this.id; + hash = 47 * hash + this.idx; hash = 47 * hash + Float.floatToIntBits(this.decmails); hash = 47 * hash + (int) (this.value ^ (this.value >>> 32)); hash = 47 * hash + Objects.hashCode(this.name); @@ -90,6 +96,9 @@ public class Json5Test { if (this.id != other.id) { return false; } + if (this.idx != other.idx) { + return false; + } if (Float.floatToIntBits(this.decmails) != Float.floatToIntBits(other.decmails)) { return false; }