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