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 &)
11static void
12CopyQuery(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
31TFilteredQuery::TFilteredQuery()
32{
33}
34
35
36TFilteredQuery::TFilteredQuery(const BQuery &query)
37	:
38	BQuery()
39{
40	CopyQuery(query, this);
41}
42
43
44TFilteredQuery::TFilteredQuery(const TFilteredQuery &query)
45	:
46	BQuery()
47{
48	CopyQuery(query, this);
49
50	// copy filters
51	fFilters = query.fFilters;
52}
53
54
55TFilteredQuery::~TFilteredQuery()
56{
57	Clear();
58}
59
60
61bool
62TFilteredQuery::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
70void
71TFilteredQuery::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
84status_t
85TFilteredQuery::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
114status_t
115TFilteredQuery::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
129int32
130TFilteredQuery::GetNextDirents(dirent *buf, size_t length, int32 count)
131{
132	// TODO: Implement ?
133	return 0;
134}
135
136
137status_t
138TFilteredQuery::Clear()
139{
140	int32 filtersCount = fFilters.CountItems();
141	for (int32 i = 0; i < filtersCount; i++)
142		delete fFilters.RemoveItemAt(i);
143
144	return BQuery::Clear();
145}
146