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