1 /* lua
/util.i
: custom lua typemaps for xapian-bindings
3 * Copyright
(C
) 2011 Xiaona Han
4 * Copyright
(C
) 2011,2012,2017,2019,2020 Olly Betts
6 * This program is free software
; you can redistribute it and
/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation
; either version
2 of the
9 * License
, or
(at your option
) any later version.
11 * This program is distributed in the hope that it will be useful
,
12 * but WITHOUT
ANY WARRANTY
; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program
; if not
, write to the Free Software
18 * Foundation
, Inc.
, 51 Franklin St
, Fifth Floor
, Boston
, MA
02110-1301
22 // "end" is a keyword in Lua
, so we rename it to
"_end"
25 %rename
("__tostring") get_description
;
27 // On platforms where
(sizeof
(long
) == 4), SWIG by default wraps
28 // Xapian
::BAD_VALUENO as a negative constant in Lua
, which is then rejected by
29 // a check which disallows passing negative values for unsigned C
++ types.
30 // This
%apply wraps it as a double constant
, and also eliminates the negative
32 %apply double
{ Xapian
::valueno
};
35 #if LUA_VERSION_NUM-0
>= 502
36 // luaL_typerror was removed in Lua
5.2.
37 int luaL_typerror
(lua_State
*L
, int narg
, const char
*tname
) {
38 const char
*msg
= lua_pushfstring
(L
, "%s expected, got %s",
39 tname
, luaL_typename
(L
, narg
));
40 return luaL_argerror
(L
, narg
, msg
);
45 %define SUB_CLASS
(NS
, CLASS
)
47 class lua##CLASS
: public NS
::CLASS
{
52 lua##CLASS
(lua_State
* S
) {
54 if
(!lua_isfunction
(L
, -1)) {
55 luaL_typerror
(L
, -1, "function");
57 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
61 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
64 bool operator
()(const std
::string
&term) const {
65 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
66 if
(!lua_isfunction
(L
, -1)) {
67 luaL_typerror
(L
, -1, "function");
70 lua_pushlstring
(L
, term.data
(), term.length
());
71 if
(lua_pcall
(L
, 1, 1, 0) != 0) {
72 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
74 if
(!lua_isboolean
(L
, -1)) {
75 luaL_error
(L
, "function must return a boolean");
77 bool result
= lua_toboolean
(L
, -1);
86 SUB_CLASS
(Xapian
, ExpandDecider
)
87 SUB_CLASS
(Xapian
, Stopper
)
90 class luaMatchDecider
: public Xapian
::MatchDecider
{
95 luaMatchDecider
(lua_State
* S
) {
97 if
(!lua_isfunction
(L
, -1)) {
98 luaL_typerror
(L
, -1, "function");
100 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
104 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
107 bool operator
()(const Xapian
::Document
&doc) const {
108 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
109 if
(!lua_isfunction
(L
, -1)) {
110 luaL_typerror
(L
, -1, "function");
113 SWIG_NewPointerObj
(L
, &doc, SWIGTYPE_p_Xapian__Document, 0);
114 if
(lua_pcall
(L
, 1, 1, 0) != 0) {
115 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
117 if
(!lua_isboolean
(L
, -1)) {
118 luaL_error
(L
, "function must return a boolean");
120 bool result
= lua_toboolean
(L
, -1);
128 class luaStemImplementation
: public Xapian
::StemImplementation
{
133 luaStemImplementation
(lua_State
* S
) {
135 if
(!lua_isfunction
(L
, -1)) {
136 luaL_typerror
(L
, -1, "function");
138 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
141 ~luaStemImplementation
() {
142 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
145 std
::string operator
()(const std
::string
&word) {
146 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
147 if
(!lua_isfunction
(L
, -1)) {
148 luaL_typerror
(L
, -1, "function");
151 lua_pushlstring
(L
, word.data
(), word.length
());
152 if
(lua_pcall
(L
, 1, 1, 0) != 0) {
153 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
155 if
(!lua_isstring
(L
, -1)) {
156 luaL_error
(L
, "function must return a string");
159 const char
* p
= lua_tolstring
(L
, -1, &len);
160 std
::string result
(p
, len
);
165 std
::string get_description
() const
{
166 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
167 if
(!lua_isfunction
(L
, -1)) {
168 luaL_typerror
(L
, -1, "function");
171 if
(lua_pcall
(L
, 0, 1, 0) != 0) {
172 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
174 if
(!lua_isstring
(L
, -1)) {
175 luaL_error
(L
, "function must return a string");
179 const char
* p
= lua_tolstring
(L
, -1, &len);
180 std
::string result
(p
, len
);
188 class luaKeyMaker
: public Xapian
::KeyMaker
{
193 luaKeyMaker
(lua_State
* S
) {
195 if
(!lua_isfunction
(L
, -1)) {
196 luaL_typerror
(L
, -1, "function");
198 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
202 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
205 std
::string operator
()(const Xapian
::Document
&doc) const {
206 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
207 if
(!lua_isfunction
(L
, -1)) {
208 luaL_typerror
(L
, -1, "function");
211 SWIG_NewPointerObj
(L
, &doc, SWIGTYPE_p_Xapian__Document, 0);
212 if
(lua_pcall
(L
, 1, 1, 0) != 0) {
213 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
215 if
(!lua_isstring
(L
, -1)) {
216 luaL_error
(L
, "function must return a string");
219 const char
* p
= lua_tolstring
(L
, -1, &len);
220 std
::string result
(p
, len
);
228 class luaRangeProcessor
: public Xapian
::RangeProcessor
{
233 luaRangeProcessor
(lua_State
* S
) {
235 if
(!lua_isfunction
(L
, -1)) {
236 luaL_typerror
(L
, -1, "function");
238 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
241 ~luaRangeProcessor
() {
242 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
245 Xapian
::Query operator
()(const std
::string
& begin, const std::string& end) {
246 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
247 if
(!lua_isfunction
(L
, -1)) {
248 luaL_typerror
(L
, -1, "function");
251 lua_pushlstring
(L
, begin.data
(), begin.length
());
252 lua_pushlstring
(L
, end.data
(), end.length
());
254 if
(lua_pcall
(L
, 2, 1, 0) != 0) {
255 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
258 // Allow the function to return a string or Query object.
259 if
(lua_isstring
(L
, -1)) {
261 const char
* p
= lua_tolstring
(L
, -1, &len);
262 std
::string result
(p
, len
);
264 return Xapian
::Query
(result
);
267 Xapian
::Query
*subq
= 0;
268 if
(!lua_isuserdata
(L
, -1) ||
269 SWIG_ConvertPtr
(L
, -1, (void
**)&subq,
270 SWIGTYPE_p_Xapian__Query
, 0) == -1) {
272 luaL_error
(L
, "function must return a string or Query object");
282 class luaValueRangeProcessor
: public Xapian
::ValueRangeProcessor
{
287 luaValueRangeProcessor
(lua_State
* S
) {
289 if
(!lua_isfunction
(L
, -1)) {
290 luaL_typerror
(L
, -1, "function");
292 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
295 ~luaValueRangeProcessor
() {
296 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
299 Xapian
::valueno operator
()(std
::string
&begin, std::string &end) {
300 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
301 if
(!lua_isfunction
(L
, -1)) {
302 luaL_typerror
(L
, -1, "function");
305 lua_pushlstring
(L
, (char
*)begin.c_str
(), begin.length
());
306 lua_pushlstring
(L
, (char
*)end.c_str
(), end.length
());
308 if
(lua_pcall
(L
, 2, 1, 0) != 0) {
309 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
311 if
(!lua_isnumber
(L
, -1)) {
312 luaL_error
(L
, "function must return a number");
314 Xapian
::valueno result
(lua_tonumber
(L
, -1));
322 class luaFieldProcessor
: public Xapian
::FieldProcessor
{
327 luaFieldProcessor
(lua_State
* S
) {
329 if
(!lua_isfunction
(L
, -1)) {
330 luaL_typerror
(L
, -1, "function");
332 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
335 ~luaFieldProcessor
() {
336 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
339 Xapian
::Query operator
()(const std
::string
&str) {
340 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
341 if
(!lua_isfunction
(L
, -1)) {
342 luaL_typerror
(L
, -1, "function");
345 lua_pushlstring
(L
, str.data
(), str.length
());
347 if
(lua_pcall
(L
, 1, 1, 0) != 0) {
348 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
351 // Allow the function to return a string or Query object.
352 if
(lua_isstring
(L
, -1)) {
354 const char
* p
= lua_tolstring
(L
, -1, &len);
355 std
::string result
(p
, len
);
357 return Xapian
::Query
(result
);
360 Xapian
::Query
*subq
= 0;
361 if
(!lua_isuserdata
(L
, -1) ||
362 SWIG_ConvertPtr
(L
, -1, (void
**)&subq,
363 SWIGTYPE_p_Xapian__Query
, 0) == -1) {
365 luaL_error
(L
, "function must return a string or Query object");
375 class luaMatchSpy
: public Xapian
::MatchSpy
{
380 luaMatchSpy
(lua_State
* S
) {
382 if
(!lua_isfunction
(L
, -1)) {
383 luaL_typerror
(L
, -1, "function");
385 r
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
389 luaL_unref
(L
, LUA_REGISTRYINDEX
, r
);
392 void operator
()(const Xapian
::Document
&doc, double wt) {
393 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, r
);
394 if
(!lua_isfunction
(L
, -1)) {
395 luaL_typerror
(L
, -1, "function");
398 SWIG_NewPointerObj
(L
, &doc, SWIGTYPE_p_Xapian__Document, 0);
399 SWIG_NewPointerObj
(L
, &wt, SWIGTYPE_p_Xapian__Weight, 0);
400 if
(lua_pcall
(L
, 2, 1, 0) != 0) {
401 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
407 %define SUB_CLASS_TYPEMAPS
(NS
, CLASS
)
409 %typemap
(typecheck
, precedence
=100) NS
::CLASS
* {
411 if
(lua_isfunction
(L
, $input
) ||
(SWIG_isptrtype
(L
, $input
) && !SWIG_ConvertPtr(L, $input, (void **) &ptr, $descriptor(NS::CLASS *), 0))) {
417 %typemap
(in
) NS
::CLASS
* {
418 if
(lua_isfunction
(L
, $input
)) {
419 $
1 = new lua##CLASS
(L
);
421 if
(!SWIG_IsOK
(SWIG_ConvertPtr
(L
, $input
, (void
**)&$1, $descriptor(NS::CLASS *), 0))) {
428 SUB_CLASS_TYPEMAPS
(Xapian
, MatchDecider
)
429 SUB_CLASS_TYPEMAPS
(Xapian
, ExpandDecider
)
430 SUB_CLASS_TYPEMAPS
(Xapian
, Stopper
)
431 SUB_CLASS_TYPEMAPS
(Xapian
, StemImplementation
)
432 SUB_CLASS_TYPEMAPS
(Xapian
, KeyMaker
)
433 SUB_CLASS_TYPEMAPS
(Xapian
, RangeProcessor
)
434 SUB_CLASS_TYPEMAPS
(Xapian
, ValueRangeProcessor
)
435 SUB_CLASS_TYPEMAPS
(Xapian
, FieldProcessor
)
436 SUB_CLASS_TYPEMAPS
(Xapian
, MatchSpy
)
439 function xapian.Iterator
(begin
, _end
)
443 if iter
:equals
(_end
) then
451 if iter
:equals
(_end
) then
461 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
463 %typemap
(typecheck
, precedence
=500) (XapianSWIGQueryItor qbegin
, XapianSWIGQueryItor qend
) {
464 $
1 = lua_istable
(L
, $input
);
465 /* FIXME
: if we add more array typemaps
, we'll need to check the elements
466 * of the array here to disambiguate.
*/
470 class XapianSWIGQueryItor
{
476 typedef std
::random_access_iterator_tag iterator_category
;
477 typedef Xapian
::Query value_type
;
478 typedef Xapian
::termcount_diff difference_type
;
479 typedef Xapian
::Query
* pointer
;
480 typedef Xapian
::Query
& reference;
482 XapianSWIGQueryItor
() { }
484 void begin
(lua_State
* S
, int index_
) {
490 void end
(lua_State
* S
, int index_
, int n
) {
500 XapianSWIGQueryItor
& operator++() {
505 Xapian
::Query operator
*() const
{
506 lua_rawgeti
(L
, index
, i
+1);
507 if
(lua_isstring
(L
, -1)) {
509 const char
*p
= lua_tolstring
(L
, -1, &len);
511 return Xapian
::Query
(string
(p
, len
));
514 Xapian
::Query
*subq
= 0;
515 if
(!lua_isuserdata
(L
, -1) ||
516 SWIG_ConvertPtr
(L
, -1, (void
**)&subq,
517 SWIGTYPE_p_Xapian__Query
, 0) == -1) {
519 luaL_argerror
(L
, index
,
520 "elements must be Query objects or strings");
527 bool operator
==(const XapianSWIGQueryItor
& o) {
531 bool operator
!=(const XapianSWIGQueryItor
& o) {
532 return
!(*this
== o
);
535 difference_type operator-
(const XapianSWIGQueryItor
&o) const {
542 %typemap
(in
) (XapianSWIGQueryItor qbegin
, XapianSWIGQueryItor qend
) {
543 if
(lua_istable
(L
, $input
)) {
545 $
2.end
(L
, $input
, lua_rawlen
(L
, $input
));
552 %define OUTPUT_ITERATOR_METHODS
(NS
, CLASS
, ITERATOR_CLASS
, ITERATOR_BEGIN
, ITERATOR_END
, DEREF_METHOD
, PARAMETER_NAME
, PARAMETER_VALUE
)
555 std
::pair
<NS
::ITERATOR_CLASS
, NS
::ITERATOR_CLASS
> DEREF_METHOD
(PARAMETER_NAME
) {
556 return std
::make_pair
($self-
>ITERATOR_BEGIN
(PARAMETER_VALUE
), $self-
>ITERATOR_END
(PARAMETER_VALUE
));
560 %typemap
(out
) std
::pair
<NS
::ITERATOR_CLASS
, NS
::ITERATOR_CLASS
> {
561 lua_getglobal
(L
, "xapian");
562 lua_pushstring
(L
, "Iterator");
566 if
(!lua_isfunction
(L
, -1)) {
567 luaL_typerror
(L
, -1, "function");
570 NS
::ITERATOR_CLASS
* begin
= new NS
::ITERATOR_CLASS
((const NS
::ITERATOR_CLASS
&)$1.first);
571 SWIG_NewPointerObj
(L
, (void
*) begin
, $descriptor
(NS
::ITERATOR_CLASS
*), 1);
573 NS
::ITERATOR_CLASS
* end
= new NS
::ITERATOR_CLASS
((const NS
::ITERATOR_CLASS
&)$1.second);
574 SWIG_NewPointerObj
(L
, (void
*) end
, $descriptor
(NS
::ITERATOR_CLASS
*), 1);
576 if
(lua_pcall
(L
, 2, 1, 0) != 0) {
577 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));
585 OUTPUT_ITERATOR_METHODS
(Xapian
, Query
, TermIterator
, get_terms_begin
, get_terms_end
, get_terms
, void
, )
587 OUTPUT_ITERATOR_METHODS
(Xapian
, QueryParser
, TermIterator
, stoplist_begin
, stoplist_end
, stoplist
, void
, )
589 OUTPUT_ITERATOR_METHODS
(Xapian
, ESet
, ESetIterator
, begin
, end
, terms
, void
, )
591 OUTPUT_ITERATOR_METHODS
(Xapian
, MSet
, MSetIterator
, begin
, end
, items
, void
, )
593 OUTPUT_ITERATOR_METHODS
(Xapian
, Document
, TermIterator
, termlist_begin
, termlist_end
, termlist
, void
, )
594 OUTPUT_ITERATOR_METHODS
(Xapian
, Document
, ValueIterator
, values_begin
, values_end
, values
, void
, )
596 OUTPUT_ITERATOR_METHODS
(Xapian
, Enquire
, TermIterator
, get_matching_terms_begin
, get_matching_terms_end
, get_matching_terms
, Xapian
::docid did
, did
)
597 OUTPUT_ITERATOR_METHODS
(Xapian
, Enquire
, TermIterator
, get_matching_terms_begin
, get_matching_terms_end
, get_matching_terms
, const MSetIterator
&it, it)
599 OUTPUT_ITERATOR_METHODS
(Xapian
, ValueCountMatchSpy
, TermIterator
, values_begin
, values_end
, values
, void
, )
600 OUTPUT_ITERATOR_METHODS
(Xapian
, ValueCountMatchSpy
, TermIterator
, top_values_begin
, top_values_end
, top_values
, size_t maxvalues
, maxvalues
)
602 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, allterms_begin
, allterms_end
, allterms
, void
, )
603 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, spellings_begin
, spellings_end
, spellings
, void
, )
604 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, PostingIterator
, postlist_begin
, postlist_end
, postlist
, const std
::string
&tname, tname)
605 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, termlist_begin
, termlist_end
, termlist
, Xapian
::docid did
, did
)
606 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, ValueIterator
, valuestream_begin
, valuestream_end
, valuestream
, Xapian
::valueno slot
, slot
)
607 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, allterms_begin
, allterms_end
, allterms
, const std
::string
&prefix, prefix)
608 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, synonyms_begin
, synonyms_end
, synonyms
, const std
::string
&term, term)
609 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, synonym_keys_begin
, synonym_keys_end
, synonym_keys
, const std
::string
&prefix, prefix)
610 OUTPUT_ITERATOR_METHODS
(Xapian
, Database
, TermIterator
, metadata_keys_begin
, metadata_keys_end
, metadata_keys
, const std
::string
&prefix, prefix)
612 %extend Xapian
::Database
{
613 std
::pair
<Xapian
::PositionIterator
, Xapian
::PositionIterator
> positionlist
(Xapian
::docid did
, const std
::string
&tname) {
614 return std
::make_pair
($self-
>positionlist_begin
(did
, tname
), $self-
>positionlist_end
(did
, tname
));
618 %typemap
(out
) std
::pair
<Xapian
::PositionIterator
, Xapian
::PositionIterator
> {
619 lua_getglobal
(L
, "xapian");
620 lua_pushstring
(L
, "Iterator");
624 if
(!lua_isfunction
(L
, -1)) {
625 luaL_typerror
(L
, -1, "function");
628 Xapian
::PositionIterator
* begin
= new Xapian
::PositionIterator
((const Xapian
::PositionIterator
&)$1.first);
629 SWIG_NewPointerObj
(L
, (void
*) begin
, SWIGTYPE_p_Xapian__PositionIterator
, 1);
631 Xapian
::PositionIterator
* end
= new Xapian
::PositionIterator
((const Xapian
::PositionIterator
&)$1.second);
632 SWIG_NewPointerObj
(L
, (void
*) end
, SWIGTYPE_p_Xapian__PositionIterator
, 1);
634 if
(lua_pcall
(L
, 2, 1, 0) != 0) {
635 luaL_error
(L
, "error running function: %s", lua_tostring
(L
, -1));