root/src/kits/storage/sniffer/PatternList.cpp
/*
 * Copyright 2002, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Tyler Dauwalder
 */

/*!
        \file PatternList.cpp
        MIME sniffer pattern list implementation
*/

#include <stdio.h>

#include "Err.h"
#include "Pattern.h"
#include "PatternList.h"

using namespace BPrivate::Storage::Sniffer;


PatternList::PatternList(Range range)
        :
        DisjList(),
        fRange(range)
{
}


PatternList::~PatternList()
{
        // Clean up
        std::vector<Pattern*>::iterator i;
        for (i = fList.begin(); i != fList.end(); i++)
                delete *i;
}


status_t
PatternList::InitCheck() const
{
        return fRange.InitCheck();
}


Err*
PatternList::GetErr() const
{
        return fRange.GetErr();
}

/*! \brief Sniffs the given data stream, searching for a match with
        any of the list's patterns.
*/
bool
PatternList::Sniff(const Data& data) const
{
        if (InitCheck() != B_OK) {
                return false;
        } else {
                bool result = false;
                std::vector<Pattern*>::const_iterator i;
                for (i = fList.begin(); i != fList.end(); i++) {
                        if (*i)
                                result |= (*i)->Sniff(fRange, data, fCaseInsensitive);
                }
                return result;
        }
}

/*! \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)
                fList.push_back(pattern);
}