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:
Tyler Dauwalder 2002-09-24 05:27:46 +00:00
parent 2f1ee757aa
commit 2150894b73
11 changed files with 189 additions and 13 deletions

View File

@ -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();

View File

@ -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:

View File

@ -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;

View File

@ -30,6 +30,7 @@ public:
Err* GetErr() const;
bool Sniff(BPositionIO *data, bool caseInsensitive) const;
ssize_t BytesNeeded() const;
private:
Range fRange;
Pattern *fPattern;

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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)

View File

@ -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;
}

View File

@ -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) {

View File

@ -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){