File: php.i

package info (click to toggle)
xapian-bindings 1.4.29-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 21,436 kB
  • sloc: cpp: 379,853; python: 10,780; cs: 9,529; java: 6,949; sh: 4,629; perl: 4,435; makefile: 1,274; ruby: 1,028; php: 586; tcl: 246
file content (359 lines) | stat: -rw-r--r-- 11,460 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
%module(directors="1") xapian
%{
/* php.i: SWIG interface file for the PHP bindings
 *
 * Copyright (C) 2004-2022 Olly Betts
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

#include "../xapian-version.h"
%}

// This works around a build failure on Illuminos:
// https://trac.xapian.org/ticket/793
%begin %{
#include <string>
%}

%{
extern "C" {
// Needed for php_array_merge().
#include <ext/standard/php_array.h>
}
%}

// Use SWIG directors for PHP wrappers.
#define XAPIAN_SWIG_DIRECTORS

%include ../xapian-head.i

/* Add a section to the output from phpinfo(). */
%pragma(php) phpinfo="\
    php_info_print_table_start();\n\
    php_info_print_table_row(2, \"Xapian Support\", \"enabled\");\n\
    php_info_print_table_row(2, \"Xapian Compiled Version\",\n\
			     XAPIAN_BINDINGS_VERSION);\n\
    php_info_print_table_row(2, \"Xapian Linked Version\",\n\
			     Xapian::version_string());\n\
    php_info_print_table_end();\
"

%pragma(php) version=PACKAGE_VERSION

%rename("is_empty") empty() const;
%rename("clone_object") clone() const;

/* Fake a namespace on open_stub() (PHP5.3 added real namespaces, but we want
 * to support older versions still. */
%rename(auto_open_stub) Xapian::Auto::open_stub;

/* Handle op as an int rather than an enum. */
%apply int { Xapian::Query::op };

/* STRING has a lower precedence that numbers, but the SWIG PHP check for
 * number (in 1.3.28 at least) includes IS_STRING which means that for a
 * method taking either int or string, the int version will always be used.
 * Simplest workaround is to set the precedence here higher that the numeric
 * precedences - i.e. SWIG_TYPECHECK_VOIDPTR instead of SWIG_TYPECHECK_STRING.
 */
%typemap(typecheck, precedence=SWIG_TYPECHECK_VOIDPTR) const std::string & {
    $1 = (Z_TYPE($input) == IS_STRING);
}

/* The SWIG overloading doesn't handle this correctly by default. */
%typemap(typecheck, precedence=SWIG_TYPECHECK_BOOL) bool {
    $1 = (Z_TYPE($input) == IS_TRUE || Z_TYPE($input) == IS_FALSE || Z_TYPE($input) == IS_LONG);
}

#define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP

%typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
    $1 = (Z_TYPE($input) == IS_ARRAY);
    /* FIXME: if we add more array typemaps, we'll need to check the elements
     * of the array here to disambiguate. */
}

%{
/** Merge _ps properties.
 *
 *  We use these to keep references to XapianPostingSource objects used in
 *  XapianQuery objects.
 */
static void merge_ps_references(zval* target_this, zval& input) {
    zval* zvq = zend_read_property(Z_OBJCE(input), Z_OBJ(input), "_ps", strlen("_ps"), false, NULL);
    if (zend_hash_num_elements(Z_ARR_P(zvq)) > 0) {
	zval* zv = zend_read_property(Z_OBJCE_P(target_this), Z_OBJ_P(target_this), "_ps", strlen("_ps"), false, NULL);
	if (zend_hash_num_elements(Z_ARR_P(zv)) == 0) {
	    ZVAL_COPY(zv, zvq);
	} else {
	    SEPARATE_ARRAY(zv);
	    php_array_merge(Z_ARR_P(zv), Z_ARR_P(zvq));
	}
    }
}

class XapianSWIGQueryItor {
#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION < 2
    Bucket* p;
#else
    zval* p;
    size_t elt_size;
#endif

    zval* target_this;

  public:
    typedef std::random_access_iterator_tag iterator_category;
    typedef Xapian::Query value_type;
    typedef Xapian::termcount_diff difference_type;
    typedef Xapian::Query * pointer;
    typedef Xapian::Query & reference;

    XapianSWIGQueryItor()
	: p(NULL) { }

    void begin(zval* input, zval* target_this_) {
	HashTable *ht = Z_ARRVAL_P(input);
#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION < 2
	p = ht->arData;
#else
	elt_size = ZEND_HASH_ELEMENT_SIZE(ht);
	p = ZEND_HASH_ELEMENT(ht, 0);
#endif
	target_this = target_this_;
    }

    void end(zval * input) {
	HashTable *ht = Z_ARRVAL_P(input);
#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION < 2
	p = ht->arData + ht->nNumUsed;
#else
	elt_size = ZEND_HASH_ELEMENT_SIZE(ht);
	p = ZEND_HASH_ELEMENT(ht, ht->nNumUsed);
#endif
    }

    XapianSWIGQueryItor & operator++() {
#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION < 2
	++p;
#else
	p = ZEND_HASH_NEXT_ELEMENT(p, elt_size);
#endif
	return *this;
    }

    Xapian::Query operator*() const {
#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION < 2
	zval *item = &p->val;
#else
	zval *item = p;
#endif

	if (Z_TYPE_P(item) == IS_STRING) {
	    size_t len = Z_STRLEN_P(item);
	    const char *str = Z_STRVAL_P(item);
	    return Xapian::Query(string(str, len));
	}

	Xapian::Query *subq = 0;
	if (SWIG_ConvertPtr(item, (void **)&subq,
			    SWIGTYPE_p_Xapian__Query, 0) < 0) {
	    subq = 0;
	}
	if (!subq) {
	    SWIG_PHP_Error(E_ERROR, "Expected XapianQuery object or string");
fail: // Label which SWIG_PHP_Error needs.
	    return Xapian::Query();
	}
	merge_ps_references(target_this, *item);
	return *subq;
    }

    bool operator==(const XapianSWIGQueryItor & o) {
	return p == o.p;
    }

    bool operator!=(const XapianSWIGQueryItor & o) {
	return !(*this == o);
    }

    difference_type operator-(const XapianSWIGQueryItor &o) const {
#if PHP_MAJOR_VERSION == 8 && PHP_MINOR_VERSION < 2
	return p - o.p;
#else
	auto d = reinterpret_cast<const char*>(p) -
		 reinterpret_cast<const char*>(o.p);
	return d / elt_size;
#endif
    }
};

%}

%typemap(in, phptype="array") (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
    // $1 and $2 are default initialised where SWIG declares them.
    if (Z_TYPE($input) == IS_ARRAY) {
	// The typecheck typemap should have ensured this is an array.
	$1.begin(&$input, ZEND_THIS);
	$2.end(&$input);
    }
}

#define XAPIAN_TERMITERATOR_PAIR_OUTPUT_TYPEMAP
%typemap(out, phptype="array") std::pair<Xapian::TermIterator, Xapian::TermIterator> {
    array_init($result);

    for (Xapian::TermIterator i = $1.first; i != $1.second; ++i) {
	const string& term = *i;
	add_next_index_stringl($result, term.data(), term.length());
    }
}

%typemap(directorin) (size_t num_tags, const std::string tags[]) {
    array_init_size($input, num_tags);

    for (size_t i = 0; i != num_tags; ++i) {
	const string& term = tags[i];
	add_next_index_stringl($input, term.data(), term.length());
    }
}

%{
#include <xapian/iterator.h>
%}

%define PHP_ITERATOR(NS, CLASS, RET_TYPE, REWIND_ACTION)
    %typemap("phpinterfaces") NS::CLASS "Iterator";
    %extend NS::CLASS {
	const NS::CLASS & key() { return *self; }
	RET_TYPE current() { return **self; }
	bool valid() { return Xapian::iterator_valid(*self); }
	void rewind() { REWIND_ACTION }
    }
%enddef

PHP_ITERATOR(Xapian, ESetIterator, std::string, Xapian::iterator_rewind(*self);)
PHP_ITERATOR(Xapian, MSetIterator, Xapian::docid, Xapian::iterator_rewind(*self);)
PHP_ITERATOR(Xapian, TermIterator, std::string, )
PHP_ITERATOR(Xapian, PositionIterator, Xapian::termpos, )
PHP_ITERATOR(Xapian, PostingIterator, Xapian::docid, )
PHP_ITERATOR(Xapian, ValueIterator, std::string, )

%include except.i

%define XAPIAN_FUNCTOR(CLASS, PARAM, CODE...)
%typemap(in, phptype="SWIGTYPE") (CLASS PARAM) %{
$typemap(in, CLASS)
{ CODE }
%}
%enddef

XAPIAN_FUNCTOR(Xapian::FieldProcessor*, proc,
    zval* zv = zend_read_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_procs", strlen("_procs"), false, NULL);
    SEPARATE_ARRAY(zv);
    Z_ADDREF($input);
    add_next_index_zval(zv, &$input);
    )

XAPIAN_FUNCTOR(Xapian::RangeProcessor*, range_proc,
    zval* zv = zend_read_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_procs", strlen("_procs"), false, NULL);
    SEPARATE_ARRAY(zv);
    Z_ADDREF($input);
    add_next_index_zval(zv, &$input);
    )

XAPIAN_FUNCTOR(Xapian::ValueRangeProcessor*, vrproc,
    zval* zv = zend_read_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_procs", strlen("_procs"), false, NULL);
    SEPARATE_ARRAY(zv);
    Z_ADDREF($input);
    add_next_index_zval(zv, &$input);
    )

XAPIAN_FUNCTOR(Xapian::Stopper*, stop,
    zend_update_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_stopper", strlen("_stopper"), &$input);
    )

XAPIAN_FUNCTOR(Xapian::KeyMaker*, sorter,
    zend_update_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_sorter", strlen("_sorter"), &$input);
    )

// Unset _sorter on any set_sort_by_...() which sets sorting by a slot.
%typemap(in, phptype="int") (Xapian::valueno sort_key) %{
$typemap(in, Xapian::valueno)
    zend_update_property_null(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_sorter", strlen("_sorter"));
%}

%typemap(out, phptype="void") (void Xapian::Enquire::set_sort_by_relevance) %{
    zend_update_property_null(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_sorter", strlen("_sorter"));
%}

%typemap(out, phptype="void") (void Xapian::Enquire::clear_matchspies) %{
    { zval z; ZVAL_EMPTY_ARRAY(&z); zend_update_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_spies", strlen("_spies"), &z); }
%}

XAPIAN_FUNCTOR(Xapian::MatchSpy*, spy,
    zval* zv = zend_read_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_spies", strlen("_spies"), false, NULL);
    SEPARATE_ARRAY(zv);
    Z_ADDREF($input);
    add_next_index_zval(zv, &$input);
    )

XAPIAN_FUNCTOR(Xapian::PostingSource*, source,
    zval* zv = zend_read_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_ps", strlen("_ps"), false, NULL);
    SEPARATE_ARRAY(zv);
    Z_ADDREF($input);
    add_next_index_zval(zv, &$input);
    )

XAPIAN_FUNCTOR(const Xapian::Query&, a, merge_ps_references(ZEND_THIS, $input);)

XAPIAN_FUNCTOR(const Xapian::Query&, b, merge_ps_references(ZEND_THIS, $input);)

XAPIAN_FUNCTOR(const Xapian::Query&, subquery, merge_ps_references(ZEND_THIS, $input);)

// Enquire::set_query() stores the PHP query object, which means we hold on to any
// references to PHP XapianPostingSource objects it contains.
XAPIAN_FUNCTOR(const Xapian::Query&, query,
    zend_update_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_query", strlen("_query"), &$input);
    )

// Then Enquire::get_query() returns the PHP query object if one is set, otherwise
// it returns the result C++ gave us (which will be an empty XapianQuery object.
// We could avoid calling C++ at all here, but I don't see an easy way to do so.
// This isn't a widely used method, and the C++ call should be pretty cheap anyway.
%typemap(out, phptype="SWIGTYPE") (const Xapian::Query& Xapian::Enquire::get_query) %{
{
    zval* zv = zend_read_property(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), "_query", strlen("_query"), false, NULL);
    if (Z_TYPE_P(zv) == IS_OBJECT) {
	RETVAL_OBJ_COPY(Z_OBJ_P(zv));
    } else {
	$typemap(out, const Query&)
    }
}
%}

%include ../xapian-headers.i

// Compatibility wrapping for Xapian::BAD_VALUENO (wrapped as a constant since
// xapian-bindings 1.4.10).
%inline %{
namespace Xapian {
static Xapian::valueno BAD_VALUENO_get() { return Xapian::BAD_VALUENO; }
}
%}
// Can't throw an exception.
%exception Xapian::BAD_VALUENO_get "$action"