Branch data Line data Source code
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
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/registry.h"
25 : :
26 : : #include "xapian/error.h"
27 : : #include "xapian/matchspy.h"
28 : : #include "xapian/postingsource.h"
29 : : #include "xapian/weight.h"
30 : :
31 : : #include "registryinternal.h"
32 : : #include "debuglog.h"
33 : :
34 : : #include <algorithm>
35 : : #include <map>
36 : :
37 : : using namespace std;
38 : :
39 : : template<class T>
40 : : static inline void
41 : 19 : register_object(map<string, T*> & registry, const T & obj)
42 : : {
43 : 19 : string name = obj.name();
44 [ - + - + - : 19 : if (rare(name.empty())) {
+ ]
45 : 0 : throw Xapian::InvalidOperationError("Unable to register object - name() method returned empty string");
46 : : }
47 : :
48 : 19 : pair<typename map<string, T *>::iterator, bool> r;
49 [ - + ][ - + ]: 19 : r = registry.insert(make_pair(name, static_cast<T*>(NULL)));
[ - + ]
50 [ + + + + + : 19 : if (!r.second) {
+ ]
51 : : // Existing element with this key, so replace the pointer with NULL
52 : : // and delete the existing pointer.
53 : : //
54 : : // If the delete throws, this will leave a NULL entry in the map, but
55 : : // that won't affect behaviour as we return NULL for "not found"
56 : : // anyway. The memory used will be leaked if the dtor throws, but
57 : : // throwing exceptions from the dtor is bad form, so that's not a big
58 : : // problem.
59 : 11 : T * p = NULL;
60 : 11 : swap(p, r.first->second);
61 [ + - + - ]: 11 : delete p;
[ + - ]
62 : : }
63 : :
64 : 16 : T * clone = obj.clone();
65 [ - + - + - : 13 : if (rare(!clone)) {
+ ]
66 : 0 : throw Xapian::InvalidOperationError("Unable to register object - clone() method returned NULL");
67 : : }
68 : :
69 : 19 : r.first->second = clone;
70 : 13 : }
71 : :
72 : : template<class T>
73 : : static inline const T *
74 : 4587 : lookup_object(map<string, T*> registry, const string & name)
75 : : {
76 : 4587 : typename map<string, T*>::const_iterator i = registry.find(name);
77 [ - + + + - : 4587 : if (i == registry.end()) {
+ ]
78 : 2 : return NULL;
79 : : }
80 : 4587 : return i->second;
81 : : }
82 : :
83 : : namespace Xapian {
84 : :
85 : 1 : Registry::Registry(const Registry & other)
86 : 1 : : internal(other.internal)
87 : : {
88 : : LOGCALL_CTOR(API, "Registry", other);
89 : 1 : }
90 : :
91 : : Registry &
92 : 1 : Registry::operator=(const Registry & other)
93 : : {
94 : : LOGCALL(API, Xapian::Registry &, "Xapian::Registry::operator=", other);
95 : 1 : internal = other.internal;
96 : 1 : return(*this);
97 : : }
98 : :
99 : 1576 : Registry::Registry()
100 : 1576 : : internal(new Registry::Internal())
101 : : {
102 : : LOGCALL_CTOR(API, "Registry", NO_ARGS);
103 : 1576 : }
104 : :
105 : 1577 : Registry::~Registry()
106 : : {
107 : : LOGCALL_DTOR(API, "Registry");
108 : :
109 : : // Note - we don't need to do anything special in this destructor, but it
110 : : // does need to be explicitly defined because the definition of the
111 : : // internals is not visible externally, which results in an error if the
112 : : // compiler tries to generate a default destructor.
113 : 1577 : }
114 : :
115 : : void
116 : 7 : Registry::register_weighting_scheme(const Xapian::Weight &wt)
117 : : {
118 : : LOGCALL_VOID(API, "Xapian::Registry::register_weighting_scheme", wt.name());
119 : 7 : register_object(internal->wtschemes, wt);
120 : 5 : }
121 : :
122 : : const Xapian::Weight *
123 : 4406 : Registry::get_weighting_scheme(const string & name) const
124 : : {
125 : : LOGCALL(API, const Xapian::Weight *, "Xapian::Registry::get_weighting_scheme", name);
126 : 4406 : RETURN(lookup_object(internal->wtschemes, name));
127 : : }
128 : :
129 : : void
130 : 8 : Registry::register_posting_source(const Xapian::PostingSource &source)
131 : : {
132 : : LOGCALL_VOID(API, "Xapian::Registry::register_posting_source", source.name());
133 : 8 : register_object(internal->postingsources, source);
134 : 6 : }
135 : :
136 : : const Xapian::PostingSource *
137 : 113 : Registry::get_posting_source(const string & name) const
138 : : {
139 : : LOGCALL(API, const Xapian::PostingSource *, "Xapian::Registry::get_posting_source", name);
140 : 113 : RETURN(lookup_object(internal->postingsources, name));
141 : : }
142 : :
143 : : void
144 : 4 : Registry::register_match_spy(const Xapian::MatchSpy &spy)
145 : : {
146 : : LOGCALL_VOID(API, "Xapian::Registry::register_match_spy", spy.name());
147 : 4 : register_object(internal->matchspies, spy);
148 : 2 : }
149 : :
150 : : const Xapian::MatchSpy *
151 : 68 : Registry::get_match_spy(const string & name) const
152 : : {
153 : : LOGCALL(API, const Xapian::MatchSpy *, "Xapian::Registry::get_match_spy", name);
154 : 68 : RETURN(lookup_object(internal->matchspies, name));
155 : : }
156 : :
157 : :
158 : 1576 : Registry::Internal::Internal()
159 : : : Xapian::Internal::RefCntBase(),
160 : : wtschemes(),
161 : 1576 : postingsources()
162 : : {
163 : 1576 : add_defaults();
164 : 1576 : }
165 : :
166 : 1576 : Registry::Internal::~Internal()
167 : : {
168 : 1576 : clear_weighting_schemes();
169 : 1576 : clear_posting_sources();
170 : 1576 : clear_match_spies();
171 : 1576 : }
172 : :
173 : : void
174 : 1576 : Registry::Internal::add_defaults()
175 : : {
176 : : Xapian::Weight * weight;
177 : 1576 : weight = new Xapian::BM25Weight;
178 : 1576 : wtschemes[weight->name()] = weight;
179 : 1576 : weight = new Xapian::BoolWeight;
180 : 1576 : wtschemes[weight->name()] = weight;
181 : 1576 : weight = new Xapian::TradWeight;
182 : 1576 : wtschemes[weight->name()] = weight;
183 : :
184 : : Xapian::PostingSource * source;
185 : 1576 : source = new Xapian::ValueWeightPostingSource(0);
186 : 1576 : postingsources[source->name()] = source;
187 : 1576 : source = new Xapian::DecreasingValueWeightPostingSource(0);
188 : 1576 : postingsources[source->name()] = source;
189 : 1576 : source = new Xapian::ValueMapPostingSource(0);
190 : 1576 : postingsources[source->name()] = source;
191 : 1576 : source = new Xapian::FixedWeightPostingSource(0.0);
192 : 1576 : postingsources[source->name()] = source;
193 : :
194 : : Xapian::MatchSpy * spy;
195 : 1576 : spy = new Xapian::ValueCountMatchSpy();
196 : 1576 : matchspies[spy->name()] = spy;
197 : 1576 : }
198 : :
199 : : void
200 : 1576 : Registry::Internal::clear_weighting_schemes()
201 : : {
202 : 1576 : map<string, Xapian::Weight*>::const_iterator i;
203 [ + + ]: 6306 : for (i = wtschemes.begin(); i != wtschemes.end(); ++i) {
204 [ + + ]: 4730 : delete i->second;
205 : : }
206 : 1576 : }
207 : :
208 : : void
209 : 1576 : Registry::Internal::clear_posting_sources()
210 : : {
211 : 1576 : map<string, Xapian::PostingSource *>::const_iterator i;
212 [ + + ]: 7884 : for (i = postingsources.begin(); i != postingsources.end(); ++i) {
213 [ + + ]: 6308 : delete i->second;
214 : : }
215 : 1576 : }
216 : :
217 : : void
218 : 1576 : Registry::Internal::clear_match_spies()
219 : : {
220 : 1576 : map<string, Xapian::MatchSpy *>::const_iterator i;
221 [ + + ]: 3154 : for (i = matchspies.begin(); i != matchspies.end(); ++i) {
222 [ + + ]: 1578 : delete i->second;
223 : : }
224 : 1576 : }
225 : :
226 : : }
|