Document xapian-compact --blocksize takes an argument
[xapian.git] / xapian-core / api / keymaker.cc
blob035ac4af3f5e9b1f7a7237c371d1a5d71c02d4ff
1 /** @file keymaker.cc
2 * @brief Build key strings for MSet ordering or collapsing.
3 */
4 /* Copyright (C) 2007,2009,2011,2015 Olly Betts
5 * Copyright (C) 2010 Richard Boulton
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <config.h>
24 #include "xapian/keymaker.h"
26 #include "xapian/document.h"
28 #include <string>
29 #include <vector>
31 using namespace std;
33 namespace Xapian {
35 KeyMaker::~KeyMaker() { }
37 string
38 MultiValueKeyMaker::operator()(const Xapian::Document & doc) const
40 string result;
42 auto i = slots.begin();
43 // Don't crash if slots is empty.
44 if (rare(i == slots.end())) return result;
46 size_t last_not_empty_forwards = 0;
47 while (true) {
48 // All values (except for the last if it's sorted forwards) need to
49 // be adjusted.
51 // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
52 string v = doc.get_value(i->slot);
53 bool reverse_sort = i->reverse;
55 if (v.empty()) {
56 v = i->defvalue;
59 if (reverse_sort || !v.empty())
60 last_not_empty_forwards = result.size();
62 if (++i == slots.end() && !reverse_sort) {
63 if (v.empty()) {
64 // Trim off all the trailing empty forwards values.
65 result.resize(last_not_empty_forwards);
66 } else {
67 // No need to adjust the last value if it's sorted forwards.
68 result += v;
70 break;
73 if (reverse_sort) {
74 // For a reverse ordered value, we subtract each byte from '\xff',
75 // except for '\0' which we convert to "\xff\0". We insert
76 // "\xff\xff" after the encoded value.
77 for (string::const_iterator j = v.begin(); j != v.end(); ++j) {
78 unsigned char ch = static_cast<unsigned char>(*j);
79 result += char(255 - ch);
80 if (ch == 0) result += '\0';
82 result.append("\xff\xff", 2);
83 if (i == slots.end()) break;
84 last_not_empty_forwards = result.size();
85 } else {
86 // For a forward ordered value (unless it's the last value), we
87 // convert any '\0' to "\0\xff". We insert "\0\0" after the
88 // encoded value.
89 string::size_type j = 0, nul;
90 while ((nul = v.find('\0', j)) != string::npos) {
91 ++nul;
92 result.append(v, j, nul - j);
93 result += '\xff';
94 j = nul;
96 result.append(v, j, string::npos);
97 if (!v.empty())
98 last_not_empty_forwards = result.size();
99 result.append("\0", 2);
102 return result;