xref: /haiku/src/bin/filteredquery/FilteredQuery.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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