Refactor to avoid warning with GCC 12.2
[xapian.git] / xapian-bindings / lua / util.i
blobcaaf9a715033999e176e42359a89f0e629553028
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
19 * USA
22 // "end" is a keyword in Lua, so we rename it to "_end"
23 %rename("_end") 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
31 // value check.
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);
42 #endif
45 %define SUB_CLASS(NS, CLASS)
47 class lua##CLASS : public NS::CLASS {
48 int r;
49 lua_State* L;
51 public:
52 lua##CLASS(lua_State* S) {
53 L = S;
54 if (!lua_isfunction(L, -1)) {
55 luaL_typerror(L, -1, "function");
57 r = luaL_ref(L, LUA_REGISTRYINDEX);
60 ~lua##CLASS() {
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);
78 lua_pop(L, 1);
79 return result;
84 %enddef
86 SUB_CLASS(Xapian, ExpandDecider)
87 SUB_CLASS(Xapian, Stopper)
90 class luaMatchDecider : public Xapian::MatchDecider {
91 int r;
92 lua_State* L;
94 public:
95 luaMatchDecider(lua_State* S) {
96 L = S;
97 if (!lua_isfunction(L, -1)) {
98 luaL_typerror(L, -1, "function");
100 r = luaL_ref(L, LUA_REGISTRYINDEX);
103 ~luaMatchDecider() {
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);
121 lua_pop(L, 1);
122 return result;
128 class luaStemImplementation : public Xapian::StemImplementation {
129 int r;
130 lua_State* L;
132 public:
133 luaStemImplementation(lua_State* S) {
134 L = 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");
158 size_t len;
159 const char * p = lua_tolstring(L, -1, &len);
160 std::string result(p, len);
161 lua_pop(L, 1);
162 return result;
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");
178 size_t len;
179 const char * p = lua_tolstring(L, -1, &len);
180 std::string result(p, len);
181 lua_pop(L, 1);
182 return result;
188 class luaKeyMaker : public Xapian::KeyMaker {
189 int r;
190 lua_State* L;
192 public:
193 luaKeyMaker(lua_State* S) {
194 L = S;
195 if (!lua_isfunction(L, -1)) {
196 luaL_typerror(L, -1, "function");
198 r = luaL_ref(L, LUA_REGISTRYINDEX);
201 ~luaKeyMaker() {
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");
218 size_t len;
219 const char * p = lua_tolstring(L, -1, &len);
220 std::string result(p, len);
221 lua_pop(L, 1);
222 return result;
228 class luaRangeProcessor : public Xapian::RangeProcessor {
229 int r;
230 lua_State* L;
232 public:
233 luaRangeProcessor(lua_State* S) {
234 L = 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)) {
260 size_t len;
261 const char * p = lua_tolstring(L, -1, &len);
262 std::string result(p, len);
263 lua_pop(L, 1);
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) {
271 lua_pop(L, 1);
272 luaL_error(L, "function must return a string or Query object");
275 lua_pop(L, 1);
276 return *subq;
282 class luaValueRangeProcessor : public Xapian::ValueRangeProcessor {
283 int r;
284 lua_State* L;
286 public:
287 luaValueRangeProcessor(lua_State* S) {
288 L = 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));
315 lua_pop(L, 1);
316 return result;
322 class luaFieldProcessor : public Xapian::FieldProcessor {
323 int r;
324 lua_State* L;
326 public:
327 luaFieldProcessor(lua_State* S) {
328 L = 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)) {
353 size_t len;
354 const char * p = lua_tolstring(L, -1, &len);
355 std::string result(p, len);
356 lua_pop(L, 1);
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) {
364 lua_pop(L, 1);
365 luaL_error(L, "function must return a string or Query object");
368 lua_pop(L, 1);
369 return *subq;
375 class luaMatchSpy : public Xapian::MatchSpy {
376 int r;
377 lua_State* L;
379 public:
380 luaMatchSpy(lua_State* S) {
381 L = S;
382 if (!lua_isfunction(L, -1)) {
383 luaL_typerror(L, -1, "function");
385 r = luaL_ref(L, LUA_REGISTRYINDEX);
388 ~luaMatchSpy() {
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 * {
410 void *ptr;
411 if (lua_isfunction(L, $input) || (SWIG_isptrtype(L, $input) && !SWIG_ConvertPtr(L, $input, (void **) &ptr, $descriptor(NS::CLASS *), 0))) {
412 $1 = 1;
413 } else {
414 $1 = 0;
417 %typemap(in) NS::CLASS * {
418 if (lua_isfunction(L, $input)) {
419 $1 = new lua##CLASS(L);
420 } else {
421 if (!SWIG_IsOK(SWIG_ConvertPtr(L, $input, (void**)&$1, $descriptor(NS::CLASS *), 0))) {
422 SWIG_fail;
427 %enddef
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)
438 %luacode {
439 function xapian.Iterator(begin, _end)
440 local iter = begin;
441 local isFirst = 1
442 return function()
443 if iter:equals(_end) then
444 return nil
445 else
446 if isFirst == 1 then
447 isFirst = 0;
448 return iter
449 else
450 iter:next()
451 if iter:equals(_end) then
452 return nil
454 return iter
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 {
471 lua_State* L;
472 int index;
473 int i;
475 public:
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_) {
485 L = S;
486 index = index_;
487 i = 0;
490 void end(lua_State * S, int index_, int n) {
491 L = S;
492 index = index_;
493 i = n;
496 void end() {
497 i = 0;
500 XapianSWIGQueryItor & operator++() {
501 ++i;
502 return *this;
505 Xapian::Query operator*() const {
506 lua_rawgeti(L, index, i+1);
507 if (lua_isstring(L, -1)) {
508 size_t len = 0;
509 const char *p = lua_tolstring(L, -1, &len);
510 lua_pop(L,1);
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) {
518 lua_pop(L, 1);
519 luaL_argerror(L, index,
520 "elements must be Query objects or strings");
523 lua_pop(L, 1);
524 return *subq;
527 bool operator==(const XapianSWIGQueryItor & o) {
528 return i == o.i;
531 bool operator!=(const XapianSWIGQueryItor & o) {
532 return !(*this == o);
535 difference_type operator-(const XapianSWIGQueryItor &o) const {
536 return i - o.i;
542 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
543 if (lua_istable(L, $input)) {
544 $1.begin(L, $input);
545 $2.end(L, $input, lua_rawlen(L, $input));
546 } else {
547 $1.end();
548 $2.end();
552 %define OUTPUT_ITERATOR_METHODS(NS, CLASS, ITERATOR_CLASS, ITERATOR_BEGIN, ITERATOR_END, DEREF_METHOD, PARAMETER_NAME, PARAMETER_VALUE)
554 %extend NS::CLASS {
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");
563 lua_gettable(L, -2);
564 lua_remove(L, -2);
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));
580 SWIG_arg++;
583 %enddef
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");
621 lua_gettable(L, -2);
622 lua_remove(L, -2);
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));
638 SWIG_arg++;