MIME Sniffer: Use memmem() to speed up matching.
This is now a POSIX method which was widely supported even before its addition to POSIX, so using it here (including on the build platform) should be OK. This takes mimeset -F of the whole src/ hierarchy from around 2.8 seconds to around 2.1 (user time goes from ~1.2s to ~0.6s.) It seems I/O is a lot of the remainder now. Also drop the TODO comment; we don't want partial matching like that, as the sniffing rules would not expect it. All tests still pass. Change-Id: Ibb190f6f9f5e73ed027e052ef665b177d3fd6f86 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10688 Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
14ea42a871
commit
64d96af568
@@ -129,12 +129,17 @@ Pattern::GetErr() const
|
|||||||
bool
|
bool
|
||||||
Pattern::Sniff(Range range, const Data& data) const
|
Pattern::Sniff(Range range, const Data& data) const
|
||||||
{
|
{
|
||||||
int32 start = range.Start();
|
int32 firstStart = range.Start();
|
||||||
int32 end = range.End();
|
int32 lastStart = range.End();
|
||||||
if ((size_t)end >= data.length)
|
int32 searchEnd = lastStart + fStringLength;
|
||||||
end = data.length - 1; // Don't bother searching beyond the end of the stream
|
if ((size_t)searchEnd > data.length) {
|
||||||
for (int i = start; i <= end; i++) {
|
// Don't search beyond the end of the stream
|
||||||
if (Sniff(i, data))
|
searchEnd = data.length;
|
||||||
|
lastStart = searchEnd - fStringLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (off_t start = firstStart; start <= lastStart; start++) {
|
||||||
|
if (_SniffNext(start, searchEnd, data))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -155,28 +160,30 @@ Pattern::BytesNeeded() const
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Pattern::Sniff(off_t start, const Data& data) const
|
Pattern::_SniffNext(off_t& start, off_t end, const Data& data) const
|
||||||
{
|
{
|
||||||
int32 len = fStringLength;
|
|
||||||
// \todo If there are fewer bytes left in the data stream
|
|
||||||
// from the given position than the length of our data
|
|
||||||
// string, should we just return false (which is what we're
|
|
||||||
// doing now), or should we compare as many bytes as we
|
|
||||||
// can and return true if those match?
|
|
||||||
if ((data.length - start) < (size_t)len)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const uint8* string = fData;
|
const uint8* string = fData;
|
||||||
const uint8* buffer = data.buffer + start;
|
const uint8* buffer = data.buffer + start;
|
||||||
|
|
||||||
// Compare the "unmasked" portion of the pattern.
|
// Try to find a start point using the "unmasked" portion of the pattern.
|
||||||
if (fUnmaskedStartLength != 0) {
|
if (fUnmaskedStartLength != 0) {
|
||||||
if (memcmp(string, buffer, fUnmaskedStartLength) != 0)
|
void* strStart = memmem(buffer, end - start, string, fUnmaskedStartLength);
|
||||||
|
if (strStart == NULL) {
|
||||||
|
start = end;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (fUnmaskedStartLength == fStringLength)
|
if (fUnmaskedStartLength == fStringLength)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
buffer = (uint8*)strStart;
|
||||||
|
start = buffer - data.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if the buffer is still long enough for a match.
|
||||||
|
int32 len = fStringLength;
|
||||||
|
if ((data.length - start) < (size_t)len)
|
||||||
|
return false;
|
||||||
|
|
||||||
// Compare the remainder.
|
// Compare the remainder.
|
||||||
string += fUnmaskedStartLength;
|
string += fUnmaskedStartLength;
|
||||||
buffer += fUnmaskedStartLength;
|
buffer += fUnmaskedStartLength;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ protected:
|
|||||||
Pattern(bool caseInsensitive, const std::string& string, std::string mask);
|
Pattern(bool caseInsensitive, const std::string& string, std::string mask);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Sniff(off_t start, const Data& data) const;
|
bool _SniffNext(off_t& start, off_t end, const Data& data) const;
|
||||||
|
|
||||||
void SetStatus(status_t status, const char *msg = NULL);
|
void SetStatus(status_t status, const char *msg = NULL);
|
||||||
void SetErrorMessage(const char *msg);
|
void SetErrorMessage(const char *msg);
|
||||||
|
|||||||
Reference in New Issue
Block a user