1da17e06bSIngo Weinhold/*
2da17e06bSIngo Weinhold * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3da17e06bSIngo Weinhold * Distributed under the terms of the MIT License.
4da17e06bSIngo Weinhold */
5da17e06bSIngo Weinhold#ifndef _ENTRY_FILTER_H
6da17e06bSIngo Weinhold#define _ENTRY_FILTER_H
7da17e06bSIngo Weinhold
8da17e06bSIngo Weinhold#include <stddef.h>
9da17e06bSIngo Weinhold#include <stdlib.h>
10da17e06bSIngo Weinhold#include <string.h>
11da17e06bSIngo Weinhold
12da17e06bSIngo Weinhold#include <new>
13da17e06bSIngo Weinhold
14da17e06bSIngo Weinhold#if defined(__BEOS__) && !defined(__HAIKU__)
15da17e06bSIngo Weinhold	// BeOS doesn't have <fnmatch.h>, but libroot.so features fnmatch() anyway
16da17e06bSIngo Weinhold	extern "C" int fnmatch(const char *pattern, const char *string, int flags);
17da17e06bSIngo Weinhold#else
18da17e06bSIngo Weinhold#	include <fnmatch.h>
19da17e06bSIngo Weinhold#endif
20da17e06bSIngo Weinhold
21da17e06bSIngo Weinholdnamespace BPrivate {
22da17e06bSIngo Weinhold
23da17e06bSIngo Weinhold
24da17e06bSIngo Weinholdclass BasicEntryFilter {
25da17e06bSIngo Weinholdpublic:
26da17e06bSIngo Weinhold	BasicEntryFilter()
27da17e06bSIngo Weinhold		: fPattern(NULL),
28da17e06bSIngo Weinhold		  fIsFileName(false)
29da17e06bSIngo Weinhold	{
30da17e06bSIngo Weinhold	}
31da17e06bSIngo Weinhold
32da17e06bSIngo Weinhold	~BasicEntryFilter()
33da17e06bSIngo Weinhold	{
34da17e06bSIngo Weinhold		free(fPattern);
35da17e06bSIngo Weinhold	}
36da17e06bSIngo Weinhold
37da17e06bSIngo Weinhold	bool SetTo(const char* pattern, bool isFileName)
38da17e06bSIngo Weinhold	{
39da17e06bSIngo Weinhold		free(fPattern);
40da17e06bSIngo Weinhold
41da17e06bSIngo Weinhold		fPattern = strdup(pattern);
42da17e06bSIngo Weinhold		if (fPattern == NULL)
43da17e06bSIngo Weinhold			return false;
44da17e06bSIngo Weinhold
45da17e06bSIngo Weinhold		fIsFileName = isFileName;
46da17e06bSIngo Weinhold
47da17e06bSIngo Weinhold		return true;
48da17e06bSIngo Weinhold	}
49da17e06bSIngo Weinhold
50da17e06bSIngo Weinhold	bool Filter(const char* path, const char* name) const
51da17e06bSIngo Weinhold	{
52da17e06bSIngo Weinhold		if (fPattern != NULL) {
53da17e06bSIngo Weinhold			if (fnmatch(fPattern, (fIsFileName ? name : path), 0) == 0)
54da17e06bSIngo Weinhold				return true;
55da17e06bSIngo Weinhold		}
56da17e06bSIngo Weinhold
57da17e06bSIngo Weinhold		return false;
58da17e06bSIngo Weinhold	}
59da17e06bSIngo Weinhold
60da17e06bSIngo Weinhold	void SetNextFilter(BasicEntryFilter* next)
61da17e06bSIngo Weinhold	{
62da17e06bSIngo Weinhold		fNextFilter = next;
63da17e06bSIngo Weinhold	}
64da17e06bSIngo Weinhold
65da17e06bSIngo Weinhold	BasicEntryFilter* NextFilter() const
66da17e06bSIngo Weinhold	{
67da17e06bSIngo Weinhold		 return fNextFilter;
68da17e06bSIngo Weinhold	}
69da17e06bSIngo Weinhold
70da17e06bSIngo Weinholdprivate:
71da17e06bSIngo Weinhold	char*				fPattern;
72da17e06bSIngo Weinhold	bool				fIsFileName;
73da17e06bSIngo Weinhold	BasicEntryFilter*	fNextFilter;
74da17e06bSIngo Weinhold};
75da17e06bSIngo Weinhold
76da17e06bSIngo Weinhold
77da17e06bSIngo Weinholdclass EntryFilter {
78da17e06bSIngo Weinholdpublic:
79da17e06bSIngo Weinhold	EntryFilter()
80da17e06bSIngo Weinhold		: fIncludeFilters(NULL),
81da17e06bSIngo Weinhold		  fExcludeFilters(NULL)
82da17e06bSIngo Weinhold	{
83da17e06bSIngo Weinhold	}
84da17e06bSIngo Weinhold
85da17e06bSIngo Weinhold	~EntryFilter()
86da17e06bSIngo Weinhold	{
87da17e06bSIngo Weinhold		while (BasicEntryFilter* filter = fIncludeFilters) {
88da17e06bSIngo Weinhold			fIncludeFilters = filter->NextFilter();
89da17e06bSIngo Weinhold			delete filter;
90da17e06bSIngo Weinhold		}
91da17e06bSIngo Weinhold
92da17e06bSIngo Weinhold		while (BasicEntryFilter* filter = fExcludeFilters) {
93da17e06bSIngo Weinhold			fExcludeFilters = filter->NextFilter();
94da17e06bSIngo Weinhold			delete filter;
95da17e06bSIngo Weinhold		}
96da17e06bSIngo Weinhold	}
97da17e06bSIngo Weinhold
98da17e06bSIngo Weinhold	void AddIncludeFilter(BasicEntryFilter* filter)
99da17e06bSIngo Weinhold	{
100da17e06bSIngo Weinhold		_AddFilter(fIncludeFilters, filter);
101da17e06bSIngo Weinhold	}
102da17e06bSIngo Weinhold
103da17e06bSIngo Weinhold	bool AddIncludeFilter(const char* pattern, bool isFilePattern)
104da17e06bSIngo Weinhold	{
105da17e06bSIngo Weinhold		return _AddFilter(fIncludeFilters, pattern, isFilePattern);
106da17e06bSIngo Weinhold	}
107da17e06bSIngo Weinhold
108da17e06bSIngo Weinhold	void AddExcludeFilter(BasicEntryFilter* filter)
109da17e06bSIngo Weinhold	{
110da17e06bSIngo Weinhold		_AddFilter(fExcludeFilters, filter);
111da17e06bSIngo Weinhold	}
112da17e06bSIngo Weinhold
113da17e06bSIngo Weinhold	bool AddExcludeFilter(const char* pattern, bool isFilePattern)
114da17e06bSIngo Weinhold	{
115da17e06bSIngo Weinhold		return _AddFilter(fExcludeFilters, pattern, isFilePattern);
116da17e06bSIngo Weinhold	}
117da17e06bSIngo Weinhold
118da17e06bSIngo Weinhold	bool Filter(const char* path) const
119da17e06bSIngo Weinhold	{
120da17e06bSIngo Weinhold		if (fExcludeFilters == NULL && fIncludeFilters)
121da17e06bSIngo Weinhold			return true;
122da17e06bSIngo Weinhold
123da17e06bSIngo Weinhold		// get leaf name
124da17e06bSIngo Weinhold		const char* name = strrchr(path, '/');
125da17e06bSIngo Weinhold		name = (name != NULL ? name + 1 : path);
126da17e06bSIngo Weinhold
127da17e06bSIngo Weinhold		// exclude filters
128da17e06bSIngo Weinhold		if (_Filter(fExcludeFilters, path, name))
129da17e06bSIngo Weinhold			return false;
130da17e06bSIngo Weinhold
131da17e06bSIngo Weinhold		// include filters -- if none are given, everything matches
132da17e06bSIngo Weinhold		return fIncludeFilters == NULL || _Filter(fIncludeFilters, path, name);
133da17e06bSIngo Weinhold	}
134da17e06bSIngo Weinhold
135da17e06bSIngo Weinholdprivate:
136da17e06bSIngo Weinhold	static void _AddFilter(BasicEntryFilter*& filterList,
137da17e06bSIngo Weinhold		BasicEntryFilter* filter)
138da17e06bSIngo Weinhold	{
139da17e06bSIngo Weinhold		filter->SetNextFilter(filterList);
140da17e06bSIngo Weinhold		filterList = filter;
141da17e06bSIngo Weinhold	}
142da17e06bSIngo Weinhold
143da17e06bSIngo Weinhold	static bool _AddFilter(BasicEntryFilter*& filterList, const char* pattern,
144da17e06bSIngo Weinhold		bool isFilePattern)
145da17e06bSIngo Weinhold	{
146da17e06bSIngo Weinhold		BasicEntryFilter* filter = new(std::nothrow) BasicEntryFilter;
147da17e06bSIngo Weinhold		if (filter == NULL)
148da17e06bSIngo Weinhold			return false;
149da17e06bSIngo Weinhold
150da17e06bSIngo Weinhold		if (!filter->SetTo(pattern, isFilePattern)) {
151da17e06bSIngo Weinhold			delete filter;
152da17e06bSIngo Weinhold			return false;
153da17e06bSIngo Weinhold		}
154da17e06bSIngo Weinhold
155da17e06bSIngo Weinhold		_AddFilter(filterList, filter);
156da17e06bSIngo Weinhold
157da17e06bSIngo Weinhold		return true;
158da17e06bSIngo Weinhold	}
159da17e06bSIngo Weinhold
160da17e06bSIngo Weinhold	static bool _Filter(const BasicEntryFilter* const& filterList,
161da17e06bSIngo Weinhold		const char* path, const char* name)
162da17e06bSIngo Weinhold	{
163da17e06bSIngo Weinhold		const BasicEntryFilter* filter = filterList;
164da17e06bSIngo Weinhold		while (filter) {
165da17e06bSIngo Weinhold			if (filter->Filter(path, name))
166da17e06bSIngo Weinhold				return true;
167da17e06bSIngo Weinhold			filter = filter->NextFilter();
168da17e06bSIngo Weinhold		}
169da17e06bSIngo Weinhold
170da17e06bSIngo Weinhold		return false;
171da17e06bSIngo Weinhold	}
172da17e06bSIngo Weinhold
173da17e06bSIngo Weinholdprivate:
174da17e06bSIngo Weinhold	BasicEntryFilter*	fIncludeFilters;
175da17e06bSIngo Weinhold	BasicEntryFilter*	fExcludeFilters;
176da17e06bSIngo Weinhold};
177da17e06bSIngo Weinhold
178da17e06bSIngo Weinhold}	// namespace BPrivate
179da17e06bSIngo Weinhold
180da17e06bSIngo Weinhold
181da17e06bSIngo Weinhold#endif	// _ENTRY_FILTER_H