49bool QMimeMagicRule::operator==(
const QMimeMagicRule &other)
const
51 return m_type == other.m_type &&
52 m_value == other.m_value &&
53 m_startPos == other.m_startPos &&
54 m_endPos == other.m_endPos &&
55 m_mask == other.m_mask &&
56 m_pattern == other.m_pattern &&
57 m_number == other.m_number &&
58 m_numberMask == other.m_numberMask &&
59 m_matchFunction == other.m_matchFunction;
63bool QMimeMagicRule::matchSubstring(
const char *dataPtr, qsizetype dataSize, quint64 rangeStart,
64 quint64 rangeLength, quint64 valueLength,
const char *valueData,
70 const quint64 size = quint64(dataSize);
71 if (rangeStart >= size || valueLength == 0 || rangeLength == 0
72 || valueLength > size - rangeStart)
76 rangeLength = qMin(rangeLength, size - rangeStart);
80 const quint64 dataNeeded = qMin(rangeLength + valueLength - 1, size - rangeStart);
86 for (quint64 i = rangeStart; i < rangeStart + rangeLength; ++i) {
87 if (i + valueLength > size)
90 if (memcmp(valueData, dataPtr + i, size_t(valueLength)) == 0) {
99 const char *readDataBase = dataPtr + rangeStart;
104 const quint64 maxStartPos = dataNeeded - valueLength + 1;
105 for (quint64 i = 0; i < maxStartPos; ++i) {
106 const char *d = readDataBase + i;
108 for (quint64 idx = 0; idx < valueLength; ++idx) {
109 if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx])) {
129 return QMimeMagicRule::matchSubstring(data.constData(), data.size(), m_startPos, rangeLength, m_pattern.size(), m_pattern.constData(), m_mask.constData());
153 QByteArray pattern(value.size(), Qt::Uninitialized);
154 char *data = pattern.data();
156 const char *p = value.constData();
157 const char *e = p + value.size();
158 for ( ; p < e; ++p) {
159 if (*p ==
'\\' && ++p < e) {
162 for (
int i = 0; i < 2 && p + 1 < e; ++i) {
164 if (
const int h = fromHex(*p); h != -1)
170 }
else if (isOctalDigit(*p)) {
172 if (p + 1 < e && isOctalDigit(p[1])) {
173 c = (c << 3) + *(++p) -
'0';
174 if (p + 1 < e && isOctalDigit(p[1]) && p[-1] <=
'3')
175 c = (c << 3) + *(++p) -
'0';
178 }
else if (*p ==
'n') {
180 }
else if (*p ==
'r') {
182 }
else if (*p ==
't') {
191 pattern.truncate(data - pattern.data());
200QMimeMagicRule::QMimeMagicRule(
const QString &type,
202 const QString &offsets,
204 QString *errorString)
205 : m_type(QMimeMagicRule::type(type.toLatin1())),
208 m_matchFunction(
nullptr)
210 if (Q_UNLIKELY(m_type == Invalid)) {
212 *errorString =
"Type "_L1 + type +
" is not supported"_L1;
217 const qsizetype colonIndex = offsets.indexOf(u':');
218 const QStringView startPosStr = QStringView{offsets}.mid(0, colonIndex);
219 const QStringView endPosStr = QStringView{offsets}.mid(colonIndex + 1);
220 if (Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString)) ||
221 Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(endPosStr, &m_endPos, errorString))) {
225 if (m_startPos < 0 || m_endPos < 0 || m_endPos < m_startPos) {
227 *errorString =
"Invalid offset range \""_L1 + offsets + u'"';
232 if (Q_UNLIKELY(m_value.isEmpty())) {
235 *errorString = QStringLiteral(
"Invalid empty magic rule value");
239 if (m_type >= Host16 && m_type <= Byte) {
241 m_number = m_value.toUInt(&ok, 0);
242 if (Q_UNLIKELY(!ok)) {
245 *errorString =
"Invalid magic rule value \""_L1 + QLatin1StringView(m_value) + u'"';
248 m_numberMask = !m_mask.isEmpty() ? m_mask.toUInt(&ok, 0) : 0;
253 m_pattern = makePattern(m_value);
255 if (!m_mask.isEmpty()) {
256 if (Q_UNLIKELY(m_mask.size() < 4 || !m_mask.startsWith(
"0x"))) {
259 *errorString =
"Invalid magic rule mask \""_L1 + QLatin1StringView(m_mask) + u'"';
262 const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
263 m_mask.constData() + 2, m_mask.size() - 2));
264 if (Q_UNLIKELY(tempMask.size() != m_pattern.size())) {
267 *errorString =
"Invalid magic rule mask size \""_L1 + QLatin1StringView(m_mask) + u'"';
272 m_mask.fill(
char(-1), m_pattern.size());
275 m_matchFunction = &QMimeMagicRule::matchString;
278 if (m_number <= quint8(-1)) {
279 if (m_numberMask == 0)
280 m_numberMask = quint8(-1);
281 m_matchFunction = &QMimeMagicRule::matchNumber<quint8>;
286 if (m_number <= quint16(-1)) {
287 m_number = m_type == Little16 ? qFromLittleEndian<quint16>(m_number) : qFromBigEndian<quint16>(m_number);
288 if (m_numberMask != 0)
289 m_numberMask = m_type == Little16 ? qFromLittleEndian<quint16>(m_numberMask) : qFromBigEndian<quint16>(m_numberMask);
293 if (m_number <= quint16(-1)) {
294 if (m_numberMask == 0)
295 m_numberMask = quint16(-1);
296 m_matchFunction = &QMimeMagicRule::matchNumber<quint16>;
301 m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
302 if (m_numberMask != 0)
303 m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
306 if (m_numberMask == 0)
307 m_numberMask = quint32(-1);
308 m_matchFunction = &QMimeMagicRule::matchNumber<quint32>;