scriptindex: Fix weird error cases
[xapian.git] / xapian-core / matcher / msetcmp.cc
blob1a4d8673fc2abdebb4c13016777559dde4080ea4
1 /** @file
2 * @brief MSetItem comparison functions.
3 */
4 /* Copyright (C) 2006,2009,2013,2017 Olly Betts
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 * USA
22 #include <config.h>
23 #include "msetcmp.h"
25 #include "omassert.h"
27 /* We use templates to generate the 14 different comparison functions
28 * which we need. This avoids having to write them all out by hand.
31 // Order by did. Helper comparison template function, which is used as the
32 // last fallback by the others.
33 template<bool FORWARD_DID, bool CHECK_DID_ZERO>
34 static inline bool
35 msetcmp_by_did(const Xapian::Internal::MSetItem &a,
36 const Xapian::Internal::MSetItem &b)
38 if (FORWARD_DID) {
39 if (CHECK_DID_ZERO) {
40 // We want dummy did 0 to compare worse than any other.
41 if (a.did == 0) return false;
42 if (b.did == 0) return true;
44 return (a.did < b.did);
45 } else {
46 return (a.did > b.did);
50 // Order by relevance, then docid.
51 template<bool FORWARD_DID>
52 static bool
53 msetcmp_by_relevance(const Xapian::Internal::MSetItem &a,
54 const Xapian::Internal::MSetItem &b)
56 if (a.wt > b.wt) return true;
57 if (a.wt < b.wt) return false;
58 return msetcmp_by_did<FORWARD_DID, true>(a, b);
61 // Order by value, then docid.
62 template<bool FORWARD_VALUE, bool FORWARD_DID>
63 static bool
64 msetcmp_by_value(const Xapian::Internal::MSetItem &a,
65 const Xapian::Internal::MSetItem &b)
67 if (!FORWARD_VALUE) {
68 // We want dummy did 0 to compare worse than any other.
69 if (a.did == 0) return false;
70 if (b.did == 0) return true;
72 int sort_cmp = a.sort_key.compare(b.sort_key);
73 if (sort_cmp > 0) return FORWARD_VALUE;
74 if (sort_cmp < 0) return !FORWARD_VALUE;
75 return msetcmp_by_did<FORWARD_DID, FORWARD_VALUE>(a, b);
78 // Order by value, then relevance, then docid.
79 template<bool FORWARD_VALUE, bool FORWARD_DID>
80 static bool
81 msetcmp_by_value_then_relevance(const Xapian::Internal::MSetItem &a,
82 const Xapian::Internal::MSetItem &b)
84 if (!FORWARD_VALUE) {
85 // two special cases to make min_item compares work when did == 0
86 if (a.did == 0) return false;
87 if (b.did == 0) return true;
89 int sort_cmp = a.sort_key.compare(b.sort_key);
90 if (sort_cmp > 0) return FORWARD_VALUE;
91 if (sort_cmp < 0) return !FORWARD_VALUE;
92 if (a.wt > b.wt) return true;
93 if (a.wt < b.wt) return false;
94 return msetcmp_by_did<FORWARD_DID, FORWARD_VALUE>(a, b);
97 // Order by relevance, then value, then docid.
98 template<bool FORWARD_VALUE, bool FORWARD_DID>
99 static bool
100 msetcmp_by_relevance_then_value(const Xapian::Internal::MSetItem &a,
101 const Xapian::Internal::MSetItem &b)
103 if (!FORWARD_VALUE) {
104 // two special cases to make min_item compares work when did == 0
105 if (a.did == 0) return false;
106 if (b.did == 0) return true;
108 if (a.wt > b.wt) return true;
109 if (a.wt < b.wt) return false;
110 int sort_cmp = a.sort_key.compare(b.sort_key);
111 if (sort_cmp > 0) return FORWARD_VALUE;
112 if (sort_cmp < 0) return !FORWARD_VALUE;
113 return msetcmp_by_did<FORWARD_DID, FORWARD_VALUE>(a, b);
116 MSetCmp
117 get_msetcmp_function(Xapian::Enquire::Internal::sort_setting sort_by,
118 bool sort_forward,
119 bool sort_val_reverse)
121 switch (sort_by) {
122 case Xapian::Enquire::Internal::REL:
123 if (sort_forward)
124 return msetcmp_by_relevance<true>;
125 else
126 return msetcmp_by_relevance<false>;
127 case Xapian::Enquire::Internal::VAL:
128 if (sort_forward) {
129 if (sort_val_reverse) {
130 return msetcmp_by_value<true, true>;
131 } else {
132 return msetcmp_by_value<false, true>;
134 } else {
135 if (sort_val_reverse) {
136 return msetcmp_by_value<true, false>;
137 } else {
138 return msetcmp_by_value<false, false>;
141 case Xapian::Enquire::Internal::VAL_REL:
142 if (sort_forward) {
143 if (sort_val_reverse) {
144 return msetcmp_by_value_then_relevance<true, true>;
145 } else {
146 return msetcmp_by_value_then_relevance<false, true>;
148 } else {
149 if (sort_val_reverse) {
150 return msetcmp_by_value_then_relevance<true, false>;
151 } else {
152 return msetcmp_by_value_then_relevance<false, false>;
155 default:
156 // Must be REL_VAL, but handle with "default" to avoid warnings
157 // about falling off the end of the function.
158 AssertEq(sort_by, Xapian::Enquire::Internal::REL_VAL);
159 if (sort_forward) {
160 if (sort_val_reverse) {
161 return msetcmp_by_relevance_then_value<true, true>;
162 } else {
163 return msetcmp_by_relevance_then_value<false, true>;
165 } else {
166 if (sort_val_reverse) {
167 return msetcmp_by_relevance_then_value<true, false>;
168 } else {
169 return msetcmp_by_relevance_then_value<false, false>;