Expand some query-related testcases
[xapian.git] / xapian-bindings / php / php.i
blobafa28dbb155fddf76a5c42b995a88f4e05b041f6
1 %module(directors="1") xapian
2 %{
3 /* php.i: SWIG interface file for the PHP bindings
5 * Copyright (C) 2004,2005,2006,2007,2008,2010,2011,2012,2014,2016,2019 Olly Betts
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
23 #include "../xapian-version.h"
26 // Use SWIG directors for PHP wrappers.
27 #define XAPIAN_SWIG_DIRECTORS
29 %include ../xapian-head.i
31 /* Add a section to the output from phpinfo(). */
32 %pragma(php) phpinfo="\
33 php_info_print_table_start();\n\
34 php_info_print_table_row(2, \"Xapian Support\", \"enabled\");\n\
35 php_info_print_table_row(2, \"Xapian Compiled Version\",\n\
36 XAPIAN_BINDINGS_VERSION);\n\
37 php_info_print_table_row(2, \"Xapian Linked Version\",\n\
38 Xapian::version_string());\n\
39 php_info_print_table_end();\
42 %rename("is_empty") empty() const;
43 %rename("clone_object") clone() const;
45 /* Fake a namespace on open_stub() (PHP5.3 added real namespaces, but we want
46 * to support older versions still. */
47 %rename(auto_open_stub) Xapian::Auto::open_stub;
49 /* Handle op as an int rather than an enum. */
50 %apply int { Xapian::Query::op };
52 %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) const SWIGTYPE & {
53 void *ptr;
54 $1 = (SWIG_ConvertPtr(*$input, (void **)&ptr, $1_descriptor, 0) == 0);
57 %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE {
58 void *ptr;
59 $1 = (SWIG_ConvertPtr(*$input, (void **)&ptr, $&1_descriptor, 0) == 0);
62 /* STRING has a lower precedence that numbers, but the SWIG PHP check for
63 * number (in 1.3.28 at least) includes IS_STRING which means that for a
64 * method taking either int or string, the int version will always be used.
65 * Simplest workaround is to set the precedence here higher that the numeric
66 * precedences - i.e. SWIG_TYPECHECK_VOIDPTR instead of SWIG_TYPECHECK_STRING.
68 %typemap(typecheck, precedence=SWIG_TYPECHECK_VOIDPTR) const std::string & {
69 $1 = (Z_TYPE_PP($input) == IS_STRING);
72 /* The SWIG overloading doesn't handle this correctly by default. */
73 %typemap(typecheck, precedence=SWIG_TYPECHECK_BOOL) bool {
74 $1 = (Z_TYPE_PP($input) == IS_BOOL || Z_TYPE_PP($input) == IS_LONG);
77 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
79 %typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
80 $1 = (Z_TYPE_PP($input) == IS_ARRAY);
81 /* FIXME: if we add more array typemaps, we'll need to check the elements
82 * of the array here to disambiguate. */
86 class XapianSWIGQueryItor {
87 HashTable *ht;
89 HashPosition i;
91 zval ** item;
93 #ifdef ZTS
94 void *** swig_zts_ctx;
95 #endif
97 void get_current_data() {
98 if (zend_hash_get_current_data_ex(ht, (void **)&item, &i) != SUCCESS) {
99 zend_hash_internal_pointer_end_ex(ht, &i);
100 ht = NULL;
104 public:
105 typedef std::random_access_iterator_tag iterator_category;
106 typedef Xapian::Query value_type;
107 typedef Xapian::termcount_diff difference_type;
108 typedef Xapian::Query * pointer;
109 typedef Xapian::Query & reference;
111 XapianSWIGQueryItor()
112 : ht(NULL) { }
114 void begin(zval ** input TSRMLS_DC) {
115 ht = Z_ARRVAL_PP(input);
116 TSRMLS_SET_CTX(swig_zts_ctx);
117 zend_hash_internal_pointer_reset_ex(ht, &i);
118 get_current_data();
121 XapianSWIGQueryItor & operator++() {
122 zend_hash_move_forward_ex(ht, &i);
123 get_current_data();
124 return *this;
127 Xapian::Query operator*() const {
128 if ((*item)->type == IS_STRING) {
129 size_t len = Z_STRLEN_PP(item);
130 const char *p = Z_STRVAL_PP(item);
131 return Xapian::Query(string(p, len));
134 TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);
135 Xapian::Query *subq = 0;
136 if (SWIG_ConvertPtr(*item, (void **)&subq,
137 SWIGTYPE_p_Xapian__Query, 0) < 0) {
138 subq = 0;
140 if (!subq) {
141 SWIG_PHP_Error(E_ERROR, "Expected XapianQuery object or string");
142 fail: // Label which SWIG_PHP_Error needs.
143 return Xapian::Query();
145 return *subq;
148 bool operator==(const XapianSWIGQueryItor & o) {
149 return ht == o.ht;
152 bool operator!=(const XapianSWIGQueryItor & o) {
153 return !(*this == o);
156 difference_type operator-(const XapianSWIGQueryItor &o) const {
157 // This is a hack - the only time where this will actually get called
158 // is when "this" is "end" and "o" is "begin", in which case the
159 // answer is the number of elements in the HashTable, which will be in
160 // o.ht.
161 return zend_hash_num_elements(o.ht);
167 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
168 // $1 and $2 are default initialised where SWIG declares them.
169 if (Z_TYPE_PP($input) == IS_ARRAY) {
170 // The typecheck typemap should have ensured this is an array.
171 $1.begin($input TSRMLS_CC);
175 #define XAPIAN_TERMITERATOR_PAIR_OUTPUT_TYPEMAP
176 %typemap(out) std::pair<Xapian::TermIterator, Xapian::TermIterator> {
177 if (array_init($result) == FAILURE) {
178 SWIG_PHP_Error(E_ERROR, "array_init failed");
181 for (Xapian::TermIterator i = $1.first; i != $1.second; ++i) {
182 /* We have to cast away const here because the PHP API is rather
183 * poorly thought out - really there should be two API methods
184 * one of which takes a const char * and copies the string and
185 * the other which takes char * and takes ownership of the string.
187 * Passing 1 as the last parameter of add_next_index_stringl() tells
188 * PHP to copy the string pointed to by p, so it won't be modified.
190 const string & term = *i;
191 char *p = const_cast<char*>(term.data());
192 add_next_index_stringl($result, p, term.length(), 1);
196 %typemap(directorin) (size_t num_tags, const std::string tags[]) {
197 if (array_init($input) == FAILURE) {
198 SWIG_PHP_Error(E_ERROR, "array_init failed");
201 for (size_t i = 0; i != num_tags; ++i) {
202 const string & term = tags[i];
203 char *p = const_cast<char*>(term.data());
204 add_next_index_stringl($input, p, term.length(), 1);
209 #include <xapian/iterator.h>
212 %define PHP_ITERATOR(NS, CLASS, RET_TYPE, REWIND_ACTION)
213 %typemap("phpinterfaces") NS::CLASS "Iterator";
214 %extend NS::CLASS {
215 const NS::CLASS & key() { return *self; }
216 RET_TYPE current() { return **self; }
217 bool valid() { return Xapian::iterator_valid(*self); }
218 void rewind() { REWIND_ACTION }
220 %enddef
222 PHP_ITERATOR(Xapian, ESetIterator, std::string, Xapian::iterator_rewind(*self);)
223 PHP_ITERATOR(Xapian, MSetIterator, Xapian::docid, Xapian::iterator_rewind(*self);)
224 PHP_ITERATOR(Xapian, TermIterator, std::string, )
225 PHP_ITERATOR(Xapian, PositionIterator, Xapian::termpos, )
226 PHP_ITERATOR(Xapian, PostingIterator, Xapian::docid, )
227 PHP_ITERATOR(Xapian, ValueIterator, std::string, )
229 %include except.i
231 %include ../xapian-headers.i
233 // Compatibility wrapping for Xapian::BAD_VALUENO (wrapped as a constant since
234 // xapian-bindings 1.4.10).
235 %inline %{
236 namespace Xapian {
237 static Xapian::valueno BAD_VALUENO_get() { return Xapian::BAD_VALUENO; }
240 // Can't throw an exception.
241 %exception Xapian::BAD_VALUENO_get "$action"