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