xapian-core  1.4.27
keymaker.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2007,2009,2011,2015 Olly Betts
5  * Copyright (C) 2010 Richard Boulton
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #include <config.h>
23 
24 #include "xapian/keymaker.h"
25 
26 #include "xapian/document.h"
27 
28 #include <string>
29 #include <vector>
30 
31 using namespace std;
32 
33 namespace Xapian {
34 
35 KeyMaker::~KeyMaker() { }
36 
37 string
38 MultiValueKeyMaker::operator()(const Xapian::Document & doc) const
39 {
40  string result;
41 
42  auto i = slots.begin();
43  // Don't crash if slots is empty.
44  if (rare(i == slots.end())) return result;
45 
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.
50  //
51  // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
52  string v = doc.get_value(i->slot);
53  bool reverse_sort = i->reverse;
54 
55  if (v.empty()) {
56  v = i->defvalue;
57  }
58 
59  if (reverse_sort || !v.empty())
60  last_not_empty_forwards = result.size();
61 
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;
69  }
70  break;
71  }
72 
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';
81  }
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;
95  }
96  result.append(v, j, string::npos);
97  if (!v.empty())
98  last_not_empty_forwards = result.size();
99  result.append("\0", 2);
100  }
101  }
102  return result;
103 }
104 
105 }
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:80
STL namespace.
#define rare(COND)
Definition: config.h:575
Build key strings for MSet ordering or collapsing.
API for working with documents.
std::string get_value(Xapian::valueno slot) const
Get value by number.
Definition: omdocument.cc:64
A handle representing a document in a Xapian database.
Definition: document.h:61