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,2024 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 %include ..
/xapian-head.i
53 /* "next" is a keyword in Perl.
*/
54 %rename
(increment_weight
) *::next
(double min_wt
);
56 /* Wrapping constant values.
*/
57 %constant int OP_AND
= Xapian
::Query
::OP_AND
;
58 %constant int OP_OR
= Xapian
::Query
::OP_OR
;
59 %constant int OP_AND_NOT
= Xapian
::Query
::OP_AND_NOT
;
60 %constant int OP_XOR
= Xapian
::Query
::OP_XOR
;
61 %constant int OP_AND_MAYBE
= Xapian
::Query
::OP_AND_MAYBE
;
62 %constant int OP_FILTER
= Xapian
::Query
::OP_FILTER
;
63 %constant int OP_NEAR
= Xapian
::Query
::OP_NEAR
;
64 %constant int OP_PHRASE
= Xapian
::Query
::OP_PHRASE
;
65 %constant int OP_VALUE_RANGE
= Xapian
::Query
::OP_VALUE_RANGE
;
66 %constant int OP_SCALE_WEIGHT
= Xapian
::Query
::OP_SCALE_WEIGHT
;
67 %constant int OP_ELITE_SET
= Xapian
::Query
::OP_ELITE_SET
;
68 %constant int OP_VALUE_GE
= Xapian
::Query
::OP_VALUE_GE
;
69 %constant int OP_SYNONYM
= Xapian
::Query
::OP_SYNONYM
;
70 %constant int OP_MAX
= Xapian
::Query
::OP_MAX
;
71 %constant int OP_WILDCARD
= Xapian
::Query
::OP_WILDCARD
;
72 %constant int OP_VALUE_LE
= Xapian
::Query
::OP_VALUE_LE
;
73 %constant int OP_INVALID
= Xapian
::Query
::OP_INVALID
;
74 %constant int ENQ_ASCENDING
= Xapian
::Enquire
::ASCENDING;
75 %constant int ENQ_DESCENDING
= Xapian
::Enquire
::DESCENDING;
76 %constant int ENQ_DONT_CARE
= Xapian
::Enquire
::DONT_CARE
;
77 %constant int FLAG_ACCUMULATE
= Xapian
::QueryParser
::FLAG_ACCUMULATE
;
78 %constant int FLAG_BOOLEAN
= Xapian
::QueryParser
::FLAG_BOOLEAN
;
79 %constant int FLAG_FUZZY
= Xapian
::QueryParser
::FLAG_FUZZY
;
80 %constant int FLAG_NO_POSITIONS
= Xapian
::QueryParser
::FLAG_NO_POSITIONS
;
81 %constant int FLAG_PHRASE
= Xapian
::QueryParser
::FLAG_PHRASE
;
82 %constant int FLAG_LOVEHATE
= Xapian
::QueryParser
::FLAG_LOVEHATE
;
83 %constant int FLAG_BOOLEAN_ANY_CASE
= Xapian
::QueryParser
::FLAG_BOOLEAN_ANY_CASE
;
84 %constant int FLAG_WILDCARD
= Xapian
::QueryParser
::FLAG_WILDCARD
;
85 %constant int FLAG_WILDCARD_GLOB
= Xapian
::QueryParser
::FLAG_WILDCARD_GLOB
;
86 %constant int FLAG_WILDCARD_MULTI
= Xapian
::QueryParser
::FLAG_WILDCARD_MULTI
;
87 %constant int FLAG_WILDCARD_SINGLE
= Xapian
::QueryParser
::FLAG_WILDCARD_SINGLE
;
88 %constant int FLAG_PURE_NOT
= Xapian
::QueryParser
::FLAG_PURE_NOT
;
89 %constant int FLAG_PARTIAL
= Xapian
::QueryParser
::FLAG_PARTIAL
;
90 %constant int FLAG_SPELLING_CORRECTION
= Xapian
::QueryParser
::FLAG_SPELLING_CORRECTION
;
91 %constant int FLAG_SYNONYM
= Xapian
::QueryParser
::FLAG_SYNONYM
;
92 %constant int FLAG_AUTO_SYNONYMS
= Xapian
::QueryParser
::FLAG_AUTO_SYNONYMS
;
93 %constant int FLAG_AUTO_MULTIWORD_SYNONYMS
= Xapian
::QueryParser
::FLAG_AUTO_MULTIWORD_SYNONYMS
;
94 %constant int FLAG_NGRAMS
= Xapian
::QueryParser
::FLAG_NGRAMS
;
95 %constant int FLAG_CJK_NGRAM
= Xapian
::QueryParser
::FLAG_CJK_NGRAM
;
96 %constant int FLAG_WORD_BREAKS
= Xapian
::QueryParser
::FLAG_WORD_BREAKS
;
97 %constant int FLAG_DEFAULT
= Xapian
::QueryParser
::FLAG_DEFAULT
;
98 %constant int STEM_NONE
= Xapian
::QueryParser
::STEM_NONE
;
99 %constant int STEM_SOME
= Xapian
::QueryParser
::STEM_SOME
;
100 %constant int STEM_SOME_FULL_POS
= Xapian
::QueryParser
::STEM_SOME_FULL_POS
;
101 %constant int STEM_ALL
= Xapian
::QueryParser
::STEM_ALL
;
102 %constant int STEM_ALL_Z
= Xapian
::QueryParser
::STEM_ALL_Z
;
103 %constant int FLAG_SPELLING
= Xapian
::TermGenerator
::FLAG_SPELLING
;
104 // FLAG_NGRAMS
, FLAG_CJK_NGRAM and FLAG_WORD_BREAKS are already set above from
105 // QueryParser
(values match
).
106 %constant int WILDCARD_LIMIT_ERROR
= Xapian
::Query
::WILDCARD_LIMIT_ERROR
;
107 %constant int WILDCARD_LIMIT_FIRST
= Xapian
::Query
::WILDCARD_LIMIT_FIRST
;
108 %constant int WILDCARD_LIMIT_MOST_FREQUENT
= Xapian
::Query
::WILDCARD_LIMIT_MOST_FREQUENT
;
110 /* Xapian
::Enquire
*/
111 %feature
("shadow") Xapian
::Enquire
::get_mset
115 my $nargs
= scalar
(@_
);
117 my $type
= ref
( $_
[2] );
118 if
( $type eq 'Xapian
::RSet'
) {
119 # get_mset
(first
, max
, rset
)
120 splice @_
, 2, 0, (0); # insert checkatleast
123 return Xapianc
::Enquire_get_mset
( @_
);
127 %feature
("shadow") Xapian
::Enquire
::set_query
130 if
(ref
($_
[1]) ne 'Xapian
::Query'
) {
131 push @_
, Xapian
::Query-
>new
(splice @_
, 1);
133 Xapianc
::Enquire_set_query
(@_
);
137 %feature
("shadow") Xapian
::Enquire
::set_sort_by_key
139 sub set_sort_by_key
{
142 $self
{_sorter
} = $sorter
;
143 Xapianc
::Enquire_set_sort_by_key
( @_
);
147 %feature
("shadow") Xapian
::Enquire
::set_sort_by_key_then_relevance
149 sub set_sort_by_key_then_relevance
{
152 $self
{_sorter
} = $sorter
;
153 Xapianc
::Enquire_set_sort_by_key_then_relevance
( @_
);
157 %feature
("shadow") Xapian
::Enquire
::set_sort_by_relevance_then_key
159 sub set_sort_by_relevance_then_key
{
162 $self
{_sorter
} = $sorter
;
163 Xapianc
::Enquire_set_sort_by_relevance_then_key
( @_
);
167 /* Xapian
::Enquire
*/
168 %extend Xapian
::Enquire
{
169 // For compatibility with Search
::Xapian.
170 Xapian
::MSet get_mset
(Xapian
::doccount first
,
171 Xapian
::doccount maxitems
,
172 const Xapian
::MatchDecider
* mdecider
) {
173 return $self-
>get_mset
(first
, maxitems
, 0, NULL, mdecider
);
178 %extend Xapian
::ESet
{
179 Xapian
::ESetIterator
FETCH(int index
) {
180 return
((*self
)[index
]);
184 /* Xapian
::ESetIterator
*/
185 %extend Xapian
::ESetIterator
{
186 std
::string get_termname
() {
187 return self-
>operator
*();
192 %extend Xapian
::MSet
{
193 Xapian
::MSetIterator
FETCH(int index
) {
194 return
((*self
)[index
]);
199 %feature
("shadow") Xapian
::Query
::Query
206 $query
= Xapianc
::new_Query
(@_
);
210 if
( $op
!~
/^\d
+$
/ ) {
211 Carp
::croak
( "USAGE: $class->new('term') or $class->new(OP, <args>)" );
213 if
( $op
== 8 ) { # FIXME
: 8 is OP_VALUE_RANGE
; eliminate hardcoded literal
215 Carp
::croak
( "USAGE: $class->new(OP_VALUE_RANGE, VALNO, START, END)" );
217 $query
= Xapianc
::new_Query
( @_
);
218 } elsif
( $op
== 9 ) { # FIXME
: OP_SCALE_WEIGHT
220 Carp
::croak
( "USAGE: $class->new(OP_SCALE_WEIGHT, QUERY, FACTOR)" );
222 $query
= Xapianc
::new_Query
( @_
);
223 } elsif
( $op
== 11 || $op
== 12 ) { # FIXME
: OP_VALUE_GE
, OP_VALUE_LE
; eliminate hardcoded literals
225 Carp
::croak
( "USAGE: $class->new(OP_VALUE_[GL]E, VALNO, LIMIT)" );
227 $query
= Xapianc
::new_Query
( @_
);
230 $query
= Xapian
::newN
( $op
, \@_
);
243 croak
("Argument $argnum is not a reference.");
244 if
(SvTYPE
(SvRV
($input
)) != SVt_PVAV
)
245 croak
("Argument $argnum is not an array.");
246 tempav
= (AV
*)SvRV
($input
);
247 len
= av_len
(tempav
);
248 $
1 = (SV
**) malloc
((len
+2)*sizeof
(SV
*));
249 for
(i
= 0; i
<= len
; i
++) {
250 tv
= av_fetch
(tempav
, i
, 0);
256 %typemap
(freearg
) SV
** {
261 class XapianSWIGQueryItor
{
267 XapianSWIGQueryItor
() { }
269 void begin
(AV
* array_
) {
278 XapianSWIGQueryItor
& operator++() {
283 Xapian
::Query operator
*() const
{
284 SV
**svp
= av_fetch
(array
, i
, 0);
286 croak
("Unexpected NULL returned by av_fetch()");
290 croak
("USAGE: Xapian::Query->new(OP, @TERMS_OR_QUERY_OBJECTS)");
294 if
(SWIG_ConvertPtr
(sv
, (void
**)&q,
295 SWIGTYPE_p_Xapian__Query
, 0) == SWIG_OK
) {
300 const char
* ptr
= SvPV
(sv
, len
);
301 return Xapian
::Query
(string
(ptr
, len
));
304 bool operator
==(const XapianSWIGQueryItor
& o) {
308 bool operator
!=(const XapianSWIGQueryItor
& o) {
309 return
!(*this
== o
);
312 typedef std
::input_iterator_tag iterator_category
;
313 typedef Xapian
::Query value_type
;
314 typedef Xapian
::termcount_diff difference_type
;
315 typedef Xapian
::Query
* pointer
;
316 typedef Xapian
::Query
& reference;
322 Xapian
::Query
* newN
(int op_
, SV
*q_
) {
323 Xapian
::Query
::op op
= (Xapian
::Query
::op
)op_
;
324 XapianSWIGQueryItor b
, e
;
326 AV
*q
= (AV
*) SvRV
(q_
);
329 e.end
(av_len
(q
) + 1);
332 return new Xapian
::Query
(op
, b
, e
);
333 } catch
(const Xapian
::Error
&error) {
334 croak
( "Exception: %s", error.get_msg
().c_str
() );
339 /* Xapian
::QueryParser
*/
340 %feature
("shadow") Xapian
::QueryParser
::QueryParser
344 my $qp
= Xapianc
::new_QueryParser
();
347 $qp-
>set_database
(@_
) if scalar
(@_
) == 1;
353 %feature
("shadow") Xapian
::QueryParser
::set_stopper
356 my
($self
, $stopper
) = @_
;
357 $self
{_stopper
} = $stopper
;
358 Xapianc
::QueryParser_set_stopper
( @_
);
362 %feature
("shadow") Xapian
::QueryParser
::add_rangeprocessor
364 sub add_rangeprocessor
{
365 my
($self
, $rproc
) = @_
;
366 push @
{$self
{_rproc
}}, $rproc
;
367 Xapianc
::QueryParser_add_rangeprocessor
( @_
);
371 /* Xapian
::SimpleStopper
*/
372 %feature
("shadow") Xapian
::SimpleStopper
::SimpleStopper
376 my $stopper
= Xapianc
::new_SimpleStopper
();
378 bless $stopper
, $class
;
387 %extend Xapian
::SimpleStopper
{
388 bool stop_word
(std
::string term
) {
389 return
(*self
)(term
);
394 %extend Xapian
::Stem
{
395 std
::string stem_word
(std
::string word
) {
396 return
(*self
)(word
);
400 /* Xapian
::TermIterator
*/
401 %rename
(get_termname
) Xapian
::TermIterator
::get_term
;
403 /* Xapian
::WritableDatabase
*/
404 %rename
(replace_document_by_term
) \
405 Xapian
::WritableDatabase
::replace_document
(std
::string_view
,
406 const Xapian
::Document
&);
407 %rename
(delete_document_by_term
) \
408 Xapian
::WritableDatabase
::delete_document
(std
::string_view
);
410 %feature
("shadow") Xapian
::WritableDatabase
::WritableDatabase
415 if
( scalar
(@_
) == 0 ) {
416 # For compatibility with Search
::Xapian
417 @_
= (''
, $Xapianc
::DB_BACKEND_INMEMORY
);
419 $self
= Xapianc
::new_WritableDatabase
(@_
);
420 bless $self
, $pkg if defined
($self
);
424 %define SUB_CLASS
(NS
, CLASS
)
426 class perl##CLASS
: public NS
::CLASS
{
430 perl##CLASS
(SV
* func
) {
431 callback
= newSVsv
(func
);
435 SvREFCNT_dec
(callback
);
438 bool operator
()(const std
::string
& term) const override {
446 SV
* arg
= sv_newmortal
();
447 sv_setpvn
(arg
, term.data
(), term.size
());
451 int count
= call_sv
(callback
, G_SCALAR
);
455 croak
("callback function should return 1 value, got %d", count
);
471 SUB_CLASS
(Xapian
, ExpandDecider
)
472 SUB_CLASS
(Xapian
, Stopper
)
475 class perlMatchDecider
: public Xapian
::MatchDecider
{
479 perlMatchDecider
(SV
* func
) {
480 callback
= newSVsv
(func
);
483 ~perlMatchDecider
() {
484 SvREFCNT_dec
(callback
);
487 bool operator
()(const Xapian
::Document
& doc) const override {
495 XPUSHs
(SWIG_NewPointerObj
(const_cast
<Xapian
::Document
*>(&doc),
496 SWIGTYPE_p_Xapian__Document
, 0));
499 int count
= call_sv
(callback
, G_SCALAR
);
503 croak
("callback function should return 1 value, got %d", count
);
518 class perlStemImplementation
: public Xapian
::StemImplementation
{
522 perlStemImplementation
(SV
* func
) {
523 callback
= newSVsv
(func
);
526 ~perlStemImplementation
() {
527 SvREFCNT_dec
(callback
);
530 std
::string operator
()(const std
::string
& word) override {
538 SV
* arg
= sv_newmortal
();
539 sv_setpvn
(arg
, word.data
(), word.size
());
543 int count
= call_sv
(callback
, G_SCALAR
);
547 croak
("callback function should return 1 value, got %d", count
);
551 const char
* ptr
= SvPV
(sv
, len
);
552 std
::string result
(ptr
, len
);
562 std
::string get_description
() const
{
563 return
"perlStemImplementation()";
569 class perlKeyMaker
: public Xapian
::KeyMaker
{
573 perlKeyMaker
(SV
* func
) {
574 callback
= newSVsv
(func
);
578 SvREFCNT_dec
(callback
);
581 std
::string operator
()(const Xapian
::Document
& doc) const override {
589 XPUSHs
(SWIG_NewPointerObj
(const_cast
<Xapian
::Document
*>(&doc),
590 SWIGTYPE_p_Xapian__Document
, 0));
593 int count
= call_sv
(callback
, G_SCALAR
);
597 croak
("callback function should return 1 value, got %d", count
);
601 const char
* ptr
= SvPV
(sv
, len
);
602 std
::string result
(ptr
, len
);
615 class perlRangeProcessor
: public Xapian
::RangeProcessor
{
619 perlRangeProcessor
(SV
* func
) {
620 callback
= newSVsv
(func
);
623 ~perlRangeProcessor
() {
624 SvREFCNT_dec
(callback
);
627 Xapian
::Query operator
()(const std
::string
& begin,
628 const std
::string
& end) override {
636 SV
* arg
= sv_newmortal
();
637 sv_setpvn
(arg
, begin.data
(), begin.size
());
639 arg
= sv_newmortal
();
640 sv_setpvn
(arg
, end.data
(), end.size
());
644 int count
= call_sv
(callback
, G_SCALAR
);
648 croak
("callback function should return 1 value, got %d", count
);
650 // Allow the function to return a string or Query object.
653 croak
("function must return a string or Query object");
655 Xapian
::Query result
;
657 if
(SWIG_ConvertPtr
(sv
, (void
**)&q,
658 SWIGTYPE_p_Xapian__Query
, 0) == SWIG_OK
) {
662 const char
* ptr
= SvPV
(sv
, len
);
663 result
= Xapian
::Query
(string
(ptr
, len
));
677 class perlFieldProcessor
: public Xapian
::FieldProcessor
{
681 perlFieldProcessor
(SV
* func
) {
682 callback
= newSVsv
(func
);
685 ~perlFieldProcessor
() {
686 SvREFCNT_dec
(callback
);
689 Xapian
::Query operator
()(const std
::string
& str) override {
697 SV
* arg
= sv_newmortal
();
698 sv_setpvn
(arg
, str.data
(), str.size
());
702 int count
= call_sv
(callback
, G_SCALAR
);
706 croak
("callback function should return 1 value, got %d", count
);
708 // Allow the function to return a string or Query object.
711 croak
("function must return a string or Query object");
713 Xapian
::Query result
;
715 if
(SWIG_ConvertPtr
(sv
, (void
**)&q,
716 SWIGTYPE_p_Xapian__Query
, 0) == SWIG_OK
) {
720 const char
* ptr
= SvPV
(sv
, len
);
721 result
= Xapian
::Query
(string
(ptr
, len
));
735 class perlMatchSpy
: public Xapian
::MatchSpy
{
739 perlMatchSpy
(SV
* func
) {
740 callback
= newSVsv
(func
);
744 SvREFCNT_dec
(callback
);
747 void operator
()(const Xapian
::Document
& doc, double wt) override {
755 PUSHs
(SWIG_NewPointerObj
(const_cast
<Xapian
::Document
*>(&doc),
756 SWIGTYPE_p_Xapian__Document
, 0));
760 (void
)call_sv
(callback
, G_VOID
);
771 %define SUB_CLASS_TYPEMAPS
(NS
, CLASS
)
773 %typemap
(typecheck
, precedence
=100) NS
::CLASS
* {
776 if
(SWIG_ConvertPtr
(sv
, &ptr, $descriptor(NS::CLASS *), 0) == SWIG_OK) {
780 /* The docs in perlapi for call_sv say
:
782 * [T
]he SV may be any of a CV
, a GV
, a reference to a CV
, a
783 * reference to a GV or
"SvPV(sv)" will be used as the name of the
786 * To make overloading work helpfully
, we don't allow passing the name
787 * of a sub. Search
::Xapian did in some cases
, but it seems unlikely
788 * anyone relied on this.
790 svtype t
= SvTYPE
(sv
);
792 t
= SvTYPE
(SvRV
(sv
));
794 $
1 = (t
== SVt_PVCV || t
== SVt_PVGV
);
797 %typemap
(in
) NS
::CLASS
* {
799 if
(SWIG_ConvertPtr
(sv
, (void
**)&$1,
800 $descriptor
(NS
::CLASS
*), 0) != SWIG_OK
) {
801 $
1 = new perl##CLASS
(sv
);
806 SUB_CLASS_TYPEMAPS
(Xapian
, MatchDecider
)
807 SUB_CLASS_TYPEMAPS
(Xapian
, ExpandDecider
)
808 SUB_CLASS_TYPEMAPS
(Xapian
, Stopper
)
809 SUB_CLASS_TYPEMAPS
(Xapian
, StemImplementation
)
810 SUB_CLASS_TYPEMAPS
(Xapian
, KeyMaker
)
811 SUB_CLASS_TYPEMAPS
(Xapian
, RangeProcessor
)
812 SUB_CLASS_TYPEMAPS
(Xapian
, FieldProcessor
)
813 SUB_CLASS_TYPEMAPS
(Xapian
, MatchSpy
)
816 %include ..
/xapian-headers.i