Document xapian-compact --blocksize takes an argument
[xapian.git] / xapian-core / api / registry.cc
blob651bd2a6b63c854da78f36cc7356ef579f44519a
1 /** @file registry.cc
2 * @brief Class for looking up user subclasses during unserialisation.
3 */
4 /* Copyright (C) 2006,2007,2008,2009,2010 Olly Betts
5 * Copyright (C) 2006,2007,2009 Lemur Consulting Ltd
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/registry.h"
26 #include "xapian/error.h"
27 #include "xapian/geospatial.h"
28 #include "xapian/intrusive_ptr.h"
29 #include "xapian/matchspy.h"
30 #include "xapian/postingsource.h"
31 #include "xapian/weight.h"
33 #include "debuglog.h"
35 #include <algorithm>
36 #include <map>
37 #include <string>
39 using namespace std;
41 class Xapian::Registry::Internal : public Xapian::Internal::intrusive_base {
42 friend class Xapian::Registry;
44 /// Registered weighting schemes.
45 std::map<std::string, Xapian::Weight *> wtschemes;
47 /// Registered external posting sources.
48 std::map<std::string, Xapian::PostingSource *> postingsources;
50 /// Registered match spies.
51 std::map<std::string, Xapian::MatchSpy *> matchspies;
53 /// Registered lat-long metrics.
54 std::map<std::string, Xapian::LatLongMetric *> lat_long_metrics;
56 /// Add the standard subclasses provided in the API.
57 void add_defaults();
59 /// Clear all registered weighting schemes.
60 void clear_weighting_schemes();
62 /// Clear all registered posting sources.
63 void clear_posting_sources();
65 /// Clear all registered match spies.
66 void clear_match_spies();
68 /// Clear all registered lat-long metrics.
69 void clear_lat_long_metrics();
71 public:
72 Internal();
73 ~Internal();
76 template<class T>
77 static inline void
78 register_object(map<string, T*> & registry, const T & obj)
80 string name = obj.name();
81 if (rare(name.empty())) {
82 throw Xapian::InvalidOperationError("Unable to register object - name() method returned empty string");
85 pair<typename map<string, T *>::iterator, bool> r;
86 r = registry.insert(make_pair(name, static_cast<T*>(NULL)));
87 if (!r.second) {
88 // Existing element with this key, so replace the pointer with NULL
89 // and delete the existing pointer.
91 // If the delete throws, this will leave a NULL entry in the map, but
92 // that won't affect behaviour as we return NULL for "not found"
93 // anyway. The memory used will be leaked if the dtor throws, but
94 // throwing exceptions from the dtor is bad form, so that's not a big
95 // problem.
96 T * p = NULL;
97 swap(p, r.first->second);
98 delete p;
101 T * clone = obj.clone();
102 if (rare(!clone)) {
103 throw Xapian::InvalidOperationError("Unable to register object - clone() method returned NULL");
106 r.first->second = clone;
109 template<class T>
110 static inline const T *
111 lookup_object(map<string, T*> registry, const string & name)
113 typename map<string, T*>::const_iterator i = registry.find(name);
114 if (i == registry.end()) {
115 return NULL;
117 return i->second;
120 namespace Xapian {
122 Registry::Internal::Internal()
124 add_defaults();
127 Registry::Internal::~Internal()
129 clear_weighting_schemes();
130 clear_posting_sources();
131 clear_match_spies();
132 clear_lat_long_metrics();
135 void
136 Registry::Internal::add_defaults()
138 Xapian::Weight * weighting_scheme;
139 weighting_scheme = new Xapian::BB2Weight;
140 wtschemes[weighting_scheme->name()] = weighting_scheme;
141 weighting_scheme = new Xapian::BM25Weight;
142 wtschemes[weighting_scheme->name()] = weighting_scheme;
143 weighting_scheme = new Xapian::BoolWeight;
144 wtschemes[weighting_scheme->name()] = weighting_scheme;
145 weighting_scheme = new Xapian::TradWeight;
146 wtschemes[weighting_scheme->name()] = weighting_scheme;
147 weighting_scheme = new Xapian::TfIdfWeight;
148 wtschemes[weighting_scheme->name()] = weighting_scheme;
149 weighting_scheme = new Xapian::InL2Weight;
150 wtschemes[weighting_scheme->name()] = weighting_scheme;
151 weighting_scheme = new Xapian::IfB2Weight;
152 wtschemes[weighting_scheme->name()] = weighting_scheme;
153 weighting_scheme = new Xapian::IneB2Weight;
154 wtschemes[weighting_scheme->name()] = weighting_scheme;
155 weighting_scheme = new Xapian::DLHWeight;
156 wtschemes[weighting_scheme->name()] = weighting_scheme;
157 weighting_scheme = new Xapian::PL2Weight;
158 wtschemes[weighting_scheme->name()] = weighting_scheme;
159 weighting_scheme = new Xapian::DPHWeight;
160 wtschemes[weighting_scheme->name()] = weighting_scheme;
161 weighting_scheme = new Xapian::LMWeight;
162 wtschemes[weighting_scheme->name()] = weighting_scheme;
164 Xapian::PostingSource * source;
165 source = new Xapian::ValueWeightPostingSource(0);
166 postingsources[source->name()] = source;
167 source = new Xapian::DecreasingValueWeightPostingSource(0);
168 postingsources[source->name()] = source;
169 source = new Xapian::ValueMapPostingSource(0);
170 postingsources[source->name()] = source;
171 source = new Xapian::FixedWeightPostingSource(0.0);
172 postingsources[source->name()] = source;
173 source = new Xapian::LatLongDistancePostingSource(0,
174 Xapian::LatLongCoords(),
175 Xapian::GreatCircleMetric());
176 postingsources[source->name()] = source;
178 Xapian::MatchSpy * spy;
179 spy = new Xapian::ValueCountMatchSpy();
180 matchspies[spy->name()] = spy;
182 Xapian::LatLongMetric * metric;
183 metric = new Xapian::GreatCircleMetric();
184 lat_long_metrics[metric->name()] = metric;
187 void
188 Registry::Internal::clear_weighting_schemes()
190 map<string, Xapian::Weight*>::const_iterator i;
191 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) {
192 delete i->second;
196 void
197 Registry::Internal::clear_posting_sources()
199 map<string, Xapian::PostingSource *>::const_iterator i;
200 for (i = postingsources.begin(); i != postingsources.end(); ++i) {
201 delete i->second;
205 void
206 Registry::Internal::clear_match_spies()
208 map<string, Xapian::MatchSpy *>::const_iterator i;
209 for (i = matchspies.begin(); i != matchspies.end(); ++i) {
210 delete i->second;
214 void
215 Registry::Internal::clear_lat_long_metrics()
217 map<string, Xapian::LatLongMetric *>::const_iterator i;
218 for (i = lat_long_metrics.begin(); i != lat_long_metrics.end(); ++i) {
219 delete i->second;
223 Registry::Registry(const Registry & other)
224 : internal(other.internal)
226 LOGCALL_CTOR(API, "Registry", other);
229 Registry &
230 Registry::operator=(const Registry & other)
232 LOGCALL(API, Xapian::Registry &, "Xapian::Registry::operator=", other);
233 internal = other.internal;
234 RETURN(*this);
237 Registry::Registry()
238 : internal(new Registry::Internal())
240 LOGCALL_CTOR(API, "Registry", NO_ARGS);
243 Registry::~Registry()
245 LOGCALL_DTOR(API, "Registry");
247 // Note - we don't need to do anything special in this destructor, but it
248 // does need to be explicitly defined because the definition of the
249 // internals is not visible externally, which results in an error if the
250 // compiler tries to generate a default destructor.
253 void
254 Registry::register_weighting_scheme(const Xapian::Weight &wt)
256 LOGCALL_VOID(API, "Xapian::Registry::register_weighting_scheme", wt.name());
257 register_object(internal->wtschemes, wt);
260 const Xapian::Weight *
261 Registry::get_weighting_scheme(const string & name) const
263 LOGCALL(API, const Xapian::Weight *, "Xapian::Registry::get_weighting_scheme", name);
264 RETURN(lookup_object(internal->wtschemes, name));
267 void
268 Registry::register_posting_source(const Xapian::PostingSource &source)
270 LOGCALL_VOID(API, "Xapian::Registry::register_posting_source", source.name());
271 register_object(internal->postingsources, source);
274 const Xapian::PostingSource *
275 Registry::get_posting_source(const string & name) const
277 LOGCALL(API, const Xapian::PostingSource *, "Xapian::Registry::get_posting_source", name);
278 RETURN(lookup_object(internal->postingsources, name));
281 void
282 Registry::register_match_spy(const Xapian::MatchSpy &spy)
284 LOGCALL_VOID(API, "Xapian::Registry::register_match_spy", spy.name());
285 register_object(internal->matchspies, spy);
288 const Xapian::MatchSpy *
289 Registry::get_match_spy(const string & name) const
291 LOGCALL(API, const Xapian::MatchSpy *, "Xapian::Registry::get_match_spy", name);
292 RETURN(lookup_object(internal->matchspies, name));
295 void
296 Registry::register_lat_long_metric(const Xapian::LatLongMetric &metric)
298 LOGCALL_VOID(API, "Xapian::Registry::register_lat_long_metric", metric.name());
299 register_object(internal->lat_long_metrics, metric);
302 const Xapian::LatLongMetric *
303 Registry::get_lat_long_metric(const string & name) const
305 LOGCALL(API, const Xapian::LatLongMetric *, "Xapian::Registry::get_lat_long_metric", name);
306 RETURN(lookup_object(internal->lat_long_metrics, name));