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