Switch to side-by-side view

--- a/src/rcldb/rcldb.cpp
+++ b/src/rcldb/rcldb.cpp
@@ -1,5 +1,5 @@
 #ifndef lint
-static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.123 2007-09-07 08:05:19 dockes Exp $ (C) 2004 J.F.Dockes";
+static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.124 2007-10-24 08:42:59 dockes Exp $ (C) 2004 J.F.Dockes";
 #endif
 /*
  *   This program is free software; you can redistribute it and/or modify
@@ -104,18 +104,20 @@
     Xapian::Database db;
     Xapian::Query    query; // query descriptor: terms and subqueries
 			    // joined by operators (or/and etc...)
-    Xapian::Enquire *enquire; // Open query descriptor.
-    Xapian::MSet     mset;    // Partial result set
+    Xapian::MatchDecider *decider;
+    Xapian::Enquire      *enquire; // Open query descriptor.
+    Xapian::MSet          mset;    // Partial result set
 
     // Term frequencies for current query. See makeAbstract, setQuery
     map<string, double>  m_termfreqs; 
     
     Native(Db *db) 
 	: m_db(db),
-	  m_isopen(false), m_iswritable(false), enquire(0) 
+	  m_isopen(false), m_iswritable(false), decider(0), enquire(0)
     { }
 
     ~Native() {
+	delete decider;
 	delete enquire;
     }
 
@@ -134,8 +136,16 @@
      */
     bool subDocs(const string &hash, vector<Xapian::docid>& docids);
 
-    /** Keep this inline */
-    bool filterMatch(Db *rdb, Xapian::Document &xdoc) {
+};
+
+class FilterMatcher : public Xapian::MatchDecider {
+public:
+    FilterMatcher(const string &topdir)
+	: m_topdir(topdir)
+    {}
+    virtual ~FilterMatcher() {}
+
+    virtual bool operator()(const Xapian::Document &xdoc) const {
 	// Parse xapian document's data and populate doc fields
 	string data = xdoc.get_data();
 	ConfSimple parms(&data);
@@ -143,16 +153,22 @@
 	// The only filtering for now is on file path (subtree)
 	string url;
 	parms.get(string("url"), url);
-	url = url.substr(7);
-	LOGDEB2(("Rcl::Db::Native:filter filter [%s] fn [%s]\n",
-		 rdb->m_filterTopDir.c_str(), url.c_str()));
-	if (url.find(rdb->m_filterTopDir) == 0) 
-	    return true;
-	return false;
-    }
+	LOGDEB2(("FilterMatcher topdir [%s] url [%s]\n",
+		 m_topdir.c_str(), url.c_str()));
+	if (url.find(m_topdir, 7) == 7) {
+	    LOGDEB(("FilterMatcher: MATCH\n"));
+	    return true; 
+	} else {
+	    LOGDEB(("FilterMatcher: NO MATCH\n"));
+	    return false;
+	}
+    }
+    
+private:
+    string m_topdir;
 };
 
-    /* See comment in class declaration */
+/* See comment in class declaration */
 bool Native::subDocs(const string &hash, vector<Xapian::docid>& docids) 
 {
     docids.clear();
@@ -1424,6 +1440,10 @@
     LOGDEB(("Db::setQuery:\n"));
 
     m_filterTopDir = sdata->getTopdir();
+    delete m_ndb->decider;
+    m_ndb->decider = 0;
+    if (!m_filterTopDir.empty())
+	m_ndb->decider = new FilterMatcher(m_filterTopDir);
     m_dbindices.clear();
     m_qOpts = opts;
     m_ndb->m_termfreqs.clear();
@@ -1760,12 +1780,8 @@
 	return false;
     }
 
-    // For now the only post-query filter is on dir subtree
-    bool postqfilter = !m_filterTopDir.empty();
-    LOGDEB1(("Topdir %s postqflt %d\n", m_asdata.topdir.c_str(), postqfilter));
-
     int xapi;
-    if (postqfilter) {
+    if (m_ndb->decider) {
 	// There is a postquery filter, does this fall in already known area ?
 	if (exti >= (int)m_dbindices.size()) {
 	    // Have to fetch xapian docs and filter until we get
@@ -1796,7 +1812,7 @@
 		for (unsigned int i = 0; i < m_ndb->mset.size() ; i++) {
 		    LOGDEB(("Db::getDoc: [%d]\n", i));
 		    Xapian::Document xdoc = m_ndb->mset[i].get_document();
-		    if (m_ndb->filterMatch(this, xdoc)) {
+		    if ((*m_ndb->decider)(xdoc)) {
 			m_dbindices.push_back(first + i);
 		    }
 		}
@@ -1807,7 +1823,6 @@
     } else {
 	xapi = exti;
     }
-
 
     // From there on, we work with a xapian enquire item number. Fetch it
     int first = m_ndb->mset.get_firstitem();