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