Home | History | Annotate | Download | only in perl5
      1 /* -----------------------------------------------------------------------------
      2  * std_vector.i
      3  *
      4  * SWIG typemaps for std::vector types
      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 // Perl as much as possible, namely, to allow the user to pass and
     14 // be returned Perl arrays.
     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 Perl 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 Perl sequence of T:s
     26 //      is returned which is most easily used in other Perl 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> (std::vector<T>* v) {
     45             if (SWIG_ConvertPtr($input,(void **) &v,
     46                                 $&1_descriptor,1) != -1) {
     47                 $1 = *v;
     48             } else if (SvROK($input)) {
     49                 AV *av = (AV *)SvRV($input);
     50                 if (SvTYPE(av) != SVt_PVAV)
     51                     SWIG_croak("Type error in argument $argnum of $symname. "
     52                                "Expected an array of " #T);
     53                 SV **tv;
     54                 I32 len = av_len(av) + 1;
     55                 T* obj;
     56                 for (int i=0; i<len; i++) {
     57                     tv = av_fetch(av, i, 0);
     58                     if (SWIG_ConvertPtr(*tv, (void **)&obj,
     59                                         $descriptor(T *),0) != -1) {
     60                         $1.push_back(*obj);
     61                     } else {
     62                         SWIG_croak("Type error in argument $argnum of "
     63                                    "$symname. "
     64                                    "Expected an array of " #T);
     65                     }
     66                 }
     67             } else {
     68                 SWIG_croak("Type error in argument $argnum of $symname. "
     69                            "Expected an array of " #T);
     70             }
     71         }
     72         %typemap(in) const vector<T>& (std::vector<T> temp,
     73                                        std::vector<T>* v),
     74                      const vector<T>* (std::vector<T> temp,
     75                                        std::vector<T>* v) {
     76             if (SWIG_ConvertPtr($input,(void **) &v,
     77                                 $1_descriptor,1) != -1) {
     78                 $1 = v;
     79             } else if (SvROK($input)) {
     80                 AV *av = (AV *)SvRV($input);
     81                 if (SvTYPE(av) != SVt_PVAV)
     82                     SWIG_croak("Type error in argument $argnum of $symname. "
     83                                "Expected an array of " #T);
     84                 SV **tv;
     85                 I32 len = av_len(av) + 1;
     86                 T* obj;
     87                 for (int i=0; i<len; i++) {
     88                     tv = av_fetch(av, i, 0);
     89                     if (SWIG_ConvertPtr(*tv, (void **)&obj,
     90                                         $descriptor(T *),0) != -1) {
     91                         temp.push_back(*obj);
     92                     } else {
     93                         SWIG_croak("Type error in argument $argnum of "
     94                                    "$symname. "
     95                                    "Expected an array of " #T);
     96                     }
     97                 }
     98                 $1 = &temp;
     99             } else {
    100                 SWIG_croak("Type error in argument $argnum of $symname. "
    101                            "Expected an array of " #T);
    102             }
    103         }
    104         %typemap(out) vector<T> {
    105             size_t len = $1.size();
    106             SV **svs = new SV*[len];
    107             for (size_t i=0; i<len; i++) {
    108                 T* ptr = new T($1[i]);
    109                 svs[i] = sv_newmortal();
    110                 SWIG_MakePtr(svs[i], (void*) ptr,
    111                              $descriptor(T *), $shadow|$owner);
    112             }
    113             AV *myav = av_make(len, svs);
    114             delete[] svs;
    115             $result = newRV_noinc((SV*) myav);
    116             sv_2mortal($result);
    117             argvi++;
    118         }
    119         %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
    120             {
    121                 /* wrapped vector? */
    122                 std::vector<T >* v;
    123                 if (SWIG_ConvertPtr($input,(void **) &v,
    124                                     $&1_descriptor,0) != -1) {
    125                     $1 = 1;
    126                 } else if (SvROK($input)) {
    127                     /* native sequence? */
    128                     AV *av = (AV *)SvRV($input);
    129                     if (SvTYPE(av) == SVt_PVAV) {
    130                         I32 len = av_len(av) + 1;
    131                         if (len == 0) {
    132                             /* an empty sequence can be of any type */
    133                             $1 = 1;
    134                         } else {
    135                             /* check the first element only */
    136                             T* obj;
    137                             SV **tv = av_fetch(av, 0, 0);
    138                             if (SWIG_ConvertPtr(*tv, (void **)&obj,
    139                                                 $descriptor(T *),0) != -1)
    140                                 $1 = 1;
    141                             else
    142                                 $1 = 0;
    143                         }
    144                     }
    145                 } else {
    146                     $1 = 0;
    147                 }
    148             }
    149         }
    150         %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
    151                                           const vector<T>* {
    152             {
    153                 /* wrapped vector? */
    154                 std::vector<T >* v;
    155                 if (SWIG_ConvertPtr($input,(void **) &v,
    156                                     $1_descriptor,0) != -1) {
    157                     $1 = 1;
    158                 } else if (SvROK($input)) {
    159                     /* native sequence? */
    160                     AV *av = (AV *)SvRV($input);
    161                     if (SvTYPE(av) == SVt_PVAV) {
    162                         I32 len = av_len(av) + 1;
    163                         if (len == 0) {
    164                             /* an empty sequence can be of any type */
    165                             $1 = 1;
    166                         } else {
    167                             /* check the first element only */
    168                             T* obj;
    169                             SV **tv = av_fetch(av, 0, 0);
    170                             if (SWIG_ConvertPtr(*tv, (void **)&obj,
    171                                                 $descriptor(T *),0) != -1)
    172                                 $1 = 1;
    173                             else
    174                                 $1 = 0;
    175                         }
    176                     }
    177                 } else {
    178                     $1 = 0;
    179                 }
    180             }
    181         }
    182       public:
    183         typedef size_t size_type;
    184         typedef T value_type;
    185         typedef const value_type& const_reference;
    186         vector(unsigned int size = 0);
    187         vector(unsigned int size, const T& value);
    188         vector(const vector<T> &);
    189 
    190         unsigned int size() const;
    191         bool empty() const;
    192         void clear();
    193         %rename(push) push_back;
    194         void push_back(const T& x);
    195         %extend {
    196             T pop() throw (std::out_of_range) {
    197                 if (self->size() == 0)
    198                     throw std::out_of_range("pop from empty vector");
    199                 T x = self->back();
    200                 self->pop_back();
    201                 return x;
    202             }
    203             T& get(int i) throw (std::out_of_range) {
    204                 int size = int(self->size());
    205                 if (i>=0 && i<size)
    206                     return (*self)[i];
    207                 else
    208                     throw std::out_of_range("vector index out of range");
    209             }
    210             void set(int i, const T& x) throw (std::out_of_range) {
    211                 int size = int(self->size());
    212                 if (i>=0 && i<size)
    213                     (*self)[i] = x;
    214                 else
    215                     throw std::out_of_range("vector index out of range");
    216             }
    217         }
    218     };
    219 
    220     // specializations for pointers
    221     template<class T> class vector<T*> {
    222         %typemap(in) vector<T*> (std::vector<T*>* v) {
    223 	    int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0);
    224             if (SWIG_IsOK(res)){
    225                 $1 = *v;
    226             } else if (SvROK($input)) {
    227                 AV *av = (AV *)SvRV($input);
    228                 if (SvTYPE(av) != SVt_PVAV)
    229                     SWIG_croak("Type error in argument $argnum of $symname. "
    230                                "Expected an array of " #T);
    231                 I32 len = av_len(av) + 1;
    232                 for (int i=0; i<len; i++) {
    233 		    void *v;
    234 		    SV **tv = av_fetch(av, i, 0);
    235 		    int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
    236                     if (SWIG_IsOK(res)) {
    237                         $1.push_back(%static_cast(v, T *));
    238                     } else {
    239                         SWIG_croak("Type error in argument $argnum of "
    240                                    "$symname. "
    241                                    "Expected an array of " #T);
    242                     }
    243                 }
    244             } else {
    245                 SWIG_croak("Type error in argument $argnum of $symname. "
    246                            "Expected an array of " #T);
    247             }
    248         }
    249         %typemap(in) const vector<T *>& (std::vector<T *> temp,std::vector<T *>* v),
    250                      const vector<T *>* (std::vector<T *> temp,std::vector<T *>* v) {
    251 	    int res = SWIG_ConvertPtr($input,(void **) &v, $1_descriptor,0);
    252             if (SWIG_IsOK(res)) {
    253                 $1 = v;
    254             } else if (SvROK($input)) {
    255                 AV *av = (AV *)SvRV($input);
    256                 if (SvTYPE(av) != SVt_PVAV)
    257                     SWIG_croak("Type error in argument $argnum of $symname. "
    258                                "Expected an array of " #T);
    259                 I32 len = av_len(av) + 1;
    260                 for (int i=0; i<len; i++) {
    261 		    void *v;
    262 		    SV **tv = av_fetch(av, i, 0);
    263 		    int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
    264                     if (SWIG_IsOK(res)) {
    265                         temp.push_back(%static_cast(v, T *));
    266                     } else {
    267                         SWIG_croak("Type error in argument $argnum of "
    268                                    "$symname. "
    269                                    "Expected an array of " #T);
    270                     }
    271                 }
    272                 $1 = &temp;
    273             } else {
    274                 SWIG_croak("Type error in argument $argnum of $symname. "
    275                            "Expected an array of " #T);
    276             }
    277         }
    278         %typemap(out) vector<T *> {
    279             size_t len = $1.size();
    280             SV **svs = new SV*[len];
    281             for (size_t i=0; i<len; i++) {
    282                 T *x = (($1_type &)$1)[i];
    283                 svs[i] = sv_newmortal();
    284 		sv_setsv(svs[i], SWIG_NewPointerObj(x, $descriptor(T *), 0));
    285             }
    286             AV *myav = av_make(len, svs);
    287             delete[] svs;
    288             $result = newRV_noinc((SV*) myav);
    289             sv_2mortal($result);
    290             argvi++;
    291         }
    292         %typecheck(SWIG_TYPECHECK_VECTOR) vector<T *> {
    293             {
    294                 /* wrapped vector? */
    295                 std::vector<T *>* v;
    296 		int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0);
    297                 if (SWIG_IsOK(res)) {
    298                     $1 = 1;
    299                 } else if (SvROK($input)) {
    300                     /* native sequence? */
    301                     AV *av = (AV *)SvRV($input);
    302                     if (SvTYPE(av) == SVt_PVAV) {
    303                         I32 len = av_len(av) + 1;
    304                         if (len == 0) {
    305                             /* an empty sequence can be of any type */
    306                             $1 = 1;
    307                         } else {
    308                             /* check the first element only */
    309 			    void *v;
    310 			    SV **tv = av_fetch(av, 0, 0);
    311 			    int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
    312                             if (SWIG_IsOK(res))
    313                                 $1 = 1;
    314                             else
    315                                 $1 = 0;
    316                         }
    317                     }
    318                 } else {
    319                     $1 = 0;
    320                 }
    321             }
    322         }
    323         %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T *>&,const vector<T *>* {
    324             {
    325                 /* wrapped vector? */
    326                 std::vector<T *> *v;
    327 		int res = SWIG_ConvertPtr($input,%as_voidptrptr(&v), $1_descriptor,0);
    328                 if (SWIG_IsOK(res)) {
    329                     $1 = 1;
    330                 } else if (SvROK($input)) {
    331                     /* native sequence? */
    332                     AV *av = (AV *)SvRV($input);
    333                     if (SvTYPE(av) == SVt_PVAV) {
    334                         I32 len = av_len(av) + 1;
    335                         if (len == 0) {
    336                             /* an empty sequence can be of any type */
    337                             $1 = 1;
    338                         } else {
    339                             /* check the first element only */
    340 			    void *v;
    341 			    SV **tv = av_fetch(av, 0, 0);
    342 			    int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
    343                             if (SWIG_IsOK(res))
    344                                 $1 = 1;
    345                             else
    346                                 $1 = 0;
    347                         }
    348                     }
    349                 } else {
    350                     $1 = 0;
    351                 }
    352             }
    353         }
    354       public:
    355         typedef size_t size_type;
    356         typedef T value_type;
    357         typedef const value_type& const_reference;
    358         vector(unsigned int size = 0);
    359         vector(unsigned int size, T *value);
    360         vector(const vector<T *> &);
    361 
    362         unsigned int size() const;
    363         bool empty() const;
    364         void clear();
    365         %rename(push) push_back;
    366         void push_back(T *x);
    367         %extend {
    368             T *pop() throw (std::out_of_range) {
    369                 if (self->size() == 0)
    370                     throw std::out_of_range("pop from empty vector");
    371                 T *x = self->back();
    372                 self->pop_back();
    373                 return x;
    374             }
    375             T *get(int i) throw (std::out_of_range) {
    376                 int size = int(self->size());
    377                 if (i>=0 && i<size)
    378                     return (*self)[i];
    379                 else
    380                     throw std::out_of_range("vector index out of range");
    381             }
    382             void set(int i, T *x) throw (std::out_of_range) {
    383                 int size = int(self->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 
    392 
    393     // specializations for built-ins
    394 
    395     %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T)
    396     template<> class vector<T> {
    397         %typemap(in) vector<T> (std::vector<T>* v) {
    398             if (SWIG_ConvertPtr($input,(void **) &v,
    399                                 $&1_descriptor,1) != -1){
    400                 $1 = *v;
    401             } else if (SvROK($input)) {
    402                 AV *av = (AV *)SvRV($input);
    403                 if (SvTYPE(av) != SVt_PVAV)
    404                     SWIG_croak("Type error in argument $argnum of $symname. "
    405                                "Expected an array of " #T);
    406                 SV **tv;
    407                 I32 len = av_len(av) + 1;
    408                 for (int i=0; i<len; i++) {
    409                     tv = av_fetch(av, i, 0);
    410                     if (CHECK_T(*tv)) {
    411                         $1.push_back((T)TO_T(*tv));
    412                     } else {
    413                         SWIG_croak("Type error in argument $argnum of "
    414                                    "$symname. "
    415                                    "Expected an array of " #T);
    416                     }
    417                 }
    418             } else {
    419                 SWIG_croak("Type error in argument $argnum of $symname. "
    420                            "Expected an array of " #T);
    421             }
    422         }
    423         %typemap(in) const vector<T>& (std::vector<T> temp,
    424                                        std::vector<T>* v),
    425                      const vector<T>* (std::vector<T> temp,
    426                                        std::vector<T>* v) {
    427             if (SWIG_ConvertPtr($input,(void **) &v,
    428                                 $1_descriptor,1) != -1) {
    429                 $1 = v;
    430             } else if (SvROK($input)) {
    431                 AV *av = (AV *)SvRV($input);
    432                 if (SvTYPE(av) != SVt_PVAV)
    433                     SWIG_croak("Type error in argument $argnum of $symname. "
    434                                "Expected an array of " #T);
    435                 SV **tv;
    436                 I32 len = av_len(av) + 1;
    437                 for (int i=0; i<len; i++) {
    438                     tv = av_fetch(av, i, 0);
    439                     if (CHECK_T(*tv)) {
    440                         temp.push_back((T)TO_T(*tv));
    441                     } else {
    442                         SWIG_croak("Type error in argument $argnum of "
    443                                    "$symname. "
    444                                    "Expected an array of " #T);
    445                     }
    446                 }
    447                 $1 = &temp;
    448             } else {
    449                 SWIG_croak("Type error in argument $argnum of $symname. "
    450                            "Expected an array of " #T);
    451             }
    452         }
    453         %typemap(out) vector<T> {
    454             size_t len = $1.size();
    455             SV **svs = new SV*[len];
    456             for (size_t i=0; i<len; i++) {
    457                 svs[i] = sv_newmortal();
    458                 FROM_T(svs[i], $1[i]);
    459             }
    460             AV *myav = av_make(len, svs);
    461             delete[] svs;
    462             $result = newRV_noinc((SV*) myav);
    463             sv_2mortal($result);
    464             argvi++;
    465         }
    466         %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
    467             {
    468                 /* wrapped vector? */
    469                 std::vector<T >* v;
    470                 if (SWIG_ConvertPtr($input,(void **) &v,
    471                                     $&1_descriptor,0) != -1) {
    472                     $1 = 1;
    473                 } else if (SvROK($input)) {
    474                     /* native sequence? */
    475                     AV *av = (AV *)SvRV($input);
    476                     if (SvTYPE(av) == SVt_PVAV) {
    477                         I32 len = av_len(av) + 1;
    478                         if (len == 0) {
    479                             /* an empty sequence can be of any type */
    480                             $1 = 1;
    481                         } else {
    482                             /* check the first element only */
    483                             SV **tv = av_fetch(av, 0, 0);
    484                             if (CHECK_T(*tv))
    485                                 $1 = 1;
    486                             else
    487                                 $1 = 0;
    488                         }
    489                     }
    490                 } else {
    491                     $1 = 0;
    492                 }
    493             }
    494         }
    495         %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
    496                                           const vector<T>* {
    497             {
    498                 /* wrapped vector? */
    499                 std::vector<T >* v;
    500                 if (SWIG_ConvertPtr($input,(void **) &v,
    501                                     $1_descriptor,0) != -1) {
    502                     $1 = 1;
    503                 } else if (SvROK($input)) {
    504                     /* native sequence? */
    505                     AV *av = (AV *)SvRV($input);
    506                     if (SvTYPE(av) == SVt_PVAV) {
    507                         I32 len = av_len(av) + 1;
    508                         if (len == 0) {
    509                             /* an empty sequence can be of any type */
    510                             $1 = 1;
    511                         } else {
    512                             /* check the first element only */
    513                             SV **tv = av_fetch(av, 0, 0);
    514                             if (CHECK_T(*tv))
    515                                 $1 = 1;
    516                             else
    517                                 $1 = 0;
    518                         }
    519                     }
    520                 } else {
    521                     $1 = 0;
    522                 }
    523             }
    524         }
    525       public:
    526         typedef size_t size_type;
    527         typedef T value_type;
    528         typedef const value_type& const_reference;
    529         vector(unsigned int size = 0);
    530         vector(unsigned int size, T value);
    531         vector(const vector<T> &);
    532 
    533         unsigned int size() const;
    534         bool empty() const;
    535         void clear();
    536         %rename(push) push_back;
    537         void push_back(T x);
    538         %extend {
    539             T pop() throw (std::out_of_range) {
    540                 if (self->size() == 0)
    541                     throw std::out_of_range("pop from empty vector");
    542                 T x = self->back();
    543                 self->pop_back();
    544                 return x;
    545             }
    546             T get(int i) throw (std::out_of_range) {
    547                 int size = int(self->size());
    548                 if (i>=0 && i<size)
    549                     return (*self)[i];
    550                 else
    551                     throw std::out_of_range("vector index out of range");
    552             }
    553             void set(int i, T x) throw (std::out_of_range) {
    554                 int size = int(self->size());
    555                 if (i>=0 && i<size)
    556                     (*self)[i] = x;
    557                 else
    558                     throw std::out_of_range("vector index out of range");
    559             }
    560         }
    561     };
    562     %enddef
    563 
    564     specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv);
    565     specialize_std_vector(char,SvIOK,SvIVX,sv_setiv);
    566     specialize_std_vector(int,SvIOK,SvIVX,sv_setiv);
    567     specialize_std_vector(short,SvIOK,SvIVX,sv_setiv);
    568     specialize_std_vector(long,SvIOK,SvIVX,sv_setiv);
    569     specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv);
    570     specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv);
    571     specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv);
    572     specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv);
    573     specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv);
    574     specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv);
    575     specialize_std_vector(std::string,SvPOK,SwigSvToString,SwigSvFromString);
    576 }
    577 
    578