Fixes for findVersionDirectivePosition()
The old code was wrong as it used QString::fromUtf8() to convert the char * array to a QString. This could lead to wrong positions when trying to find the #version directive, as any valid utf8 sequence in a comment before could have lead to wrong offsets compared to the 8 bit data. Fix this and optimize the code at the same time to avoid creating a copy of the data and using QRegularExpression. Also fixes building Qt with -no-feature-regularexpression Change-Id: I2d84875ef59b3a0fb4d8b069bf56f4372c57ccdc Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
parent
01c3565d3e
commit
c442244907
@ -432,73 +432,84 @@ static QVersionDirectivePosition findVersionDirectivePosition(const char *source
|
|||||||
{
|
{
|
||||||
Q_ASSERT(source);
|
Q_ASSERT(source);
|
||||||
|
|
||||||
QString working = QString::fromUtf8(source);
|
|
||||||
|
|
||||||
// According to the GLSL spec the #version directive must not be
|
// According to the GLSL spec the #version directive must not be
|
||||||
// preceded by anything but whitespace and comments.
|
// preceded by anything but whitespace and comments.
|
||||||
// In order to not get confused by #version directives within a
|
// In order to not get confused by #version directives within a
|
||||||
// multiline comment, we need to run a minimal preprocessor first.
|
// multiline comment, we need to do some minimal comment parsing
|
||||||
|
// while searching for the directive.
|
||||||
enum {
|
enum {
|
||||||
Normal,
|
Normal,
|
||||||
|
StartOfLine,
|
||||||
|
PreprocessorDirective,
|
||||||
CommentStarting,
|
CommentStarting,
|
||||||
MultiLineComment,
|
MultiLineComment,
|
||||||
SingleLineComment,
|
SingleLineComment,
|
||||||
CommentEnding
|
CommentEnding
|
||||||
} state = Normal;
|
} state = StartOfLine;
|
||||||
|
|
||||||
for (QChar *c = working.begin(); c != working.end(); ++c) {
|
const char *c = source;
|
||||||
|
while (*c) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Normal:
|
case PreprocessorDirective:
|
||||||
if (*c == QLatin1Char('/'))
|
if (*c == ' ' || *c == '\t')
|
||||||
|
break;
|
||||||
|
if (!strncmp(c, "version", strlen("version"))) {
|
||||||
|
// Found version directive
|
||||||
|
c += strlen("version");
|
||||||
|
while (*c && *c != '\n')
|
||||||
|
++c;
|
||||||
|
int splitPosition = c - source + 1;
|
||||||
|
int linePosition = int(std::count(source, c, '\n')) + 1;
|
||||||
|
return QVersionDirectivePosition(splitPosition, linePosition);
|
||||||
|
} else if (*c == '/')
|
||||||
state = CommentStarting;
|
state = CommentStarting;
|
||||||
|
else if (*c == '\n')
|
||||||
|
state = StartOfLine;
|
||||||
|
else
|
||||||
|
state = Normal;
|
||||||
|
break;
|
||||||
|
case StartOfLine:
|
||||||
|
if (*c == ' ' || *c == '\t')
|
||||||
|
break;
|
||||||
|
else if (*c == '#') {
|
||||||
|
state = PreprocessorDirective;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = Normal;
|
||||||
|
// fall through
|
||||||
|
case Normal:
|
||||||
|
if (*c == '/')
|
||||||
|
state = CommentStarting;
|
||||||
|
else if (*c == '\n')
|
||||||
|
state = StartOfLine;
|
||||||
break;
|
break;
|
||||||
case CommentStarting:
|
case CommentStarting:
|
||||||
if (*c == QLatin1Char('*'))
|
if (*c == '*')
|
||||||
state = MultiLineComment;
|
state = MultiLineComment;
|
||||||
else if (*c == QLatin1Char('/'))
|
else if (*c == '/')
|
||||||
state = SingleLineComment;
|
state = SingleLineComment;
|
||||||
else
|
else
|
||||||
state = Normal;
|
state = Normal;
|
||||||
break;
|
break;
|
||||||
case MultiLineComment:
|
case MultiLineComment:
|
||||||
if (*c == QLatin1Char('*'))
|
if (*c == '*')
|
||||||
state = CommentEnding;
|
state = CommentEnding;
|
||||||
else if (*c == QLatin1Char('#'))
|
|
||||||
*c = QLatin1Char('_');
|
|
||||||
break;
|
break;
|
||||||
case SingleLineComment:
|
case SingleLineComment:
|
||||||
if (*c == QLatin1Char('\n'))
|
if (*c == '\n')
|
||||||
state = Normal;
|
state = Normal;
|
||||||
else if (*c == QLatin1Char('#'))
|
|
||||||
*c = QLatin1Char('_');
|
|
||||||
break;
|
break;
|
||||||
case CommentEnding:
|
case CommentEnding:
|
||||||
if (*c == QLatin1Char('/')) {
|
if (*c == '/')
|
||||||
state = Normal;
|
state = Normal;
|
||||||
} else {
|
else if (*c != QLatin1Char('*'))
|
||||||
if (*c == QLatin1Char('#'))
|
|
||||||
*c = QLatin1Char('_');
|
|
||||||
if (*c != QLatin1Char('*'))
|
|
||||||
state = MultiLineComment;
|
state = MultiLineComment;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
++c;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for #version directive
|
return QVersionDirectivePosition(0, 1);
|
||||||
int splitPosition = 0;
|
|
||||||
int linePosition = 1;
|
|
||||||
|
|
||||||
static const QRegularExpression pattern(QStringLiteral("^\\s*#\\s*version.*(\\n)?"),
|
|
||||||
QRegularExpression::MultilineOption
|
|
||||||
| QRegularExpression::OptimizeOnFirstUsageOption);
|
|
||||||
QRegularExpressionMatch match = pattern.match(working);
|
|
||||||
if (match.hasMatch()) {
|
|
||||||
splitPosition = match.capturedEnd();
|
|
||||||
linePosition += int(std::count(working.begin(), working.begin() + splitPosition, QLatin1Char('\n')));
|
|
||||||
}
|
|
||||||
|
|
||||||
return QVersionDirectivePosition(splitPosition, linePosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user