private int indexOfNextChar()

in src/main/core-api/java/com/mysql/cj/util/StringInspector.java [340:478]


    private int indexOfNextChar(Set<SearchMode> searchMode) {
        if (this.source == null || this.pos >= this.stopAt) {
            return -1;
        }

        char c0 = Character.MIN_VALUE; // Current char.
        char c1 = this.source.charAt(this.pos); // Lookahead(1).
        char c2 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE; // Lookahead(2).

        for (; this.pos < this.stopAt; this.pos++) {
            c0 = c1;
            c1 = c2;
            c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;

            boolean dashDashCommentImmediateEnd = false;
            boolean checkSkipConditions = !searchMode.contains(SearchMode.ALLOW_BACKSLASH_ESCAPE) || !this.escaped;

            if (checkSkipConditions && searchMode.contains(SearchMode.SKIP_BETWEEN_MARKERS) && this.openingMarkers.indexOf(c0) != -1) {
                // Opening marker found, skip until closing.
                indexOfClosingMarker(searchMode);
                if (this.pos >= this.stopAt) {
                    this.pos--; // Reached stop position. Correct position will be set by outer loop.
                } else {
                    // Reset lookahead.
                    c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                    c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;
                }

            } else if (checkSkipConditions && searchMode.contains(SearchMode.SKIP_BLOCK_COMMENTS) && c0 == '/' && c1 == '*' && c2 != '!' && c2 != '+') {
                // Comments block found, skip until end of block ("*/") (backslash escape doesn't work in comments).
                // Does not include hint blocks ("/*!" or "/*+").
                this.pos++; // Move to next char ('*').
                while (++this.pos < this.stopAt && (this.source.charAt(this.pos) != '*'
                        || (this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE) != '/')) {
                    // Continue
                }
                if (this.pos >= this.stopAt) {
                    this.pos--; // Reached stop position. Correct position will be set by outer loop.
                } else {
                    this.pos++; // Move to next char ('/').
                }

                // Reset lookahead.
                c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;

            } else if (checkSkipConditions && searchMode.contains(SearchMode.SKIP_LINE_COMMENTS)
                    && (c0 == '-' && c1 == '-' && (Character.isWhitespace(c2) || (dashDashCommentImmediateEnd = c2 == ';') || c2 == Character.MIN_VALUE)
                            || c0 == '#')) {
                if (dashDashCommentImmediateEnd) {
                    // Comments line found but closed immediately by query delimiter marker.
                    this.pos++; // Move to next char ('-').
                    this.pos++; // Move to next char (';').
                    // Reset lookahead.
                    c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                    c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;
                } else {
                    // Comments line found, skip until EOL (backslash escape doesn't work on comments).
                    while (++this.pos < this.stopAt && (c0 = this.source.charAt(this.pos)) != '\n' && c0 != '\r') {
                        // Continue.
                    }
                    if (this.pos >= this.stopAt) {
                        this.pos--; // Reached stop position. Correct position will be set by outer loop.
                    } else {
                        // Reset lookahead.
                        c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                        if (c0 == '\r' && c1 == '\n') {
                            // \r\n sequence found.
                            this.pos++; // Skip next char ('\n').
                            c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                        }
                        c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;
                    }
                }

            } else if (checkSkipConditions && searchMode.contains(SearchMode.SKIP_HINT_BLOCKS) && c0 == '/' && c1 == '*' && c2 == '+') {
                // Hints block found, skip until end of block ("*/") (backslash escape doesn't work in hints).
                this.pos++; // Move to next char ('*').
                this.pos++; // Move to next char ('+').
                while (++this.pos < this.stopAt && (this.source.charAt(this.pos) != '*'
                        || (this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE) != '/')) {
                    // Continue
                }
                if (this.pos >= this.stopAt) {
                    this.pos--; // Reached stop position. Correct position will be set by outer loop.
                } else {
                    this.pos++; // Move to next char ('/').
                }

                // Reset lookahead.
                c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;

            } else if (checkSkipConditions && searchMode.contains(SearchMode.SKIP_MYSQL_MARKERS) && c0 == '/' && c1 == '*' && c2 == '!') {
                // MySQL specific block found, move to end of opening marker ("/*![12345]").
                this.pos++; // Move to next char ('*').
                this.pos++; // Move to next char ('!').
                if (c2 == '!') {
                    // Check if 5 digits MySQL version reference comes next, if so skip them.
                    int i = 0;
                    for (; i < NON_COMMENTS_MYSQL_VERSION_REF_LENGTH; i++) {
                        if (this.pos + 1 + i >= this.srcLen || !Character.isDigit(this.source.charAt(this.pos + 1 + i))) {
                            break;
                        }
                    }
                    if (i == NON_COMMENTS_MYSQL_VERSION_REF_LENGTH) {
                        this.pos += NON_COMMENTS_MYSQL_VERSION_REF_LENGTH;
                        if (this.pos >= this.stopAt) {
                            this.pos = this.stopAt - 1; // Reached stop position. Correct position will be set by outer loop.
                        }
                    }
                }

                // Reset lookahead.
                c1 = this.pos + 1 < this.srcLen ? this.source.charAt(this.pos + 1) : Character.MIN_VALUE;
                c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;

                this.inMysqlBlock = true;

            } else if (this.inMysqlBlock && checkSkipConditions && searchMode.contains(SearchMode.SKIP_MYSQL_MARKERS) && c0 == '*' && c1 == '/') {
                // MySQL block closing marker ("*/") found.
                this.pos++; // move to next char ('/')
                // Reset lookahead.
                c1 = c2;
                c2 = this.pos + 2 < this.srcLen ? this.source.charAt(this.pos + 2) : Character.MIN_VALUE;

                this.inMysqlBlock = false;

            } else if (!searchMode.contains(SearchMode.SKIP_WHITE_SPACE) || !Character.isWhitespace(c0)) {
                // Whitespace is not affected by backslash escapes.
                return this.pos;
            }

            // Reaching here means that the position has incremented thus an 'escaped' status no longer holds.
            this.escaped = false;
        }

        return -1;
    }