52 return m_type == other.m_type &&
53 m_value == other.m_value &&
54 m_startPos == other.m_startPos &&
55 m_endPos == other.m_endPos &&
56 m_mask == other.m_mask &&
57 m_pattern == other.m_pattern &&
58 m_number == other.m_number &&
59 m_numberMask == other.m_numberMask &&
60 m_matchFunction == other.m_matchFunction;
64bool QMimeMagicRule::matchSubstring(
const char *dataPtr, qsizetype dataSize, quint64 rangeStart,
65 quint64 rangeLength, quint64 valueLength,
const char *valueData,
71 const quint64 size = quint64(dataSize);
72 if (rangeStart >= size || valueLength == 0 || rangeLength == 0
73 || valueLength > size - rangeStart)
77 rangeLength = qMin(rangeLength, size - rangeStart);
81 const quint64 dataNeeded = qMin(rangeLength + valueLength - 1, size - rangeStart);
87 for (quint64 i = rangeStart; i < rangeStart + rangeLength; ++i) {
88 if (i + valueLength > size)
91 if (memcmp(valueData, dataPtr + i, size_t(valueLength)) == 0) {
100 const char *readDataBase = dataPtr + rangeStart;
105 const quint64 maxStartPos = dataNeeded - valueLength + 1;
106 for (quint64 i = 0; i < maxStartPos; ++i) {
107 const char *d = readDataBase + i;
109 for (quint64 idx = 0; idx < valueLength; ++idx) {
110 if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx])) {
131 return QMimeMagicRule::matchSubstring(data.constData(), data.size(), m_startPos, rangeLength, m_pattern.size(), m_pattern.constData(), m_mask.constData());
176 return m_regExp->matchView(subject, 0, QRegularExpression::NormalMatch,
181 m_regExp->matchView(subject, 0, QRegularExpression::NormalMatch, options);
191 QByteArray pattern(value.size(), Qt::Uninitialized);
192 char *data = pattern.data();
194 const char *p = value.constData();
195 const char *e = p + value.size();
196 for ( ; p < e; ++p) {
197 if (*p ==
'\\' && ++p < e) {
200 for (
int i = 0; i < 2 && p + 1 < e; ++i) {
201 const int h = fromHex(p[1]);
205 c = i == 0 ?
char(h) :
char((c << 4) + h);
208 }
else if (isOctalDigit(*p)) {
210 if (p + 1 < e && isOctalDigit(p[1])) {
211 c = (c << 3) + *(++p) -
'0';
212 if (p + 1 < e && isOctalDigit(p[1]) && p[-1] <=
'3')
213 c = (c << 3) + *(++p) -
'0';
216 }
else if (*p ==
'n') {
218 }
else if (*p ==
'r') {
220 }
else if (*p ==
't') {
229 pattern.truncate(data - pattern.data());
240 const QString &offsets,
243 QString *errorString)
247 m_matchFunction(
nullptr)
252 *errorString =
"Type regex is only supported in Qt's internal database"_L1;
255 if (Q_UNLIKELY(m_type ==
Invalid)) {
257 *errorString =
"Type "_L1 + type +
" is not supported"_L1;
262 const qsizetype colonIndex = offsets.indexOf(u':');
263 const QStringView startPosStr = QStringView{offsets}.mid(0, colonIndex);
264 const QStringView endPosStr = QStringView{offsets}.mid(colonIndex + 1);
265 if (Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString)) ||
266 Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(endPosStr, &m_endPos, errorString))) {
270 if (m_startPos < 0 || m_endPos < 0 || m_endPos < m_startPos) {
272 *errorString =
"Invalid offset range \""_L1 + offsets + u'"';
277 if (Q_UNLIKELY(m_value.isEmpty())) {
280 *errorString = QStringLiteral(
"Invalid empty magic rule value");
286 m_number = m_value.toUInt(&ok, 0);
287 if (Q_UNLIKELY(!ok)) {
290 *errorString =
"Invalid magic rule value \""_L1 + QLatin1StringView(m_value) + u'"';
293 m_numberMask = !m_mask.isEmpty() ? m_mask.toUInt(&ok, 0) : 0;
298 m_pattern = makePattern(m_value);
300 if (!m_mask.isEmpty()) {
301 if (Q_UNLIKELY(m_mask.size() < 4 || !m_mask.startsWith(
"0x"))) {
304 *errorString =
"Invalid magic rule mask \""_L1 + QLatin1StringView(m_mask) + u'"';
307 const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
308 m_mask.constData() + 2, m_mask.size() - 2));
309 if (Q_UNLIKELY(tempMask.size() != m_pattern.size())) {
312 *errorString =
"Invalid magic rule mask size \""_L1 + QLatin1StringView(m_mask) + u'"';
317 m_mask.fill(
char(-1), m_pattern.size());
323 if (m_number <= quint8(-1)) {
324 if (m_numberMask == 0)
325 m_numberMask = quint8(-1);
326 m_matchFunction = &QMimeMagicRule::matchNumber<quint8>;
331 if (m_number <= quint16(-1)) {
332 m_number = m_type == Little16 ? qFromLittleEndian<quint16>(m_number) : qFromBigEndian<quint16>(m_number);
333 if (m_numberMask != 0)
334 m_numberMask = m_type == Little16 ? qFromLittleEndian<quint16>(m_numberMask) : qFromBigEndian<quint16>(m_numberMask);
338 if (m_number <= quint16(-1)) {
339 if (m_numberMask == 0)
340 m_numberMask = quint16(-1);
341 m_matchFunction = &QMimeMagicRule::matchNumber<quint16>;
346 m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
347 if (m_numberMask != 0)
348 m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
351 if (m_numberMask == 0)
352 m_numberMask = quint32(-1);
353 m_matchFunction = &QMimeMagicRule::matchNumber<quint32>;
356 if (Q_UNLIKELY(!m_mask.isEmpty())) {
359 *errorString =
"Invalid magic rule mask \""_L1 + QLatin1StringView(m_mask)
360 +
"\": regex rules have no mask"_L1;
363#if QT_CONFIG(regularexpression)
365 m_regExp.emplace(QString::fromUtf8(makePattern(m_value)));
366 if (Q_UNLIKELY(!m_regExp->isValid())) {
369 *errorString =
"Invalid regular expression \""_L1 + QString::fromUtf8(m_value)
370 +
"\": "_L1 + m_regExp->errorString();