Fix unittest to build when getting UUIDs from /proc
[xapian.git] / xapian-bindings / lua / util.i
blob9221789ca371974930c3fa7ad34c265f52557c18
1 /* lua/util.i: custom lua typemaps for xapian-bindings
3 * Copyright (C) 2011 Xiaona Han
4 * Copyright (C) 2011,2012,2017 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;
28 #if LUA_VERSION_NUM-0 >= 502
29 // luaL_typerror was removed in Lua 5.2.
30 int luaL_typerror (lua_State *L, int narg, const char *tname) {
31 const char *msg = lua_pushfstring(L, "%s expected, got %s",
32 tname, luaL_typename(L, narg));
33 return luaL_argerror(L, narg, msg);
35 #endif
38 %define SUB_CLASS(NS, CLASS)
40 class lua##CLASS : public NS::CLASS {
41 int r;
42 lua_State* L;
44 public:
45 lua##CLASS(lua_State* S) {
46 L = S;
47 if (!lua_isfunction(L, -1)) {
48 luaL_typerror(L, -1, "function");
50 r = luaL_ref(L, LUA_REGISTRYINDEX);
53 ~lua##CLASS() {
54 luaL_unref(L, LUA_REGISTRYINDEX, r);
57 bool operator()(const std::string &term) const {
58 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
59 if (!lua_isfunction(L, -1)) {
60 luaL_typerror(L, -1, "function");
63 lua_pushlstring(L, (char *)term.c_str(), term.length());
64 if (lua_pcall(L, 1, 1, 0) != 0) {
65 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
67 if (!lua_isboolean(L, -1)) {
68 luaL_error(L, "function must return a boolean");
70 bool result = lua_toboolean(L, -1);
71 lua_pop(L, 1);
72 return result;
77 %enddef
79 SUB_CLASS(Xapian, ExpandDecider)
80 SUB_CLASS(Xapian, Stopper)
83 class luaMatchDecider : public Xapian::MatchDecider {
84 int r;
85 lua_State* L;
87 public:
88 luaMatchDecider(lua_State* S) {
89 L = S;
90 if (!lua_isfunction(L, -1)) {
91 luaL_typerror(L, -1, "function");
93 r = luaL_ref(L, LUA_REGISTRYINDEX);
96 ~luaMatchDecider() {
97 luaL_unref(L, LUA_REGISTRYINDEX, r);
100 bool operator()(const Xapian::Document &doc) const {
101 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
102 if (!lua_isfunction(L, -1)) {
103 luaL_typerror(L, -1, "function");
106 SWIG_NewPointerObj(L, &doc, SWIGTYPE_p_Xapian__Document, 0);
107 if (lua_pcall(L, 1, 1, 0) != 0) {
108 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
110 if (!lua_isboolean(L, -1)) {
111 luaL_error(L, "function must return a boolean");
113 bool result = lua_toboolean(L, -1);
114 lua_pop(L, 1);
115 return result;
121 class luaStemImplementation : public Xapian::StemImplementation {
122 int r;
123 lua_State* L;
125 public:
126 luaStemImplementation(lua_State* S) {
127 L = S;
128 if (!lua_isfunction(L, -1)) {
129 luaL_typerror(L, -1, "function");
131 r = luaL_ref(L, LUA_REGISTRYINDEX);
134 ~luaStemImplementation() {
135 luaL_unref(L, LUA_REGISTRYINDEX, r);
138 std::string operator()(const std::string &word) {
139 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
140 if (!lua_isfunction(L, -1)) {
141 luaL_typerror(L, -1, "function");
144 lua_pushlstring(L, (char *)word.c_str(), word.length());
145 if (lua_pcall(L, 1, 1, 0) != 0) {
146 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
148 if (!lua_isstring(L, -1)) {
149 luaL_error(L, "function must return a string");
151 size_t len;
152 const char * p = lua_tolstring(L, -1, &len);
153 std::string result(p, len);
154 lua_pop(L, 1);
155 return result;
158 std::string get_description() const {
159 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
160 if (!lua_isfunction(L, -1)) {
161 luaL_typerror(L, -1, "function");
164 if (lua_pcall(L, 0, 1, 0) != 0) {
165 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
167 if (!lua_isstring(L, -1)) {
168 luaL_error(L, "function must return a string");
171 size_t len;
172 const char * p = lua_tolstring(L, -1, &len);
173 std::string result(p, len);
174 lua_pop(L, 1);
175 return result;
181 class luaKeyMaker : public Xapian::KeyMaker {
182 int r;
183 lua_State* L;
185 public:
186 luaKeyMaker(lua_State* S) {
187 L = S;
188 if (!lua_isfunction(L, -1)) {
189 luaL_typerror(L, -1, "function");
191 r = luaL_ref(L, LUA_REGISTRYINDEX);
194 ~luaKeyMaker() {
195 luaL_unref(L, LUA_REGISTRYINDEX, r);
198 std::string operator()(const Xapian::Document &doc) const {
199 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
200 if (!lua_isfunction(L, -1)) {
201 luaL_typerror(L, -1, "function");
204 SWIG_NewPointerObj(L, &doc, SWIGTYPE_p_Xapian__Document, 0);
205 if (lua_pcall(L, 1, 1, 0) != 0) {
206 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
208 if (!lua_isstring(L, -1)) {
209 luaL_error(L, "function must return a string");
211 size_t len;
212 const char * p = lua_tolstring(L, -1, &len);
213 std::string result(p, len);
214 lua_pop(L, 1);
215 return result;
221 class luaRangeProcessor : public Xapian::RangeProcessor {
222 int r;
223 lua_State* L;
225 public:
226 luaRangeProcessor(lua_State* S) {
227 L = S;
228 if (!lua_isfunction(L, -1)) {
229 luaL_typerror(L, -1, "function");
231 r = luaL_ref(L, LUA_REGISTRYINDEX);
234 ~luaRangeProcessor() {
235 luaL_unref(L, LUA_REGISTRYINDEX, r);
238 Xapian::Query operator()(const std::string& begin, const std::string& end) {
239 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
240 if (!lua_isfunction(L, -1)) {
241 luaL_typerror(L, -1, "function");
244 lua_pushlstring(L, (char *)begin.c_str(), begin.length());
245 lua_pushlstring(L, (char *)end.c_str(), end.length());
247 if (lua_pcall(L, 2, 1, 0) != 0) {
248 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
251 // Allow the function to return a string or Query object.
252 if (lua_isstring(L, -1)) {
253 size_t len;
254 const char * p = lua_tolstring(L, -1, &len);
255 std::string result(p, len);
256 lua_pop(L, 1);
257 return Xapian::Query(result);
260 Xapian::Query *subq = 0;
261 if (!lua_isuserdata(L, -1) ||
262 SWIG_ConvertPtr(L, -1, (void **)&subq,
263 SWIGTYPE_p_Xapian__Query, 0) == -1) {
264 lua_pop(L, 1);
265 luaL_error(L, "function must return a string or Query object");
268 lua_pop(L, 1);
269 return *subq;
275 class luaValueRangeProcessor : public Xapian::ValueRangeProcessor {
276 int r;
277 lua_State* L;
279 public:
280 luaValueRangeProcessor(lua_State* S) {
281 L = S;
282 if (!lua_isfunction(L, -1)) {
283 luaL_typerror(L, -1, "function");
285 r = luaL_ref(L, LUA_REGISTRYINDEX);
288 ~luaValueRangeProcessor() {
289 luaL_unref(L, LUA_REGISTRYINDEX, r);
292 Xapian::valueno operator()(std::string &begin, std::string &end) {
293 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
294 if (!lua_isfunction(L, -1)) {
295 luaL_typerror(L, -1, "function");
298 lua_pushlstring(L, (char *)begin.c_str(), begin.length());
299 lua_pushlstring(L, (char *)end.c_str(), end.length());
301 if (lua_pcall(L, 2, 1, 0) != 0) {
302 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
304 if (!lua_isnumber(L, -1)) {
305 luaL_error(L, "function must return a number");
307 Xapian::valueno result(lua_tonumber(L, -1));
308 lua_pop(L, 1);
309 return result;
315 class luaFieldProcessor : public Xapian::FieldProcessor {
316 int r;
317 lua_State* L;
319 public:
320 luaFieldProcessor(lua_State* S) {
321 L = S;
322 if (!lua_isfunction(L, -1)) {
323 luaL_typerror(L, -1, "function");
325 r = luaL_ref(L, LUA_REGISTRYINDEX);
328 ~luaFieldProcessor() {
329 luaL_unref(L, LUA_REGISTRYINDEX, r);
332 Xapian::Query operator()(const std::string &str) {
333 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
334 if (!lua_isfunction(L, -1)) {
335 luaL_typerror(L, -1, "function");
338 lua_pushlstring(L, (char *)str.c_str(), str.length());
340 if (lua_pcall(L, 1, 1, 0) != 0) {
341 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
344 // Allow the function to return a string or Query object.
345 if (lua_isstring(L, -1)) {
346 size_t len;
347 const char * p = lua_tolstring(L, -1, &len);
348 std::string result(p, len);
349 lua_pop(L, 1);
350 return Xapian::Query(result);
353 Xapian::Query *subq = 0;
354 if (!lua_isuserdata(L, -1) ||
355 SWIG_ConvertPtr(L, -1, (void **)&subq,
356 SWIGTYPE_p_Xapian__Query, 0) == -1) {
357 lua_pop(L, 1);
358 luaL_error(L, "function must return a string or Query object");
361 lua_pop(L, 1);
362 return *subq;
368 class luaMatchSpy : public Xapian::MatchSpy {
369 int r;
370 lua_State* L;
372 public:
373 luaMatchSpy(lua_State* S) {
374 L = S;
375 if (!lua_isfunction(L, -1)) {
376 luaL_typerror(L, -1, "function");
378 r = luaL_ref(L, LUA_REGISTRYINDEX);
381 ~luaMatchSpy() {
382 luaL_unref(L, LUA_REGISTRYINDEX, r);
385 void operator()(const Xapian::Document &doc, double wt) {
386 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
387 if (!lua_isfunction(L, -1)) {
388 luaL_typerror(L, -1, "function");
391 SWIG_NewPointerObj(L, &doc, SWIGTYPE_p_Xapian__Document, 0);
392 SWIG_NewPointerObj(L, &wt, SWIGTYPE_p_Xapian__Weight, 0);
393 if (lua_pcall(L, 2, 1, 0) != 0) {
394 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
400 %define SUB_CLASS_TYPEMAPS(NS, CLASS)
402 %typemap(typecheck, precedence=100) NS::CLASS * {
403 void *ptr;
404 if (lua_isfunction(L, $input) || (SWIG_isptrtype(L, $input) && !SWIG_ConvertPtr(L, $input, (void **) &ptr, $descriptor(NS::CLASS *), 0))) {
405 $1 = 1;
406 } else {
407 $1 = 0;
410 %typemap(in) NS::CLASS * {
411 if (lua_isfunction(L, $input)) {
412 $1 = new lua##CLASS(L);
413 } else {
414 if (!SWIG_IsOK(SWIG_ConvertPtr(L, $input, (void**)&$1, $descriptor(NS::CLASS *), 0))) {
415 SWIG_fail;
420 %enddef
421 SUB_CLASS_TYPEMAPS(Xapian, MatchDecider)
422 SUB_CLASS_TYPEMAPS(Xapian, ExpandDecider)
423 SUB_CLASS_TYPEMAPS(Xapian, Stopper)
424 SUB_CLASS_TYPEMAPS(Xapian, StemImplementation)
425 SUB_CLASS_TYPEMAPS(Xapian, KeyMaker)
426 SUB_CLASS_TYPEMAPS(Xapian, RangeProcessor)
427 SUB_CLASS_TYPEMAPS(Xapian, ValueRangeProcessor)
428 SUB_CLASS_TYPEMAPS(Xapian, FieldProcessor)
430 %luacode {
431 function xapian.Iterator(begin, _end)
432 local iter = begin;
433 local isFirst = 1
434 return function()
435 if iter:equals(_end) then
436 return nil
437 else
438 if isFirst == 1 then
439 isFirst = 0;
440 return iter
441 else
442 iter:next()
443 if iter:equals(_end) then
444 return nil
446 return iter
453 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
455 %typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
456 $1 = lua_istable(L, $input);
457 /* FIXME: if we add more array typemaps, we'll need to check the elements
458 * of the array here to disambiguate. */
462 class XapianSWIGQueryItor {
463 lua_State* L;
464 int index;
465 int i;
467 public:
468 typedef std::random_access_iterator_tag iterator_category;
469 typedef Xapian::Query value_type;
470 typedef Xapian::termcount_diff difference_type;
471 typedef Xapian::Query * pointer;
472 typedef Xapian::Query & reference;
474 XapianSWIGQueryItor() { }
476 void begin(lua_State * S, int index_) {
477 L = S;
478 index = index_;
479 i = 0;
482 void end(lua_State * S, int index_, int n) {
483 L = S;
484 index = index_;
485 i = n;
488 void end() {
489 i = 0;
492 XapianSWIGQueryItor & operator++() {
493 ++i;
494 return *this;
497 Xapian::Query operator*() const {
498 lua_rawgeti(L, index, i+1);
499 if (lua_isstring(L, -1)) {
500 size_t len = 0;
501 const char *p = lua_tolstring(L, -1, &len);
502 lua_pop(L,1);
503 return Xapian::Query(string(p, len));
506 Xapian::Query *subq = 0;
507 if (!lua_isuserdata(L, -1) ||
508 SWIG_ConvertPtr(L, -1, (void **)&subq,
509 SWIGTYPE_p_Xapian__Query, 0) == -1) {
510 lua_pop(L, 1);
511 luaL_argerror(L, index,
512 "elements must be Query objects or strings");
515 lua_pop(L, 1);
516 return *subq;
519 bool operator==(const XapianSWIGQueryItor & o) {
520 return i == o.i;
523 bool operator!=(const XapianSWIGQueryItor & o) {
524 return !(*this == o);
527 difference_type operator-(const XapianSWIGQueryItor &o) const {
528 return i - o.i;
534 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
535 if (lua_istable(L, $input)) {
536 $1.begin(L, $input);
537 $2.end(L, $input, lua_rawlen(L, $input));
538 } else {
539 $1.end();
540 $2.end();
544 %define OUTPUT_ITERATOR_METHODS(NS, CLASS, ITERATOR_CLASS, ITERATOR_BEGIN, ITERATOR_END, DEREF_METHOD, PARAMETER_NAME, PARAMETER_VALUE)
546 %extend NS::CLASS {
547 std::pair<NS::ITERATOR_CLASS , NS::ITERATOR_CLASS> DEREF_METHOD(PARAMETER_NAME) {
548 return std::make_pair($self->ITERATOR_BEGIN(PARAMETER_VALUE), $self->ITERATOR_END(PARAMETER_VALUE));
552 %typemap(out) std::pair<NS::ITERATOR_CLASS, NS::ITERATOR_CLASS> {
553 lua_getglobal(L, "xapian");
554 lua_pushstring(L, "Iterator");
555 lua_gettable(L, -2);
556 lua_remove(L, -2);
558 if (!lua_isfunction(L, -1)) {
559 luaL_typerror(L, -1, "function");
562 NS::ITERATOR_CLASS * begin = new NS::ITERATOR_CLASS((const NS::ITERATOR_CLASS &)$1.first);
563 SWIG_NewPointerObj(L, (void *) begin, $descriptor(NS::ITERATOR_CLASS *), 1);
565 NS::ITERATOR_CLASS * end = new NS::ITERATOR_CLASS((const NS::ITERATOR_CLASS &)$1.second);
566 SWIG_NewPointerObj(L, (void *) end, $descriptor(NS::ITERATOR_CLASS *), 1);
568 if (lua_pcall(L, 2, 1, 0) != 0) {
569 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
572 SWIG_arg++;
575 %enddef
577 OUTPUT_ITERATOR_METHODS(Xapian, Query, TermIterator, get_terms_begin, get_terms_end, get_terms, void, )
579 OUTPUT_ITERATOR_METHODS(Xapian, QueryParser, TermIterator, stoplist_begin, stoplist_end, stoplist, void, )
581 OUTPUT_ITERATOR_METHODS(Xapian, ESet, ESetIterator, begin, end, terms, void, )
583 OUTPUT_ITERATOR_METHODS(Xapian, MSet, MSetIterator, begin, end, items, void, )
585 OUTPUT_ITERATOR_METHODS(Xapian, Document, TermIterator, termlist_begin, termlist_end, termlist, void, )
586 OUTPUT_ITERATOR_METHODS(Xapian, Document, ValueIterator, values_begin, values_end, values, void, )
588 OUTPUT_ITERATOR_METHODS(Xapian, Enquire, TermIterator, get_matching_terms_begin, get_matching_terms_end, get_matching_terms, Xapian::docid did, did)
589 OUTPUT_ITERATOR_METHODS(Xapian, Enquire, TermIterator, get_matching_terms_begin, get_matching_terms_end, get_matching_terms, const MSetIterator &it, it)
591 OUTPUT_ITERATOR_METHODS(Xapian, ValueCountMatchSpy, TermIterator, values_begin, values_end, values, void, )
592 OUTPUT_ITERATOR_METHODS(Xapian, ValueCountMatchSpy, TermIterator, top_values_begin, top_values_end, top_values, size_t maxvalues, maxvalues)
594 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, allterms_begin, allterms_end, allterms, void, )
595 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, spellings_begin, spellings_end, spellings, void, )
596 OUTPUT_ITERATOR_METHODS(Xapian, Database, PostingIterator, postlist_begin, postlist_end, postlist, const std::string &tname, tname)
597 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, termlist_begin, termlist_end, termlist, Xapian::docid did, did)
598 OUTPUT_ITERATOR_METHODS(Xapian, Database, ValueIterator, valuestream_begin, valuestream_end, valuestream, Xapian::valueno slot, slot)
599 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, allterms_begin, allterms_end, allterms, const std::string &prefix, prefix)
600 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, synonyms_begin, synonyms_end, synonyms, const std::string &term, term)
601 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, synonym_keys_begin, synonym_keys_end, synonym_keys, const std::string &prefix, prefix)
602 OUTPUT_ITERATOR_METHODS(Xapian, Database, TermIterator, metadata_keys_begin, metadata_keys_end, metadata_keys, const std::string &prefix, prefix)
604 %extend Xapian::Database {
605 std::pair<Xapian::PositionIterator , Xapian::PositionIterator> positionlist(Xapian::docid did, const std::string &tname) {
606 return std::make_pair($self->positionlist_begin(did, tname), $self->positionlist_end(did, tname));
610 %typemap(out) std::pair<Xapian::PositionIterator, Xapian::PositionIterator> {
611 lua_getglobal(L, "xapian");
612 lua_pushstring(L, "Iterator");
613 lua_gettable(L, -2);
614 lua_remove(L, -2);
616 if (!lua_isfunction(L, -1)) {
617 luaL_typerror(L, -1, "function");
620 Xapian::PositionIterator * begin = new Xapian::PositionIterator((const Xapian::PositionIterator &)$1.first);
621 SWIG_NewPointerObj(L, (void *) begin, SWIGTYPE_p_Xapian__PositionIterator, 1);
623 Xapian::PositionIterator * end = new Xapian::PositionIterator((const Xapian::PositionIterator &)$1.second);
624 SWIG_NewPointerObj(L, (void *) end, SWIGTYPE_p_Xapian__PositionIterator, 1);
626 if (lua_pcall(L, 2, 1, 0) != 0) {
627 luaL_error(L, "error running function: %s", lua_tostring(L, -1));
630 SWIG_arg++;