scriptindex: Support multiple index action arguments
[xapian.git] / xapian-bindings / php / php.i
blob231b7a3c866a28df534d93c1913453f05339b797
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 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 /* SWIG's default typemap accepts "Null" when an object is passed by
78 reference, and the C++ wrapper code then dereferences a NULL pointer
79 which causes a SEGV. */
80 %typemap(in) SWIGTYPE & {
81 if (SWIG_ConvertPtr(*$input, (void**)&$1, $1_descriptor, 0) < 0 || $1 == NULL) {
82 SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor");
86 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
88 %typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
89 $1 = (Z_TYPE_PP($input) == IS_ARRAY);
90 /* FIXME: if we add more array typemaps, we'll need to check the elements
91 * of the array here to disambiguate. */
95 class XapianSWIGQueryItor {
96 HashTable *ht;
98 HashPosition i;
100 zval ** item;
102 #ifdef ZTS
103 void *** swig_zts_ctx;
104 #endif
106 void get_current_data() {
107 if (zend_hash_get_current_data_ex(ht, (void **)&item, &i) != SUCCESS) {
108 zend_hash_internal_pointer_end_ex(ht, &i);
109 ht = NULL;
113 public:
114 typedef std::random_access_iterator_tag iterator_category;
115 typedef Xapian::Query value_type;
116 typedef Xapian::termcount_diff difference_type;
117 typedef Xapian::Query * pointer;
118 typedef Xapian::Query & reference;
120 XapianSWIGQueryItor()
121 : ht(NULL) { }
123 void begin(zval ** input TSRMLS_DC) {
124 ht = Z_ARRVAL_PP(input);
125 TSRMLS_SET_CTX(swig_zts_ctx);
126 zend_hash_internal_pointer_reset_ex(ht, &i);
127 get_current_data();
130 XapianSWIGQueryItor & operator++() {
131 zend_hash_move_forward_ex(ht, &i);
132 get_current_data();
133 return *this;
136 Xapian::Query operator*() const {
137 if ((*item)->type == IS_STRING) {
138 size_t len = Z_STRLEN_PP(item);
139 const char *p = Z_STRVAL_PP(item);
140 return Xapian::Query(string(p, len));
143 TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);
144 Xapian::Query *subq = 0;
145 if (SWIG_ConvertPtr(*item, (void **)&subq,
146 SWIGTYPE_p_Xapian__Query, 0) < 0) {
147 subq = 0;
149 if (!subq) {
150 SWIG_PHP_Error(E_ERROR, "Expected XapianQuery object or string");
151 fail: // Label which SWIG_PHP_Error needs.
152 return Xapian::Query();
154 return *subq;
157 bool operator==(const XapianSWIGQueryItor & o) {
158 return ht == o.ht;
161 bool operator!=(const XapianSWIGQueryItor & o) {
162 return !(*this == o);
165 difference_type operator-(const XapianSWIGQueryItor &o) const {
166 // This is a hack - the only time where this will actually get called
167 // is when "this" is "end" and "o" is "begin", in which case the
168 // answer is the number of elements in the HashTable, which will be in
169 // o.ht.
170 return zend_hash_num_elements(o.ht);
176 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
177 // $1 and $2 are default initialised where SWIG declares them.
178 if (Z_TYPE_PP($input) == IS_ARRAY) {
179 // The typecheck typemap should have ensured this is an array.
180 $1.begin($input TSRMLS_CC);
184 #define XAPIAN_TERMITERATOR_PAIR_OUTPUT_TYPEMAP
185 %typemap(out) std::pair<Xapian::TermIterator, Xapian::TermIterator> {
186 if (array_init($result) == FAILURE) {
187 SWIG_PHP_Error(E_ERROR, "array_init failed");
190 for (Xapian::TermIterator i = $1.first; i != $1.second; ++i) {
191 /* We have to cast away const here because the PHP API is rather
192 * poorly thought out - really there should be two API methods
193 * one of which takes a const char * and copies the string and
194 * the other which takes char * and takes ownership of the string.
196 * Passing 1 as the last parameter of add_next_index_stringl() tells
197 * PHP to copy the string pointed to by p, so it won't be modified.
199 const string & term = *i;
200 char *p = const_cast<char*>(term.data());
201 add_next_index_stringl($result, p, term.length(), 1);
205 %typemap(directorin) (size_t num_tags, const std::string tags[]) {
206 if (array_init($input) == FAILURE) {
207 SWIG_PHP_Error(E_ERROR, "array_init failed");
210 for (size_t i = 0; i != num_tags; ++i) {
211 const string & term = tags[i];
212 char *p = const_cast<char*>(term.data());
213 add_next_index_stringl($input, p, term.length(), 1);
218 #include <xapian/iterator.h>
221 %define PHP_ITERATOR(NS, CLASS, RET_TYPE, REWIND_ACTION)
222 %typemap("phpinterfaces") NS::CLASS "Iterator";
223 %extend NS::CLASS {
224 const NS::CLASS & key() { return *self; }
225 RET_TYPE current() { return **self; }
226 bool valid() { return Xapian::iterator_valid(*self); }
227 void rewind() { REWIND_ACTION }
229 %enddef
231 PHP_ITERATOR(Xapian, ESetIterator, std::string, Xapian::iterator_rewind(*self);)
232 PHP_ITERATOR(Xapian, MSetIterator, Xapian::docid, Xapian::iterator_rewind(*self);)
233 PHP_ITERATOR(Xapian, TermIterator, std::string, )
234 PHP_ITERATOR(Xapian, PositionIterator, Xapian::termpos, )
235 PHP_ITERATOR(Xapian, PostingIterator, Xapian::docid, )
236 PHP_ITERATOR(Xapian, ValueIterator, std::string, )
238 %include except.i
240 %include ../xapian-headers.i