1//----------------------------------------------------------------------
2//  This software is part of the OpenBeOS distribution and is covered
3//  by the MIT License.
4//---------------------------------------------------------------------
5/*!
6	\file Rule.cpp
7	MIME sniffer rule implementation
8*/
9
10#include <sniffer/Err.h>
11#include <sniffer/DisjList.h>
12#include <sniffer/Rule.h>
13#include <DataIO.h>
14#include <stdio.h>
15
16using namespace BPrivate::Storage::Sniffer;
17
18/*! \brief Creates an unitialized Sniffer::Rule object. To initialize it, you
19	must pass a pointer to the object to Sniffer::parse().
20*/
21Rule::Rule()
22	: fPriority(0.0)
23	, fConjList(NULL)
24{
25}
26
27Rule::~Rule() {
28	Unset();
29}
30
31status_t
32Rule::InitCheck() const {
33	return fConjList ? B_OK : B_NO_INIT;
34}
35
36//! Returns the priority of the rule. 0.0 <= priority <= 1.0.
37double
38Rule::Priority() const {
39	return fPriority;
40}
41
42//! Sniffs the given data stream. Returns true if the rule matches, false if not.
43bool
44Rule::Sniff(BPositionIO *data) const {
45	if (InitCheck() != B_OK)
46		return false;
47	else {
48		bool result = true;
49		std::vector<DisjList*>::const_iterator i;
50		for (i = fConjList->begin(); i != fConjList->end(); i++) {
51			if (*i)
52				result &= (*i)->Sniff(data);
53		}
54		return result;
55	}
56}
57
58/*! \brief Returns the number of bytes needed for this rule to perform a complete sniff,
59	or an error code if something goes wrong.
60*/
61ssize_t
62Rule::BytesNeeded() const
63{
64	ssize_t result = InitCheck();
65
66	// Tally up the BytesNeeded() values for all the DisjLists and return the largest.
67	if (result == B_OK) {
68		result = 0; // Just to be safe...
69		std::vector<DisjList*>::const_iterator i;
70		for (i = fConjList->begin(); i != fConjList->end(); i++) {
71			if (*i) {
72				ssize_t bytes = (*i)->BytesNeeded();
73				if (bytes >= 0) {
74					if (bytes > result)
75						result = bytes;
76				} else {
77					result = bytes;
78					break;
79				}
80			}
81		}
82	}
83	return result;
84}
85
86
87void
88Rule::Unset() {
89 	if (fConjList){
90		delete fConjList;
91		fConjList = NULL;
92	}
93}
94
95//! Called by Parser::Parse() after successfully parsing a sniffer rule.
96void
97Rule::SetTo(double priority, std::vector<DisjList*>* list) {
98	Unset();
99	if (0.0 <= priority && priority <= 1.0)
100		fPriority = priority;
101	else
102		throw new Err("Sniffer pattern error: invalid priority", -1);
103	fConjList = list;
104}
105
106
107
108
109
110
111