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