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:
@@ -9,6 +9,8 @@
|
|||||||
#ifndef _SNIFFER_DISJ_LIST_H
|
#ifndef _SNIFFER_DISJ_LIST_H
|
||||||
#define _SNIFFER_DISJ_LIST_H
|
#define _SNIFFER_DISJ_LIST_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
class BPositionIO;
|
class BPositionIO;
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
@@ -20,7 +22,9 @@ class DisjList {
|
|||||||
public:
|
public:
|
||||||
DisjList();
|
DisjList();
|
||||||
virtual ~DisjList();
|
virtual ~DisjList();
|
||||||
|
|
||||||
virtual bool Sniff(BPositionIO *data) const = 0;
|
virtual bool Sniff(BPositionIO *data) const = 0;
|
||||||
|
virtual ssize_t BytesNeeded() const = 0;
|
||||||
|
|
||||||
void SetCaseInsensitive(bool how);
|
void SetCaseInsensitive(bool how);
|
||||||
bool IsCaseInsensitive();
|
bool IsCaseInsensitive();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public:
|
|||||||
Err* GetErr() const;
|
Err* GetErr() const;
|
||||||
|
|
||||||
bool Sniff(Range range, BPositionIO *data, bool caseInsensitive) 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);
|
status_t SetTo(const std::string &string, const std::string &mask);
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public:
|
|||||||
Err* GetErr() const;
|
Err* GetErr() const;
|
||||||
|
|
||||||
virtual bool Sniff(BPositionIO *data) const;
|
virtual bool Sniff(BPositionIO *data) const;
|
||||||
|
virtual ssize_t BytesNeeded() const;
|
||||||
|
|
||||||
void Add(Pattern *pattern);
|
void Add(Pattern *pattern);
|
||||||
private:
|
private:
|
||||||
std::vector<Pattern*> fList;
|
std::vector<Pattern*> fList;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
Err* GetErr() const;
|
Err* GetErr() const;
|
||||||
|
|
||||||
bool Sniff(BPositionIO *data, bool caseInsensitive) const;
|
bool Sniff(BPositionIO *data, bool caseInsensitive) const;
|
||||||
|
ssize_t BytesNeeded() const;
|
||||||
private:
|
private:
|
||||||
Range fRange;
|
Range fRange;
|
||||||
Pattern *fPattern;
|
Pattern *fPattern;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
Err* GetErr() const;
|
Err* GetErr() const;
|
||||||
|
|
||||||
virtual bool Sniff(BPositionIO *data) const;
|
virtual bool Sniff(BPositionIO *data) const;
|
||||||
|
virtual ssize_t BytesNeeded() const;
|
||||||
void Add(RPattern *rpattern);
|
void Add(RPattern *rpattern);
|
||||||
private:
|
private:
|
||||||
std::vector<RPattern*> fList;
|
std::vector<RPattern*> fList;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#define _SNIFFER_RULE_H
|
#define _SNIFFER_RULE_H
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class BPositionIO;
|
class BPositionIO;
|
||||||
@@ -29,9 +31,9 @@ public:
|
|||||||
~Rule();
|
~Rule();
|
||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
double Priority() const;
|
double Priority() const;
|
||||||
bool Sniff(BPositionIO *data) const;
|
bool Sniff(BPositionIO *data) const;
|
||||||
|
ssize_t BytesNeeded() const;
|
||||||
private:
|
private:
|
||||||
friend class Parser;
|
friend class Parser;
|
||||||
|
|
||||||
|
|||||||
@@ -94,8 +94,21 @@ Pattern::Sniff(Range range, BPositionIO *data, bool caseInsensitive) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes the BPositionIO object is in the correct
|
// BytesNeeded
|
||||||
// position from which to sniff
|
/*! \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
|
bool
|
||||||
Pattern::Sniff(off_t start, off_t size, BPositionIO *data, bool caseInsensitive) const {
|
Pattern::Sniff(off_t start, off_t size, BPositionIO *data, bool caseInsensitive) const {
|
||||||
off_t len = fString.length();
|
off_t len = fString.length();
|
||||||
@@ -140,6 +153,52 @@ Pattern::Sniff(off_t start, off_t size, BPositionIO *data, bool caseInsensitive)
|
|||||||
} else
|
} else
|
||||||
return false;
|
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
|
void
|
||||||
Pattern::SetStatus(status_t status, const char *msg) {
|
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
|
void
|
||||||
PatternList::Add(Pattern *pattern) {
|
PatternList::Add(Pattern *pattern) {
|
||||||
if (pattern)
|
if (pattern)
|
||||||
|
|||||||
@@ -23,15 +23,12 @@ RPattern::RPattern(Range range, Pattern *pattern)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
RPattern::InitCheck() const {
|
RPattern::InitCheck() const {
|
||||||
if (fRange.InitCheck() != B_OK)
|
status_t err = fRange.InitCheck();
|
||||||
return fRange.InitCheck();
|
if (!err)
|
||||||
else if (fPattern) {
|
err = fPattern ? B_OK : B_BAD_VALUE;
|
||||||
if (fPattern->InitCheck() != B_OK)
|
if (!err)
|
||||||
return fPattern->InitCheck();
|
err = fPattern->InitCheck();
|
||||||
else
|
return err;
|
||||||
return B_OK;
|
|
||||||
} else
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Err*
|
Err*
|
||||||
@@ -60,5 +57,18 @@ RPattern::Sniff(BPositionIO *data, bool caseInsensitive) const {
|
|||||||
return fPattern->Sniff(fRange, data, caseInsensitive);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,34 @@ RPatternList::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
|
||||||
|
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
|
void
|
||||||
RPatternList::Add(RPattern *rpattern) {
|
RPatternList::Add(RPattern *rpattern) {
|
||||||
if (rpattern)
|
if (rpattern)
|
||||||
|
|||||||
@@ -11,9 +11,13 @@
|
|||||||
#include <sniffer/DisjList.h>
|
#include <sniffer/DisjList.h>
|
||||||
#include <sniffer/Rule.h>
|
#include <sniffer/Rule.h>
|
||||||
#include <DataIO.h>
|
#include <DataIO.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
using namespace BPrivate::Storage::Sniffer;
|
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()
|
Rule::Rule()
|
||||||
: fPriority(0.0)
|
: fPriority(0.0)
|
||||||
, fConjList(NULL)
|
, 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
|
void
|
||||||
Rule::Unset() {
|
Rule::Unset() {
|
||||||
if (fConjList){
|
if (fConjList){
|
||||||
|
|||||||
Reference in New Issue
Block a user