Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // |
2 | // SWIG typemaps for std::vector | |
3 | // Luigi Ballabio | |
4 | // Apr 8, 2002 | |
5 | // | |
6 | // Ruby implementation | |
7 | ||
8 | %include <std_common.i> | |
9 | ||
10 | // ------------------------------------------------------------------------ | |
11 | // std::vector | |
12 | // | |
13 | // The aim of all that follows would be to integrate std::vector with | |
14 | // Ruby as much as possible, namely, to allow the user to pass and | |
15 | // be returned Ruby arrays | |
16 | // const declarations are used to guess the intent of the function being | |
17 | // exported; therefore, the following rationale is applied: | |
18 | // | |
19 | // -- f(std::vector<T>), f(const std::vector<T>&), f(const std::vector<T>*): | |
20 | // the parameter being read-only, either a Ruby array or a | |
21 | // previously wrapped std::vector<T> can be passed. | |
22 | // -- f(std::vector<T>&), f(std::vector<T>*): | |
23 | // the parameter must be modified; therefore, only a wrapped std::vector | |
24 | // can be passed. | |
25 | // -- std::vector<T> f(): | |
26 | // the vector is returned by copy; therefore, a Ruby array of T:s | |
27 | // is returned which is most easily used in other Ruby functions | |
28 | // -- std::vector<T>& f(), std::vector<T>* f(), const std::vector<T>& f(), | |
29 | // const std::vector<T>* f(): | |
30 | // the vector is returned by reference; therefore, a wrapped std::vector | |
31 | // is returned | |
32 | // ------------------------------------------------------------------------ | |
33 | ||
34 | %{ | |
35 | #include <vector> | |
36 | #include <algorithm> | |
37 | #include <stdexcept> | |
38 | %} | |
39 | ||
40 | // exported class | |
41 | ||
42 | namespace std { | |
43 | ||
44 | %mixin vector "Enumerable"; | |
45 | ||
46 | template<class T> class vector { | |
47 | %typemap(in) vector<T> { | |
48 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
49 | unsigned int size = RARRAY($input)->len; | |
50 | $1 = std::vector<T >(size); | |
51 | for (unsigned int i=0; i<size; i++) { | |
52 | VALUE o = RARRAY($input)->ptr[i]; | |
53 | T* x; | |
54 | SWIG_ConvertPtr(o, (void **) &x, $descriptor(T *), 1); | |
55 | (($1_type &)$1)[i] = *x; | |
56 | } | |
57 | } else { | |
58 | void *ptr; | |
59 | SWIG_ConvertPtr($input, &ptr, $&1_descriptor, 1); | |
60 | $1 = *(($&1_type) ptr); | |
61 | } | |
62 | } | |
63 | %typemap(in) const vector<T>& (std::vector<T> temp), | |
64 | const vector<T>* (std::vector<T> temp) { | |
65 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
66 | unsigned int size = RARRAY($input)->len; | |
67 | temp = std::vector<T >(size); | |
68 | $1 = &temp; | |
69 | for (unsigned int i=0; i<size; i++) { | |
70 | VALUE o = RARRAY($input)->ptr[i]; | |
71 | T* x; | |
72 | SWIG_ConvertPtr(o, (void **) &x, $descriptor(T *), 1); | |
73 | temp[i] = *x; | |
74 | } | |
75 | } else { | |
76 | SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 1); | |
77 | } | |
78 | } | |
79 | %typemap(out) vector<T> { | |
80 | $result = rb_ary_new2($1.size()); | |
81 | for (unsigned int i=0; i<$1.size(); i++) { | |
82 | T* x = new T((($1_type &)$1)[i]); | |
83 | rb_ary_store($result,i, | |
84 | SWIG_NewPointerObj((void *) x, | |
85 | $descriptor(T *), 1)); | |
86 | } | |
87 | } | |
88 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { | |
89 | /* native sequence? */ | |
90 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
91 | unsigned int size = RARRAY($input)->len; | |
92 | if (size == 0) { | |
93 | /* an empty sequence can be of any type */ | |
94 | $1 = 1; | |
95 | } else { | |
96 | /* check the first element only */ | |
97 | T* x; | |
98 | VALUE o = RARRAY($input)->ptr[0]; | |
99 | if ((SWIG_ConvertPtr(o,(void **) &x, | |
100 | $descriptor(T *),0)) != -1) | |
101 | $1 = 1; | |
102 | else | |
103 | $1 = 0; | |
104 | } | |
105 | } else { | |
106 | /* wrapped vector? */ | |
107 | std::vector<T >* v; | |
108 | if (SWIG_ConvertPtr($input,(void **) &v, | |
109 | $&1_descriptor,0) != -1) | |
110 | $1 = 1; | |
111 | else | |
112 | $1 = 0; | |
113 | } | |
114 | } | |
115 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, | |
116 | const vector<T>* { | |
117 | /* native sequence? */ | |
118 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
119 | unsigned int size = RARRAY($input)->len; | |
120 | if (size == 0) { | |
121 | /* an empty sequence can be of any type */ | |
122 | $1 = 1; | |
123 | } else { | |
124 | /* check the first element only */ | |
125 | T* x; | |
126 | VALUE o = RARRAY($input)->ptr[0]; | |
127 | if ((SWIG_ConvertPtr(o,(void **) &x, | |
128 | $descriptor(T *),0)) != -1) | |
129 | $1 = 1; | |
130 | else | |
131 | $1 = 0; | |
132 | } | |
133 | } else { | |
134 | /* wrapped vector? */ | |
135 | std::vector<T >* v; | |
136 | if (SWIG_ConvertPtr($input,(void **) &v, | |
137 | $1_descriptor,0) != -1) | |
138 | $1 = 1; | |
139 | else | |
140 | $1 = 0; | |
141 | } | |
142 | } | |
143 | public: | |
144 | vector(unsigned int size = 0); | |
145 | vector(unsigned int size, const T& value); | |
146 | vector(const vector<T> &); | |
147 | ||
148 | %rename(__len__) size; | |
149 | unsigned int size() const; | |
150 | %rename("empty?") empty; | |
151 | bool empty() const; | |
152 | void clear(); | |
153 | %rename(push) push_back; | |
154 | void push_back(const T& x); | |
155 | %extend { | |
156 | T pop() throw (std::out_of_range) { | |
157 | if (self->size() == 0) | |
158 | throw std::out_of_range("pop from empty vector"); | |
159 | T x = self->back(); | |
160 | self->pop_back(); | |
161 | return x; | |
162 | } | |
163 | T& __getitem__(int i) throw (std::out_of_range) { | |
164 | int size = int(self->size()); | |
165 | if (i<0) i += size; | |
166 | if (i>=0 && i<size) | |
167 | return (*self)[i]; | |
168 | else | |
169 | throw std::out_of_range("vector index out of range"); | |
170 | } | |
171 | void __setitem__(int i, const T& x) throw (std::out_of_range) { | |
172 | int size = int(self->size()); | |
173 | if (i<0) i+= size; | |
174 | if (i>=0 && i<size) | |
175 | (*self)[i] = x; | |
176 | else | |
177 | throw std::out_of_range("vector index out of range"); | |
178 | } | |
179 | void each() { | |
180 | for (unsigned int i=0; i<self->size(); i++) { | |
181 | T* x = &((*self)[i]); | |
182 | rb_yield(SWIG_NewPointerObj((void *) x, | |
183 | $descriptor(T *), 0)); | |
184 | } | |
185 | } | |
186 | } | |
187 | }; | |
188 | ||
189 | // Partial specialization for vectors of pointers. [ beazley ] | |
190 | ||
191 | %mixin vector<T*> "Enumerable"; | |
192 | template<class T> class vector<T*> { | |
193 | %typemap(in) vector<T*> { | |
194 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
195 | unsigned int size = RARRAY($input)->len; | |
196 | $1 = std::vector<T* >(size); | |
197 | for (unsigned int i=0; i<size; i++) { | |
198 | VALUE o = RARRAY($input)->ptr[i]; | |
199 | T* x; | |
200 | SWIG_ConvertPtr(o, (void **) &x, $descriptor(T *), 1); | |
201 | (($1_type &)$1)[i] = x; | |
202 | } | |
203 | } else { | |
204 | void *ptr; | |
205 | SWIG_ConvertPtr($input, &ptr, $&1_descriptor, 1); | |
206 | $1 = *(($&1_type) ptr); | |
207 | } | |
208 | } | |
209 | %typemap(in) const vector<T*>& (std::vector<T*> temp), | |
210 | const vector<T*>* (std::vector<T*> temp) { | |
211 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
212 | unsigned int size = RARRAY($input)->len; | |
213 | temp = std::vector<T* >(size); | |
214 | $1 = &temp; | |
215 | for (unsigned int i=0; i<size; i++) { | |
216 | VALUE o = RARRAY($input)->ptr[i]; | |
217 | T* x; | |
218 | SWIG_ConvertPtr(o, (void **) &x, $descriptor(T *), 1); | |
219 | temp[i] = x; | |
220 | } | |
221 | } else { | |
222 | SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 1); | |
223 | } | |
224 | } | |
225 | %typemap(out) vector<T*> { | |
226 | $result = rb_ary_new2($1.size()); | |
227 | for (unsigned int i=0; i<$1.size(); i++) { | |
228 | T* x = new T((($1_type &)$1)[i]); | |
229 | rb_ary_store($result,i, | |
230 | SWIG_NewPointerObj((void *) x, | |
231 | $descriptor(T *), 0)); | |
232 | } | |
233 | } | |
234 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T*> { | |
235 | /* native sequence? */ | |
236 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
237 | unsigned int size = RARRAY($input)->len; | |
238 | if (size == 0) { | |
239 | /* an empty sequence can be of any type */ | |
240 | $1 = 1; | |
241 | } else { | |
242 | /* check the first element only */ | |
243 | T* x; | |
244 | VALUE o = RARRAY($input)->ptr[0]; | |
245 | if ((SWIG_ConvertPtr(o,(void **) &x, | |
246 | $descriptor(T *),0)) != -1) | |
247 | $1 = 1; | |
248 | else | |
249 | $1 = 0; | |
250 | } | |
251 | } else { | |
252 | /* wrapped vector? */ | |
253 | std::vector<T* >* v; | |
254 | if (SWIG_ConvertPtr($input,(void **) &v, | |
255 | $&1_descriptor,0) != -1) | |
256 | $1 = 1; | |
257 | else | |
258 | $1 = 0; | |
259 | } | |
260 | } | |
261 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T*>&, | |
262 | const vector<T*>* { | |
263 | /* native sequence? */ | |
264 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
265 | unsigned int size = RARRAY($input)->len; | |
266 | if (size == 0) { | |
267 | /* an empty sequence can be of any type */ | |
268 | $1 = 1; | |
269 | } else { | |
270 | /* check the first element only */ | |
271 | T* x; | |
272 | VALUE o = RARRAY($input)->ptr[0]; | |
273 | if ((SWIG_ConvertPtr(o,(void **) &x, | |
274 | $descriptor(T *),0)) != -1) | |
275 | $1 = 1; | |
276 | else | |
277 | $1 = 0; | |
278 | } | |
279 | } else { | |
280 | /* wrapped vector? */ | |
281 | std::vector<T* >* v; | |
282 | if (SWIG_ConvertPtr($input,(void **) &v, | |
283 | $1_descriptor,0) != -1) | |
284 | $1 = 1; | |
285 | else | |
286 | $1 = 0; | |
287 | } | |
288 | } | |
289 | public: | |
290 | vector(unsigned int size = 0); | |
291 | vector(unsigned int size, T * &value); | |
292 | vector(const vector<T*> &); | |
293 | ||
294 | %rename(__len__) size; | |
295 | unsigned int size() const; | |
296 | %rename("empty?") empty; | |
297 | bool empty() const; | |
298 | void clear(); | |
299 | %rename(push) push_back; | |
300 | void push_back(T* x); | |
301 | %extend { | |
302 | T* pop() throw (std::out_of_range) { | |
303 | if (self->size() == 0) | |
304 | throw std::out_of_range("pop from empty vector"); | |
305 | T* x = self->back(); | |
306 | self->pop_back(); | |
307 | return x; | |
308 | } | |
309 | T* __getitem__(int i) throw (std::out_of_range) { | |
310 | int size = int(self->size()); | |
311 | if (i<0) i += size; | |
312 | if (i>=0 && i<size) | |
313 | return (*self)[i]; | |
314 | else | |
315 | throw std::out_of_range("vector index out of range"); | |
316 | } | |
317 | void __setitem__(int i, T* x) throw (std::out_of_range) { | |
318 | int size = int(self->size()); | |
319 | if (i<0) i+= size; | |
320 | if (i>=0 && i<size) | |
321 | (*self)[i] = x; | |
322 | else | |
323 | throw std::out_of_range("vector index out of range"); | |
324 | } | |
325 | void each() { | |
326 | for (unsigned int i=0; i<self->size(); i++) { | |
327 | T* x = (*self)[i]; | |
328 | rb_yield(SWIG_NewPointerObj((void *) x, | |
329 | $descriptor(T *), 0)); | |
330 | } | |
331 | } | |
332 | } | |
333 | }; | |
334 | ||
335 | ||
336 | // specializations for built-ins | |
337 | ||
338 | %define specialize_std_vector(T,CHECK,CONVERT_FROM,CONVERT_TO) | |
339 | %mixin vector<T> "Enumerable"; | |
340 | template<> class vector<T> { | |
341 | %typemap(in) vector<T> { | |
342 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
343 | unsigned int size = RARRAY($input)->len; | |
344 | $1 = std::vector<T >(size); | |
345 | for (unsigned int i=0; i<size; i++) { | |
346 | VALUE o = RARRAY($input)->ptr[i]; | |
347 | if (CHECK(o)) | |
348 | (($1_type &)$1)[i] = (T)(CONVERT_FROM(o)); | |
349 | else | |
350 | rb_raise(rb_eTypeError, | |
351 | "wrong argument type" | |
352 | " (expected vector<" #T ">)"); | |
353 | } | |
354 | } else { | |
355 | void *ptr; | |
356 | SWIG_ConvertPtr($input, &ptr, $&1_descriptor, 1); | |
357 | $1 = *(($&1_type) ptr); | |
358 | } | |
359 | } | |
360 | %typemap(in) const vector<T>& (std::vector<T> temp), | |
361 | const vector<T>* (std::vector<T> temp) { | |
362 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
363 | unsigned int size = RARRAY($input)->len; | |
364 | temp = std::vector<T >(size); | |
365 | $1 = &temp; | |
366 | for (unsigned int i=0; i<size; i++) { | |
367 | VALUE o = RARRAY($input)->ptr[i]; | |
368 | if (CHECK(o)) | |
369 | temp[i] = (T)(CONVERT_FROM(o)); | |
370 | else | |
371 | rb_raise(rb_eTypeError, | |
372 | "wrong argument type" | |
373 | " (expected vector<" #T ">)"); | |
374 | } | |
375 | } else { | |
376 | SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 1); | |
377 | } | |
378 | } | |
379 | %typemap(out) vector<T> { | |
380 | $result = rb_ary_new2($1.size()); | |
381 | for (unsigned int i=0; i<$1.size(); i++) | |
382 | rb_ary_store($result,i,CONVERT_TO((($1_type &)$1)[i])); | |
383 | } | |
384 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { | |
385 | /* native sequence? */ | |
386 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
387 | unsigned int size = RARRAY($input)->len; | |
388 | if (size == 0) { | |
389 | /* an empty sequence can be of any type */ | |
390 | $1 = 1; | |
391 | } else { | |
392 | /* check the first element only */ | |
393 | VALUE o = RARRAY($input)->ptr[0]; | |
394 | if (CHECK(o)) | |
395 | $1 = 1; | |
396 | else | |
397 | $1 = 0; | |
398 | } | |
399 | } else { | |
400 | /* wrapped vector? */ | |
401 | std::vector<T >* v; | |
402 | if (SWIG_ConvertPtr($input,(void **) &v, | |
403 | $&1_descriptor,0) != -1) | |
404 | $1 = 1; | |
405 | else | |
406 | $1 = 0; | |
407 | } | |
408 | } | |
409 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, | |
410 | const vector<T>* { | |
411 | /* native sequence? */ | |
412 | if (rb_obj_is_kind_of($input,rb_cArray)) { | |
413 | unsigned int size = RARRAY($input)->len; | |
414 | if (size == 0) { | |
415 | /* an empty sequence can be of any type */ | |
416 | $1 = 1; | |
417 | } else { | |
418 | /* check the first element only */ | |
419 | VALUE o = RARRAY($input)->ptr[0]; | |
420 | if (CHECK(o)) | |
421 | $1 = 1; | |
422 | else | |
423 | $1 = 0; | |
424 | } | |
425 | } else { | |
426 | /* wrapped vector? */ | |
427 | std::vector<T >* v; | |
428 | if (SWIG_ConvertPtr($input,(void **) &v, | |
429 | $1_descriptor,0) != -1) | |
430 | $1 = 1; | |
431 | else | |
432 | $1 = 0; | |
433 | } | |
434 | } | |
435 | public: | |
436 | vector(unsigned int size = 0); | |
437 | vector(unsigned int size, const T& value); | |
438 | vector(const vector<T> &); | |
439 | ||
440 | %rename(__len__) size; | |
441 | unsigned int size() const; | |
442 | %rename("empty?") empty; | |
443 | bool empty() const; | |
444 | void clear(); | |
445 | %rename(push) push_back; | |
446 | void push_back(T x); | |
447 | %extend { | |
448 | T pop() throw (std::out_of_range) { | |
449 | if (self->size() == 0) | |
450 | throw std::out_of_range("pop from empty vector"); | |
451 | T x = self->back(); | |
452 | self->pop_back(); | |
453 | return x; | |
454 | } | |
455 | T __getitem__(int i) throw (std::out_of_range) { | |
456 | int size = int(self->size()); | |
457 | if (i<0) i += size; | |
458 | if (i>=0 && i<size) | |
459 | return (*self)[i]; | |
460 | else | |
461 | throw std::out_of_range("vector index out of range"); | |
462 | } | |
463 | void __setitem__(int i, T x) throw (std::out_of_range) { | |
464 | int size = int(self->size()); | |
465 | if (i<0) i+= size; | |
466 | if (i>=0 && i<size) | |
467 | (*self)[i] = x; | |
468 | else | |
469 | throw std::out_of_range("vector index out of range"); | |
470 | } | |
471 | void each() { | |
472 | for (unsigned int i=0; i<self->size(); i++) | |
473 | rb_yield(CONVERT_TO((*self)[i])); | |
474 | } | |
475 | } | |
476 | }; | |
477 | %enddef | |
478 | ||
479 | specialize_std_vector(bool,SWIG_BOOL_P,SWIG_RB2BOOL,SWIG_BOOL2RB); | |
480 | specialize_std_vector(char,FIXNUM_P,FIX2INT,INT2NUM); | |
481 | specialize_std_vector(int,FIXNUM_P,FIX2INT,INT2NUM); | |
482 | specialize_std_vector(short,FIXNUM_P,FIX2INT,INT2NUM); | |
483 | specialize_std_vector(long,FIXNUM_P,FIX2INT,INT2NUM); | |
484 | specialize_std_vector(unsigned char,FIXNUM_P,FIX2INT,INT2NUM); | |
485 | specialize_std_vector(unsigned int,FIXNUM_P,FIX2INT,INT2NUM); | |
486 | specialize_std_vector(unsigned short,FIXNUM_P,FIX2INT,INT2NUM); | |
487 | specialize_std_vector(unsigned long,FIXNUM_P,FIX2INT,INT2NUM); | |
488 | specialize_std_vector(double,SWIG_FLOAT_P,SWIG_NUM2DBL,rb_float_new); | |
489 | specialize_std_vector(float,SWIG_FLOAT_P,SWIG_NUM2DBL,rb_float_new); | |
490 | specialize_std_vector(std::string,SWIG_STRING_P,SWIG_RB2STR,SWIG_STR2RB); | |
491 | ||
492 | } | |
493 |