#include "FilteredQuery.h" #include #include #include #include // Helper function to copy a query. // Used to avoid code duplication in // TFilteredQuery(const BQuery &) and TFilteredQuery(const TFilteredQuery &) static void CopyQuery(const BQuery &query, BQuery *dest) { ASSERT(dest); BQuery &nonConst = const_cast(query); // BQuery doesn't have a copy constructor, // so we have to do the work ourselves... // Copy the predicate BString buffer; nonConst.GetPredicate(&buffer); dest->SetPredicate(buffer.String()); // Copy the targetted volume BVolume volume(nonConst.TargetDevice()); dest->SetVolume(&volume); } TFilteredQuery::TFilteredQuery() { } TFilteredQuery::TFilteredQuery(const BQuery &query) : BQuery() { CopyQuery(query, this); } TFilteredQuery::TFilteredQuery(const TFilteredQuery &query) : BQuery() { CopyQuery(query, this); // copy filters fFilters = query.fFilters; } TFilteredQuery::~TFilteredQuery() { Clear(); } bool TFilteredQuery::AddFilter(filter_function filter, void *arg) { filter_pair *filterPair = new filter_pair(filter, arg); return fFilters.AddItem(filterPair); } void TFilteredQuery::RemoveFilter(filter_function function) { int32 count = fFilters.CountItems(); for (int32 i = 0; i < count; i++) { filter_pair *pair = fFilters.ItemAt(i); if (pair->filter == function) { delete fFilters.RemoveItemAt(i); break; } } } status_t TFilteredQuery::GetNextRef(entry_ref *ref) { entry_ref tmpRef; status_t result; int32 filterCount = fFilters.CountItems(); while ((result = BQuery::GetNextRef(&tmpRef)) == B_OK) { bool accepted = true; // We have a match, so let the entry_ref go through the filters // and see if it passes all the requirements for (int32 i = 0; i < filterCount; i++) { filter_pair *pair = fFilters.ItemAt(i); filter_function filter = pair->filter; accepted = (*filter)(&tmpRef, pair->args); if (!accepted) break; } if (accepted) { // Ok, this entry_ref passed all tests *ref = tmpRef; break; } } return result; } status_t TFilteredQuery::GetNextEntry(BEntry *entry, bool traverse) { // This code is almost a full copy/paste from Haiku's // BQuery::GetNextEntry(BEntry *entry, bool traverse) entry_ref ref; status_t error = GetNextRef(&ref); if (error == B_OK) error = entry->SetTo(&ref, traverse); return error; } status_t TFilteredQuery::Clear() { int32 filtersCount = fFilters.CountItems(); for (int32 i = 0; i < filtersCount; i++) delete fFilters.RemoveItemAt(i); return BQuery::Clear(); }