public String readString()

in core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java [4902:5145]


    public String readString() {
        char quote = this.ch;
        if (quote == '"' || quote == '\'') {
            final byte[] bytes = this.bytes;
            int valueLength;
            int offset = this.offset;
            final int start = offset, end = this.end;
            final long byteVectorQuote = quote == '\'' ? 0x2727_2727_2727_2727L : 0x2222_2222_2222_2222L;
            boolean ascii = true;
            valueEscape = false;

            {
                int i = 0;
                int upperBound = offset + ((end - offset) & ~7);
                while (offset < upperBound) {
                    long v = getLongLE(bytes, offset);
                    if ((v & 0x8080808080808080L) != 0 || JSONReaderUTF8.containsSlashOrQuote(v, byteVectorQuote)) {
                        break;
                    }

                    offset += 8;
                    i += 8;
                }
                // ...

                for (; ; ++i) {
                    if (offset >= end) {
                        throw new JSONException("invalid escape character EOI");
                    }

                    int c = bytes[offset];
                    if (c == '\\') {
                        valueEscape = true;
                        c = bytes[offset + 1];
                        offset += (c == 'u' ? 6 : (c == 'x' ? 4 : 2));
                        if (ascii && (c == 'u' || c == 'x')) {
                            ascii = false;
                        }
                        continue;
                    }

                    if (c >= 0) {
                        if (c == quote) {
                            valueLength = i;
                            break;
                        }
                        offset++;
                    } else {
                        ascii = false;
                        switch ((c & 0xFF) >> 4) {
                            case 12:
                            case 13: {
                                /* 110x xxxx   10xx xxxx*/
                                offset += 2;
                                break;
                            }
                            case 14: {
                                offset += 3;
                                break;
                            }
                            default: {
                                /* 10xx xxxx,  1111 xxxx */
                                if ((c >> 3) == -2) {
                                    offset += 4;
                                    i++;
                                    break;
                                }

                                throw new JSONException("malformed input around byte " + offset);
                            }
                        }
                    }
                }
            }

            String str;
            if (valueEscape) {
                if (ascii && STRING_CREATOR_JDK11 != null) {
                    byte[] chars = new byte[valueLength];
                    offset = start;
                    for (int i = 0; ; ++i) {
                        byte ch = bytes[offset];
                        if (ch == '\\') {
                            ch = bytes[++offset];
                            switch (ch) {
                                case '\\':
                                case '"':
                                    break;
                                case 'b':
                                    ch = '\b';
                                    break;
                                case 't':
                                    ch = '\t';
                                    break;
                                case 'n':
                                    ch = '\n';
                                    break;
                                case 'f':
                                    ch = '\f';
                                    break;
                                case 'r':
                                    ch = '\r';
                                    break;
                                default:
                                    ch = (byte) char1(ch);
                                    break;
                            }
                        }
                        else if (ch == quote) {
                            break;
                        }
                        chars[i] = ch;
                        offset++;
                    }

                    str = STRING_CREATOR_JDK11.apply(chars, LATIN1);
                } else {
                    char[] chars = new char[valueLength];
                    offset = start;
                    for (int i = 0; ; ++i) {
                        int ch = bytes[offset];
                        if (ch == '\\') {
                            ch = bytes[++offset];
                            switch (ch) {
                                case 'u': {
                                    ch = hexDigit4(bytes, check3(offset + 1, end));
                                    offset += 4;
                                    break;
                                }
                                case 'x': {
                                    ch = char2(bytes[offset + 1], bytes[offset + 2]);
                                    offset += 2;
                                    break;
                                }
                                case '\\':
                                case '"':
                                    break;
                                case 'b':
                                    ch = '\b';
                                    break;
                                case 't':
                                    ch = '\t';
                                    break;
                                case 'n':
                                    ch = '\n';
                                    break;
                                case 'f':
                                    ch = '\f';
                                    break;
                                case 'r':
                                    ch = '\r';
                                    break;
                                default:
                                    ch = char1(ch);
                                    break;
                            }
                            chars[i] = (char) ch;
                            offset++;
                        }
                        else if (ch == quote) {
                            break;
                        }
                        else {
                            if (ch >= 0) {
                                chars[i] = (char) ch;
                                offset++;
                            }
                            else {
                                switch ((ch & 0xFF) >> 4) {
                                    case 12:
                                    case 13: {
                                        /* 110x xxxx   10xx xxxx*/
                                        chars[i] = (char) (((ch & 0x1F) << 6) | (bytes[offset + 1] & 0x3F));
                                        offset += 2;
                                        break;
                                    }
                                    case 14: {
                                        chars[i] = (char)
                                                (((ch & 0x0F) << 12) |
                                                        ((bytes[offset + 1] & 0x3F) << 6) |
                                                        ((bytes[offset + 2] & 0x3F) << 0));
                                        offset += 3;
                                        break;
                                    }
                                    default: {
                                        /* 10xx xxxx,  1111 xxxx */
                                        char2_utf8(bytes, offset, ch, chars, i);
                                        offset += 4;
                                        i++;
                                    }
                                }
                            }
                        }
                    }

                    str = new String(chars);
                }
            } else if (ascii) {
                int strlen = offset - start;
                if (strlen == 1) {
                    str = TypeUtils.toString((char) (bytes[start] & 0xff));
                } else if (strlen == 2) {
                    str = TypeUtils.toString(
                            (char) (bytes[start] & 0xff),
                            (char) (bytes[start + 1] & 0xff)
                    );
                } else if (STRING_CREATOR_JDK11 != null) {
                    str = STRING_CREATOR_JDK11.apply(
                            Arrays.copyOfRange(this.bytes, this.offset, offset),
                            LATIN1);
                } else {
                    str = new String(bytes, start, offset - start, StandardCharsets.US_ASCII);
                }
            } else {
                str = new String(bytes, start, offset - start, StandardCharsets.UTF_8);
            }

            long features = context.features;
            if ((features & (MASK_TRIM_STRING | MASK_EMPTY_STRING_AS_NULL)) != 0) {
                str = stringValue(str, features);
            }

            int ch = ++offset == end ? EOI : bytes[offset++];
            while (ch <= ' ' && (1L << ch & SPACE) != 0) {
                ch = offset == end ? EOI : bytes[offset++];
            }

            if (comma = ch == ',') {
                ch = offset == end ? EOI : bytes[offset++];
                while (ch <= ' ' && (1L << ch & SPACE) != 0) {
                    ch = offset == end ? EOI : bytes[offset++];
                }
            }

            this.ch = (char) ch;
            this.offset = offset;
            return str;
        } else if (quote == 'n') {
            readNull();
            return null;
        }

        return readStringNotMatch();
    }