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,
int rangeStart,
int rangeLength,
64 qsizetype valueLength,
const char *valueData,
const char *mask)
68 const qsizetype dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart);
74 for (
int i = rangeStart; i < rangeStart + rangeLength; ++i) {
75 if (i + valueLength > dataSize)
78 if (memcmp(valueData, dataPtr + i, valueLength) == 0) {
87 const char *readDataBase = dataPtr + rangeStart;
92 const qsizetype maxStartPos = dataNeeded - valueLength + 1;
93 for (
int i = 0; i < maxStartPos; ++i) {
94 const char *d = readDataBase + i;
96 for (
int idx = 0; idx < valueLength; ++idx) {
97 if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx])) {
115 return QMimeMagicRule::matchSubstring(data.constData(), data.size(), m_startPos, rangeLength, m_pattern.size(), m_pattern.constData(), m_mask.constData());
139 QByteArray pattern(value.size(), Qt::Uninitialized);
140 char *data = pattern.data();
142 const char *p = value.constData();
143 const char *e = p + value.size();
144 for ( ; p < e; ++p) {
145 if (*p ==
'\\' && ++p < e) {
148 for (
int i = 0; i < 2 && p + 1 < e; ++i) {
150 if (
const int h = fromHex(*p); h != -1)
156 }
else if (isOctalDigit(*p)) {
158 if (p + 1 < e && isOctalDigit(p[1])) {
159 c = (c << 3) + *(++p) -
'0';
160 if (p + 1 < e && isOctalDigit(p[1]) && p[-1] <=
'3')
161 c = (c << 3) + *(++p) -
'0';
164 }
else if (*p ==
'n') {
166 }
else if (*p ==
'r') {
168 }
else if (*p ==
't') {
177 pattern.truncate(data - pattern.data());
186QMimeMagicRule::QMimeMagicRule(
const QString &type,
188 const QString &offsets,
190 QString *errorString)
191 : m_type(QMimeMagicRule::type(type.toLatin1())),
194 m_matchFunction(
nullptr)
196 if (Q_UNLIKELY(m_type == Invalid)) {
198 *errorString =
"Type "_L1 + type +
" is not supported"_L1;
203 const qsizetype colonIndex = offsets.indexOf(u':');
204 const QStringView startPosStr = QStringView{offsets}.mid(0, colonIndex);
205 const QStringView endPosStr = QStringView{offsets}.mid(colonIndex + 1);
206 if (Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(startPosStr, &m_startPos, errorString)) ||
207 Q_UNLIKELY(!QMimeTypeParserBase::parseNumber(endPosStr, &m_endPos, errorString))) {
212 if (Q_UNLIKELY(m_value.isEmpty())) {
215 *errorString = QStringLiteral(
"Invalid empty magic rule value");
219 if (m_type >= Host16 && m_type <= Byte) {
221 m_number = m_value.toUInt(&ok, 0);
222 if (Q_UNLIKELY(!ok)) {
225 *errorString =
"Invalid magic rule value \""_L1 + QLatin1StringView(m_value) + u'"';
228 m_numberMask = !m_mask.isEmpty() ? m_mask.toUInt(&ok, 0) : 0;
233 m_pattern = makePattern(m_value);
235 if (!m_mask.isEmpty()) {
236 if (Q_UNLIKELY(m_mask.size() < 4 || !m_mask.startsWith(
"0x"))) {
239 *errorString =
"Invalid magic rule mask \""_L1 + QLatin1StringView(m_mask) + u'"';
242 const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
243 m_mask.constData() + 2, m_mask.size() - 2));
244 if (Q_UNLIKELY(tempMask.size() != m_pattern.size())) {
247 *errorString =
"Invalid magic rule mask size \""_L1 + QLatin1StringView(m_mask) + u'"';
252 m_mask.fill(
char(-1), m_pattern.size());
255 m_matchFunction = &QMimeMagicRule::matchString;
258 if (m_number <= quint8(-1)) {
259 if (m_numberMask == 0)
260 m_numberMask = quint8(-1);
261 m_matchFunction = &QMimeMagicRule::matchNumber<quint8>;
266 if (m_number <= quint16(-1)) {
267 m_number = m_type == Little16 ? qFromLittleEndian<quint16>(m_number) : qFromBigEndian<quint16>(m_number);
268 if (m_numberMask != 0)
269 m_numberMask = m_type == Little16 ? qFromLittleEndian<quint16>(m_numberMask) : qFromBigEndian<quint16>(m_numberMask);
273 if (m_number <= quint16(-1)) {
274 if (m_numberMask == 0)
275 m_numberMask = quint16(-1);
276 m_matchFunction = &QMimeMagicRule::matchNumber<quint16>;
281 m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
282 if (m_numberMask != 0)
283 m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
286 if (m_numberMask == 0)
287 m_numberMask = quint32(-1);
288 m_matchFunction = &QMimeMagicRule::matchNumber<quint32>;