Skip to content

Commit

Permalink
optimize readString
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Feb 12, 2025
1 parent 4099158 commit 71f84e5
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class EishayParseUTF8BytesTest {
static final EishayParseUTF8Bytes benchmark = new EishayParseUTF8Bytes();

public static void fastjson2() {
for (int j = 0; j < 10; j++) {
for (int j = 0; j < 5; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000 * 1000; ++i) {
benchmark.fastjson2(BH);
Expand Down
32 changes: 10 additions & 22 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java
Original file line number Diff line number Diff line change
Expand Up @@ -1474,7 +1474,16 @@ public String readString() {
offset = readEscaped(bytes, start, quote, buf);
str = new String(buf);
} else {
str = subString(bytes, start, offset);
str = new String(bytes, start, offset - start, StandardCharsets.ISO_8859_1);
}

long features = context.features;
if ((features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}

int ch = ++offset == end ? EOI : bytes[offset++];
Expand Down Expand Up @@ -1544,27 +1553,6 @@ protected final int readEscaped(byte[] bytes, int offset, byte quote, char[] buf
return offset;
}

protected final String subString(byte[] bytes, int start, int offset) {
String str;
if (this.str != null) {
str = this.str.substring(start, offset);
} else if (STRING_CREATOR_JDK11 != null) {
str = STRING_CREATOR_JDK11.apply(Arrays.copyOfRange(bytes, start, offset), LATIN1);
} else if (ANDROID) {
str = getLatin1String(start, offset - start);
} else {
str = new String(bytes, start, offset - start, StandardCharsets.ISO_8859_1);
}
if ((context.features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}
return str;
}

public static JSONReaderASCII of(Context ctx, String str, byte[] bytes, int offset, int length) {
return IOUtils.isNonSlashASCII(bytes, offset, length)
? new JSONReaderASCIINonSlash(ctx, str, bytes, offset, length)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.alibaba.fastjson2;

import com.alibaba.fastjson2.util.IOUtils;

import java.nio.charset.StandardCharsets;

final class JSONReaderASCIINonSlash
extends JSONReaderASCII {
JSONReaderASCIINonSlash(Context ctx, String str, byte[] bytes, int offset, int length) {
Expand All @@ -11,19 +15,21 @@ public String readString() {
char quote = this.ch;
if (quote == '"' || quote == '\'') {
final byte[] bytes = this.bytes;
int offset = this.offset;
final int start = offset, end = this.end;
valueEscape = false;
for (; ; offset++) {
if (offset >= end) {
throw new JSONException("invalid escape character EOI");
}
if (bytes[offset] == quote) {
break;
}
int offset = IOUtils.indexOfQuote(bytes, quote, start, end);
if (offset == -1) {
throw new JSONException("invalid escape character EOI");
}

String str = subString(bytes, start, offset);
String str = new String(bytes, start, offset - start, StandardCharsets.ISO_8859_1);
long features = context.features;
if ((features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}

int ch = ++offset == end ? EOI : bytes[offset++];
while (ch <= ' ' && (1L << ch & SPACE) != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ public String readString() {
str = new String(chars, start, offset - start);
}

if ((context.features & Feature.TrimString.mask) != 0) {
long features = context.features;
if ((features & Feature.TrimString.mask) != 0) {
str = str.trim();
}
// empty string to null
if (str.isEmpty() && (context.features & Feature.EmptyStringAsNull.mask) != 0) {
if (str.isEmpty() && (features & Feature.EmptyStringAsNull.mask) != 0) {
str = null;
}

Expand Down
21 changes: 5 additions & 16 deletions core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1709,14 +1709,6 @@ public static int digit2(byte[] bytes, int off) {
return (d & 0xF) * 10 + (d >> 8);
}

private static int digit2(int x) {
int d;
if ((((x & 0xF0F0) - 0x3030) | (((d = x & 0x0F0F) + 0x0606) & 0xF0F0)) != 0) {
return -1;
}
return (d & 0xF) * 10 + (d >> 8);
}

public static int digit1(char[] chars, int off) {
int d = UNSAFE.getByte(chars, ARRAY_CHAR_BASE_OFFSET + ((long) off << 1)) - '0';
return d >= 0 && d <= 9 ? d : -1;
Expand Down Expand Up @@ -2075,19 +2067,16 @@ && notContains(d0 | (d1 << 8), 0x5C5C5C5C5C5C5C5CL)
public static boolean isNonSlashASCII(byte[] bytes, int off, int len) {
int end = off + len;
int upperBound = off + (len & ~7);
long address = ARRAY_BYTE_BASE_OFFSET + off;
long d;
long addr = ARRAY_BYTE_BASE_OFFSET + off;
long d, x;
while (off < upperBound
&& ((d = UNSAFE.getLong(bytes, address)) & 0x8080808080808080L) == 0
&& notContains(d, 0x5C5C5C5C5C5C5C5CL)
) {
address += 8;
&& (((d = UNSAFE.getLong(bytes, addr)) | (((x = d ^ 0x5C5C5C5C5C5C5C5CL) - 0x0101010101010101L) & ~x)) & 0x8080808080808080L) == 0) {
addr += 8;
off += 8;
}

while (off++ < end) {
byte b;
if (((b = UNSAFE.getByte(bytes, address++)) & 0x80) != 0 || b == '\\') {
if (((b = UNSAFE.getByte(bytes, addr++)) & 0x80) != 0 || b == '\\') {
return false;
}
}
Expand Down

0 comments on commit 71f84e5

Please sign in to comment.