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