Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // |
2 | // SWIG typemaps for std::vector | |
3 | // Luigi Ballabio | |
4 | // Apr 8, 2002 | |
5 | // | |
6 | // MzScheme 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 | // MzScheme as much as possible, namely, to allow the user to pass and | |
15 | // be returned MzScheme vectors or lists. | |
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 MzScheme sequence 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 MzScheme vector of T:s | |
27 | // is returned which is most easily used in other MzScheme 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 | template<class T> class vector { | |
45 | %typemap(in) vector<T> { | |
46 | if (SCHEME_VECTORP($input)) { | |
47 | unsigned int size = SCHEME_VEC_SIZE($input); | |
48 | $1 = std::vector<T >(size); | |
49 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
50 | for (unsigned int i=0; i<size; i++) { | |
51 | (($1_type &)$1)[i] = | |
52 | *((T*) SWIG_MustGetPtr(items[i], | |
53 | $descriptor(T *), | |
54 | $argnum, 0)); | |
55 | } | |
56 | } else if (SCHEME_NULLP($input)) { | |
57 | $1 = std::vector<T >(); | |
58 | } else if (SCHEME_PAIRP($input)) { | |
59 | Scheme_Object *head, *tail; | |
60 | $1 = std::vector<T >(); | |
61 | tail = $input; | |
62 | while (!SCHEME_NULLP(tail)) { | |
63 | head = scheme_car(tail); | |
64 | tail = scheme_cdr(tail); | |
65 | $1.push_back(*((T*)SWIG_MustGetPtr(head, | |
66 | $descriptor(T *), | |
67 | $argnum, 0))); | |
68 | } | |
69 | } else { | |
70 | $1 = *(($&1_type) | |
71 | SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); | |
72 | } | |
73 | } | |
74 | %typemap(in) const vector<T>& (std::vector<T> temp), | |
75 | const vector<T>* (std::vector<T> temp) { | |
76 | if (SCHEME_VECTORP($input)) { | |
77 | unsigned int size = SCHEME_VEC_SIZE($input); | |
78 | temp = std::vector<T >(size); | |
79 | $1 = &temp; | |
80 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
81 | for (unsigned int i=0; i<size; i++) { | |
82 | temp[i] = *((T*) SWIG_MustGetPtr(items[i], | |
83 | $descriptor(T *), | |
84 | $argnum, 0)); | |
85 | } | |
86 | } else if (SCHEME_NULLP($input)) { | |
87 | temp = std::vector<T >(); | |
88 | $1 = &temp; | |
89 | } else if (SCHEME_PAIRP($input)) { | |
90 | temp = std::vector<T >(); | |
91 | $1 = &temp; | |
92 | Scheme_Object *head, *tail; | |
93 | tail = $input; | |
94 | while (!SCHEME_NULLP(tail)) { | |
95 | head = scheme_car(tail); | |
96 | tail = scheme_cdr(tail); | |
97 | temp.push_back(*((T*) SWIG_MustGetPtr(head, | |
98 | $descriptor(T *), | |
99 | $argnum, 0))); | |
100 | } | |
101 | } else { | |
102 | $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum, 0); | |
103 | } | |
104 | } | |
105 | %typemap(out) vector<T> { | |
106 | $result = scheme_make_vector($1.size(),scheme_undefined); | |
107 | Scheme_Object** els = SCHEME_VEC_ELS($result); | |
108 | for (unsigned int i=0; i<$1.size(); i++) { | |
109 | T* x = new T((($1_type &)$1)[i]); | |
110 | els[i] = SWIG_NewPointerObj(x,$descriptor(T *), 1); | |
111 | } | |
112 | } | |
113 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { | |
114 | /* native sequence? */ | |
115 | if (SCHEME_VECTORP($input)) { | |
116 | unsigned int size = SCHEME_VEC_SIZE($input); | |
117 | if (size == 0) { | |
118 | /* an empty sequence can be of any type */ | |
119 | $1 = 1; | |
120 | } else { | |
121 | /* check the first element only */ | |
122 | T* x; | |
123 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
124 | if (SWIG_ConvertPtr(items[0],(void**) &x, | |
125 | $descriptor(T *), 0) != -1) | |
126 | $1 = 1; | |
127 | else | |
128 | $1 = 0; | |
129 | } | |
130 | } else if (SCHEME_NULLP($input)) { | |
131 | /* again, an empty sequence can be of any type */ | |
132 | $1 = 1; | |
133 | } else if (SCHEME_PAIRP($input)) { | |
134 | /* check the first element only */ | |
135 | T* x; | |
136 | Scheme_Object *head = scheme_car($input); | |
137 | if (SWIG_ConvertPtr(head,(void**) &x, | |
138 | $descriptor(T *), 0) != -1) | |
139 | $1 = 1; | |
140 | else | |
141 | $1 = 0; | |
142 | } else { | |
143 | /* wrapped vector? */ | |
144 | std::vector<T >* v; | |
145 | if (SWIG_ConvertPtr($input,(void **) &v, | |
146 | $&1_descriptor, 0) != -1) | |
147 | $1 = 1; | |
148 | else | |
149 | $1 = 0; | |
150 | } | |
151 | } | |
152 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, | |
153 | const vector<T>* { | |
154 | /* native sequence? */ | |
155 | if (SCHEME_VECTORP($input)) { | |
156 | unsigned int size = SCHEME_VEC_SIZE($input); | |
157 | if (size == 0) { | |
158 | /* an empty sequence can be of any type */ | |
159 | $1 = 1; | |
160 | } else { | |
161 | /* check the first element only */ | |
162 | T* x; | |
163 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
164 | if (SWIG_ConvertPtr(items[0],(void**) &x, | |
165 | $descriptor(T *), 0) != -1) | |
166 | $1 = 1; | |
167 | else | |
168 | $1 = 0; | |
169 | } | |
170 | } else if (SCHEME_NULLP($input)) { | |
171 | /* again, an empty sequence can be of any type */ | |
172 | $1 = 1; | |
173 | } else if (SCHEME_PAIRP($input)) { | |
174 | /* check the first element only */ | |
175 | T* x; | |
176 | Scheme_Object *head = scheme_car($input); | |
177 | if (SWIG_ConvertPtr(head,(void**) &x, | |
178 | $descriptor(T *), 0) != -1) | |
179 | $1 = 1; | |
180 | else | |
181 | $1 = 0; | |
182 | } else { | |
183 | /* wrapped vector? */ | |
184 | std::vector<T >* v; | |
185 | if (SWIG_ConvertPtr($input,(void **) &v, | |
186 | $1_descriptor, 0) != -1) | |
187 | $1 = 1; | |
188 | else | |
189 | $1 = 0; | |
190 | } | |
191 | } | |
192 | public: | |
193 | vector(unsigned int size = 0); | |
194 | vector(unsigned int size, const T& value); | |
195 | vector(const vector<T>&); | |
196 | %rename(length) size; | |
197 | unsigned int size() const; | |
198 | %rename("empty?") empty; | |
199 | bool empty() const; | |
200 | %rename("clear!") clear; | |
201 | void clear(); | |
202 | %rename("set!") set; | |
203 | %rename("pop!") pop; | |
204 | %rename("push!") push_back; | |
205 | void push_back(const T& x); | |
206 | %extend { | |
207 | T pop() throw (std::out_of_range) { | |
208 | if (self->size() == 0) | |
209 | throw std::out_of_range("pop from empty vector"); | |
210 | T x = self->back(); | |
211 | self->pop_back(); | |
212 | return x; | |
213 | } | |
214 | T& ref(int i) throw (std::out_of_range) { | |
215 | int size = int(self->size()); | |
216 | if (i>=0 && i<size) | |
217 | return (*self)[i]; | |
218 | else | |
219 | throw std::out_of_range("vector index out of range"); | |
220 | } | |
221 | void set(int i, const T& x) throw (std::out_of_range) { | |
222 | int size = int(self->size()); | |
223 | if (i>=0 && i<size) | |
224 | (*self)[i] = x; | |
225 | else | |
226 | throw std::out_of_range("vector index out of range"); | |
227 | } | |
228 | } | |
229 | }; | |
230 | ||
231 | ||
232 | // specializations for built-ins | |
233 | ||
234 | %define specialize_std_vector(T,CHECK,CONVERT_FROM,CONVERT_TO) | |
235 | template<> class vector<T> { | |
236 | %typemap(in) vector<T> { | |
237 | if (SCHEME_VECTORP($input)) { | |
238 | unsigned int size = SCHEME_VEC_SIZE($input); | |
239 | $1 = std::vector<T >(size); | |
240 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
241 | for (unsigned int i=0; i<size; i++) { | |
242 | Scheme_Object* o = items[i]; | |
243 | if (CHECK(o)) | |
244 | (($1_type &)$1)[i] = (T)(CONVERT_FROM(o)); | |
245 | else | |
246 | scheme_wrong_type(FUNC_NAME, "vector<" #T ">", | |
247 | $argnum - 1, argc, argv); | |
248 | } | |
249 | } else if (SCHEME_NULLP($input)) { | |
250 | $1 = std::vector<T >(); | |
251 | } else if (SCHEME_PAIRP($input)) { | |
252 | Scheme_Object *head, *tail; | |
253 | $1 = std::vector<T >(); | |
254 | tail = $input; | |
255 | while (!SCHEME_NULLP(tail)) { | |
256 | head = scheme_car(tail); | |
257 | tail = scheme_cdr(tail); | |
258 | if (CHECK(head)) | |
259 | $1.push_back((T)(CONVERT_FROM(head))); | |
260 | else | |
261 | scheme_wrong_type(FUNC_NAME, "vector<" #T ">", | |
262 | $argnum - 1, argc, argv); | |
263 | } | |
264 | } else { | |
265 | $1 = *(($&1_type) | |
266 | SWIG_MustGetPtr($input,$&1_descriptor,$argnum, 0)); | |
267 | } | |
268 | } | |
269 | %typemap(in) const vector<T>& (std::vector<T> temp), | |
270 | const vector<T>* (std::vector<T> temp) { | |
271 | if (SCHEME_VECTORP($input)) { | |
272 | unsigned int size = SCHEME_VEC_SIZE($input); | |
273 | temp = std::vector<T >(size); | |
274 | $1 = &temp; | |
275 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
276 | for (unsigned int i=0; i<size; i++) { | |
277 | Scheme_Object* o = items[i]; | |
278 | if (CHECK(o)) | |
279 | temp[i] = (T)(CONVERT_FROM(o)); | |
280 | else | |
281 | scheme_wrong_type(FUNC_NAME, "vector<" #T ">", | |
282 | $argnum - 1, argc, argv); | |
283 | } | |
284 | } else if (SCHEME_NULLP($input)) { | |
285 | temp = std::vector<T >(); | |
286 | $1 = &temp; | |
287 | } else if (SCHEME_PAIRP($input)) { | |
288 | temp = std::vector<T >(); | |
289 | $1 = &temp; | |
290 | Scheme_Object *head, *tail; | |
291 | tail = $input; | |
292 | while (!SCHEME_NULLP(tail)) { | |
293 | head = scheme_car(tail); | |
294 | tail = scheme_cdr(tail); | |
295 | if (CHECK(head)) | |
296 | temp.push_back((T)(CONVERT_FROM(head))); | |
297 | else | |
298 | scheme_wrong_type(FUNC_NAME, "vector<" #T ">", | |
299 | $argnum - 1, argc, argv); | |
300 | } | |
301 | } else { | |
302 | $1 = ($1_ltype) SWIG_MustGetPtr($input,$1_descriptor,$argnum - 1, 0); | |
303 | } | |
304 | } | |
305 | %typemap(out) vector<T> { | |
306 | $result = scheme_make_vector($1.size(),scheme_undefined); | |
307 | Scheme_Object** els = SCHEME_VEC_ELS($result); | |
308 | for (unsigned int i=0; i<$1.size(); i++) | |
309 | els[i] = CONVERT_TO((($1_type &)$1)[i]); | |
310 | } | |
311 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { | |
312 | /* native sequence? */ | |
313 | if (SCHEME_VECTORP($input)) { | |
314 | unsigned int size = SCHEME_VEC_SIZE($input); | |
315 | if (size == 0) { | |
316 | /* an empty sequence can be of any type */ | |
317 | $1 = 1; | |
318 | } else { | |
319 | /* check the first element only */ | |
320 | T* x; | |
321 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
322 | $1 = CHECK(items[0]) ? 1 : 0; | |
323 | } | |
324 | } else if (SCHEME_NULLP($input)) { | |
325 | /* again, an empty sequence can be of any type */ | |
326 | $1 = 1; | |
327 | } else if (SCHEME_PAIRP($input)) { | |
328 | /* check the first element only */ | |
329 | T* x; | |
330 | Scheme_Object *head = scheme_car($input); | |
331 | $1 = CHECK(head) ? 1 : 0; | |
332 | } else { | |
333 | /* wrapped vector? */ | |
334 | std::vector<T >* v; | |
335 | $1 = (SWIG_ConvertPtr($input,(void **) &v, | |
336 | $&1_descriptor, 0) != -1) ? 1 : 0; | |
337 | } | |
338 | } | |
339 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, | |
340 | const vector<T>* { | |
341 | /* native sequence? */ | |
342 | if (SCHEME_VECTORP($input)) { | |
343 | unsigned int size = SCHEME_VEC_SIZE($input); | |
344 | if (size == 0) { | |
345 | /* an empty sequence can be of any type */ | |
346 | $1 = 1; | |
347 | } else { | |
348 | /* check the first element only */ | |
349 | T* x; | |
350 | Scheme_Object** items = SCHEME_VEC_ELS($input); | |
351 | $1 = CHECK(items[0]) ? 1 : 0; | |
352 | } | |
353 | } else if (SCHEME_NULLP($input)) { | |
354 | /* again, an empty sequence can be of any type */ | |
355 | $1 = 1; | |
356 | } else if (SCHEME_PAIRP($input)) { | |
357 | /* check the first element only */ | |
358 | T* x; | |
359 | Scheme_Object *head = scheme_car($input); | |
360 | $1 = CHECK(head) ? 1 : 0; | |
361 | } else { | |
362 | /* wrapped vector? */ | |
363 | std::vector<T >* v; | |
364 | $1 = (SWIG_ConvertPtr($input,(void **) &v, | |
365 | $1_descriptor, 0) != -1) ? 1 : 0; | |
366 | } | |
367 | } | |
368 | public: | |
369 | vector(unsigned int size = 0); | |
370 | vector(unsigned int size, const T& value); | |
371 | vector(const vector<T>&); | |
372 | %rename(length) size; | |
373 | unsigned int size() const; | |
374 | %rename("empty?") empty; | |
375 | bool empty() const; | |
376 | %rename("clear!") clear; | |
377 | void clear(); | |
378 | %rename("set!") set; | |
379 | %rename("pop!") pop; | |
380 | %rename("push!") push_back; | |
381 | void push_back(T x); | |
382 | %extend { | |
383 | T pop() throw (std::out_of_range) { | |
384 | if (self->size() == 0) | |
385 | throw std::out_of_range("pop from empty vector"); | |
386 | T x = self->back(); | |
387 | self->pop_back(); | |
388 | return x; | |
389 | } | |
390 | T ref(int i) throw (std::out_of_range) { | |
391 | int size = int(self->size()); | |
392 | if (i>=0 && i<size) | |
393 | return (*self)[i]; | |
394 | else | |
395 | throw std::out_of_range("vector index out of range"); | |
396 | } | |
397 | void set(int i, T x) throw (std::out_of_range) { | |
398 | int size = int(self->size()); | |
399 | if (i>=0 && i<size) | |
400 | (*self)[i] = x; | |
401 | else | |
402 | throw std::out_of_range("vector index out of range"); | |
403 | } | |
404 | } | |
405 | }; | |
406 | %enddef | |
407 | ||
408 | specialize_std_vector(bool,SCHEME_BOOLP,SCHEME_TRUEP,\ | |
409 | swig_make_boolean); | |
410 | specialize_std_vector(char,SCHEME_INTP,SCHEME_INT_VAL,\ | |
411 | scheme_make_integer_value); | |
412 | specialize_std_vector(int,SCHEME_INTP,SCHEME_INT_VAL,\ | |
413 | scheme_make_integer_value); | |
414 | specialize_std_vector(short,SCHEME_INTP,SCHEME_INT_VAL,\ | |
415 | scheme_make_integer_value); | |
416 | specialize_std_vector(long,SCHEME_INTP,SCHEME_INT_VAL,\ | |
417 | scheme_make_integer_value); | |
418 | specialize_std_vector(unsigned char,SCHEME_INTP,SCHEME_INT_VAL,\ | |
419 | scheme_make_integer_value); | |
420 | specialize_std_vector(unsigned int,SCHEME_INTP,SCHEME_INT_VAL,\ | |
421 | scheme_make_integer_value); | |
422 | specialize_std_vector(unsigned short,SCHEME_INTP,SCHEME_INT_VAL,\ | |
423 | scheme_make_integer_value); | |
424 | specialize_std_vector(unsigned long,SCHEME_INTP,SCHEME_INT_VAL,\ | |
425 | scheme_make_integer_value); | |
426 | specialize_std_vector(float,SCHEME_REALP,scheme_real_to_double,\ | |
427 | scheme_make_double); | |
428 | specialize_std_vector(double,SCHEME_REALP,scheme_real_to_double,\ | |
429 | scheme_make_double); | |
430 | specialize_std_vector(std::string,SCHEME_STRINGP,swig_scm_to_string,\ | |
431 | swig_make_string); | |
432 | ||
433 | } | |
434 |