3 /* perl.i
: SWIG interface file for the Perl bindings
5 * Copyright
(C
) 2009 Kosei Moriyama
6 * Copyright
(C
) 2011,2012,2013,2015,2016,2019,2020 Olly Betts
8 * This program is free software
; you can redistribute it and
/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation
; either version
2 of the
11 * License
, or
(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
26 // Older Perl headers contain things which cause warnings with more recent
27 // C
++ compilers. There's nothing we can really do about them
, so just
30 # pragma clang diagnostic push
31 # pragma clang diagnostic ignored
"-Wreserved-user-defined-literal"
32 #elif defined __GNUC__
33 // Warning added in GCC
4.8 and we don't support anything older.
34 # pragma GCC diagnostic push
35 # pragma GCC diagnostic ignored
"-Wliteral-suffix"
45 # pragma clang diagnostic pop
46 #elif defined __GNUC__
47 # pragma GCC diagnostic pop
51 /* The XS Xapian never wrapped these
, and they're now deprecated.
*/
52 #define XAPIAN_BINDINGS_SKIP_DEPRECATED_DB_FACTORIES
54 %include ..
/xapian-head.i
56 /* "next" is a keyword in Perl.
*/
57 %rename
(increment_weight
) *::next
(double min_wt
);
59 /* Wrapping constant values.
*/
60 %constant int OP_AND
= Xapian
::Query
::OP_AND
;
61 %constant int OP_OR
= Xapian
::Query
::OP_OR
;
62 %constant int OP_AND_NOT
= Xapian
::Query
::OP_AND_NOT
;
63 %constant int OP_XOR
= Xapian
::Query
::OP_XOR
;
64 %constant int OP_AND_MAYBE
= Xapian
::Query
::OP_AND_MAYBE
;
65 %constant int OP_FILTER
= Xapian
::Query
::OP_FILTER
;
66 %constant int OP_NEAR
= Xapian
::Query
::OP_NEAR
;
67 %constant int OP_PHRASE
= Xapian
::Query
::OP_PHRASE
;
68 %constant int OP_VALUE_RANGE
= Xapian
::Query
::OP_VALUE_RANGE
;
69 %constant int OP_SCALE_WEIGHT
= Xapian
::Query
::OP_SCALE_WEIGHT
;
70 %constant int OP_ELITE_SET
= Xapian
::Query
::OP_ELITE_SET
;
71 %constant int OP_VALUE_GE
= Xapian
::Query
::OP_VALUE_GE
;
72 %constant int OP_SYNONYM
= Xapian
::Query
::OP_SYNONYM
;
73 %constant int OP_MAX
= Xapian
::Query
::OP_MAX
;
74 %constant int OP_WILDCARD
= Xapian
::Query
::OP_WILDCARD
;
75 %constant int OP_VALUE_LE
= Xapian
::Query
::OP_VALUE_LE
;
76 %constant int OP_INVALID
= Xapian
::Query
::OP_INVALID
;
77 %constant int ENQ_ASCENDING
= Xapian
::Enquire
::ASCENDING;
78 %constant int ENQ_DESCENDING
= Xapian
::Enquire
::DESCENDING;
79 %constant int ENQ_DONT_CARE
= Xapian
::Enquire
::DONT_CARE
;
80 %constant int FLAG_ACCUMULATE
= Xapian
::QueryParser
::FLAG_ACCUMULATE
;
81 %constant int FLAG_BOOLEAN
= Xapian
::QueryParser
::FLAG_BOOLEAN
;
82 %constant int FLAG_NO_POSITIONS
= Xapian
::QueryParser
::FLAG_NO_POSITIONS
;
83 %constant int FLAG_PHRASE
= Xapian
::QueryParser
::FLAG_PHRASE
;
84 %constant int FLAG_LOVEHATE
= Xapian
::QueryParser
::FLAG_LOVEHATE
;
85 %constant int FLAG_BOOLEAN_ANY_CASE
= Xapian
::QueryParser
::FLAG_BOOLEAN_ANY_CASE
;
86 %constant int FLAG_WILDCARD
= Xapian
::QueryParser
::FLAG_WILDCARD
;
87 %constant int FLAG_PURE_NOT
= Xapian
::QueryParser
::FLAG_PURE_NOT
;
88 %constant int FLAG_PARTIAL
= Xapian
::QueryParser
::FLAG_PARTIAL
;
89 %constant int FLAG_SPELLING_CORRECTION
= Xapian
::QueryParser
::FLAG_SPELLING_CORRECTION
;
90 %constant int FLAG_SYNONYM
= Xapian
::QueryParser
::FLAG_SYNONYM
;
91 %constant int FLAG_AUTO_SYNONYMS
= Xapian
::QueryParser
::FLAG_AUTO_SYNONYMS
;
92 %constant int FLAG_AUTO_MULTIWORD_SYNONYMS
= Xapian
::QueryParser
::FLAG_AUTO_MULTIWORD_SYNONYMS
;
93 %constant int FLAG_CJK_NGRAM
= Xapian
::QueryParser
::FLAG_CJK_NGRAM
;
94 %constant int FLAG_DEFAULT
= Xapian
::QueryParser
::FLAG_DEFAULT
;
95 %constant int STEM_NONE
= Xapian
::QueryParser
::STEM_NONE
;
96 %constant int STEM_SOME
= Xapian
::QueryParser
::STEM_SOME
;
97 %constant int STEM_SOME_FULL_POS
= Xapian
::QueryParser
::STEM_SOME_FULL_POS
;
98 %constant int STEM_ALL
= Xapian
::QueryParser
::STEM_ALL
;
99 %constant int STEM_ALL_Z
= Xapian
::QueryParser
::STEM_ALL_Z
;
100 %constant int FLAG_SPELLING
= Xapian
::TermGenerator
::FLAG_SPELLING
;
101 // FLAG_CJK_NGRAM already set above from QueryParser
(values match
).
102 %constant int WILDCARD_LIMIT_ERROR
= Xapian
::Query
::WILDCARD_LIMIT_ERROR
;
103 %constant int WILDCARD_LIMIT_FIRST
= Xapian
::Query
::WILDCARD_LIMIT_FIRST
;
104 %constant int WILDCARD_LIMIT_MOST_FREQUENT
= Xapian
::Query
::WILDCARD_LIMIT_MOST_FREQUENT
;
106 /* Xapian
::Enquire
*/
107 %feature
("shadow") Xapian
::Enquire
::get_mset
111 my $nargs
= scalar
(@_
);
113 my $type
= ref
( $_
[2] );
114 if
( $type eq 'Xapian
::RSet'
) {
115 # get_mset
(first
, max
, rset
)
116 splice @_
, 2, 0, (0); # insert checkatleast
119 return Xapianc
::Enquire_get_mset
( @_
);
123 %feature
("shadow") Xapian
::Enquire
::set_query
126 if
(ref
($_
[1]) ne 'Xapian
::Query'
) {
127 push @_
, Xapian
::Query-
>new
(splice @_
, 1);
129 Xapianc
::Enquire_set_query
(@_
);
133 %feature
("shadow") Xapian
::Enquire
::set_sort_by_key
135 sub set_sort_by_key
{
138 $self
{_sorter
} = $sorter
;
139 Xapianc
::Enquire_set_sort_by_key
( @_
);
143 %feature
("shadow") Xapian
::Enquire
::set_sort_by_key_then_relevance
145 sub set_sort_by_key_then_relevance
{
148 $self
{_sorter
} = $sorter
;
149 Xapianc
::Enquire_set_sort_by_key_then_relevance
( @_
);
153 %feature
("shadow") Xapian
::Enquire
::set_sort_by_relevance_then_key
155 sub set_sort_by_relevance_then_key
{
158 $self
{_sorter
} = $sorter
;
159 Xapianc
::Enquire_set_sort_by_relevance_then_key
( @_
);
163 /* Xapian
::Enquire
*/
164 %extend Xapian
::Enquire
{
165 // For compatibility with Search
::Xapian.
166 Xapian
::MSet get_mset
(Xapian
::doccount first
,
167 Xapian
::doccount maxitems
,
168 const Xapian
::MatchDecider
* mdecider
) {
169 return $self-
>get_mset
(first
, maxitems
, 0, NULL, mdecider
);
174 %extend Xapian
::ESet
{
175 Xapian
::ESetIterator
FETCH(int index
) {
176 return
((*self
)[index
]);
180 /* Xapian
::ESetIterator
*/
181 %extend Xapian
::ESetIterator
{
182 std
::string get_termname
() {
183 return self-
>operator
*();
188 %extend Xapian
::MSet
{
189 Xapian
::MSetIterator
FETCH(int index
) {
190 return
((*self
)[index
]);
195 %feature
("shadow") Xapian
::Query
::Query
202 $query
= Xapianc
::new_Query
(@_
);
206 if
( $op
!~
/^\d
+$
/ ) {
207 Carp
::croak
( "USAGE: $class->new('term') or $class->new(OP, <args>)" );
209 if
( $op
== 8 ) { # FIXME
: 8 is OP_VALUE_RANGE
; eliminate hardcoded literal
211 Carp
::croak
( "USAGE: $class->new(OP_VALUE_RANGE, VALNO, START, END)" );
213 $query
= Xapianc
::new_Query
( @_
);
214 } elsif
( $op
== 9 ) { # FIXME
: OP_SCALE_WEIGHT
216 Carp
::croak
( "USAGE: $class->new(OP_SCALE_WEIGHT, QUERY, FACTOR)" );
218 $query
= Xapianc
::new_Query
( @_
);
219 } elsif
( $op
== 11 || $op
== 12 ) { # FIXME
: OP_VALUE_GE
, OP_VALUE_LE
; eliminate hardcoded literals
221 Carp
::croak
( "USAGE: $class->new(OP_VALUE_[GL]E, VALNO, LIMIT)" );
223 $query
= Xapianc
::new_Query
( @_
);
226 $query
= Xapian
::newN
( $op
, \@_
);
239 croak
("Argument $argnum is not a reference.");
240 if
(SvTYPE
(SvRV
($input
)) != SVt_PVAV
)
241 croak
("Argument $argnum is not an array.");
242 tempav
= (AV
*)SvRV
($input
);
243 len
= av_len
(tempav
);
244 $
1 = (SV
**) malloc
((len
+2)*sizeof
(SV
*));
245 for
(i
= 0; i
<= len
; i
++) {
246 tv
= av_fetch
(tempav
, i
, 0);
252 %typemap
(freearg
) SV
** {
257 class XapianSWIGQueryItor
{
263 XapianSWIGQueryItor
() { }
265 void begin
(AV
* array_
) {
274 XapianSWIGQueryItor
& operator++() {
279 Xapian
::Query operator
*() const
{
280 SV
**svp
= av_fetch
(array
, i
, 0);
282 croak
("Unexpected NULL returned by av_fetch()");
286 croak
("USAGE: Xapian::Query->new(OP, @TERMS_OR_QUERY_OBJECTS)");
290 if
(SWIG_ConvertPtr
(sv
, (void
**)&q,
291 SWIGTYPE_p_Xapian__Query
, 0) == SWIG_OK
) {
296 const char
* ptr
= SvPV
(sv
, len
);
297 return Xapian
::Query
(string
(ptr
, len
));
300 bool operator
==(const XapianSWIGQueryItor
& o) {
304 bool operator
!=(const XapianSWIGQueryItor
& o) {
305 return
!(*this
== o
);
308 typedef std
::input_iterator_tag iterator_category
;
309 typedef Xapian
::Query value_type
;
310 typedef Xapian
::termcount_diff difference_type
;
311 typedef Xapian
::Query
* pointer
;
312 typedef Xapian
::Query
& reference;
318 Xapian
::Query
* newN
(int op_
, SV
*q_
) {
319 Xapian
::Query
::op op
= (Xapian
::Query
::op
)op_
;
320 XapianSWIGQueryItor b
, e
;
322 AV
*q
= (AV
*) SvRV
(q_
);
325 e.end
(av_len
(q
) + 1);
328 return new Xapian
::Query
(op
, b
, e
);
329 } catch
(const Xapian
::Error
&error) {
330 croak
( "Exception: %s", error.get_msg
().c_str
() );
335 /* Xapian
::QueryParser
*/
336 %feature
("shadow") Xapian
::QueryParser
::QueryParser
340 my $qp
= Xapianc
::new_QueryParser
();
343 $qp-
>set_database
(@_
) if scalar
(@_
) == 1;
349 %feature
("shadow") Xapian
::QueryParser
::set_stopper
352 my
($self
, $stopper
) = @_
;
353 $self
{_stopper
} = $stopper
;
354 Xapianc
::QueryParser_set_stopper
( @_
);
358 %feature
("shadow") Xapian
::QueryParser
::add_rangeprocessor
360 sub add_rangeprocessor
{
361 my
($self
, $rproc
) = @_
;
362 push @
{$self
{_rproc
}}, $rproc
;
363 Xapianc
::QueryParser_add_rangeprocessor
( @_
);
367 %feature
("shadow") Xapian
::QueryParser
::add_valuerangeprocessor
369 sub add_valuerangeprocessor
{
370 my
($self
, $vrproc
) = @_
;
371 push @
{$self
{_vrproc
}}, $vrproc
;
372 Xapianc
::QueryParser_add_valuerangeprocessor
( @_
);
376 /* Xapian
::SimpleStopper
*/
377 %feature
("shadow") Xapian
::SimpleStopper
::SimpleStopper
381 my $stopper
= Xapianc
::new_SimpleStopper
();
383 bless $stopper
, $class
;
392 %extend Xapian
::SimpleStopper
{
393 bool stop_word
(std
::string term
) {
394 return
(*self
)(term
);
399 %extend Xapian
::Stem
{
400 std
::string stem_word
(std
::string word
) {
401 return
(*self
)(word
);
405 /* Xapian
::TermIterator
*/
406 %rename
(get_termname
) Xapian
::TermIterator
::get_term
;
408 /* Xapian
::WritableDatabase
*/
409 %rename
(replace_document_by_term
) \
410 Xapian
::WritableDatabase
::replace_document
(const std
::string
&,
411 const Xapian
::Document
&);
412 %rename
(delete_document_by_term
) \
413 Xapian
::WritableDatabase
::delete_document
(const std
::string
&);
415 %feature
("shadow") Xapian
::WritableDatabase
::WritableDatabase
420 if
( scalar
(@_
) == 0 ) {
421 # For compatibility with Search
::Xapian
422 @_
= (''
, $Xapianc
::DB_BACKEND_INMEMORY
);
424 $self
= Xapianc
::new_WritableDatabase
(@_
);
425 bless $self
, $pkg if defined
($self
);
429 %define SUB_CLASS
(NS
, CLASS
)
431 class perl##CLASS
: public NS
::CLASS
{
435 perl##CLASS
(SV
* func
) {
436 callback
= newSVsv
(func
);
440 SvREFCNT_dec
(callback
);
443 bool operator
()(const std
::string
&term) const {
451 SV
* arg
= sv_newmortal
();
452 sv_setpvn
(arg
, term.data
(), term.size
());
456 int count
= call_sv
(callback
, G_SCALAR
);
460 croak
("callback function should return 1 value, got %d", count
);
476 SUB_CLASS
(Xapian
, ExpandDecider
)
477 SUB_CLASS
(Xapian
, Stopper
)
480 class perlMatchDecider
: public Xapian
::MatchDecider
{
484 perlMatchDecider
(SV
* func
) {
485 callback
= newSVsv
(func
);
488 ~perlMatchDecider
() {
489 SvREFCNT_dec
(callback
);
492 bool operator
()(const Xapian
::Document
&doc) const {
500 XPUSHs
(SWIG_NewPointerObj
(const_cast
<Xapian
::Document
*>(&doc),
501 SWIGTYPE_p_Xapian__Document
, 0));
504 int count
= call_sv
(callback
, G_SCALAR
);
508 croak
("callback function should return 1 value, got %d", count
);
523 class perlStemImplementation
: public Xapian
::StemImplementation
{
527 perlStemImplementation
(SV
* func
) {
528 callback
= newSVsv
(func
);
531 ~perlStemImplementation
() {
532 SvREFCNT_dec
(callback
);
535 std
::string operator
()(const std
::string
& word) {
543 SV
* arg
= sv_newmortal
();
544 sv_setpvn
(arg
, word.data
(), word.size
());
548 int count
= call_sv
(callback
, G_SCALAR
);
552 croak
("callback function should return 1 value, got %d", count
);
556 const char
* ptr
= SvPV
(sv
, len
);
557 std
::string result
(ptr
, len
);
567 std
::string get_description
() const
{
568 return
"perlStemImplementation()";
574 class perlKeyMaker
: public Xapian
::KeyMaker
{
578 perlKeyMaker
(SV
* func
) {
579 callback
= newSVsv
(func
);
583 SvREFCNT_dec
(callback
);
586 std
::string operator
()(const Xapian
::Document
&doc) const {
594 XPUSHs
(SWIG_NewPointerObj
(const_cast
<Xapian
::Document
*>(&doc),
595 SWIGTYPE_p_Xapian__Document
, 0));
598 int count
= call_sv
(callback
, G_SCALAR
);
602 croak
("callback function should return 1 value, got %d", count
);
606 const char
* ptr
= SvPV
(sv
, len
);
607 std
::string result
(ptr
, len
);
620 class perlRangeProcessor
: public Xapian
::RangeProcessor
{
624 perlRangeProcessor
(SV
* func
) {
625 callback
= newSVsv
(func
);
628 ~perlRangeProcessor
() {
629 SvREFCNT_dec
(callback
);
632 Xapian
::Query operator
()(const std
::string
& begin, const std::string& end) {
640 SV
* arg
= sv_newmortal
();
641 sv_setpvn
(arg
, begin.data
(), begin.size
());
643 arg
= sv_newmortal
();
644 sv_setpvn
(arg
, end.data
(), end.size
());
648 int count
= call_sv
(callback
, G_SCALAR
);
652 croak
("callback function should return 1 value, got %d", count
);
654 // Allow the function to return a string or Query object.
657 croak
("function must return a string or Query object");
659 Xapian
::Query result
;
661 if
(SWIG_ConvertPtr
(sv
, (void
**)&q,
662 SWIGTYPE_p_Xapian__Query
, 0) == SWIG_OK
) {
666 const char
* ptr
= SvPV
(sv
, len
);
667 result
= Xapian
::Query
(string
(ptr
, len
));
681 class perlFieldProcessor
: public Xapian
::FieldProcessor
{
685 perlFieldProcessor
(SV
* func
) {
686 callback
= newSVsv
(func
);
689 ~perlFieldProcessor
() {
690 SvREFCNT_dec
(callback
);
693 Xapian
::Query operator
()(const std
::string
&str) {
701 SV
* arg
= sv_newmortal
();
702 sv_setpvn
(arg
, str.data
(), str.size
());
706 int count
= call_sv
(callback
, G_SCALAR
);
710 croak
("callback function should return 1 value, got %d", count
);
712 // Allow the function to return a string or Query object.
715 croak
("function must return a string or Query object");
717 Xapian
::Query result
;
719 if
(SWIG_ConvertPtr
(sv
, (void
**)&q,
720 SWIGTYPE_p_Xapian__Query
, 0) == SWIG_OK
) {
724 const char
* ptr
= SvPV
(sv
, len
);
725 result
= Xapian
::Query
(string
(ptr
, len
));
739 class perlMatchSpy
: public Xapian
::MatchSpy
{
743 perlMatchSpy
(SV
* func
) {
744 callback
= newSVsv
(func
);
748 SvREFCNT_dec
(callback
);
751 void operator
()(const Xapian
::Document
&doc, double wt) {
759 PUSHs
(SWIG_NewPointerObj
(const_cast
<Xapian
::Document
*>(&doc),
760 SWIGTYPE_p_Xapian__Document
, 0));
764 (void
)call_sv
(callback
, G_VOID
);
775 %define SUB_CLASS_TYPEMAPS
(NS
, CLASS
)
777 %typemap
(typecheck
, precedence
=100) NS
::CLASS
* {
780 if
(SWIG_ConvertPtr
(sv
, &ptr, $descriptor(NS::CLASS *), 0) == SWIG_OK) {
784 /* The docs in perlapi for call_sv say
:
786 * [T
]he SV may be any of a CV
, a GV
, a reference to a CV
, a
787 * reference to a GV or
"SvPV(sv)" will be used as the name of the
790 * To make overloading work helpfully
, we don't allow passing the name
791 * of a sub. Search
::Xapian did in some cases
, but it seems unlikely
792 * anyone relied on this.
794 svtype t
= SvTYPE
(sv
);
796 t
= SvTYPE
(SvRV
(sv
));
798 $
1 = (t
== SVt_PVCV || t
== SVt_PVGV
);
801 %typemap
(in
) NS
::CLASS
* {
803 if
(SWIG_ConvertPtr
(sv
, (void
**)&$1,
804 $descriptor
(NS
::CLASS
*), 0) != SWIG_OK
) {
805 $
1 = new perl##CLASS
(sv
);
810 SUB_CLASS_TYPEMAPS
(Xapian
, MatchDecider
)
811 SUB_CLASS_TYPEMAPS
(Xapian
, ExpandDecider
)
812 SUB_CLASS_TYPEMAPS
(Xapian
, Stopper
)
813 SUB_CLASS_TYPEMAPS
(Xapian
, StemImplementation
)
814 SUB_CLASS_TYPEMAPS
(Xapian
, KeyMaker
)
815 SUB_CLASS_TYPEMAPS
(Xapian
, RangeProcessor
)
816 SUB_CLASS_TYPEMAPS
(Xapian
, FieldProcessor
)
817 SUB_CLASS_TYPEMAPS
(Xapian
, MatchSpy
)
820 %include ..
/xapian-headers.i