1 #include "FilteredQuery.h" 2 3 #include <Debug.h> 4 #include <Entry.h> 5 #include <String.h> 6 #include <Volume.h> 7 8 // Helper function to copy a query. 9 // Used to avoid code duplication in 10 // TFilteredQuery(const BQuery &) and TFilteredQuery(const TFilteredQuery &) 11 static void 12 CopyQuery(const BQuery &query, BQuery *dest) 13 { 14 ASSERT(dest); 15 16 BQuery &nonConst = const_cast<BQuery &>(query); 17 18 // BQuery doesn't have a copy constructor, 19 // so we have to do the work ourselves... 20 // Copy the predicate 21 BString buffer; 22 nonConst.GetPredicate(&buffer); 23 dest->SetPredicate(buffer.String()); 24 25 // Copy the targetted volume 26 BVolume volume(nonConst.TargetDevice()); 27 dest->SetVolume(&volume); 28 } 29 30 31 TFilteredQuery::TFilteredQuery() 32 { 33 } 34 35 36 TFilteredQuery::TFilteredQuery(const BQuery &query) 37 : 38 BQuery() 39 { 40 CopyQuery(query, this); 41 } 42 43 44 TFilteredQuery::TFilteredQuery(const TFilteredQuery &query) 45 : 46 BQuery() 47 { 48 CopyQuery(query, this); 49 50 // copy filters 51 fFilters = query.fFilters; 52 } 53 54 55 TFilteredQuery::~TFilteredQuery() 56 { 57 Clear(); 58 } 59 60 61 bool 62 TFilteredQuery::AddFilter(filter_function filter, void *arg) 63 { 64 filter_pair *filterPair = new filter_pair(filter, arg); 65 66 return fFilters.AddItem(filterPair); 67 } 68 69 70 void 71 TFilteredQuery::RemoveFilter(filter_function function) 72 { 73 int32 count = fFilters.CountItems(); 74 for (int32 i = 0; i < count; i++) { 75 filter_pair *pair = fFilters.ItemAt(i); 76 if (pair->filter == function) { 77 delete fFilters.RemoveItemAt(i); 78 break; 79 } 80 } 81 } 82 83 84 status_t 85 TFilteredQuery::GetNextRef(entry_ref *ref) 86 { 87 entry_ref tmpRef; 88 status_t result; 89 90 int32 filterCount = fFilters.CountItems(); 91 while ((result = BQuery::GetNextRef(&tmpRef)) == B_OK) { 92 bool accepted = true; 93 // We have a match, so let the entry_ref go through the filters 94 // and see if it passes all the requirements 95 for (int32 i = 0; i < filterCount; i++) { 96 filter_pair *pair = fFilters.ItemAt(i); 97 filter_function filter = pair->filter; 98 accepted = (*filter)(&tmpRef, pair->args); 99 if (!accepted) 100 break; 101 } 102 103 if (accepted) { 104 // Ok, this entry_ref passed all tests 105 *ref = tmpRef; 106 break; 107 } 108 } 109 110 return result; 111 } 112 113 114 status_t 115 TFilteredQuery::GetNextEntry(BEntry *entry, bool traverse) 116 { 117 // This code is almost a full copy/paste from Haiku's 118 // BQuery::GetNextEntry(BEntry *entry, bool traverse) 119 120 entry_ref ref; 121 status_t error = GetNextRef(&ref); 122 if (error == B_OK) 123 error = entry->SetTo(&ref, traverse); 124 125 return error; 126 } 127 128 129 status_t 130 TFilteredQuery::Clear() 131 { 132 int32 filtersCount = fFilters.CountItems(); 133 for (int32 i = 0; i < filtersCount; i++) 134 delete fFilters.RemoveItemAt(i); 135 136 return BQuery::Clear(); 137 } 138