mimetypes/qmimemagicrule.cpp

Switch to Source codePreprocessed file
LineSource CodeCoverage
1 -
2 -
3 -
4 -
5 -
6static const char magicRuleTypes_string[] = -
7 "invalid\0" -
8 "string\0" -
9 "host16\0" -
10 "host32\0" -
11 "big16\0" -
12 "big32\0" -
13 "little16\0" -
14 "little32\0" -
15 "byte\0" -
16 "\0"; -
17 -
18static const int magicRuleTypes_indices[] = { -
19 0, 8, 15, 22, 29, 35, 41, 50, 59, 65, 0 -
20}; -
21 -
22QMimeMagicRule::Type QMimeMagicRule::type(const QByteArray &theTypeName) -
23{ -
24 for (int i = String; i <= Byte; ++i) {
never evaluated: i <= Byte
0
25 if (theTypeName == magicRuleTypes_string + magicRuleTypes_indices[i])
never evaluated: theTypeName == magicRuleTypes_string + magicRuleTypes_indices[i]
0
26 return Type(i);
never executed: return Type(i);
0
27 }
never executed: }
0
28 return Invalid;
never executed: return Invalid;
0
29} -
30 -
31QByteArray QMimeMagicRule::typeName(QMimeMagicRule::Type theType) -
32{ -
33 return magicRuleTypes_string + magicRuleTypes_indices[theType];
never executed: return magicRuleTypes_string + magicRuleTypes_indices[theType];
0
34} -
35 -
36class QMimeMagicRulePrivate -
37{ -
38public: -
39 bool operator==(const QMimeMagicRulePrivate &other) const; -
40 -
41 QMimeMagicRule::Type type; -
42 QByteArray value; -
43 int startPos; -
44 int endPos; -
45 QByteArray mask; -
46 -
47 QByteArray pattern; -
48 quint32 number; -
49 quint32 numberMask; -
50 -
51 typedef bool (*MatchFunction)(const QMimeMagicRulePrivate *d, const QByteArray &data); -
52 MatchFunction matchFunction; -
53}; -
54 -
55bool QMimeMagicRulePrivate::operator==(const QMimeMagicRulePrivate &other) const -
56{ -
57 return type == other.type && 0
58 value == other.value && 0
59 startPos == other.startPos && 0
60 endPos == other.endPos && 0
61 mask == other.mask && 0
62 pattern == other.pattern && 0
63 number == other.number && 0
64 numberMask == other.numberMask && 0
65 matchFunction == other.matchFunction;
never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
0
66} -
67 -
68 -
69bool QMimeMagicRule::matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength, -
70 int valueLength, const char *valueData, const char *mask) -
71{ -
72 -
73 -
74 const int dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart); -
75 -
76 if (!mask) {
evaluated: !mask
TRUEFALSE
yes
Evaluation Count:8252
yes
Evaluation Count:180
180-8252
77 -
78 -
79 bool found = false; -
80 for (int i = rangeStart; i < rangeStart + rangeLength; ++i) {
evaluated: i < rangeStart + rangeLength
TRUEFALSE
yes
Evaluation Count:37617
yes
Evaluation Count:5204
5204-37617
81 if (i + valueLength > dataSize)
evaluated: i + valueLength > dataSize
TRUEFALSE
yes
Evaluation Count:3008
yes
Evaluation Count:34609
3008-34609
82 break;
executed: break;
Execution Count:3008
3008
83 -
84 if (memcmp(valueData, dataPtr + i, valueLength) == 0) {
evaluated: memcmp(valueData, dataPtr + i, valueLength) == 0
TRUEFALSE
yes
Evaluation Count:40
yes
Evaluation Count:34569
40-34569
85 found = true; -
86 break;
executed: break;
Execution Count:40
40
87 } -
88 }
executed: }
Execution Count:34569
34569
89 if (!found)
evaluated: !found
TRUEFALSE
yes
Evaluation Count:8212
yes
Evaluation Count:40
40-8212
90 return false;
executed: return false;
Execution Count:8212
8212
91 } else {
executed: }
Execution Count:40
40
92 bool found = false; -
93 const char *readDataBase = dataPtr + rangeStart; -
94 -
95 -
96 -
97 -
98 const int maxStartPos = dataNeeded - valueLength + 1; -
99 for (int i = 0; i < maxStartPos; ++i) {
evaluated: i < maxStartPos
TRUEFALSE
yes
Evaluation Count:128
yes
Evaluation Count:180
128-180
100 const char *d = readDataBase + i; -
101 bool valid = true; -
102 for (int idx = 0; idx < valueLength; ++idx) {
partially evaluated: idx < valueLength
TRUEFALSE
yes
Evaluation Count:192
no
Evaluation Count:0
0-192
103 if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx])) {
evaluated: ((*d++) & mask[idx]) != (valueData[idx] & mask[idx])
TRUEFALSE
yes
Evaluation Count:128
yes
Evaluation Count:64
64-128
104 valid = false; -
105 break;
executed: break;
Execution Count:128
128
106 } -
107 }
executed: }
Execution Count:64
64
108 if (valid)
partially evaluated: valid
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:128
0-128
109 found = true;
never executed: found = true;
0
110 }
executed: }
Execution Count:128
128
111 if (!found)
partially evaluated: !found
TRUEFALSE
yes
Evaluation Count:180
no
Evaluation Count:0
0-180
112 return false;
executed: return false;
Execution Count:180
180
113 }
never executed: }
0
114 -
115 return true;
executed: return true;
Execution Count:40
40
116} -
117 -
118static bool matchString(const QMimeMagicRulePrivate *d, const QByteArray &data) -
119{ -
120 const int rangeLength = d->endPos - d->startPos + 1; -
121 return QMimeMagicRule::matchSubstring(data.constData(), data.size(), d->startPos, rangeLength, d->pattern.size(), d->pattern.constData(), d->mask.constData());
never executed: return QMimeMagicRule::matchSubstring(data.constData(), data.size(), d->startPos, rangeLength, d->pattern.size(), d->pattern.constData(), d->mask.constData());
0
122} -
123 -
124template <typename T> -
125static bool matchNumber(const QMimeMagicRulePrivate *d, const QByteArray &data) -
126{ -
127 const T value(d->number); -
128 const T mask(d->numberMask); -
129 -
130 -
131 -
132 -
133 const char *p = data.constData() + d->startPos; -
134 const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), d->endPos + 1); -
135 for ( ; p <= e; ++p) {
never evaluated: p <= e
0
136 if ((*reinterpret_cast<const T*>(p) & mask) == (value & mask))
never evaluated: (*reinterpret_cast<const T*>(p) & mask) == (value & mask)
0
137 return true;
never executed: return true;
0
138 }
never executed: }
0
139 -
140 return false;
never executed: return false;
0
141} -
142 -
143static inline QByteArray makePattern(const QByteArray &value) -
144{ -
145 QByteArray pattern(value.size(), Qt::Uninitialized); -
146 char *data = pattern.data(); -
147 -
148 const char *p = value.constData(); -
149 const char *e = p + value.size(); -
150 for ( ; p < e; ++p) {
never evaluated: p < e
0
151 if (*p == '\\' && ++p < e) {
never evaluated: *p == '\\'
never evaluated: ++p < e
0
152 if (*p == 'x') {
never evaluated: *p == 'x'
0
153 char c = 0; -
154 for (int i = 0; i < 2 && p + 1 < e; ++i) {
never evaluated: i < 2
never evaluated: p + 1 < e
0
155 ++p; -
156 if (*p >= '0' && *p <= '9')
never evaluated: *p >= '0'
never evaluated: *p <= '9'
0
157 c = (c << 4) + *p - '0';
never executed: c = (c << 4) + *p - '0';
0
158 else if (*p >= 'a' && *p <= 'f')
never evaluated: *p >= 'a'
never evaluated: *p <= 'f'
0
159 c = (c << 4) + *p - 'a' + 10;
never executed: c = (c << 4) + *p - 'a' + 10;
0
160 else if (*p >= 'A' && *p <= 'F')
never evaluated: *p >= 'A'
never evaluated: *p <= 'F'
0
161 c = (c << 4) + *p - 'A' + 10;
never executed: c = (c << 4) + *p - 'A' + 10;
0
162 else -
163 continue;
never executed: continue;
0
164 } -
165 *data++ = c; -
166 } else if (*p >= '0' && *p <= '7') {
never evaluated: *p >= '0'
never evaluated: *p <= '7'
never executed: }
0
167 char c = *p - '0'; -
168 if (p + 1 < e && p[1] >= '0' && p[1] <= '7') {
never evaluated: p + 1 < e
never evaluated: p[1] >= '0'
never evaluated: p[1] <= '7'
0
169 c = (c << 3) + *(++p) - '0'; -
170 if (p + 1 < e && p[1] >= '0' && p[1] <= '7' && p[-1] <= '3')
never evaluated: p + 1 < e
never evaluated: p[1] >= '0'
never evaluated: p[1] <= '7'
never evaluated: p[-1] <= '3'
0
171 c = (c << 3) + *(++p) - '0';
never executed: c = (c << 3) + *(++p) - '0';
0
172 }
never executed: }
0
173 *data++ = c; -
174 } else if (*p == 'n') {
never executed: }
never evaluated: *p == 'n'
0
175 *data++ = '\n'; -
176 } else if (*p == 'r') {
never executed: }
never evaluated: *p == 'r'
0
177 *data++ = '\r'; -
178 } else {
never executed: }
0
179 *data++ = *p; -
180 }
never executed: }
0
181 } else { -
182 *data++ = *p; -
183 }
never executed: }
0
184 } -
185 pattern.truncate(data - pattern.data()); -
186 -
187 return pattern;
never executed: return pattern;
0
188} -
189 -
190QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType, -
191 const QByteArray &theValue, -
192 int theStartPos, -
193 int theEndPos, -
194 const QByteArray &theMask) : -
195 d(new QMimeMagicRulePrivate) -
196{ -
197 qt_noop(); -
198 -
199 d->type = theType; -
200 d->value = theValue; -
201 d->startPos = theStartPos; -
202 d->endPos = theEndPos; -
203 d->mask = theMask; -
204 d->matchFunction = 0; -
205 -
206 if (d->type >= Host16 && d->type <= Byte) {
never evaluated: d->type >= Host16
never evaluated: d->type <= Byte
0
207 bool ok; -
208 d->number = d->value.toUInt(&ok, 0); -
209 qt_noop(); -
210 d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0;
never evaluated: !d->mask.isEmpty()
0
211 }
never executed: }
0
212 -
213 switch (d->type) { -
214 case String: -
215 d->pattern = makePattern(d->value); -
216 d->pattern.squeeze(); -
217 if (!d->mask.isEmpty()) {
never evaluated: !d->mask.isEmpty()
0
218 qt_noop(); -
219 d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2)); -
220 qt_noop(); -
221 } else {
never executed: }
0
222 d->mask.fill(char(-1), d->pattern.size()); -
223 }
never executed: }
0
224 d->mask.squeeze(); -
225 d->matchFunction = matchString; -
226 break;
never executed: break;
0
227 case Byte: -
228 if (d->number <= quint8(-1)) {
never evaluated: d->number <= quint8(-1)
0
229 if (d->numberMask == 0)
never evaluated: d->numberMask == 0
0
230 d->numberMask = quint8(-1);
never executed: d->numberMask = quint8(-1);
0
231 d->matchFunction = matchNumber<quint8>; -
232 }
never executed: }
0
233 break;
never executed: break;
0
234 case Big16: -
235 case Host16: -
236 case Little16: -
237 if (d->number <= quint16(-1)) {
never evaluated: d->number <= quint16(-1)
0
238 d->number = d->type == Little16 ? qFromLittleEndian<quint16>(d->number) : qFromBigEndian<quint16>(d->number);
never evaluated: d->type == Little16
0
239 if (d->numberMask == 0)
never evaluated: d->numberMask == 0
0
240 d->numberMask = quint16(-1);
never executed: d->numberMask = quint16(-1);
0
241 d->matchFunction = matchNumber<quint16>; -
242 }
never executed: }
0
243 break;
never executed: break;
0
244 case Big32: -
245 case Host32: -
246 case Little32: -
247 if (d->number <= quint32(-1)) {
never evaluated: d->number <= quint32(-1)
0
248 d->number = d->type == Little32 ? qFromLittleEndian<quint32>(d->number) : qFromBigEndian<quint32>(d->number);
never evaluated: d->type == Little32
0
249 if (d->numberMask == 0)
never evaluated: d->numberMask == 0
0
250 d->numberMask = quint32(-1);
never executed: d->numberMask = quint32(-1);
0
251 d->matchFunction = matchNumber<quint32>; -
252 }
never executed: }
0
253 break;
never executed: break;
0
254 default: -
255 break;
never executed: break;
0
256 } -
257}
never executed: }
0
258 -
259QMimeMagicRule::QMimeMagicRule(const QMimeMagicRule &other) : -
260 d(new QMimeMagicRulePrivate(*other.d)) -
261{ -
262}
never executed: }
0
263 -
264QMimeMagicRule::~QMimeMagicRule() -
265{ -
266} -
267 -
268QMimeMagicRule &QMimeMagicRule::operator=(const QMimeMagicRule &other) -
269{ -
270 *d = *other.d; -
271 return *this;
never executed: return *this;
0
272} -
273 -
274bool QMimeMagicRule::operator==(const QMimeMagicRule &other) const -
275{ -
276 return d == other.d || 0
277 *d == *other.d;
never executed: return d == other.d || *d == *other.d;
0
278} -
279 -
280QMimeMagicRule::Type QMimeMagicRule::type() const -
281{ -
282 return d->type;
never executed: return d->type;
0
283} -
284 -
285QByteArray QMimeMagicRule::value() const -
286{ -
287 return d->value;
never executed: return d->value;
0
288} -
289 -
290int QMimeMagicRule::startPos() const -
291{ -
292 return d->startPos;
never executed: return d->startPos;
0
293} -
294 -
295int QMimeMagicRule::endPos() const -
296{ -
297 return d->endPos;
never executed: return d->endPos;
0
298} -
299 -
300QByteArray QMimeMagicRule::mask() const -
301{ -
302 QByteArray result = d->mask; -
303 if (d->type == String) {
never evaluated: d->type == String
0
304 -
305 result = "0x" + result.toHex(); -
306 }
never executed: }
0
307 return result;
never executed: return result;
0
308} -
309 -
310bool QMimeMagicRule::isValid() const -
311{ -
312 return d->matchFunction;
never executed: return d->matchFunction;
0
313} -
314 -
315bool QMimeMagicRule::matches(const QByteArray &data) const -
316{ -
317 const bool ok = d->matchFunction && d->matchFunction(d.data(), data);
never evaluated: d->matchFunction
never evaluated: d->matchFunction(d.data(), data)
0
318 if (!ok)
never evaluated: !ok
0
319 return false;
never executed: return false;
0
320 -
321 -
322 if (m_subMatches.isEmpty())
never evaluated: m_subMatches.isEmpty()
0
323 return true;
never executed: return true;
0
324 -
325 -
326 -
327 for ( QList<QMimeMagicRule>::const_iterator it = m_subMatches.begin(), end = m_subMatches.end() ; -
328 it != end ; ++it ) {
never evaluated: it != end
0
329 if ((*it).matches(data)) {
never evaluated: (*it).matches(data)
0
330 -
331 return true;
never executed: return true;
0
332 } -
333 }
never executed: }
0
334 return false;
never executed: return false;
0
335 -
336 -
337} -
338 -
339 -
340 -
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial