1 /** @file branchpostlist.h
2  * @brief virtual base class for branched types of postlist
3  */
4 /* Copyright 1999,2000,2001 BrightStation PLC
5  * Copyright 2002 Ananova Ltd
6  * Copyright 2003,2004,2007,2011 Olly Betts
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21  * USA
22  */
23 
24 #ifndef OM_HGUARD_BRANCHPOSTLIST_H
25 #define OM_HGUARD_BRANCHPOSTLIST_H
26 
27 #include "multimatch.h"
28 #include "api/postlist.h"
29 
30 /** Base class for postlists which are generated by merging two
31  *  sub-postlists.
32  *
33  *  These postlists form a tree which is used to perform a sum over all the
34  *  terms in the query for each document, in order to calculate the score
35  *  for that document.
36  */
37 class BranchPostList : public PostList {
38     private:
39 	// Prevent copying
40 	BranchPostList(const BranchPostList &);
41 	BranchPostList & operator=(const BranchPostList &);
42 
43     protected:
44 	/// Left sub-postlist
45 	PostList *l;
46 
47 	/// Right sub-postlist
48 	PostList *r;
49 
50 	/** The object which is using this postlist to perform
51 	 *  a match.  This object needs to be notified when the
52 	 *  tree changes such that the maximum weights need to be
53 	 *  recalculated.
54 	 */
55 	MultiMatch *matcher;
56 
57 	/** Utility method, to call recalc_maxweight() and do the pruning
58 	 *  if a next() or skip_to() returns non-NULL result.
59 	 */
handle_prune(PostList * & kid,PostList * ret)60 	void handle_prune(PostList *&kid, PostList *ret) {
61 	    if (ret) {
62 		delete kid;
63 		kid = ret;
64 
65 		// now tell matcher that maximum weights need recalculation.
66 		matcher->recalc_maxweight();
67 	    }
68 	}
69 
70     public:
BranchPostList(PostList * l_,PostList * r_,MultiMatch * matcher_)71 	BranchPostList(PostList *l_, PostList *r_, MultiMatch *matcher_)
72 		: l(l_), r(r_), matcher(matcher_) {}
73 
74 	virtual ~BranchPostList();
75 };
76 
77 // Helper functions - call next/skip_to on a postlist and handle any
78 // resulting prune
79 //
80 // Returns true iff a prune was handled, so the caller can recalculate
81 // weights etc if necessary
82 inline bool
next_handling_prune(PostList * & pl,double w_min,MultiMatch * matcher)83 next_handling_prune(PostList * & pl, double w_min, MultiMatch *matcher)
84 {
85     PostList *p = pl->next(w_min);
86     if (!p) return false;
87     delete pl;
88     pl = p;
89     // now tell matcher that maximum weights need recalculation.
90     if (matcher) matcher->recalc_maxweight();
91     return true;
92 }
93 
94 inline bool
skip_to_handling_prune(PostList * & pl,Xapian::docid did,double w_min,MultiMatch * matcher)95 skip_to_handling_prune(PostList * & pl, Xapian::docid did, double w_min,
96 		       MultiMatch *matcher)
97 {
98     PostList *p = pl->skip_to(did, w_min);
99     if (!p) return false;
100     delete pl;
101     pl = p;
102     // now tell matcher that maximum weights need recalculation.
103     if (matcher) matcher->recalc_maxweight();
104     return true;
105 }
106 
107 inline bool
check_handling_prune(PostList * & pl,Xapian::docid did,double w_min,MultiMatch * matcher,bool & valid)108 check_handling_prune(PostList * & pl, Xapian::docid did, double w_min,
109 		     MultiMatch *matcher, bool & valid)
110 {
111     PostList *p = pl->check(did, w_min, valid);
112     if (!p) return false;
113     delete pl;
114     pl = p;
115     // now tell matcher that maximum weights need recalculation.
116     if (matcher) matcher->recalc_maxweight();
117     return true;
118 }
119 
120 #endif /* OM_HGUARD_BRANCHPOSTLIST_H */
121