/* * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef _ENTRY_FILTER_H #define _ENTRY_FILTER_H #include #include #include #include #if defined(__BEOS__) && !defined(__HAIKU__) // BeOS doesn't have , but libroot.so features fnmatch() anyway extern "C" int fnmatch(const char *pattern, const char *string, int flags); #else # include #endif namespace BPrivate { class BasicEntryFilter { public: BasicEntryFilter() : fPattern(NULL), fIsFileName(false) { } ~BasicEntryFilter() { free(fPattern); } bool SetTo(const char* pattern, bool isFileName) { free(fPattern); fPattern = strdup(pattern); if (fPattern == NULL) return false; fIsFileName = isFileName; return true; } bool Filter(const char* path, const char* name) const { if (fPattern != NULL) { if (fnmatch(fPattern, (fIsFileName ? name : path), 0) == 0) return true; } return false; } void SetNextFilter(BasicEntryFilter* next) { fNextFilter = next; } BasicEntryFilter* NextFilter() const { return fNextFilter; } private: char* fPattern; bool fIsFileName; BasicEntryFilter* fNextFilter; }; class EntryFilter { public: EntryFilter() : fIncludeFilters(NULL), fExcludeFilters(NULL) { } ~EntryFilter() { while (BasicEntryFilter* filter = fIncludeFilters) { fIncludeFilters = filter->NextFilter(); delete filter; } while (BasicEntryFilter* filter = fExcludeFilters) { fExcludeFilters = filter->NextFilter(); delete filter; } } void AddIncludeFilter(BasicEntryFilter* filter) { _AddFilter(fIncludeFilters, filter); } bool AddIncludeFilter(const char* pattern, bool isFilePattern) { return _AddFilter(fIncludeFilters, pattern, isFilePattern); } void AddExcludeFilter(BasicEntryFilter* filter) { _AddFilter(fExcludeFilters, filter); } bool AddExcludeFilter(const char* pattern, bool isFilePattern) { return _AddFilter(fExcludeFilters, pattern, isFilePattern); } bool Filter(const char* path) const { if (fExcludeFilters == NULL && fIncludeFilters) return true; // get leaf name const char* name = strrchr(path, '/'); name = (name != NULL ? name + 1 : path); // exclude filters if (_Filter(fExcludeFilters, path, name)) return false; // include filters -- if none are given, everything matches return fIncludeFilters == NULL || _Filter(fIncludeFilters, path, name); } private: static void _AddFilter(BasicEntryFilter*& filterList, BasicEntryFilter* filter) { filter->SetNextFilter(filterList); filterList = filter; } static bool _AddFilter(BasicEntryFilter*& filterList, const char* pattern, bool isFilePattern) { BasicEntryFilter* filter = new(std::nothrow) BasicEntryFilter; if (filter == NULL) return false; if (!filter->SetTo(pattern, isFilePattern)) { delete filter; return false; } _AddFilter(filterList, filter); return true; } static bool _Filter(const BasicEntryFilter* const& filterList, const char* path, const char* name) { const BasicEntryFilter* filter = filterList; while (filter) { if (filter->Filter(path, name)) return true; filter = filter->NextFilter(); } return false; } private: BasicEntryFilter* fIncludeFilters; BasicEntryFilter* fExcludeFilters; }; } // namespace BPrivate #endif // _ENTRY_FILTER_H