Update for 1.2.25.1
[xapian.git] / search-xapian / Xapian.xs
blobc6effe5049fe4fc88047b42b2d6a74469da4b7fa
1 // Disable any deprecation warnings for Xapian methods/functions/classes.
2 #define XAPIAN_DEPRECATED(D) D
3 #include <xapian.h>
4 #include <string>
5 #include <vector>
7 // Stop Perl headers from even thinking of doing '#define bool char' or
8 // '#define bool int', which they would do with compilers other than GCC.
9 #define HAS_BOOL
11 extern "C" {
12 #include "EXTERN.h"
13 #include "perl.h"
14 #include "XSUB.h"
17 /* Perl's embed.h defines get_context, but that mangles
18  * Xapian::Error::get_context(). */
19 #ifdef get_context
20 # undef get_context
21 #endif
23 using namespace std;
24 using namespace Xapian;
26 // For some classes, we want extra slots to keep references to set objects in.
28 struct Enquire_perl {
29     Enquire real_obj;
30     SV * sorter;
31     vector<SV *> matchspies;
33     Enquire_perl(const Xapian::Database & db) : real_obj(db), sorter(NULL) { }
35     void ref_sorter(SV * sv) {
36         SvREFCNT_inc(sv);
37         swap(sv, sorter);
38         SvREFCNT_dec(sv);
39     }
41     void ref_matchspy(SV* sv) {
42         SvREFCNT_inc(sv);
43         matchspies.push_back(sv);
44     }
46     void ref_clear_matchspies(SV* sv) {
47         vector<SV *>::const_iterator i;
48         for (i = matchspies.begin(); i != matchspies.end(); ++i) {
49             SvREFCNT_dec(*i);
50         }
51         matchspies.clear();
52     }
54     ~Enquire_perl() {
55         SvREFCNT_dec(sorter);
56         sorter = NULL;
57         ref_clear_matchspies(NULL);
58     }
61 struct QueryParser_perl {
62     QueryParser real_obj;
63     SV * stopper;
64     vector<SV *> vrps;
66     QueryParser_perl() : real_obj(), stopper(NULL) { }
68     void ref_stopper(SV * sv) {
69         SvREFCNT_inc(sv);
70         swap(sv, stopper);
71         SvREFCNT_dec(sv);
72     }
74     void ref_vrp(SV * sv) {
75         SvREFCNT_inc(sv);
76         vrps.push_back(sv);
77     }
79     ~QueryParser_perl() {
80         SvREFCNT_dec(stopper);
81         stopper = NULL;
82         vector<SV *>::const_iterator i;
83         for (i = vrps.begin(); i != vrps.end(); ++i) {
84             SvREFCNT_dec(*i);
85         }
86         vrps.clear();
87     }
90 struct TermGenerator_perl {
91     TermGenerator real_obj;
92     SV * stopper;
94     TermGenerator_perl() : real_obj(), stopper(NULL) { }
96     void ref_stopper(SV * sv) {
97         SvREFCNT_inc(sv);
98         swap(sv, stopper);
99         SvREFCNT_dec(sv);
100     }
102     ~TermGenerator_perl() {
103         SvREFCNT_dec(stopper);
104         stopper = NULL;
105     }
108 #define XAPIAN_PERL_NEW(CLASS, PARAMS) (&((new CLASS##_perl PARAMS)->real_obj))
109 #define XAPIAN_PERL_CAST(CLASS, OBJ) ((CLASS##_perl*)(void*)(OBJ))
110 #define XAPIAN_PERL_REF(CLASS, OBJ, MEMB, SV) XAPIAN_PERL_CAST(CLASS, OBJ)->ref_##MEMB(SV)
111 #define XAPIAN_PERL_DESTROY(CLASS, OBJ) delete XAPIAN_PERL_CAST(CLASS, OBJ)
113 extern void handle_exception(void);
115 /* PerlStopper class
117  * Make operator() call Perl $OBJECT->stop_word
118  */
120 class PerlStopper : public Stopper {
121     public:
122         PerlStopper(SV * obj) { SV_stopper_ref = newRV_inc(obj); }
123         ~PerlStopper() { sv_2mortal(SV_stopper_ref); }
124         bool operator()(const string &term) const {
125             dSP ;
127             ENTER ;
128             SAVETMPS ;
130             PUSHMARK(SP);
131             PUSHs(SvRV(SV_stopper_ref));
132             PUSHs(sv_2mortal(newSVpv(term.data(), term.size())));
133             PUTBACK ;
135             int count = call_method("stop_word", G_SCALAR);
137             SPAGAIN ;
139             if (count != 1)
140                 croak("callback function should return 1 value, got %d", count);
142             // Breaks with SvTRUE(POPs) ?!?!?!
143             bool r = SvTRUE(SP[0]);
144             POPs ;
146             PUTBACK ;
147             FREETMPS ;
148             LEAVE ;
150             return r;
151         }
153     private:
154         SV * SV_stopper_ref;
157 class perlMatchDecider : public Xapian::MatchDecider {
158     SV *callback;
160   public:
161     perlMatchDecider(SV *func) {
162         callback = newSVsv(func);
163     }
165     ~perlMatchDecider() {
166         SvREFCNT_dec(callback);
167     }
169     bool operator()(const Xapian::Document &doc) const {
170         dSP;
172         ENTER;
173         SAVETMPS;
175         PUSHMARK(SP);
177         SV *arg = sv_newmortal();
179         Document *pdoc = new Document(doc);
180         sv_setref_pv(arg, "Search::Xapian::Document", (void *)pdoc);
181         XPUSHs(arg);
183         PUTBACK;
185         int count = call_sv(callback, G_SCALAR);
187         SPAGAIN;
188         if (count != 1)
189             croak("callback function should return 1 value, got %d", count);
191         int decide_actual_result = POPi;
193         PUTBACK;
195         FREETMPS;
196         LEAVE;
198         return decide_actual_result;
199     }
202 class perlExpandDecider : public Xapian::ExpandDecider {
203     SV *callback;
205   public:
206     perlExpandDecider(SV *func) {
207         callback = newSVsv(func);
208     }
210     ~perlExpandDecider() {
211         SvREFCNT_dec(callback);
212     }
214     bool operator()(const string &term) const {
215         dSP;
217         ENTER;
218         SAVETMPS;
220         PUSHMARK(SP);
222         XPUSHs(sv_2mortal(newSVpv(term.data(), term.size())));
224         PUTBACK;
226         int count = call_sv(callback, G_SCALAR);
228         SPAGAIN;
229         if (count != 1)
230             croak("callback function should return 1 value, got %d", count);
232         int decide_actual_result = POPi;
234         PUTBACK;
236         FREETMPS;
237         LEAVE;
239         return decide_actual_result;
240     }
244 MODULE = Search::Xapian         PACKAGE = Search::Xapian
246 PROTOTYPES: ENABLE
248 string
249 sortable_serialise(double value)
251 double
252 sortable_unserialise(string value)
254 const char *
255 version_string()
258 major_version()
261 minor_version()
264 revision()
266 INCLUDE: XS/BM25Weight.xs
267 INCLUDE: XS/BoolWeight.xs
268 INCLUDE: XS/Database.xs
269 INCLUDE: XS/Document.xs
270 INCLUDE: XS/Enquire.xs
271 INCLUDE: XS/MSet.xs
272 INCLUDE: XS/MSetIterator.xs
273 INCLUDE: XS/ESet.xs
274 INCLUDE: XS/Error.xs
275 INCLUDE: XS/ESetIterator.xs
276 INCLUDE: XS/RSet.xs
277 INCLUDE: XS/MultiValueSorter.xs
278 INCLUDE: XS/Query.xs
279 INCLUDE: XS/QueryParser.xs
280 INCLUDE: XS/SimpleStopper.xs
281 INCLUDE: XS/Stem.xs
282 INCLUDE: XS/Stopper.xs
283 INCLUDE: XS/TermGenerator.xs
284 INCLUDE: XS/TermIterator.xs
285 INCLUDE: XS/TradWeight.xs
286 INCLUDE: XS/PostingIterator.xs
287 INCLUDE: XS/PositionIterator.xs
288 INCLUDE: XS/ValueIterator.xs
289 INCLUDE: XS/WritableDatabase.xs
290 INCLUDE: XS/Weight.xs
292 INCLUDE: XS/DateValueRangeProcessor.xs
293 INCLUDE: XS/NumberValueRangeProcessor.xs
294 INCLUDE: XS/StringValueRangeProcessor.xs
296 INCLUDE: XS/MatchSpy.xs
297 INCLUDE: XS/ValueCountMatchSpy.xs
299 BOOT:
300     {
301         HV *mHvStash = gv_stashpv( "Search::Xapian", TRUE );
302 // Perl >= probably 5.10 doesn't need the const_cast<> here.
303 #define ENUM_CONST(P, C) newCONSTSUB( mHvStash, const_cast<char*>(#P), newSViv(C) )
305         ENUM_CONST(OP_AND, Query::OP_AND);
306         ENUM_CONST(OP_OR, Query::OP_OR);
307         ENUM_CONST(OP_AND_NOT, Query::OP_AND_NOT);
308         ENUM_CONST(OP_XOR, Query::OP_XOR);
309         ENUM_CONST(OP_AND_MAYBE, Query::OP_AND_MAYBE);
310         ENUM_CONST(OP_FILTER, Query::OP_FILTER);
311         ENUM_CONST(OP_NEAR, Query::OP_NEAR);
312         ENUM_CONST(OP_PHRASE, Query::OP_PHRASE);
313         ENUM_CONST(OP_VALUE_RANGE, Query::OP_VALUE_RANGE);
314         ENUM_CONST(OP_SCALE_WEIGHT, Query::OP_SCALE_WEIGHT);
315         ENUM_CONST(OP_ELITE_SET, Query::OP_ELITE_SET);
316         ENUM_CONST(OP_VALUE_GE, Query::OP_VALUE_GE);
317         ENUM_CONST(OP_VALUE_LE, Query::OP_VALUE_LE);
319         ENUM_CONST(DB_OPEN, DB_OPEN);
320         ENUM_CONST(DB_CREATE, DB_CREATE);
321         ENUM_CONST(DB_CREATE_OR_OPEN, DB_CREATE_OR_OPEN);
322         ENUM_CONST(DB_CREATE_OR_OVERWRITE, DB_CREATE_OR_OVERWRITE);
324         ENUM_CONST(ENQ_DESCENDING, Enquire::DESCENDING);
325         ENUM_CONST(ENQ_ASCENDING, Enquire::ASCENDING);
326         ENUM_CONST(ENQ_DONT_CARE, Enquire::DONT_CARE);
328         ENUM_CONST(FLAG_BOOLEAN, QueryParser::FLAG_BOOLEAN);
329         ENUM_CONST(FLAG_PHRASE, QueryParser::FLAG_PHRASE);
330         ENUM_CONST(FLAG_LOVEHATE, QueryParser::FLAG_LOVEHATE);
331         ENUM_CONST(FLAG_BOOLEAN_ANY_CASE, QueryParser::FLAG_BOOLEAN_ANY_CASE);
332         ENUM_CONST(FLAG_WILDCARD, QueryParser::FLAG_WILDCARD);
333         ENUM_CONST(FLAG_PURE_NOT, QueryParser::FLAG_PURE_NOT);
334         ENUM_CONST(FLAG_PARTIAL, QueryParser::FLAG_PARTIAL);
335         ENUM_CONST(FLAG_SPELLING_CORRECTION, QueryParser::FLAG_SPELLING_CORRECTION);
336         ENUM_CONST(FLAG_SYNONYM, QueryParser::FLAG_SYNONYM);
337         ENUM_CONST(FLAG_AUTO_SYNONYMS, QueryParser::FLAG_AUTO_SYNONYMS);
338         ENUM_CONST(FLAG_AUTO_MULTIWORD_SYNONYMS, QueryParser::FLAG_AUTO_SYNONYMS);
339         ENUM_CONST(FLAG_DEFAULT, QueryParser::FLAG_DEFAULT);
341         ENUM_CONST(STEM_NONE, QueryParser::STEM_NONE);
342         ENUM_CONST(STEM_SOME, QueryParser::STEM_SOME);
343         ENUM_CONST(STEM_ALL, QueryParser::STEM_ALL);
345         ENUM_CONST(FLAG_SPELLING, TermGenerator::FLAG_SPELLING);
347         ENUM_CONST(BAD_VALUENO, BAD_VALUENO);
348     }