CharArray

This commit is contained in:
redkale
2024-09-17 10:34:35 +08:00
parent 1cfc17766a
commit a7cddab9fb
3 changed files with 194 additions and 66 deletions

View File

@@ -123,6 +123,10 @@ public class JsonCharsWriter extends JsonWriter {
*/ */
@Override @Override
public void writeLatin1To(final boolean quote, final String value) { public void writeLatin1To(final boolean quote, final String value) {
if (value == null) {
writeNull();
return;
}
int len = value.length(); int len = value.length();
if (quote) { if (quote) {
expand(len + 2); expand(len + 2);

View File

@@ -6,6 +6,7 @@
package org.redkale.convert.json; package org.redkale.convert.json;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import org.redkale.convert.*; import org.redkale.convert.*;
import static org.redkale.convert.Reader.*; import static org.redkale.convert.Reader.*;
@@ -27,6 +28,8 @@ public class JsonReader extends Reader {
private int limit; private int limit;
private CharArray array;
// public static ObjectPool<JsonReader> createPool(int max) { // public static ObjectPool<JsonReader> createPool(int max) {
// return new ObjectPool<>(max, (Object... params) -> new JsonReader(), null, JsonReader::recycle); // return new ObjectPool<>(max, (Object... params) -> new JsonReader(), null, JsonReader::recycle);
// } // }
@@ -69,9 +72,23 @@ public class JsonReader extends Reader {
this.position = -1; this.position = -1;
this.limit = -1; this.limit = -1;
this.text = null; this.text = null;
if (this.array != null) {
if (this.array.content.length > 102400) {
this.array = null;
} else {
this.array.clear();
}
}
return true; return true;
} }
protected CharArray array() {
if (array == null) {
array = new CharArray();
}
return array.clear();
}
public void close() { public void close() {
this.recycle(); this.recycle();
} }
@@ -369,59 +386,6 @@ public class JsonReader extends Reader {
return null; 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值 * 读取一个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) + ")"); + position + ") in (" + new String(this.text) + ")");
} }
final int start = ++currpos; final int start = ++currpos;
CharArray array = null;
char c;
for (; ; ) { for (; ; ) {
char ch = text0[currpos]; char ch = text0[currpos];
if (ch == expected) { if (ch == expected) {
break; break;
} else if (ch == '\\') { } else if (ch == '\\') {
this.position = currpos - 1; if (array == null) {
return readEscapeValue(expected, start); 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++; currpos++;
} }
this.position = 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) { private String readEscapeValue(final char expected, int start) {
StringBuilder array = new StringBuilder(); CharArray array = this.array();
final char[] text0 = this.text; final char[] text0 = this.text;
int pos = this.position; int pos = this.position;
array.append(text0, start, pos + 1 - start); array.append(text0, start, pos + 1 - start);
@@ -933,7 +989,7 @@ public class JsonReader extends Reader {
c = text0[++pos]; c = text0[++pos];
if (c == expected) { if (c == expected) {
this.position = pos; this.position = pos;
return array.toString(); return array.toStringThenClear();
} else if (c == '\\') { } else if (c == '\\') {
c = text0[++pos]; c = text0[++pos];
switch (c) { switch (c) {
@@ -992,4 +1048,63 @@ public class JsonReader extends Reader {
digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = -3; // -3可能跳过 digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = -3; // -3可能跳过
digits[','] = digits['}'] = digits[']'] = digits[':'] = -4; // -4退出 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);
}
}
} }

View File

@@ -8,16 +8,14 @@ package org.redkale.test.convert;
import java.util.*; import java.util.*;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.redkale.convert.Convert; import org.redkale.convert.Convert;
import org.redkale.convert.ConvertSmallString;
import org.redkale.convert.json.*; import org.redkale.convert.json.*;
/** @author zhangjx */ /** @author zhangjx */
public class Json5Test { public class Json5Test {
private boolean main;
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
Json5Test test = new Json5Test(); Json5Test test = new Json5Test();
test.main = true;
test.run1(); test.run1();
test.run2(); test.run2();
} }
@@ -36,14 +34,16 @@ public class Json5Test {
JsonConvert convert = JsonConvert.root(); JsonConvert convert = JsonConvert.root();
Json5Bean bean = new Json5Bean(); Json5Bean bean = new Json5Bean();
bean.id = 500; bean.id = 500;
bean.idx = 600;
bean.decmails = 3.2f; bean.decmails = 3.2f;
bean.value = 44444; bean.value = 44444;
bean.name = "haha"; bean.name = "ha\t\"ha";
String json = "{/*多行\r\n注释**/\"decmails\":3.2,//单行注释\r\n\"id\":0x1F4,\"name\":\"haha\",\"value\":44444,}"; 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); Json5Bean bean2 = convert.convertFrom(Json5Bean.class, json);
if (!main) { System.out.println(bean2.name);
Assertions.assertTrue(bean.equals(bean2)); Assertions.assertTrue(bean.equals(bean2));
}
System.out.println(convert.convertTo(bean2)); System.out.println(convert.convertTo(bean2));
String arrayJson = "[" + json + "," + json + "," + "]"; String arrayJson = "[" + json + "," + json + "," + "]";
@@ -59,16 +59,22 @@ public class Json5Test {
public int id; public int id;
public int idx;
public float decmails; public float decmails;
public long value; public long value;
public String name; public String name;
@ConvertSmallString
public String desc;
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;
hash = 47 * hash + this.id; hash = 47 * hash + this.id;
hash = 47 * hash + this.idx;
hash = 47 * hash + Float.floatToIntBits(this.decmails); hash = 47 * hash + Float.floatToIntBits(this.decmails);
hash = 47 * hash + (int) (this.value ^ (this.value >>> 32)); hash = 47 * hash + (int) (this.value ^ (this.value >>> 32));
hash = 47 * hash + Objects.hashCode(this.name); hash = 47 * hash + Objects.hashCode(this.name);
@@ -90,6 +96,9 @@ public class Json5Test {
if (this.id != other.id) { if (this.id != other.id) {
return false; return false;
} }
if (this.idx != other.idx) {
return false;
}
if (Float.floatToIntBits(this.decmails) != Float.floatToIntBits(other.decmails)) { if (Float.floatToIntBits(this.decmails) != Float.floatToIntBits(other.decmails)) {
return false; return false;
} }