Skip to content

Commit 3f109c4

Browse files
committed
Fix format text parsing
1 parent 86e9a84 commit 3f109c4

1 file changed

Lines changed: 44 additions & 10 deletions

File tree

‎src/plugins/synth/internal/parameters/ParameterExpressionUtils.cpp‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,39 @@ namespace {
1313
return static_cast<double>((value > 0.0) - (value < 0.0));
1414
}
1515

16+
bool parseFixedPointSpecifier(const QString &displayTemplate, qsizetype index,
17+
qsizetype *specifierLength, int *precision = nullptr) {
18+
if (index + 2 >= displayTemplate.size() || displayTemplate.at(index) != u'%'
19+
|| displayTemplate.at(index + 1) != u'.') {
20+
return false;
21+
}
22+
23+
auto cursor = index + 2;
24+
int parsedPrecision{};
25+
bool hasDigit{};
26+
while (cursor < displayTemplate.size()) {
27+
const auto character = displayTemplate.at(cursor);
28+
if (character < u'0' || character > u'9')
29+
break;
30+
31+
const auto digit = character.unicode() - u'0';
32+
if (parsedPrecision > (std::numeric_limits<int>::max() - digit) / 10)
33+
return false;
34+
parsedPrecision = parsedPrecision * 10 + digit;
35+
hasDigit = true;
36+
++cursor;
37+
}
38+
39+
if (!hasDigit || cursor >= displayTemplate.size() || displayTemplate.at(cursor) != u'f')
40+
return false;
41+
42+
if (specifierLength)
43+
*specifierLength = cursor - index + 1;
44+
if (precision)
45+
*precision = parsedPrecision;
46+
return true;
47+
}
48+
1649
}
1750

1851
namespace Synth::Internal::ParameterExpressionUtils {
@@ -62,10 +95,9 @@ namespace Synth::Internal::ParameterExpressionUtils {
6295
index += 2;
6396
continue;
6497
}
65-
if (index + 3 < displayTemplate.size()
66-
&& (displayTemplate.mid(index, 4) == QStringLiteral("%.2f")
67-
|| displayTemplate.mid(index, 4) == QStringLiteral("%.3f"))) {
68-
index += 4;
98+
qsizetype specifierLength{};
99+
if (parseFixedPointSpecifier(displayTemplate, index, &specifierLength)) {
100+
index += specifierLength;
69101
continue;
70102
}
71103
if (errorPosition)
@@ -99,13 +131,15 @@ namespace Synth::Internal::ParameterExpressionUtils {
99131
integerValue = static_cast<qint64>(std::round(value));
100132
result.append(locale.toString(integerValue));
101133
index += 2;
102-
} else if (index + 3 < displayTemplate.size()
103-
&& (displayTemplate.mid(index, 4) == QStringLiteral("%.2f")
104-
|| displayTemplate.mid(index, 4) == QStringLiteral("%.3f"))) {
105-
const int precision = displayTemplate.at(index + 2).digitValue();
106-
result.append(locale.toString(value, 'f', precision));
107-
index += 4;
108134
} else {
135+
qsizetype specifierLength{};
136+
int precision{};
137+
if (parseFixedPointSpecifier(displayTemplate, index, &specifierLength, &precision)) {
138+
result.append(locale.toString(value, 'f', precision));
139+
index += specifierLength;
140+
continue;
141+
}
142+
109143
// Configurations are validated before reaching runtime. Keeping an inert literal
110144
// fallback here prevents an untrusted template from becoming a format string.
111145
result.append(u'%');

0 commit comments

Comments
 (0)