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
public void writeLatin1To(final boolean quote, final String value) {
if (value == null) {
writeNull();
return;
}
int len = value.length();
if (quote) {
expand(len + 2);

View File

@@ -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<JsonReader> 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);
}
}
}

View File

@@ -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;
}