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