Branch data Line data Source code
1 : : /** @file keymaker.cc
2 : : * @brief Build key strings for MSet ordering or collapsing.
3 : : */
4 : : /* Copyright (C) 2007,2009 Olly Betts
5 : : *
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.
10 : : *
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.
15 : : *
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 USA
19 : : */
20 : :
21 : : #include <config.h>
22 : :
23 : : #include "xapian/keymaker.h"
24 : :
25 : : #include "xapian/document.h"
26 : :
27 : : #include <string>
28 : : #include <vector>
29 : :
30 : : using namespace std;
31 : :
32 : : namespace Xapian {
33 : :
34 [ # # ][ # # ]: 141 : KeyMaker::~KeyMaker() { }
[ - + ]
35 : :
36 : : string
37 : 440 : MultiValueKeyMaker::operator()(const Xapian::Document & doc) const
38 : : {
39 : 440 : string result;
40 : :
41 : 440 : vector<pair<Xapian::valueno, bool> >::const_iterator i = valnos.begin();
42 : : // Don't crash if valnos is empty.
43 [ + + ]: 440 : if (rare(i == valnos.end())) return result;
44 : :
45 : 377 : size_t last_not_empty_forwards = 0;
46 [ + + ]: 788 : while (true) {
47 : : // All values (except for the last if it's sorted forwards) need to
48 : : // be adjusted.
49 : : //
50 : : // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
51 : 788 : string v = doc.get_value(i->first);
52 : 788 : bool reverse_sort = i->second;
53 : :
54 [ + + + + ]: 788 : if (reverse_sort || !v.empty())
[ + + ]
55 : 650 : last_not_empty_forwards = result.size();
56 : :
57 [ + + ][ + + ]: 788 : if (++i == valnos.end() && !reverse_sort) {
[ + + ]
58 [ + + ]: 127 : if (v.empty()) {
59 : : // Trim off all the trailing empty forwards values.
60 : 43 : result.resize(last_not_empty_forwards);
61 : : } else {
62 : : // No need to adjust the last value if it's sorted forwards.
63 : 127 : result += v;
64 : : }
65 : : break;
66 : : }
67 : :
68 [ + + ]: 661 : if (reverse_sort) {
69 : : // For a reverse ordered value, we subtract each byte from '\xff',
70 : : // except for '\0' which we convert to "\xff\0". We insert
71 : : // "\xff\xff" after the encoded value.
72 [ + + ]: 695 : for (string::const_iterator j = v.begin(); j != v.end(); ++j) {
73 : 405 : unsigned char ch(*j);
74 : 405 : result += char(255 - ch);
75 [ + + ]: 405 : if (ch == 0) result += '\0';
76 : : }
77 : 290 : result.append("\xff\xff", 2);
78 [ + + ]: 290 : if (i == valnos.end()) break;
79 : 40 : last_not_empty_forwards = result.size();
80 : : } else {
81 : : // For a forward ordered value (unless it's the last value), we
82 : : // convert any '\0' to "\0\xff". We insert "\0\0" after the
83 : : // encoded value.
84 : 371 : string::size_type j = 0, nul;
85 [ + + ]: 382 : while ((nul = v.find('\0', j)) != string::npos) {
86 : 11 : ++nul;
87 : 11 : result.append(v, j, nul - j);
88 : 11 : result += '\xff';
89 : 11 : j = nul;
90 : : }
91 : 371 : result.append(v, j, string::npos);
92 [ + + ]: 371 : if (!v.empty())
93 : 276 : last_not_empty_forwards = result.size();
94 : 411 : result.append("\0", 2);
95 : : }
96 : : }
97 : 440 : return result;
98 : : }
99 : :
100 : : string
101 : 435 : MultiValueSorter::operator()(const Xapian::Document & doc) const
102 : : {
103 : 435 : string result;
104 : :
105 : 435 : vector<pair<Xapian::valueno, bool> >::const_iterator i = valnos.begin();
106 : : // Don't crash if valnos is empty.
107 [ + + ]: 435 : if (rare(i == valnos.end())) return result;
108 : :
109 [ + + ]: 767 : while (true) {
110 : : // All values (except for the last if it's sorted forwards) need to
111 : : // be adjusted.
112 : : //
113 : : // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
114 : 767 : string v = doc.get_value(i->first);
115 : 767 : bool reverse_sort = !i->second;
116 : :
117 [ + + + + ]: 767 : if (++i == valnos.end() && !reverse_sort) {
[ + + ]
118 : : // No need to adjust the last value if it's sorted forwards.
119 : 123 : result += v;
120 : : break;
121 : : }
122 : :
123 [ + + ]: 644 : if (reverse_sort) {
124 : : // For a reverse ordered value, we subtract each byte from '\xff',
125 : : // except for '\0' which we convert to "\xff\0". We insert
126 : : // "\xff\xff" after the encoded value.
127 [ + + ]: 694 : for (string::const_iterator j = v.begin(); j != v.end(); ++j) {
128 : 405 : unsigned char ch(*j);
129 : 405 : result += char(255 - ch);
130 [ + + ]: 405 : if (ch == 0) result += '\0';
131 : : }
132 : 289 : result.append("\xff\xff", 2);
133 [ + + ]: 289 : if (i == valnos.end()) break;
134 : : } else {
135 : : // For a forward ordered value (unless it's the last value), we
136 : : // convert any '\0' to "\0\xff". We insert "\0\0" after the
137 : : // encoded value.
138 : 355 : string::size_type j = 0, nul;
139 [ + + ]: 363 : while ((nul = v.find('\0', j)) != string::npos) {
140 : 8 : ++nul;
141 : 8 : result.append(v, j, nul - j);
142 : 8 : result += '\xff';
143 : 8 : j = nul;
144 : : }
145 : 355 : result.append(v, j, string::npos);
146 : 395 : result.append("\0", 2);
147 : : }
148 : : }
149 : 435 : return result;
150 : : }
151 : :
152 : : }
|