[PATCH] Filtering in FindVisitor - take 2
Igor Pechtchanski
pechtcha@cs.nyu.edu
Tue Mar 18 14:25:00 GMT 2003
On Mon, 17 Mar 2003, Igor Pechtchanski wrote:
> On 18 Mar 2003, Robert Collins wrote:
>
> > On Tue, 2003-03-18 at 05:23, Igor Pechtchanski wrote:
> > > This patch implements a FilterVisitor class that is a decorator on a
> > > FindVisitor and filters files according to the supplied Filter class (also
> > > implemented). It also implements a particular filter, ExcludeNameFilter,
> > > that excludes any files with names matching a pattern.
> > > The two new files, FilterVisitor.cc and FilterVisitor.h, will have to be
> > > 'cvs add'ed.
> > > Igor
> > > ==============================================================================
> > > ChangeLog:
> > > 2003-03-17 Igor Pechtchanski <pechtcha@cs.nyu.edu>
> > >
> > > * postinstall.cc (do_postinstall): Filter out '*.done'.
> > > * FilterVisitor.h: New header file. Declare the
> > > FilterVisitor, Filter, and ExcludeNameFilter classes.
> > > * FilterVisitor.cc: New file. Implement FilterVisitor,
> > > Filter, and ExcludeNameFilter.
> > > * Makefile.am: Add FilterVisitor.cc and FilterVisitor.h
> > > to inilint_SOURCES and setup_SOURCES.
> >
> > Looks nice.
> >
> > The strmatching logic should be a method of String++ IMO.
>
> I thought about it, but wasn't sure what the "right" way of putting it in
> was. I'd guess
>
> bool String::matches(String const &pattern);
>
> i.e., the receiver is the string to match, rather than
>
> bool String::match(String const &filename);
>
> i.e., the receiver is the pattern...
Ok, included.
> I'll also move StringError to String.h/cc.
... in a later patch - it's irrelevant for this one.
> > Also FilterVisitor isn't needed for inilint.
> > Cheers,
> > Rob
>
> Is FindVisitor? That's what I modeled it after. What are the criteria?
> Igor
Argh, noise... I wasn't thinking. Though you might consider using it for
inilint in the future. ;-)
Igor
==============================================================================
ChangeLog:
2003-03-18 Igor Pechtchanski <pechtcha@cs.nyu.edu>
* postinstall.cc (do_postinstall): Filter out '*.done'.
* FilterVisitor.h: New header file. Declare the
FilterVisitor, Filter, and ExcludeNameFilter classes.
* FilterVisitor.cc: New file. Implement FilterVisitor,
Filter, and ExcludeNameFilter.
* String++.h (String::matches): New instance function.
* String++.cc (String::matches): Implement.
(strmatch) Import and adapt for <buf,len> strings.
* Makefile.am (setup_SOURCES): Add FilterVisitor.cc and
FilterVisitor.h to value.
--
http://cs.nyu.edu/~pechtcha/
|\ _,,,---,,_ pechtcha@cs.nyu.edu
ZZZzz /,`.-'`' -. ;-;;,_ igor@watson.ibm.com
|,4- ) )-,_. ,\ ( `'-' Igor Pechtchanski
'---''(_/--' `-'\_) fL a.k.a JaguaR-R-R-r-r-r-.-.-. Meow!
Oh, boy, virtual memory! Now I'm gonna make myself a really *big* RAMdisk!
-- /usr/games/fortune
-------------- next part --------------
Index: FilterVisitor.cc
===================================================================
RCS file: FilterVisitor.cc
diff -N FilterVisitor.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ FilterVisitor.cc 18 Mar 2003 14:01:36 -0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003 Igor Pechtchanski.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A copy of the GNU General Public License can be found at
+ * http://www.gnu.org/
+ *
+ * Written by Igor Pechtchanski <pechtcha@cs.nyu.edu>
+ *
+ */
+
+#if 0
+static const char *cvsid =
+ "\n%%% $Id$\n";
+#endif
+
+#include "FilterVisitor.h"
+#include "String++.h"
+#include "find.h"
+
+#include <iostream>
+
+FilterVisitor::FilterVisitor(FindVisitor *visitor, Filter *filter)
+ : _visitor(visitor), _filter(filter) {}
+
+FilterVisitor::~FilterVisitor() {}
+
+void
+FilterVisitor::visitFile(String const &basePath, WIN32_FIND_DATA const *aFile)
+{
+ if (_filter->matchFile(basePath, aFile))
+ _visitor->visitFile(basePath, aFile);
+}
+
+void
+FilterVisitor::visitDirectory(String const &basePath, WIN32_FIND_DATA const *aDir)
+{
+ if (_filter->matchDirectory(basePath, aDir))
+ _visitor->visitDirectory(basePath, aDir);
+}
+
+Filter::Filter() {}
+Filter::~Filter() {}
+
+bool
+Filter::matchFile(String const &basePath, WIN32_FIND_DATA const *aFile)
+{
+ return true;
+}
+
+bool
+Filter::matchDirectory(String const &basePath, WIN32_FIND_DATA const *aDir)
+{
+ return true;
+}
+
+ExcludeNameFilter::ExcludeNameFilter() : _filePattern(""), _dirPattern("") {}
+
+ExcludeNameFilter::~ExcludeNameFilter(){}
+
+ExcludeNameFilter::ExcludeNameFilter(String const &filePattern,
+ String const &dirPattern)
+ : _filePattern(filePattern), _dirPattern(dirPattern) {}
+
+bool
+ExcludeNameFilter::matchFile(String const &basePath, WIN32_FIND_DATA const *aFile)
+{
+ return !(basePath + aFile->cFileName).matches(_filePattern);
+}
+
+bool
+ExcludeNameFilter::matchDirectory(String const &basePath, WIN32_FIND_DATA const *aDir)
+{
+ return !(basePath + aDir->cFileName).matches(_dirPattern);
+}
+
Index: FilterVisitor.h
===================================================================
RCS file: FilterVisitor.h
diff -N FilterVisitor.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ FilterVisitor.h 18 Mar 2003 14:01:36 -0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003 Igor Pechtchanski.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A copy of the GNU General Public License can be found at
+ * http://www.gnu.org/
+ *
+ * Written by Igor Pechtchanski <pechtcha@cs.nyu.edu>
+ *
+ */
+
+#ifndef _FILTERVISITOR_H_
+#define _FILTERVISITOR_H_
+
+#include "FindVisitor.h"
+#include "String++.h"
+
+/* For the wfd definition. See the TODO in find.cc */
+#include "win32.h"
+
+class Filter
+{
+public:
+ virtual bool matchFile(String const &basePath, WIN32_FIND_DATA const *);
+ virtual bool matchDirectory(String const &basePath, WIN32_FIND_DATA const *);
+ virtual ~ Filter();
+protected:
+ Filter();
+ Filter(Filter const &);
+ Filter & operator= (Filter const &);
+};
+
+class FilterVisitor : public FindVisitor
+{
+public:
+ virtual void visitFile(String const &basePath, WIN32_FIND_DATA const *);
+ virtual void visitDirectory(String const &basePath, WIN32_FIND_DATA const *);
+ FilterVisitor (FindVisitor *visitor, Filter *filter);
+ virtual ~ FilterVisitor ();
+protected:
+ FilterVisitor ();
+ FilterVisitor (FilterVisitor const &);
+ FilterVisitor & operator= (FilterVisitor const &);
+private:
+ FindVisitor *_visitor;
+ Filter *_filter;
+};
+
+class ExcludeNameFilter : public Filter
+{
+public:
+ ExcludeNameFilter (String const &filePattern, String const &dirPattern = "");
+ virtual ~ ExcludeNameFilter ();
+
+ virtual bool matchFile(String const &basePath, WIN32_FIND_DATA const *);
+ virtual bool matchDirectory(String const &basePath, WIN32_FIND_DATA const *);
+protected:
+ ExcludeNameFilter ();
+ ExcludeNameFilter (ExcludeNameFilter const &);
+ ExcludeNameFilter & operator= (ExcludeNameFilter const &);
+private:
+ String _filePattern;
+ String _dirPattern;
+};
+
+#endif // _FILTERVISITOR_H_
Index: Makefile.am
===================================================================
RCS file: /cvs/cygwin-apps/setup/Makefile.am,v
retrieving revision 2.27
diff -u -p -r2.27 Makefile.am
--- Makefile.am 10 Mar 2003 15:47:53 -0000 2.27
+++ Makefile.am 18 Mar 2003 14:01:36 -0000
@@ -153,6 +153,8 @@ setup_SOURCES = \
find.h \
FindVisitor.cc \
FindVisitor.h \
+ FilterVisitor.cc \
+ FilterVisitor.h \
filemanip.cc \
filemanip.h \
fromcwd.cc \
Index: String++.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/String++.cc,v
retrieving revision 2.9
diff -u -p -r2.9 String++.cc
--- String++.cc 17 Mar 2003 22:23:33 -0000 2.9
+++ String++.cc 18 Mar 2003 14:01:36 -0000
@@ -252,6 +252,149 @@ String::casecompare (String const lhs, S
return lhs.casecompare (rhs);
}
+/*
+ * This supports two wildcard characters, '*' and '?', as well as the
+ * '[]'-style character sets ('^' to invert).
+ * Use '\' to escape special characters.
+ * Shamelessly stolen from fileutils-4.1 (adapted for <buf,len> strings).
+ */
+static bool
+strmatch (const unsigned char *pattern, size_t plen,
+ const unsigned char *name, size_t nlen)
+{
+ register const unsigned char *pend = pattern + plen, *nend = name + nlen;
+ register const unsigned char *p = pattern, *n = name;
+ register unsigned char c;
+
+ while (p < pend)
+ {
+ c = *p++;
+ switch (c)
+ {
+ case '?': /* A '?' matches exactly one character */
+ if (n == nend)
+ return false;
+ break;
+
+ case '\\': /* Escape next character */
+ if (p == pend)
+ return false;
+ c = *p++;
+ if (n == nend || *n != c)
+ return false;
+ break;
+
+ case '*': /* A '*' matches any number of characters */
+ while (p < pend && (c == '?' || c == '*'))
+ {
+ c = *p++;
+ if (c == '?')
+ {
+ /* A '?' needs to match one character. */
+ if (n == nend)
+ /* There isn't another character; no match. */
+ return false;
+ else
+ /* One character of the name is consumed in matching
+ this ? wildcard, so *??? won't match if there are
+ less than three characters. */
+ ++n;
+ }
+ }
+
+ if (p == pend)
+ return true;
+
+ {
+ unsigned char c1 = (c == '\\') ? *p : c;
+ for (--p; n != nend; ++n) /* Eat up all chars */
+ if ((c == '[' || *n == c1) && strmatch (p, pend-p, n, nend-n))
+ return true;
+ return false;
+ }
+
+ case '[': /* A '[A-Z]' matches any char between 'A' and 'Z' */
+ {
+ /* Nonzero if the sense of the character class is inverted. */
+ register bool invert;
+
+ if (n == nend)
+ return false;
+
+ invert = (*p == '^');
+ if (invert)
+ ++p;
+
+ if (p == pend)
+ /* [ (unterminated) loses. */
+ return false;
+
+ c = *p++;
+ for (;;)
+ {
+ register unsigned char cstart = c, cend = c;
+
+ if (p == pend)
+ /* [ (unterminated) loses. */
+ return false;
+
+ c = *p++;
+
+ if (c == '-' && *p != ']')
+ {
+ if (p == pend)
+ return false;
+ cend = *p++;
+
+ c = *p++;
+ }
+
+ if (*n >= cstart && *n <= cend)
+ goto matched;
+
+ if (c == ']')
+ break;
+ }
+ if (!invert)
+ return false;
+ break;
+
+ matched:;
+ /* Skip the rest of the [...] that already matched. */
+ while (c != ']')
+ {
+ if (p == pend)
+ /* [... (unterminated) loses. */
+ return false;
+
+ c = *p++;
+ }
+ if (invert)
+ return false;
+ }
+ break;
+
+ default:
+ if (n == nend || c != *n)
+ return false;
+ }
+
+ ++n;
+ }
+
+ if (n == nend)
+ return true;
+
+ return false;
+}
+
+bool
+String::matches (String const &pattern) const
+{
+ return strmatch (pattern.theData->theString, pattern.theData->length,
+ theData->theString, theData->length);
+}
+
/* TODO: research how wide char and unicode interoperate with
* C++ streams
*/
Index: String++.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/String++.h,v
retrieving revision 2.9
diff -u -p -r2.9 String++.h
--- String++.h 17 Mar 2003 22:23:33 -0000 2.9
+++ String++.h 18 Mar 2003 14:01:36 -0000
@@ -62,6 +62,7 @@ public:
{
return s1.casecompare (s2) < 0;
}};
+ bool matches (String const &pattern) const;
private:
class _data {
Index: postinstall.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/postinstall.cc,v
retrieving revision 2.9
diff -u -p -r2.9 postinstall.cc
--- postinstall.cc 19 May 2002 03:07:51 -0000 2.9
+++ postinstall.cc 17 Mar 2003 18:01:51 -0000
@@ -26,6 +26,7 @@ static const char *cvsid =
#include "mount.h"
#include "script.h"
#include "FindVisitor.h"
+#include "FilterVisitor.h"
class RunFindVisitor : public FindVisitor
{
@@ -48,6 +49,8 @@ do_postinstall (HINSTANCE h, HWND owner)
init_run_script ();
SetCurrentDirectory (get_root_dir ().cstr_oneuse());
RunFindVisitor myVisitor;
+ ExcludeNameFilter notDone("*.done");
+ FilterVisitor excludeDoneVisitor(&myVisitor, ¬Done);
String postinst = cygpath ("/etc/postinstall");
- Find (postinst).accept (myVisitor);
+ Find (postinst).accept (excludeDoneVisitor);
}
More information about the Cygwin-apps
mailing list