Factor out function to decode 2 hex digits
[xapian.git] / xapian-core / include / xapian / matchspy.h
blobbdff2fc0450595a442346f00e162655b040a5332
1 /** @file
2 * @brief MatchSpy implementation.
3 */
4 /* Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014,2015 Olly Betts
5 * Copyright (C) 2007,2009 Lemur Consulting Ltd
6 * Copyright (C) 2010 Richard Boulton
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #ifndef XAPIAN_INCLUDED_MATCHSPY_H
24 #define XAPIAN_INCLUDED_MATCHSPY_H
26 #if !defined XAPIAN_IN_XAPIAN_H && !defined XAPIAN_LIB_BUILD
27 # error Never use <xapian/matchspy.h> directly; include <xapian.h> instead.
28 #endif
30 #include <xapian/attributes.h>
31 #include <xapian/intrusive_ptr.h>
32 #include <xapian/termiterator.h>
33 #include <xapian/visibility.h>
35 #include <string>
36 #include <map>
38 namespace Xapian {
40 class Document;
41 class Registry;
43 /** Abstract base class for match spies.
45 * The subclasses will generally accumulate information seen during the match,
46 * to calculate aggregate functions, or other profiles of the matching
47 * documents.
49 class XAPIAN_VISIBILITY_DEFAULT MatchSpy
50 : public Xapian::Internal::opt_intrusive_base {
51 private:
52 /// Don't allow assignment.
53 void operator=(const MatchSpy &);
55 /// Don't allow copying.
56 MatchSpy(const MatchSpy &);
58 public:
59 /// Default constructor, needed by subclass constructors.
60 XAPIAN_NOTHROW(MatchSpy()) {}
62 /** Virtual destructor, because we have virtual methods. */
63 virtual ~MatchSpy();
65 /** Register a document with the match spy.
67 * This is called by the matcher once with each document seen by the
68 * matcher during the match process. Note that the matcher will often not
69 * see all the documents which match the query, due to optimisations which
70 * allow low-weighted documents to be skipped, and allow the match process
71 * to be terminated early.
73 * @param doc The document seen by the match spy.
74 * @param wt The weight of the document.
76 virtual void operator()(const Xapian::Document &doc,
77 double wt) = 0;
79 /** Clone the match spy.
81 * The clone should inherit the configuration of the parent, but need not
82 * inherit the state. ie, the clone does not need to be passed
83 * information about the results seen by the parent.
85 * If you don't want to support the remote backend in your match spy, you
86 * can use the default implementation which simply throws
87 * Xapian::UnimplementedError.
89 * Note that the returned object will be deallocated by Xapian after use
90 * with "delete". If you want to handle the deletion in a special way
91 * (for example when wrapping the Xapian API for use from another
92 * language) then you can define a static <code>operator delete</code>
93 * method in your subclass as shown here:
94 * https://trac.xapian.org/ticket/554#comment:1
96 virtual MatchSpy * clone() const;
98 /** Return the name of this match spy.
100 * This name is used by the remote backend. It is passed with the
101 * serialised parameters to the remote server so that it knows which class
102 * to create.
104 * Return the full namespace-qualified name of your class here - if your
105 * class is called MyApp::FooMatchSpy, return "MyApp::FooMatchSpy" from
106 * this method.
108 * If you don't want to support the remote backend in your match spy, you
109 * can use the default implementation which simply throws
110 * Xapian::UnimplementedError.
112 virtual std::string name() const;
114 /** Return this object's parameters serialised as a single string.
116 * If you don't want to support the remote backend in your match spy, you
117 * can use the default implementation which simply throws
118 * Xapian::UnimplementedError.
120 virtual std::string serialise() const;
122 /** Unserialise parameters.
124 * This method unserialises parameters serialised by the @a serialise()
125 * method and allocates and returns a new object initialised with them.
127 * If you don't want to support the remote backend in your match spy, you
128 * can use the default implementation which simply throws
129 * Xapian::UnimplementedError.
131 * Note that the returned object will be deallocated by Xapian after use
132 * with "delete". If you want to handle the deletion in a special way
133 * (for example when wrapping the Xapian API for use from another
134 * language) then you can define a static <code>operator delete</code>
135 * method in your subclass as shown here:
136 * https://trac.xapian.org/ticket/554#comment:1
138 * @param serialised A string containing the serialised results.
139 * @param context Registry object to use for unserialisation to permit
140 * MatchSpy subclasses with sub-MatchSpy objects to be
141 * implemented.
143 virtual MatchSpy * unserialise(const std::string & serialised,
144 const Registry & context) const;
146 /** Serialise the results of this match spy.
148 * If you don't want to support the remote backend in your match spy, you
149 * can use the default implementation which simply throws
150 * Xapian::UnimplementedError.
152 virtual std::string serialise_results() const;
154 /** Unserialise some results, and merge them into this matchspy.
156 * The order in which results are merged should not be significant, since
157 * this order is not specified (and will vary depending on the speed of
158 * the search in each sub-database).
160 * If you don't want to support the remote backend in your match spy, you
161 * can use the default implementation which simply throws
162 * Xapian::UnimplementedError.
164 * @param serialised A string containing the serialised results.
166 virtual void merge_results(const std::string & serialised);
168 /** Return a string describing this object.
170 * This default implementation returns a generic answer, to avoid forcing
171 * those deriving their own MatchSpy subclasses from having to implement
172 * this (they may not care what get_description() gives for their
173 * subclass).
175 virtual std::string get_description() const;
177 /** Start reference counting this object.
179 * You can hand ownership of a dynamically allocated MatchSpy
180 * object to Xapian by calling release() and then passing the object to a
181 * Xapian method. Xapian will arrange to delete the object once it is no
182 * longer required.
184 MatchSpy * release() {
185 opt_intrusive_base::release();
186 return this;
189 /** Start reference counting this object.
191 * You can hand ownership of a dynamically allocated MatchSpy
192 * object to Xapian by calling release() and then passing the object to a
193 * Xapian method. Xapian will arrange to delete the object once it is no
194 * longer required.
196 const MatchSpy * release() const {
197 opt_intrusive_base::release();
198 return this;
203 /** Class for counting the frequencies of values in the matching documents.
205 class XAPIAN_VISIBILITY_DEFAULT ValueCountMatchSpy : public MatchSpy {
206 public:
207 struct Internal;
209 #ifndef SWIG // SWIG doesn't need to know about the internal class
210 /// @private @internal
211 struct XAPIAN_VISIBILITY_DEFAULT Internal
212 : public Xapian::Internal::intrusive_base
214 /// The slot to count.
215 Xapian::valueno slot;
217 /// Total number of documents seen by the match spy.
218 Xapian::doccount total;
220 /// The values seen so far, together with their frequency.
221 std::map<std::string, Xapian::doccount> values;
223 Internal() : slot(Xapian::BAD_VALUENO), total(0) {}
224 explicit Internal(Xapian::valueno slot_) : slot(slot_), total(0) {}
226 #endif
228 protected:
229 /** @private @internal Reference counted internals. */
230 Xapian::Internal::intrusive_ptr<Internal> internal;
232 public:
233 /// Construct an empty ValueCountMatchSpy.
234 ValueCountMatchSpy() {}
236 /// Construct a MatchSpy which counts the values in a particular slot.
237 explicit ValueCountMatchSpy(Xapian::valueno slot_)
238 : internal(new Internal(slot_)) {}
240 /** Return the total number of documents tallied. */
241 size_t XAPIAN_NOTHROW(get_total() const) {
242 return internal.get() ? internal->total : 0;
245 /** Get an iterator over the values seen in the slot.
247 * Items will be returned in ascending alphabetical order.
249 * During the iteration, the frequency of the current value can be
250 * obtained with the get_termfreq() method on the iterator.
252 TermIterator values_begin() const;
254 /** End iterator corresponding to values_begin() */
255 TermIterator XAPIAN_NOTHROW(values_end() const) {
256 return TermIterator();
259 /** Get an iterator over the most frequent values seen in the slot.
261 * Items will be returned in descending order of frequency. Values with
262 * the same frequency will be returned in ascending alphabetical order.
264 * During the iteration, the frequency of the current value can be
265 * obtained with the get_termfreq() method on the iterator.
267 * @param maxvalues The maximum number of values to return.
269 TermIterator top_values_begin(size_t maxvalues) const;
271 /** End iterator corresponding to top_values_begin() */
272 TermIterator XAPIAN_NOTHROW(top_values_end(size_t) const) {
273 return TermIterator();
276 /** Implementation of virtual operator().
278 * This implementation tallies values for a matching document.
280 * @param doc The document to tally values for.
281 * @param wt The weight of the document (ignored by this class).
283 void operator()(const Xapian::Document &doc, double wt);
285 virtual MatchSpy * clone() const;
286 virtual std::string name() const;
287 virtual std::string serialise() const;
288 virtual MatchSpy * unserialise(const std::string & serialised,
289 const Registry & context) const;
290 virtual std::string serialise_results() const;
291 virtual void merge_results(const std::string & serialised);
292 virtual std::string get_description() const;
297 #endif // XAPIAN_INCLUDED_MATCHSPY_H