2 * @brief Build key strings for MSet ordering or collapsing.
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
24 #include "xapian/keymaker.h"
26 #include "xapian/document.h"
35 KeyMaker::~KeyMaker() { }
38 MultiValueKeyMaker::operator()(const Xapian::Document
& doc
) const
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;
48 // All values (except for the last if it's sorted forwards) need to
51 // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
52 string v
= doc
.get_value(i
->slot
);
53 bool reverse_sort
= i
->reverse
;
59 if (reverse_sort
|| !v
.empty())
60 last_not_empty_forwards
= result
.size();
62 if (++i
== slots
.end() && !reverse_sort
) {
64 // Trim off all the trailing empty forwards values.
65 result
.resize(last_not_empty_forwards
);
67 // No need to adjust the last value if it's sorted forwards.
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();
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
89 string::size_type j
= 0, nul
;
90 while ((nul
= v
.find('\0', j
)) != string::npos
) {
92 result
.append(v
, j
, nul
- j
);
96 result
.append(v
, j
, string::npos
);
98 last_not_empty_forwards
= result
.size();
99 result
.append("\0", 2);