Cache compiled regexps used in $transform
[xapian.git] / xapian-bindings / python3 / util.i
blob703a593572d87bb64485baf4bc856dde67524ba3
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 /* So iterator objects match the Python3 iterator API. */
34 %rename(__next__) next;
36 /* Hide "unsafe" C++ iterator methods. */
37 %rename(_allterms_begin) Xapian::Database::allterms_begin;
38 %rename(_allterms_end) Xapian::Database::allterms_end;
39 %rename(_metadata_keys_begin) Xapian::Database::metadata_keys_begin;
40 %rename(_metadata_keys_end) Xapian::Database::metadata_keys_end;
41 %rename(_synonym_keys_begin) Xapian::Database::synonym_keys_begin;
42 %rename(_synonym_keys_end) Xapian::Database::synonym_keys_end;
43 %rename(_synonyms_begin) Xapian::Database::synonyms_begin;
44 %rename(_synonyms_end) Xapian::Database::synonyms_end;
45 %rename(_spellings_begin) Xapian::Database::spellings_begin;
46 %rename(_spellings_end) Xapian::Database::spellings_end;
47 %rename(_positionlist_begin) Xapian::Database::positionlist_begin;
48 %rename(_positionlist_end) Xapian::Database::positionlist_end;
49 %rename(_postlist_begin) Xapian::Database::postlist_begin;
50 %rename(_postlist_end) Xapian::Database::postlist_end;
51 %rename(_termlist_begin) Xapian::Database::termlist_begin;
52 %rename(_termlist_end) Xapian::Database::termlist_end;
53 %rename(_termlist_begin) Xapian::Document::termlist_begin;
54 %rename(_termlist_end) Xapian::Document::termlist_end;
55 %rename(_values_begin) Xapian::Document::values_begin;
56 %rename(_values_end) Xapian::Document::values_end;
57 %rename(_get_matching_terms_begin) Xapian::Enquire::get_matching_terms_begin;
58 %rename(_get_matching_terms_end) Xapian::Enquire::get_matching_terms_end;
59 %rename(_begin) Xapian::ESet::begin;
60 %rename(_end) Xapian::ESet::end;
61 %rename(_begin) Xapian::MSet::begin;
62 %rename(_end) Xapian::MSet::end;
63 %rename(_positionlist_begin) Xapian::PostingIterator::positionlist_begin;
64 %rename(_positionlist_end) Xapian::PostingIterator::positionlist_end;
65 %rename(_get_terms_begin) Xapian::Query::get_terms_begin;
66 %rename(_get_terms_end) Xapian::Query::get_terms_end;
67 %rename(_stoplist_begin) Xapian::QueryParser::stoplist_begin;
68 %rename(_stoplist_end) Xapian::QueryParser::stoplist_end;
69 %rename(_unstem_begin) Xapian::QueryParser::unstem_begin;
70 %rename(_unstem_end) Xapian::QueryParser::unstem_end;
71 %rename(_positionlist_begin) Xapian::TermIterator::positionlist_begin;
72 %rename(_positionlist_end) Xapian::TermIterator::positionlist_end;
74 /* We replace the get_hit() method with one which returns an MSetitem. */
75 %rename(_get_hit_internal) Xapian::MSet::get_hit;
77 /* Force xapian.BAD_VALUENO to be handled as a constant rather than a
78 * read-only variable (ticket#297).
80 %ignore Xapian::BAD_VALUENO;
81 %constant Xapian::valueno BAD_VALUENO = Xapian::BAD_VALUENO;
84 namespace Xapian {
85 Query *get_py_query(PyObject *obj) {
86 PyObject * mythis = PyObject_GetAttrString(obj, "this");
87 if (!mythis)
88 return 0;
90 Query * retval = 0;
91 int res = SWIG_ConvertPtr(mythis, (void **)&retval,
92 SWIGTYPE_p_Xapian__Query, 0);
93 if (!SWIG_IsOK(res)) {
94 retval = 0;
96 Py_DECREF(mythis);
97 return retval;
102 namespace Xapian {
103 %extend TermIterator {
104 bool __eq__(const TermIterator &other) {
105 return (*self)==other;
107 bool __ne__(const TermIterator &other) {
108 return (*self)!=other;
111 %rename(_TermIterator) TermIterator;
113 %extend PositionIterator {
114 bool __eq__(const PositionIterator &other) {
115 return (*self)==other;
117 bool __ne__(const PositionIterator &other) {
118 return (*self)!=other;
121 %rename(_PositionIterator) PositionIterator;
123 %extend PostingIterator {
124 bool __eq__(const PostingIterator &other) {
125 return (*self)==other;
127 bool __ne__(const PostingIterator &other) {
128 return (*self)!=other;
131 %rename(_PostingIterator) PostingIterator;
133 %extend ValueIterator {
134 bool __eq__(const ValueIterator &other) {
135 return (*self)==other;
137 bool __ne__(const ValueIterator &other) {
138 return (*self)!=other;
141 %rename(_ValueIterator) ValueIterator;
143 %extend MSetIterator {
144 bool __eq__(const MSetIterator &other) {
145 return (*self)==other;
147 bool __ne__(const MSetIterator &other) {
148 return (*self)!=other;
151 %rename(_MSetIterator) MSetIterator;
153 %extend ESetIterator {
154 bool __eq__(const ESetIterator &other) {
155 return (*self)==other;
157 bool __ne__(const ESetIterator &other) {
158 return (*self)!=other;
161 %rename(_ESetIterator) ESetIterator;
163 %extend MSet {
164 // for comparison
165 int __cmp__(const MSet &other) {
166 if (self->get_max_possible() != other.get_max_possible()) {
167 return (self->get_max_possible() < other.get_max_possible())? -1 : 1;
169 if (self->size() != other.size()) {
170 return (self->size() < other.size())? -1 : 1;
173 for (size_t i=0; i<self->size(); ++i) {
174 if (*(*self)[i] != *other[i]) {
175 return (*(*self)[i] < *other[i])? -1 : 1;
177 if ((*self)[i].get_weight() != other[i].get_weight()) {
178 return ((*self)[i].get_weight() < other[i].get_weight())? -1 : 1;
181 return 0;
186 %fragment("XapianSWIG_anystring_as_ptr", "header", fragment="SWIG_AsPtr_std_string") {
187 /* Utility function which works like SWIG_AsPtr_std_string, but
188 * converts unicode strings to UTF-8 simple strings first. */
189 static int
190 XapianSWIG_anystring_as_ptr(PyObject * obj, std::string **val)
192 if (PyUnicode_Check(obj)) {
193 PyObject * strobj = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(obj), PyUnicode_GET_SIZE(obj), "ignore");
194 if (strobj == NULL) return SWIG_ERROR;
195 char *p;
196 Py_ssize_t len;
197 PyBytes_AsStringAndSize(strobj, &p, &len);
198 if (val) *val = new std::string(p, len);
199 Py_DECREF(strobj);
200 return SWIG_OK;
201 } else if (PyBytes_Check(obj)) {
202 char *p;
203 Py_ssize_t len;
204 PyBytes_AsStringAndSize(obj, &p, &len);
205 if (val) *val = new std::string(p, len);
206 return SWIG_OK;
207 } else {
208 return SWIG_AsPtr_std_string(obj, val);
213 /* These typemaps depends somewhat heavily on the internals of SWIG, so
214 * might break with future versions of SWIG.
216 %typemap(in, fragment="XapianSWIG_anystring_as_ptr") const std::string &(int res = SWIG_OLDOBJ) {
217 std::string *ptr = (std::string *)0;
218 res = XapianSWIG_anystring_as_ptr($input, &ptr);
219 if (!SWIG_IsOK(res)) {
220 %argument_fail(res, "$type", $symname, $argnum);
222 if (!ptr) {
223 %argument_nullref("$type", $symname, $argnum);
225 $1 = ptr;
227 %typemap(in, fragment="XapianSWIG_anystring_as_ptr") std::string {
228 std::string *ptr = (std::string *)0;
229 int res = XapianSWIG_anystring_as_ptr($input, &ptr);
230 if (!SWIG_IsOK(res) || !ptr) {
231 %argument_fail((ptr ? res : SWIG_TypeError), "$type", $symname, $argnum);
233 $1 = *ptr;
234 if (SWIG_IsNewObj(res)) delete ptr;
236 %typemap(freearg, noblock=1, match="in") const std::string & {
237 if (SWIG_IsNewObj(res$argnum)) %delete($1);
239 %typemap(typecheck, noblock=1, precedence=900, fragment="XapianSWIG_anystring_as_ptr") const std::string & {
240 if (PyUnicode_Check($input)) {
241 $1 = 1;
242 } else if (PyBytes_Check($input)) {
243 $1 = 1;
244 } else {
245 int res = SWIG_AsPtr_std_string($input, (std::string**)(0));
246 $1 = SWIG_CheckState(res);
250 /* This typemap is only currently needed for returning a value from the
251 * get_description() method of a Stopper subclass to a C++ caller, but might be
252 * more generally useful in future.
254 %typemap(directorout, noblock=1, fragment="XapianSWIG_anystring_as_ptr") std::string {
255 std::string *swig_optr = 0;
256 int swig_ores;
258 PyObject * tmp = $input;
259 Py_INCREF(tmp);
260 swig_ores = XapianSWIG_anystring_as_ptr(tmp, &swig_optr);
261 Py_DECREF(tmp);
263 if (!SWIG_IsOK(swig_ores) || !swig_optr) {
264 %dirout_fail((swig_optr ? swig_ores : SWIG_TypeError), "$type");
266 $result = *swig_optr;
267 if (SWIG_IsNewObj(swig_ores)) %delete(swig_optr);
270 /** This pair of typemaps implements conversion of the return value of
271 * ValueRangeProcessor subclasses implemented in Python from a tuple of
272 * (valueno, begin, end) to a return value of valueno, and assigning the new
273 * values of begin and end to the parameters.
275 %typemap(directorin,noblock=1) std::string & {
276 $input = SWIG_From_std_string(static_cast< std::string >($1_name));
278 %typemap(directorout,noblock=1) Xapian::valueno {
279 if (!PyTuple_Check($input)) {
280 %dirout_fail(SWIG_TypeError, "($type, std::string, std::string)");
282 if (PyTuple_Size($input) != 3) {
283 %dirout_fail(SWIG_IndexError, "($type, std::string, std::string)");
286 // Set the return value from the first item of the tuple.
287 unsigned int swig_val;
288 int swig_res = SWIG_AsVal_unsigned_SS_int(PyTuple_GET_ITEM((PyObject *)$input, 0), &swig_val);
289 if (!SWIG_IsOK(swig_res)) {
290 %dirout_fail(swig_res, "($type, std::string, std::string)");
292 c_result = static_cast< Xapian::valueno >(swig_val);
294 // Set "begin" from the second item of the tuple.
295 std::string *ptr = (std::string *)0;
296 swig_res = SWIG_AsPtr_std_string(PyTuple_GET_ITEM((PyObject *)$input, 1), &ptr);
297 if (!SWIG_IsOK(swig_res) || !ptr) {
298 delete ptr;
299 ptr = (std::string *)0;
300 %dirout_fail((ptr ? swig_res : SWIG_TypeError), "($type, std::string, std::string)");
302 begin = *ptr;
303 delete ptr;
304 ptr = (std::string *)0;
306 // Set "end" from the third item of the tuple.
307 swig_res = SWIG_AsPtr_std_string(PyTuple_GET_ITEM((PyObject *)$input, 2), &ptr);
308 if (!SWIG_IsOK(swig_res) || !ptr) {
309 delete ptr;
310 ptr = (std::string *)0;
311 %dirout_fail((ptr ? swig_res : SWIG_TypeError), "($type, std::string, std::string)");
313 end = *ptr;
314 delete ptr;
315 ptr = (std::string *)0;
318 /* These typemaps handle ValueRangeProcessors, which take non-const references
319 * to std::string and modify the strings.
321 %typemap(in) std::string &begin (std::string temp),
322 std::string &end (std::string temp) {
323 std::string *ptr = (std::string *)0;
324 int res = XapianSWIG_anystring_as_ptr($input, &ptr);
325 if (!SWIG_IsOK(res) || !ptr) {
326 %argument_fail((ptr ? res : SWIG_TypeError), "$type", $symname, $argnum);
328 temp = *ptr;
329 $1 = &temp;
330 if (SWIG_IsNewObj(res)) delete ptr;
332 %typemap(argout) (std::string &begin, std::string &end) {
333 PyObject * str;
334 PyObject * newresult;
336 // Put the existing result into the first item of a new 3-tuple.
337 newresult = PyTuple_New(3);
338 if (newresult == 0) {
339 Py_DECREF($result);
340 $result = NULL;
341 SWIG_fail;
343 PyTuple_SET_ITEM(newresult, 0, $result);
344 $result = newresult;
346 str = PyBytes_FromStringAndSize($1->data(), $1->size());
347 if (str == 0) {
348 Py_DECREF($result);
349 $result = NULL;
350 SWIG_fail;
352 PyTuple_SET_ITEM($result, 1, str);
354 str = PyBytes_FromStringAndSize($2->data(), $2->size());
355 if (str == 0) {
356 Py_DECREF($result);
357 $result = NULL;
358 SWIG_fail;
361 PyTuple_SET_ITEM($result, 2, str);
364 %typemap(directorin) (size_t num_tags, const std::string tags[]) {
365 PyObject * result = PyList_New(num_tags);
366 if (result == 0) {
367 return NULL;
370 for (size_t i = 0; i != num_tags; ++i) {
371 PyObject * str = PyBytes_FromStringAndSize(tags[i].data(), tags[i].size());
372 if (str == 0) {
373 Py_DECREF(result);
374 return NULL;
377 PyList_SET_ITEM(result, i, str);
379 $input = result;
382 /* vim:set syntax=cpp:set noexpandtab: */