Cache compiled regexps used in $transform
[xapian.git] / xapian-bindings / python / util.i
blobafb75822bf196217f4948d852b2129858447f73d
1 %{
2 /* python/util.i: custom Python typemaps for xapian-bindings
4 * Copyright (C) 1999,2000,2001 BrightStation PLC
5 * Copyright (C) 2002 Ananova Ltd
6 * Copyright (C) 2002,2003 James Aylett
7 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2013 Olly Betts
8 * Copyright (C) 2007 Lemur Consulting Ltd
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
23 * USA
27 %include typemaps.i
28 %include stl.i
30 /* Wrap get_description() methods as str(). */
31 %rename(__str__) get_description;
33 /* Hide "unsafe" C++ iterator methods. */
34 %rename(_allterms_begin) Xapian::Database::allterms_begin;
35 %rename(_allterms_end) Xapian::Database::allterms_end;
36 %rename(_metadata_keys_begin) Xapian::Database::metadata_keys_begin;
37 %rename(_metadata_keys_end) Xapian::Database::metadata_keys_end;
38 %rename(_synonym_keys_begin) Xapian::Database::synonym_keys_begin;
39 %rename(_synonym_keys_end) Xapian::Database::synonym_keys_end;
40 %rename(_synonyms_begin) Xapian::Database::synonyms_begin;
41 %rename(_synonyms_end) Xapian::Database::synonyms_end;
42 %rename(_spellings_begin) Xapian::Database::spellings_begin;
43 %rename(_spellings_end) Xapian::Database::spellings_end;
44 %rename(_positionlist_begin) Xapian::Database::positionlist_begin;
45 %rename(_positionlist_end) Xapian::Database::positionlist_end;
46 %rename(_postlist_begin) Xapian::Database::postlist_begin;
47 %rename(_postlist_end) Xapian::Database::postlist_end;
48 %rename(_termlist_begin) Xapian::Database::termlist_begin;
49 %rename(_termlist_end) Xapian::Database::termlist_end;
50 %rename(_termlist_begin) Xapian::Document::termlist_begin;
51 %rename(_termlist_end) Xapian::Document::termlist_end;
52 %rename(_values_begin) Xapian::Document::values_begin;
53 %rename(_values_end) Xapian::Document::values_end;
54 %rename(_get_matching_terms_begin) Xapian::Enquire::get_matching_terms_begin;
55 %rename(_get_matching_terms_end) Xapian::Enquire::get_matching_terms_end;
56 %rename(_begin) Xapian::ESet::begin;
57 %rename(_end) Xapian::ESet::end;
58 %rename(_begin) Xapian::MSet::begin;
59 %rename(_end) Xapian::MSet::end;
60 %rename(_positionlist_begin) Xapian::PostingIterator::positionlist_begin;
61 %rename(_positionlist_end) Xapian::PostingIterator::positionlist_end;
62 %rename(_get_terms_begin) Xapian::Query::get_terms_begin;
63 %rename(_get_terms_end) Xapian::Query::get_terms_end;
64 %rename(_stoplist_begin) Xapian::QueryParser::stoplist_begin;
65 %rename(_stoplist_end) Xapian::QueryParser::stoplist_end;
66 %rename(_unstem_begin) Xapian::QueryParser::unstem_begin;
67 %rename(_unstem_end) Xapian::QueryParser::unstem_end;
68 %rename(_positionlist_begin) Xapian::TermIterator::positionlist_begin;
69 %rename(_positionlist_end) Xapian::TermIterator::positionlist_end;
71 /* We replace the get_hit() method with one which returns an MSetitem. */
72 %rename(_get_hit_internal) Xapian::MSet::get_hit;
74 /* Force xapian.BAD_VALUENO to be handled as a constant rather than a
75 * read-only variable (ticket#297).
77 %ignore Xapian::BAD_VALUENO;
78 %constant Xapian::valueno BAD_VALUENO = Xapian::BAD_VALUENO;
81 namespace Xapian {
82 Query *get_py_query(PyObject *obj) {
83 #if PY_VERSION_HEX < 0x02050000
84 // In Python 2.4 (and presumably earlier), PyObject_GetAttrString()
85 // takes a char* parameter which causes a warning with GCC >= 4.2.
86 // This is fixed in Python 2.5.
87 PyObject * mythis = PyObject_GetAttrString(obj, (char *)"this");
88 #else
89 PyObject * mythis = PyObject_GetAttrString(obj, "this");
90 #endif
91 if (!mythis)
92 return 0;
94 Query * retval = 0;
95 int res = SWIG_ConvertPtr(mythis, (void **)&retval,
96 SWIGTYPE_p_Xapian__Query, 0);
97 if (!SWIG_IsOK(res)) {
98 retval = 0;
100 Py_DECREF(mythis);
101 return retval;
106 %typedef PyObject *LangSpecificListType;
108 %inline %{
109 #define MSET_DID 0
110 #define MSET_WT 1
111 #define MSET_RANK 2
112 #define MSET_PERCENT 3
113 #define MSET_DOCUMENT 4
115 #define ESET_TNAME 0
116 #define ESET_WT 1
119 %feature("nothread") Xapian::MSet::items;
121 /* The GIL must be held when this is called. */
122 PyObject *Xapian_MSet_items_get(Xapian::MSet *mset)
124 PyObject *retval = PyList_New(mset->size());
125 if (retval == 0) {
126 return NULL;
129 Py_ssize_t idx = 0;
130 for (Xapian::MSetIterator i = mset->begin(); i != mset->end(); ++i) {
131 PyObject *t = PyTuple_New(4);
132 if (!t) {
133 Py_DECREF(retval);
134 return NULL;
137 PyList_SET_ITEM(retval, idx++, t);
139 PyTuple_SET_ITEM(t, MSET_DID, PyInt_FromLong(*i));
140 PyTuple_SET_ITEM(t, MSET_WT, PyFloat_FromDouble(i.get_weight()));
141 PyTuple_SET_ITEM(t, MSET_RANK, PyInt_FromLong(i.get_rank()));
142 PyTuple_SET_ITEM(t, MSET_PERCENT, PyInt_FromLong(i.get_percent()));
144 return retval;
148 %feature("nothread") Xapian::ESet::items;
150 /* The GIL must be held when this is called. */
151 PyObject *Xapian_ESet_items_get(Xapian::ESet *eset)
153 PyObject *retval = PyList_New(eset->size());
154 if (retval == 0) {
155 return NULL;
158 Py_ssize_t idx = 0;
159 for (Xapian::ESetIterator i = eset->begin(); i != eset->end(); ++i) {
160 PyObject *t = PyTuple_New(2);
161 if (!t) {
162 Py_DECREF(retval);
163 return NULL;
166 PyList_SET_ITEM(retval, idx++, t);
168 PyObject * str = PyString_FromStringAndSize((*i).data(), (*i).size());
169 if (str == 0) {
170 Py_DECREF(retval);
171 return NULL;
174 PyTuple_SET_ITEM(t, ESET_TNAME, str);
175 PyTuple_SET_ITEM(t, ESET_WT, PyFloat_FromDouble(i.get_weight()));
177 return retval;
181 namespace Xapian {
182 %extend TermIterator {
183 bool __eq__(const TermIterator &other) {
184 return (*self)==other;
186 bool __ne__(const TermIterator &other) {
187 return (*self)!=other;
190 %rename(_TermIterator) TermIterator;
192 %extend PositionIterator {
193 bool __eq__(const PositionIterator &other) {
194 return (*self)==other;
196 bool __ne__(const PositionIterator &other) {
197 return (*self)!=other;
200 %rename(_PositionIterator) PositionIterator;
202 %extend PostingIterator {
203 bool __eq__(const PostingIterator &other) {
204 return (*self)==other;
206 bool __ne__(const PostingIterator &other) {
207 return (*self)!=other;
210 %rename(_PostingIterator) PostingIterator;
212 %extend ValueIterator {
213 bool __eq__(const ValueIterator &other) {
214 return (*self)==other;
216 bool __ne__(const ValueIterator &other) {
217 return (*self)!=other;
220 %rename(_ValueIterator) ValueIterator;
222 %extend MSetIterator {
223 bool __eq__(const MSetIterator &other) {
224 return (*self)==other;
226 bool __ne__(const MSetIterator &other) {
227 return (*self)!=other;
230 %rename(_MSetIterator) MSetIterator;
232 %extend ESetIterator {
233 bool __eq__(const ESetIterator &other) {
234 return (*self)==other;
236 bool __ne__(const ESetIterator &other) {
237 return (*self)!=other;
240 %rename(_ESetIterator) ESetIterator;
242 %extend MSet {
243 %immutable;
244 // access to the items array
245 PyObject *items;
246 %mutable;
248 // for comparison
249 int __cmp__(const MSet &other) {
250 if (self->get_max_possible() != other.get_max_possible()) {
251 return (self->get_max_possible() < other.get_max_possible())? -1 : 1;
253 if (self->size() != other.size()) {
254 return (self->size() < other.size())? -1 : 1;
257 for (size_t i=0; i<self->size(); ++i) {
258 if (*(*self)[i] != *other[i]) {
259 return (*(*self)[i] < *other[i])? -1 : 1;
261 if ((*self)[i].get_weight() != other[i].get_weight()) {
262 return ((*self)[i].get_weight() < other[i].get_weight())? -1 : 1;
265 return 0;
269 //%apply LangSpecificListType items { PyObject *items }
271 %extend ESet {
272 %immutable;
273 PyObject *items;
274 %mutable;
278 %fragment("XapianSWIG_anystring_as_ptr", "header", fragment="SWIG_AsPtr_std_string") {
279 /* Utility function which works like SWIG_AsPtr_std_string, but
280 * converts unicode strings to UTF-8 simple strings first. */
281 static int
282 XapianSWIG_anystring_as_ptr(PyObject ** obj, std::string **val)
284 if (PyUnicode_Check(*obj)) {
285 PyObject * strobj = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(*obj), PyUnicode_GET_SIZE(*obj), "ignore");
286 if (strobj == NULL) return SWIG_ERROR;
287 int res = SWIG_AsPtr_std_string(strobj, val);
288 Py_DECREF(strobj);
289 return res;
290 } else {
291 return SWIG_AsPtr_std_string(*obj, val);
296 /* These typemaps depends somewhat heavily on the internals of SWIG, so
297 * might break with future versions of SWIG.
299 %typemap(in, fragment="XapianSWIG_anystring_as_ptr") const std::string &(int res = SWIG_OLDOBJ) {
300 std::string *ptr = (std::string *)0;
301 res = XapianSWIG_anystring_as_ptr(&($input), &ptr);
302 if (!SWIG_IsOK(res)) {
303 %argument_fail(res, "$type", $symname, $argnum);
305 if (!ptr) {
306 %argument_nullref("$type", $symname, $argnum);
308 $1 = ptr;
310 %typemap(in, fragment="XapianSWIG_anystring_as_ptr") std::string {
311 std::string *ptr = (std::string *)0;
312 int res = XapianSWIG_anystring_as_ptr(&($input), &ptr);
313 if (!SWIG_IsOK(res) || !ptr) {
314 %argument_fail((ptr ? res : SWIG_TypeError), "$type", $symname, $argnum);
316 $1 = *ptr;
317 if (SWIG_IsNewObj(res)) delete ptr;
319 %typemap(freearg, noblock=1, match="in") const std::string & {
320 if (SWIG_IsNewObj(res$argnum)) %delete($1);
322 %typemap(typecheck, noblock=1, precedence=900, fragment="XapianSWIG_anystring_as_ptr") const std::string & {
323 int res = XapianSWIG_anystring_as_ptr(&($input), (std::string**)(0));
324 $1 = SWIG_CheckState(res);
327 /* This typemap is only currently needed for returning a value from the
328 * get_description() method of a Stopper subclass to a C++ caller, but might be
329 * more generally useful in future.
331 %typemap(directorout, noblock=1, fragment="XapianSWIG_anystring_as_ptr") std::string {
332 std::string *swig_optr = 0;
333 int swig_ores;
335 PyObject * tmp = $input;
336 Py_INCREF(tmp);
337 swig_ores = XapianSWIG_anystring_as_ptr(&tmp, &swig_optr);
338 Py_DECREF(tmp);
340 if (!SWIG_IsOK(swig_ores) || !swig_optr) {
341 %dirout_fail((swig_optr ? swig_ores : SWIG_TypeError), "$type");
343 $result = *swig_optr;
344 if (SWIG_IsNewObj(swig_ores)) %delete(swig_optr);
347 /** This pair of typemaps implements conversion of the return value of
348 * ValueRangeProcessor subclasses implemented in Python from a tuple of
349 * (valueno, begin, end) to a return value of valueno, and assigning the new
350 * values of begin and end to the parameters.
352 %typemap(directorin,noblock=1) std::string & {
353 $input = SWIG_From_std_string(static_cast< std::string >($1_name));
355 %typemap(directorout,noblock=1) Xapian::valueno {
356 if (!PyTuple_Check($input)) {
357 %dirout_fail(SWIG_TypeError, "($type, std::string, std::string)");
359 if (PyTuple_Size($input) != 3) {
360 %dirout_fail(SWIG_IndexError, "($type, std::string, std::string)");
363 // Set the return value from the first item of the tuple.
364 unsigned int swig_val;
365 int swig_res = SWIG_AsVal_unsigned_SS_int(PyTuple_GET_ITEM((PyObject *)$input, 0), &swig_val);
366 if (!SWIG_IsOK(swig_res)) {
367 %dirout_fail(swig_res, "($type, std::string, std::string)");
369 c_result = static_cast< Xapian::valueno >(swig_val);
371 // Set "begin" from the second item of the tuple.
372 std::string *ptr = (std::string *)0;
373 swig_res = SWIG_AsPtr_std_string(PyTuple_GET_ITEM((PyObject *)$input, 1), &ptr);
374 if (!SWIG_IsOK(swig_res) || !ptr) {
375 delete ptr;
376 ptr = (std::string *)0;
377 %dirout_fail((ptr ? swig_res : SWIG_TypeError), "($type, std::string, std::string)");
379 begin = *ptr;
380 delete ptr;
381 ptr = (std::string *)0;
383 // Set "end" from the third item of the tuple.
384 swig_res = SWIG_AsPtr_std_string(PyTuple_GET_ITEM((PyObject *)$input, 2), &ptr);
385 if (!SWIG_IsOK(swig_res) || !ptr) {
386 delete ptr;
387 ptr = (std::string *)0;
388 %dirout_fail((ptr ? swig_res : SWIG_TypeError), "($type, std::string, std::string)");
390 end = *ptr;
391 delete ptr;
392 ptr = (std::string *)0;
395 /* These typemaps handle ValueRangeProcessors, which take non-const references
396 * to std::string and modify the strings.
398 %typemap(in) std::string &begin (std::string temp),
399 std::string &end (std::string temp) {
400 std::string *ptr = (std::string *)0;
401 int res = SWIG_AsPtr_std_string($input, &ptr);
402 if (!SWIG_IsOK(res) || !ptr) {
403 %argument_fail((ptr ? res : SWIG_TypeError), "$type", $symname, $argnum);
405 temp = *ptr;
406 $1 = &temp;
407 if (SWIG_IsNewObj(res)) delete ptr;
409 %typemap(argout) (std::string &begin, std::string &end) {
410 PyObject * str;
411 PyObject * newresult;
413 // Put the existing result into the first item of a new 3-tuple.
414 newresult = PyTuple_New(3);
415 if (newresult == 0) {
416 Py_DECREF($result);
417 $result = NULL;
418 SWIG_fail;
420 PyTuple_SET_ITEM(newresult, 0, $result);
421 $result = newresult;
423 str = PyString_FromStringAndSize($1->data(), $1->size());
424 if (str == 0) {
425 Py_DECREF($result);
426 $result = NULL;
427 SWIG_fail;
429 PyTuple_SET_ITEM($result, 1, str);
431 str = PyString_FromStringAndSize($2->data(), $2->size());
432 if (str == 0) {
433 Py_DECREF($result);
434 $result = NULL;
435 SWIG_fail;
438 PyTuple_SET_ITEM($result, 2, str);
441 %typemap(directorin) (size_t num_tags, const std::string tags[]) {
442 PyObject * result = PyList_New(num_tags);
443 if (result == 0) {
444 return NULL;
447 for (size_t i = 0; i != num_tags; ++i) {
448 PyObject * str = PyString_FromStringAndSize(tags[i].data(), tags[i].size());
449 if (str == 0) {
450 Py_DECREF(result);
451 return NULL;
454 PyList_SET_ITEM(result, i, str);
456 $input = result;
459 /* vim:set syntax=cpp:set noexpandtab: */