Added BytesNeeded() functions to all the sniffer classes to allow
a pre-read data stream to be sniffed instead of actual files on disk. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1149 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2f1ee757aa
commit
2150894b73
|
@ -9,6 +9,8 @@
|
|||
#ifndef _SNIFFER_DISJ_LIST_H
|
||||
#define _SNIFFER_DISJ_LIST_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
class BPositionIO;
|
||||
|
||||
namespace BPrivate {
|
||||
|
@ -20,7 +22,9 @@ class DisjList {
|
|||
public:
|
||||
DisjList();
|
||||
virtual ~DisjList();
|
||||
|
||||
virtual bool Sniff(BPositionIO *data) const = 0;
|
||||
virtual ssize_t BytesNeeded() const = 0;
|
||||
|
||||
void SetCaseInsensitive(bool how);
|
||||
bool IsCaseInsensitive();
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
Err* GetErr() const;
|
||||
|
||||
bool Sniff(Range range, BPositionIO *data, bool caseInsensitive) const;
|
||||
ssize_t BytesNeeded() const;
|
||||
|
||||
status_t SetTo(const std::string &string, const std::string &mask);
|
||||
private:
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
Err* GetErr() const;
|
||||
|
||||
virtual bool Sniff(BPositionIO *data) const;
|
||||
virtual ssize_t BytesNeeded() const;
|
||||
|
||||
void Add(Pattern *pattern);
|
||||
private:
|
||||
std::vector<Pattern*> fList;
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
Err* GetErr() const;
|
||||
|
||||
bool Sniff(BPositionIO *data, bool caseInsensitive) const;
|
||||
ssize_t BytesNeeded() const;
|
||||
private:
|
||||
Range fRange;
|
||||
Pattern *fPattern;
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
Err* GetErr() const;
|
||||
|
||||
virtual bool Sniff(BPositionIO *data) const;
|
||||
virtual ssize_t BytesNeeded() const;
|
||||
void Add(RPattern *rpattern);
|
||||
private:
|
||||
std::vector<RPattern*> fList;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#define _SNIFFER_RULE_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
class BPositionIO;
|
||||
|
@ -28,10 +30,10 @@ public:
|
|||
Rule();
|
||||
~Rule();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
status_t InitCheck() const;
|
||||
double Priority() const;
|
||||
bool Sniff(BPositionIO *data) const;
|
||||
ssize_t BytesNeeded() const;
|
||||
private:
|
||||
friend class Parser;
|
||||
|
||||
|
|
|
@ -94,8 +94,21 @@ Pattern::Sniff(Range range, BPositionIO *data, bool caseInsensitive) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Assumes the BPositionIO object is in the correct
|
||||
// position from which to sniff
|
||||
// BytesNeeded
|
||||
/*! \brief Returns the number of bytes needed to perform a complete sniff, or an error
|
||||
code if something goes wrong.
|
||||
*/
|
||||
ssize_t
|
||||
Pattern::BytesNeeded() const
|
||||
{
|
||||
ssize_t result = InitCheck();
|
||||
if (result == B_OK)
|
||||
result = fString.length();
|
||||
return result;
|
||||
}
|
||||
|
||||
//#define OPTIMIZATION_IS_FOR_CHUMPS
|
||||
#if OPTIMIZATION_IS_FOR_CHUMPS
|
||||
bool
|
||||
Pattern::Sniff(off_t start, off_t size, BPositionIO *data, bool caseInsensitive) const {
|
||||
off_t len = fString.length();
|
||||
|
@ -140,6 +153,52 @@ Pattern::Sniff(off_t start, off_t size, BPositionIO *data, bool caseInsensitive)
|
|||
} else
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bool
|
||||
Pattern::Sniff(off_t start, off_t size, BPositionIO *data, bool caseInsensitive) const {
|
||||
off_t len = fString.length();
|
||||
char *buffer = new(nothrow) char[len+1];
|
||||
if (buffer) {
|
||||
ssize_t bytesRead = data->ReadAt(start, buffer, len);
|
||||
// \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 (bytesRead < len)
|
||||
return false;
|
||||
else {
|
||||
bool result = true;
|
||||
if (caseInsensitive) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
char secondChar;
|
||||
if ('A' <= fString[i] && fString[i] <= 'Z')
|
||||
secondChar = 'a' + (fString[i] - 'A'); // Also check lowercase
|
||||
else if ('a' <= fString[i] && fString[i] <= 'z')
|
||||
secondChar = 'A' + (fString[i] - 'a'); // Also check uppercase
|
||||
else
|
||||
secondChar = fString[i]; // Check the same char twice as punishment for doing a case insensitive search ;-)
|
||||
if (((fString[i] & fMask[i]) != (buffer[i] & fMask[i]))
|
||||
&& ((secondChar & fMask[i]) != (buffer[i] & fMask[i])))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((fString[i] & fMask[i]) != (buffer[i] & fMask[i])) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Pattern::SetStatus(status_t status, const char *msg) {
|
||||
|
|
|
@ -56,6 +56,41 @@ PatternList::Sniff(BPositionIO *data) const {
|
|||
}
|
||||
}
|
||||
|
||||
/*! \brief Returns the number of bytes needed to perform a complete sniff, or an error
|
||||
code if something goes wrong.
|
||||
*/
|
||||
ssize_t
|
||||
PatternList::BytesNeeded() const
|
||||
{
|
||||
ssize_t result = InitCheck();
|
||||
|
||||
// Find the number of bytes needed to sniff any of our
|
||||
// patterns from a single location in a data stream
|
||||
if (result == B_OK) {
|
||||
result = 0; // I realize it already *is* zero if it == B_OK, but just in case that changes...
|
||||
std::vector<Pattern*>::const_iterator i;
|
||||
for (i = fList.begin(); i != fList.end(); i++) {
|
||||
if (*i) {
|
||||
ssize_t bytes = (*i)->BytesNeeded();
|
||||
if (bytes >= 0) {
|
||||
if (bytes > result)
|
||||
result = bytes;
|
||||
} else {
|
||||
result = bytes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now add on the number of bytes needed to get to the
|
||||
// furthest allowed starting point
|
||||
if (result >= 0)
|
||||
result += fRange.End();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PatternList::Add(Pattern *pattern) {
|
||||
if (pattern)
|
||||
|
|
|
@ -23,15 +23,12 @@ RPattern::RPattern(Range range, Pattern *pattern)
|
|||
|
||||
status_t
|
||||
RPattern::InitCheck() const {
|
||||
if (fRange.InitCheck() != B_OK)
|
||||
return fRange.InitCheck();
|
||||
else if (fPattern) {
|
||||
if (fPattern->InitCheck() != B_OK)
|
||||
return fPattern->InitCheck();
|
||||
else
|
||||
return B_OK;
|
||||
} else
|
||||
return B_BAD_VALUE;
|
||||
status_t err = fRange.InitCheck();
|
||||
if (!err)
|
||||
err = fPattern ? B_OK : B_BAD_VALUE;
|
||||
if (!err)
|
||||
err = fPattern->InitCheck();
|
||||
return err;
|
||||
}
|
||||
|
||||
Err*
|
||||
|
@ -60,5 +57,18 @@ RPattern::Sniff(BPositionIO *data, bool caseInsensitive) const {
|
|||
return fPattern->Sniff(fRange, data, caseInsensitive);
|
||||
}
|
||||
|
||||
/*! \brief Returns the number of bytes needed to perform a complete sniff, or an error
|
||||
code if something goes wrong.
|
||||
*/
|
||||
ssize_t
|
||||
RPattern::BytesNeeded() const
|
||||
{
|
||||
ssize_t result = InitCheck();
|
||||
if (result == B_OK)
|
||||
result = fPattern->BytesNeeded();
|
||||
if (result >= 0)
|
||||
result += fRange.End();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,6 +55,34 @@ RPatternList::Sniff(BPositionIO *data) const {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Returns the number of bytes needed to perform a complete sniff, or an error
|
||||
code if something goes wrong.
|
||||
*/
|
||||
ssize_t
|
||||
RPatternList::BytesNeeded() const
|
||||
{
|
||||
ssize_t result = InitCheck();
|
||||
|
||||
// Tally up the BytesNeeded() values for all the RPatterns and return the largest.
|
||||
if (result == B_OK) {
|
||||
result = 0; // Just to be safe...
|
||||
std::vector<RPattern*>::const_iterator i;
|
||||
for (i = fList.begin(); i != fList.end(); i++) {
|
||||
if (*i) {
|
||||
ssize_t bytes = (*i)->BytesNeeded();
|
||||
if (bytes >= 0) {
|
||||
if (bytes > result)
|
||||
result = bytes;
|
||||
} else {
|
||||
result = bytes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
RPatternList::Add(RPattern *rpattern) {
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
#include <sniffer/DisjList.h>
|
||||
#include <sniffer/Rule.h>
|
||||
#include <DataIO.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace BPrivate::Storage::Sniffer;
|
||||
|
||||
/*! \brief Creates an unitialized Sniffer::Rule object. To initialize it, you
|
||||
must pass a pointer to the object to Sniffer::parse().
|
||||
*/
|
||||
Rule::Rule()
|
||||
: fPriority(0.0)
|
||||
, fConjList(NULL)
|
||||
|
@ -51,6 +55,35 @@ Rule::Sniff(BPositionIO *data) const {
|
|||
}
|
||||
}
|
||||
|
||||
/*! \brief Returns the number of bytes needed for this rule to perform a complete sniff,
|
||||
or an error code if something goes wrong.
|
||||
*/
|
||||
ssize_t
|
||||
Rule::BytesNeeded() const
|
||||
{
|
||||
ssize_t result = InitCheck();
|
||||
|
||||
// Tally up the BytesNeeded() values for all the DisjLists and return the largest.
|
||||
if (result == B_OK) {
|
||||
result = 0; // Just to be safe...
|
||||
std::vector<DisjList*>::const_iterator i;
|
||||
for (i = fConjList->begin(); i != fConjList->end(); i++) {
|
||||
if (*i) {
|
||||
ssize_t bytes = (*i)->BytesNeeded();
|
||||
if (bytes >= 0) {
|
||||
if (bytes > result)
|
||||
result = bytes;
|
||||
} else {
|
||||
result = bytes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Rule::Unset() {
|
||||
if (fConjList){
|
||||
|
|
Loading…
Reference in New Issue