1 %module(directors="1") xapian
2 %{
3 /* ruby.i: SWIG interface file for the Ruby bindings
4  *
5  * Original version by Paul Legato (plegato@nks.net), 4/17/06.
6  * Based on the php4 and python util.i files.
7  *
8  * Copyright (C) 2006 Networked Knowledge Systems, Inc.
9  * Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2019 Olly Betts
10  * Copyright (C) 2010 Richard Boulton
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
25  * USA
26  */
27 
28 %}
29 
30 %begin %{
31 // The Ruby 2.3 headers contain things which cause warnings with more recent
32 // C++ compilers.  There's nothing we can really do about them, so just
33 // suppress them.
34 #ifdef __clang__
35 # pragma clang diagnostic push
36 # pragma clang diagnostic ignored "-Wdeprecated-register"
37 # pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
38 #elif defined __GNUC__
39 // Warning added in GCC 4.8 and we don't support anything older.
40 # pragma GCC diagnostic push
41 # pragma GCC diagnostic ignored "-Wliteral-suffix"
42 #endif
43 
44 #include <ruby.h>
45 
46 #ifdef __clang__
47 # pragma clang diagnostic pop
48 #elif defined __GNUC__
49 # pragma GCC diagnostic pop
50 #endif
51 %}
52 
53 // Use SWIG directors for Ruby wrappers.
54 #define XAPIAN_SWIG_DIRECTORS
55 
56 // We don't use the Iterator and ConstIterator wrappers which SWIG now offers,
57 // so disable them to reduce the generated C++ wrapper code.
58 #define SWIG_NO_EXPORT_ITERATOR_METHODS
59 
60 %include ../xapian-head.i
61 
62 /////////////////////////////////////
63 // Rename function and method names to match Ruby conventions
64 // e.g. from get_data to data and from set_data to data=
65 
66 // Getters
67 %rename("available_languages") get_available_languages;
68 %rename("avlength") get_avlength;
69 %rename("collapse_count") get_collapse_count;
70 %rename("collection_freq") get_collection_freq;
71 %rename("context") get_context;
72 %rename("data") get_data;
73 %rename("default_op") get_default_op;
74 %rename("description") get_description;
75 %rename("docid") get_docid;
76 %rename("document_id") get_document_id;
77 %rename("document_percentage") get_document_percentage;
78 %rename("doccount") get_doccount;
79 %rename("doclength") get_doclength;
80 %rename("document") get_document;
81 %rename("ebound") get_ebound;
82 %rename("eset") get_eset;
83 %rename("firstitem") get_firstitem;
84 %rename("hit") get_hit;
85 %rename("lastdocid") get_lastdocid;
86 %rename("length") get_length;
87 %rename("matches_estimated") get_matches_estimated;
88 %rename("matches_lower_bound") get_matches_lower_bound;
89 %rename("matches_upper_bound") get_matches_upper_bound;
90 %rename("matching_terms") get_matching_terms;
91 %rename("max_attained") get_max_attained;
92 %rename("max_possible") get_max_possible;
93 %rename("maxextra") get_maxextra;
94 %rename("maxpart") get_maxpart;
95 %rename("mset") get_mset;
96 %rename("msg") get_msg;
97 %rename("op_name") get_op_name;
98 %rename("percent") get_percent;
99 %rename("query") get_query;
100 %rename("rank") get_rank;
101 %rename("sumextra") get_sumextra;
102 %rename("sumpart") get_sumpart;
103 %rename("termfreq") get_termfreq;
104 %rename("terms") get_terms;
105 %rename("term") get_term;
106 %rename("termpos") get_termpos;
107 %rename("termweight") get_termweight;
108 %rename("type") get_type;
109 %rename("value") get_value;
110 %rename("valueno") get_valueno;
111 %rename("wdf") get_wdf;
112 %rename("weight") get_weight;
113 
114 // These are 'dangerous' methods; i.e. they can cause a segfault if used
115 // improperly.  We prefix with _dangerous_ so that Ruby users will not use them
116 // inadvertently.
117 //
118 // There is a safe wrapper for their functionality provided in xapian.rb.
119 
120 // in Xapian::Document and Xapian::Database
121 %rename("_dangerous_termlist_begin") termlist_begin;
122 %rename("_dangerous_termlist_end") termlist_end;
123 // in Xapian::Query
124 %rename("_dangerous_terms_begin") get_terms_begin;
125 %rename("_dangerous_terms_end") get_terms_end;
126 // in Xapian::Query
127 %rename("_dangerous_unique_terms_begin") get_unique_terms_begin;
128 %rename("_dangerous_unique_terms_end") get_unique_terms_end;
129 // in Xapian::Enquire
130 %rename("_dangerous_matching_terms_begin") get_matching_terms_begin;
131 %rename("_dangerous_matching_terms_end") get_matching_terms_end;
132 // in Xapian::Database
133 %rename("_dangerous_allterms_begin") allterms_begin;
134 %rename("_dangerous_allterms_end") allterms_end;
135 // in Xapian::Database
136 %rename("_dangerous_metadata_keys_begin") metadata_keys_begin;
137 %rename("_dangerous_metadata_keys_end") metadata_keys_end;
138 // in Xapian::Database
139 %rename("_dangerous_postlist_begin") postlist_begin;
140 %rename("_dangerous_postlist_end") postlist_end;
141 // in Xapian::Database
142 %rename("_dangerous_positionlist_begin") positionlist_begin;
143 %rename("_dangerous_positionlist_end") positionlist_end;
144 // in Xapian::Database
145 %rename("_dangerous_spellings_begin") spellings_begin;
146 %rename("_dangerous_spellings_end") spellings_end;
147 // in Xapian::Database
148 %rename("_dangerous_synonyms_begin") synonyms_begin;
149 %rename("_dangerous_synonyms_end") synonyms_end;
150 // in Xapian::Database
151 %rename("_dangerous_synonym_keys_begin") synonym_keys_begin;
152 %rename("_dangerous_synonym_keys_end") synonym_keys_end;
153 // in Xapian::Database
154 %rename("_dangerous_valuestream_begin") valuestream_begin;
155 %rename("_dangerous_valuestream_end") valuestream_end;
156 // in Xapian::Document and Xapian::ValueCountMatchSpy
157 %rename("_dangerous_values_begin") values_begin;
158 %rename("_dangerous_values_end") values_end;
159 // in Xapian::ValueCountMatchSpy
160 %rename("_dangerous_top_values_begin") top_values_begin;
161 %rename("_dangerous_top_values_end") top_values_end;
162 // in Xapian::QueryParser
163 %rename("_dangerous_stoplist_begin") stoplist_begin;
164 %rename("_dangerous_stoplist_end") stoplist_end;
165 // in Xapian::QueryParser
166 %rename("_dangerous_unstem_begin") unstem_begin;
167 %rename("_dangerous_unstem_end") unstem_end;
168 
169 
170 // MSetIterators are not dangerous, just inconvenient to use within a Ruby
171 // idiom.
172 %rename ("_begin") begin;
173 %rename ("_end") end;
174 %rename ("_back") back;
175 
176 
177 
178 // Setters
179 %rename("collapse_key=") set_collapse_key;
180 %rename("cutoff!") set_cutoff;
181 %rename("data=") set_data;
182 %rename("database=") set_database;
183 %rename("default_op=") set_default_op;
184 %rename("docid_order=") set_docid_order;
185 %rename("document=") set_document;
186 %rename("query=") set_query(const Xapian::Query &);
187 %rename("query!") set_query(const Xapian::Query &, Xapian::termcount qlen);
188 %rename("sort_by_relevance!") set_sort_by_relevance;
189 %rename("sort_by_relevance_then_value!") set_sort_by_relevance_then_value;
190 %rename("sort_by_value_then_relevance!") set_sort_by_value_then_relevance;
191 %rename("sort_by_value!") set_sort_by_value;
192 %rename("stemmer=") set_stemmer;
193 %rename("stemming_strategy=") set_stemming_strategy;
194 %rename("stopper=") set_stopper;
195 %rename("weighting_scheme=") set_weighting_scheme;
196 
197 // Booleans
198 %predicate empty;
199 
200 #define XAPIAN_MIXED_SUBQUERIES_BY_ITERATOR_TYPEMAP
201 
202 /* FIXME:
203  * Check to see what is equivalent to a C++ Vector for the purposes of a Query
204  * instantiation.
205  * At the moment, we take Ruby Arrays.
206  */
207 %typemap(typecheck, precedence=500) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
208     $1 = (TYPE($input) == T_ARRAY);
209     /* Currently, the only wrapped method which takes a Ruby array is the
210      * "extra" constructor Query(OP, ARRAY), where ARRAY can contain any mix of
211      * strings and Query objects.
212      *
213      * If we ever had a method (or function) which had two overloaded forms
214      * only differentiated by what type of array can be passed we'd need to
215      * look at the type of the array elements in the typecheck typemaps.
216      */
217 }
218 
219 %{
220 class XapianSWIGQueryItor {
221     VALUE array;
222 
223     int i;
224 
225   public:
226     typedef std::random_access_iterator_tag iterator_category;
227     typedef Xapian::Query value_type;
228     typedef Xapian::termcount_diff difference_type;
229     typedef Xapian::Query * pointer;
230     typedef Xapian::Query & reference;
231 
XapianSWIGQueryItor()232     XapianSWIGQueryItor() { }
233 
begin(VALUE array_)234     void begin(VALUE array_) {
235 	array = array_;
236 	i = 0;
237     }
238 
end(int n)239     void end(int n) {
240 	i = n;
241     }
242 
243     XapianSWIGQueryItor & operator++() {
244 	++i;
245 	return *this;
246     }
247 
248     Xapian::Query operator*() const {
249 	VALUE entry = rb_ary_entry(array, i);
250 	if (TYPE(entry) == T_STRING) {
251 	    return Xapian::Query(string(RSTRING_PTR(entry),
252 					RSTRING_LEN(entry)));
253 	}
254 
255 	// array element may be a Xapian::Query object. Add it if it is,
256 	// otherwise error out.
257 	Xapian::Query *subq = 0;
258 	if (SWIG_ConvertPtr(entry, (void **)&subq,
259 			    SWIGTYPE_p_Xapian__Query, 0) < 0 || !subq) {
260 	    SWIG_exception(SWIG_ValueError, "Elements of Arrays passed to Query must be either Strings or other Query objects");
261 	    return Xapian::Query();
262 	}
263 	return *subq;
264     }
265 
266     bool operator==(const XapianSWIGQueryItor & o) {
267 	return i == o.i;
268     }
269 
270     bool operator!=(const XapianSWIGQueryItor & o) {
271 	return !(*this == o);
272     }
273 
274     difference_type operator-(const XapianSWIGQueryItor &o) const {
275 	return i - o.i;
276     }
277 };
278 
279 %}
280 
281 %typemap(in) (XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend) {
282     if (TYPE($input) == T_ARRAY) {
283 	// The typecheck typemap should have ensured this is an array.
284 	$1.begin($input);
285 	$2.end(RARRAY_LEN($input));
286     } else {
287 	$1.end(0);
288 	$2.end(0);
289     }
290 }
291 
292 %typemap(directorin) (size_t num_tags, const std::string tags[]) {
293     $input = rb_ary_new();
294     for (size_t i = 0; i != num_tags; ++i) {
295 	VALUE str = rb_str_new(tags[i].data(), tags[i].size());
296 	rb_ary_push($input, str);
297     }
298 }
299 
300 // For MatchDecider::operator() and ExpandDecider::operator().
301 %typemap(directorout) int = bool;
302 
303 %include ../generic/except.i
304 
305 %include ../xapian-headers.i
306 
307 %include extra.i
308