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