Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // |
2 | // SWIG typemaps for std::vector | |
3 | // Luigi Ballabio and Manu ??? and Kristopher Blom | |
4 | // Apr 26, 2002, updated Nov 13, 2002[blom] | |
5 | // | |
6 | // Tcl 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 | // Tcl as much as possible, namely, to allow the user to pass and | |
15 | // be returned Tcl 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 Tcl list 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 Tcl list of T:s | |
27 | // is returned which is most easily used in other Tcl functions procs | |
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 | #include <string> | |
39 | ||
40 | Tcl_Obj* SwigString_FromString(std::string s) { | |
41 | return Tcl_NewStringObj(s.c_str(), s.length()); | |
42 | } | |
43 | ||
44 | int SwigString_AsString(Tcl_Interp *interp, Tcl_Obj *o, std::string *val) { | |
45 | int len; | |
46 | const char* temp = Tcl_GetStringFromObj(o, &len); | |
47 | if(temp == NULL) | |
48 | return TCL_ERROR; | |
49 | *val = temp; | |
50 | return TCL_OK; | |
51 | } | |
52 | ||
53 | // behaviour of this is such as the real Tcl_GetIntFromObj | |
54 | template <typename Type> | |
55 | int SwigInt_As(Tcl_Interp *interp, Tcl_Obj *o, Type *val) { | |
56 | int temp_val, return_val; | |
57 | return_val = Tcl_GetIntFromObj(interp, o, &temp_val); | |
58 | *val = (Type) temp_val; | |
59 | return return_val; | |
60 | } | |
61 | ||
62 | // behaviour of this is such as the real Tcl_GetDoubleFromObj | |
63 | template <typename Type> | |
64 | int SwigDouble_As(Tcl_Interp *interp, Tcl_Obj *o, Type *val) { | |
65 | int return_val; | |
66 | double temp_val; | |
67 | return_val = Tcl_GetDoubleFromObj(interp, o, &temp_val); | |
68 | *val = (Type) temp_val; | |
69 | return return_val; | |
70 | } | |
71 | ||
72 | %} | |
73 | ||
74 | // exported class | |
75 | ||
76 | namespace std { | |
77 | ||
78 | template<class T> class vector { | |
79 | %typemap(in) vector<T> (std::vector<T> *v) { | |
80 | Tcl_Obj **listobjv; | |
81 | int nitems; | |
82 | int i; | |
83 | T* temp; | |
84 | ||
85 | if (SWIG_ConvertPtr($input, (void **) &v, \ | |
86 | $&1_descriptor, 0) == 0){ | |
87 | $1 = *v; | |
88 | } else { | |
89 | // It isn't a vector<T> so it should be a list of T's | |
90 | if(Tcl_ListObjGetElements(interp, $input, \ | |
91 | &nitems, &listobjv) == TCL_ERROR) | |
92 | return TCL_ERROR; | |
93 | $1 = std::vector<T>(); | |
94 | for (i = 0; i < nitems; i++) { | |
95 | if ((SWIG_ConvertPtr(listobjv[i],(void **) &temp, | |
96 | $descriptor(T *),0)) != 0) { | |
97 | char message[] = | |
98 | "list of " #T " expected"; | |
99 | Tcl_SetResult(interp, message, TCL_VOLATILE); | |
100 | return TCL_ERROR; | |
101 | } | |
102 | $1.push_back(*temp); | |
103 | } | |
104 | } | |
105 | } | |
106 | ||
107 | %typemap(in) const vector<T>* (std::vector<T> *v, std::vector<T> w), | |
108 | const vector<T>& (std::vector<T> *v, std::vector<T> w) { | |
109 | Tcl_Obj **listobjv; | |
110 | int nitems; | |
111 | int i; | |
112 | T* temp; | |
113 | ||
114 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
115 | $&1_descriptor, 0) == 0) { | |
116 | $1 = v; | |
117 | } else { | |
118 | // It isn't a vector<T> so it should be a list of T's | |
119 | if(Tcl_ListObjGetElements(interp, $input, | |
120 | &nitems, &listobjv) == TCL_ERROR) | |
121 | return TCL_ERROR; | |
122 | w = std::vector<T>(); | |
123 | for (i = 0; i < nitems; i++) { | |
124 | if ((SWIG_ConvertPtr(listobjv[i],(void **) &temp, | |
125 | $descriptor(T *),0)) != 0) { | |
126 | char message[] = | |
127 | "list of " #T " expected"; | |
128 | Tcl_SetResult(interp, message, TCL_VOLATILE); | |
129 | return TCL_ERROR; | |
130 | } | |
131 | w.push_back(*temp); | |
132 | } | |
133 | $1 = &w; | |
134 | } | |
135 | } | |
136 | ||
137 | %typemap(out) vector<T> { | |
138 | for (unsigned int i=0; i<$1.size(); i++) { | |
139 | T* ptr = new T((($1_type &)$1)[i]); | |
140 | Tcl_ListObjAppendElement(interp, $result, \ | |
141 | SWIG_NewInstanceObj(ptr, | |
142 | $descriptor(T *), | |
143 | 0)); | |
144 | } | |
145 | } | |
146 | ||
147 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { | |
148 | Tcl_Obj **listobjv; | |
149 | int nitems; | |
150 | T* temp; | |
151 | std::vector<T> *v; | |
152 | ||
153 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
154 | $&1_descriptor, 0) == 0) { | |
155 | /* wrapped vector */ | |
156 | $1 = 1; | |
157 | } else { | |
158 | // It isn't a vector<T> so it should be a list of T's | |
159 | if(Tcl_ListObjGetElements(interp, $input, | |
160 | &nitems, &listobjv) == TCL_ERROR) | |
161 | $1 = 0; | |
162 | else | |
163 | if (nitems == 0) | |
164 | $1 = 1; | |
165 | //check the first value to see if it is of correct type | |
166 | else if ((SWIG_ConvertPtr(listobjv[0], | |
167 | (void **) &temp, | |
168 | $descriptor(T *),0)) != 0) | |
169 | $1 = 0; | |
170 | else | |
171 | $1 = 1; | |
172 | } | |
173 | } | |
174 | ||
175 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, | |
176 | const vector<T>* { | |
177 | Tcl_Obj **listobjv; | |
178 | int nitems; | |
179 | T* temp; | |
180 | std::vector<T> *v; | |
181 | ||
182 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
183 | $1_descriptor, 0) == 0){ | |
184 | /* wrapped vector */ | |
185 | $1 = 1; | |
186 | } else { | |
187 | // It isn't a vector<T> so it should be a list of T's | |
188 | if(Tcl_ListObjGetElements(interp, $input, | |
189 | &nitems, &listobjv) == TCL_ERROR) | |
190 | $1 = 0; | |
191 | else | |
192 | if (nitems == 0) | |
193 | $1 = 1; | |
194 | //check the first value to see if it is of correct type | |
195 | else if ((SWIG_ConvertPtr(listobjv[0], | |
196 | (void **) &temp, | |
197 | $descriptor(T *),0)) != 0) | |
198 | $1 = 0; | |
199 | else | |
200 | $1 = 1; | |
201 | } | |
202 | } | |
203 | ||
204 | public: | |
205 | vector(unsigned int size = 0); | |
206 | vector(unsigned int size, const T& value); | |
207 | vector(const vector<T> &); | |
208 | ||
209 | unsigned int size() const; | |
210 | bool empty() const; | |
211 | void clear(); | |
212 | %rename(push) push_back; | |
213 | void push_back(const T& x); | |
214 | %extend { | |
215 | T pop() throw (std::out_of_range) { | |
216 | if (self->size() == 0) | |
217 | throw std::out_of_range("pop from empty vector"); | |
218 | T x = self->back(); | |
219 | self->pop_back(); | |
220 | return x; | |
221 | } | |
222 | T& get(int i) throw (std::out_of_range) { | |
223 | int size = int(self->size()); | |
224 | if (i<0) i += size; | |
225 | if (i>=0 && i<size) | |
226 | return (*self)[i]; | |
227 | else | |
228 | throw std::out_of_range("vector index out of range"); | |
229 | } | |
230 | void set(int i, const T& x) throw (std::out_of_range) { | |
231 | int size = int(self->size()); | |
232 | if (i<0) i+= size; | |
233 | if (i>=0 && i<size) | |
234 | (*self)[i] = x; | |
235 | else | |
236 | throw std::out_of_range("vector index out of range"); | |
237 | } | |
238 | } | |
239 | }; | |
240 | ||
241 | ||
242 | // specializations for built-ins | |
243 | ||
244 | %define specialize_std_vector(T, CONVERT_FROM, CONVERT_TO) | |
245 | template<> class vector<T> { | |
246 | ||
247 | %typemap(in) vector<T> (std::vector<T> *v){ | |
248 | Tcl_Obj **listobjv; | |
249 | int nitems; | |
250 | int i; | |
251 | T temp; | |
252 | ||
253 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
254 | $&1_descriptor, 0) == 0) { | |
255 | $1 = *v; | |
256 | } else { | |
257 | // It isn't a vector<T> so it should be a list of T's | |
258 | if(Tcl_ListObjGetElements(interp, $input, | |
259 | &nitems, &listobjv) == TCL_ERROR) | |
260 | return TCL_ERROR; | |
261 | $1 = std::vector<T>(); | |
262 | for (i = 0; i < nitems; i++) { | |
263 | if (CONVERT_FROM(interp, listobjv[i], &temp) == TCL_ERROR) | |
264 | return TCL_ERROR; | |
265 | $1.push_back(temp); | |
266 | } | |
267 | } | |
268 | } | |
269 | ||
270 | %typemap(in) const vector<T>& (std::vector<T> *v,std::vector<T> w), | |
271 | const vector<T>* (std::vector<T> *v,std::vector<T> w) { | |
272 | Tcl_Obj **listobjv; | |
273 | int nitems; | |
274 | int i; | |
275 | T temp; | |
276 | ||
277 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
278 | $1_descriptor, 0) == 0) { | |
279 | $1 = v; | |
280 | } else { | |
281 | // It isn't a vector<T> so it should be a list of T's | |
282 | if(Tcl_ListObjGetElements(interp, $input, | |
283 | &nitems, &listobjv) == TCL_ERROR) | |
284 | return TCL_ERROR; | |
285 | w = std::vector<T>(); | |
286 | for (i = 0; i < nitems; i++) { | |
287 | if (CONVERT_FROM(interp, listobjv[i], &temp) == TCL_ERROR) | |
288 | return TCL_ERROR; | |
289 | w.push_back(temp); | |
290 | } | |
291 | $1 = &w; | |
292 | } | |
293 | } | |
294 | ||
295 | %typemap(out) vector<T> { | |
296 | for (unsigned int i=0; i<$1.size(); i++) { | |
297 | Tcl_ListObjAppendElement(interp, $result, \ | |
298 | CONVERT_TO((($1_type &)$1)[i])); | |
299 | } | |
300 | } | |
301 | ||
302 | %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> { | |
303 | Tcl_Obj **listobjv; | |
304 | int nitems; | |
305 | T temp; | |
306 | std::vector<T> *v; | |
307 | ||
308 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
309 | $&1_descriptor, 0) == 0){ | |
310 | /* wrapped vector */ | |
311 | $1 = 1; | |
312 | } else { | |
313 | // It isn't a vector<T> so it should be a list of T's | |
314 | if(Tcl_ListObjGetElements(interp, $input, | |
315 | &nitems, &listobjv) == TCL_ERROR) | |
316 | $1 = 0; | |
317 | else | |
318 | if (nitems == 0) | |
319 | $1 = 1; | |
320 | //check the first value to see if it is of correct type | |
321 | if (CONVERT_FROM(interp, listobjv[0], &temp) == TCL_ERROR) | |
322 | $1 = 0; | |
323 | else | |
324 | $1 = 1; | |
325 | } | |
326 | } | |
327 | ||
328 | %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&, | |
329 | const vector<T>*{ | |
330 | Tcl_Obj **listobjv; | |
331 | int nitems; | |
332 | T temp; | |
333 | std::vector<T> *v; | |
334 | ||
335 | if(SWIG_ConvertPtr($input, (void **) &v, \ | |
336 | $1_descriptor, 0) == 0){ | |
337 | /* wrapped vector */ | |
338 | $1 = 1; | |
339 | } else { | |
340 | // It isn't a vector<T> so it should be a list of T's | |
341 | if(Tcl_ListObjGetElements(interp, $input, | |
342 | &nitems, &listobjv) == TCL_ERROR) | |
343 | $1 = 0; | |
344 | else | |
345 | if (nitems == 0) | |
346 | $1 = 1; | |
347 | //check the first value to see if it is of correct type | |
348 | if (CONVERT_FROM(interp, listobjv[0], &temp) == TCL_ERROR) | |
349 | $1 = 0; | |
350 | else | |
351 | $1 = 1; | |
352 | } | |
353 | } | |
354 | ||
355 | public: | |
356 | vector(unsigned int size = 0); | |
357 | vector(unsigned int size, const T& value); | |
358 | vector(const vector<T> &); | |
359 | ||
360 | unsigned int size() const; | |
361 | bool empty() const; | |
362 | void clear(); | |
363 | %rename(push) push_back; | |
364 | void push_back(T x); | |
365 | %extend { | |
366 | T pop() throw (std::out_of_range) { | |
367 | if (self->size() == 0) | |
368 | throw std::out_of_range("pop from empty vector"); | |
369 | T x = self->back(); | |
370 | self->pop_back(); | |
371 | return x; | |
372 | } | |
373 | T get(int i) throw (std::out_of_range) { | |
374 | int size = int(self->size()); | |
375 | if (i<0) i += size; | |
376 | if (i>=0 && i<size) | |
377 | return (*self)[i]; | |
378 | else | |
379 | throw std::out_of_range("vector index out of range"); | |
380 | } | |
381 | void set(int i, T x) throw (std::out_of_range) { | |
382 | int size = int(self->size()); | |
383 | if (i<0) i+= size; | |
384 | if (i>=0 && i<size) | |
385 | (*self)[i] = x; | |
386 | else | |
387 | throw std::out_of_range("vector index out of range"); | |
388 | } | |
389 | } | |
390 | }; | |
391 | %enddef | |
392 | ||
393 | specialize_std_vector(bool, Tcl_GetBoolFromObj, Tcl_NewBooleanObj); | |
394 | specialize_std_vector(char, Tcl_GetIntFromObj,Tcl_NewIntObj); | |
395 | specialize_std_vector(int, Tcl_GetIntFromObj,Tcl_NewIntObj); | |
396 | specialize_std_vector(short, SwigInt_As<short>, Tcl_NewIntObj); | |
397 | specialize_std_vector(long, SwigInt_As<long>, Tcl_NewIntObj); | |
398 | specialize_std_vector(unsigned char, | |
399 | SwigInt_As<unsigned char>, Tcl_NewIntObj); | |
400 | specialize_std_vector(unsigned int, | |
401 | SwigInt_As<unsigned int>, Tcl_NewIntObj); | |
402 | specialize_std_vector(unsigned short, | |
403 | SwigInt_As<unsigned short>, Tcl_NewIntObj); | |
404 | specialize_std_vector(unsigned long, | |
405 | SwigInt_As<unsigned long>, Tcl_NewIntObj); | |
406 | specialize_std_vector(double, Tcl_GetDoubleFromObj, Tcl_NewDoubleObj); | |
407 | specialize_std_vector(float, SwigDouble_As<float>, Tcl_NewDoubleObj); | |
408 | specialize_std_vector(std::string, | |
409 | SwigString_AsString, SwigString_FromString); | |
410 | ||
411 | } | |
412 | ||
413 |