Home | History | Annotate | Download | only in perl5
      1 /* -----------------------------------------------------------------------------
      2  * std_list.i
      3  *
      4  * SWIG typemaps for std::list types
      5  * ----------------------------------------------------------------------------- */
      6 
      7 %include <std_common.i>
      8 %include <exception.i>
      9 
     10 // containers
     11 
     12 
     13 // ------------------------------------------------------------------------
     14 // std::list
     15 //
     16 // The aim of all that follows would be to integrate std::list with
     17 // Perl as much as possible, namely, to allow the user to pass and
     18 // be returned Perl arrays.
     19 // const declarations are used to guess the intent of the function being
     20 // exported; therefore, the following rationale is applied:
     21 //
     22 //   -- f(std::list<T>), f(const std::list<T>&), f(const std::list<T>*):
     23 //      the parameter being read-only, either a Perl sequence or a
     24 //      previously wrapped std::list<T> can be passed.
     25 //   -- f(std::list<T>&), f(std::list<T>*):
     26 //      the parameter must be modified; therefore, only a wrapped std::list
     27 //      can be passed.
     28 //   -- std::list<T> f():
     29 //      the list is returned by copy; therefore, a Perl sequence of T:s
     30 //      is returned which is most easily used in other Perl functions
     31 //   -- std::list<T>& f(), std::list<T>* f(), const std::list<T>& f(),
     32 //      const std::list<T>* f():
     33 //      the list is returned by reference; therefore, a wrapped std::list
     34 //      is returned
     35 // ------------------------------------------------------------------------
     36 
     37 %{
     38 #include <list>
     39 #include <algorithm>
     40 #include <stdexcept>
     41 %}
     42 
     43 // exported class
     44 
     45 namespace std {
     46 
     47     template<class T> class list {
     48         %typemap(in) list<T> (std::list<T>* v) {
     49             if (SWIG_ConvertPtr($input,(void **) &v,
     50                                 $&1_descriptor,1) != -1) {
     51                 $1 = *v;
     52             } else if (SvROK($input)) {
     53                 AV *av = (AV *)SvRV($input);
     54                 if (SvTYPE(av) != SVt_PVAV)
     55                     SWIG_croak("Type error in argument $argnum of $symname. "
     56                                "Expected an array of " #T);
     57                 SV **tv;
     58                 I32 len = av_len(av) + 1;
     59                 T* obj;
     60                 for (int i=0; i<len; i++) {
     61                     tv = av_fetch(av, i, 0);
     62                     if (SWIG_ConvertPtr(*tv, (void **)&obj,
     63                                         $descriptor(T *),0) != -1) {
     64                         $1.push_back(*obj);
     65                     } else {
     66                         SWIG_croak("Type error in argument $argnum of "
     67                                    "$symname. "
     68                                    "Expected an array of " #T);
     69                     }
     70                 }
     71             } else {
     72                 SWIG_croak("Type error in argument $argnum of $symname. "
     73                            "Expected an array of " #T);
     74             }
     75         }
     76         %typemap(in) const list<T>& (std::list<T> temp,
     77                                        std::list<T>* v),
     78                      const list<T>* (std::list<T> temp,
     79                                        std::list<T>* v) {
     80             if (SWIG_ConvertPtr($input,(void **) &v,
     81                                 $1_descriptor,1) != -1) {
     82                 $1 = v;
     83             } else if (SvROK($input)) {
     84                 AV *av = (AV *)SvRV($input);
     85                 if (SvTYPE(av) != SVt_PVAV)
     86                     SWIG_croak("Type error in argument $argnum of $symname. "
     87                                "Expected an array of " #T);
     88                 SV **tv;
     89                 I32 len = av_len(av) + 1;
     90                 T* obj;
     91                 for (int i=0; i<len; i++) {
     92                     tv = av_fetch(av, i, 0);
     93                     if (SWIG_ConvertPtr(*tv, (void **)&obj,
     94                                         $descriptor(T *),0) != -1) {
     95                         temp.push_back(*obj);
     96                     } else {
     97                         SWIG_croak("Type error in argument $argnum of "
     98                                    "$symname. "
     99                                    "Expected an array of " #T);
    100                     }
    101                 }
    102                 $1 = &temp;
    103             } else {
    104                 SWIG_croak("Type error in argument $argnum of $symname. "
    105                            "Expected an array of " #T);
    106             }
    107         }
    108         %typemap(out) list<T> {
    109 	    std::list<T>::const_iterator i;
    110             unsigned int j;
    111             int len = $1.size();
    112             SV **svs = new SV*[len];
    113             for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) {
    114                 T* ptr = new T(*i);
    115                 svs[j] = sv_newmortal();
    116                 SWIG_MakePtr(svs[j], (void*) ptr,
    117                              $descriptor(T *), $shadow|$owner);
    118             }
    119             AV *myav = av_make(len, svs);
    120             delete[] svs;
    121             $result = newRV_noinc((SV*) myav);
    122             sv_2mortal($result);
    123             argvi++;
    124         }
    125         %typecheck(SWIG_TYPECHECK_LIST) list<T> {
    126             {
    127                 /* wrapped list? */
    128                 std::list<T >* v;
    129                 if (SWIG_ConvertPtr($input,(void **) &v,
    130                                     $1_&descriptor,0) != -1) {
    131                     $1 = 1;
    132                 } else if (SvROK($input)) {
    133                     /* native sequence? */
    134                     AV *av = (AV *)SvRV($input);
    135                     if (SvTYPE(av) == SVt_PVAV) {
    136                         SV **tv;
    137                         I32 len = av_len(av) + 1;
    138                         if (len == 0) {
    139                             /* an empty sequence can be of any type */
    140                             $1 = 1;
    141                         } else {
    142                             /* check the first element only */
    143                             T* obj;
    144                             tv = av_fetch(av, 0, 0);
    145                             if (SWIG_ConvertPtr(*tv, (void **)&obj,
    146                                                 $descriptor(T *),0) != -1)
    147                                 $1 = 1;
    148                             else
    149                                 $1 = 0;
    150                         }
    151                     }
    152                 } else {
    153                     $1 = 0;
    154                 }
    155             }
    156         }
    157         %typecheck(SWIG_TYPECHECK_LIST) const list<T>&,
    158                                           const list<T>* {
    159             {
    160                 /* wrapped list? */
    161                 std::list<T >* v;
    162                 if (SWIG_ConvertPtr($input,(void **) &v,
    163                                     $1_descriptor,0) != -1) {
    164                     $1 = 1;
    165                 } else if (SvROK($input)) {
    166                     /* native sequence? */
    167                     AV *av = (AV *)SvRV($input);
    168                     if (SvTYPE(av) == SVt_PVAV) {
    169                         SV **tv;
    170                         I32 len = av_len(av) + 1;
    171                         if (len == 0) {
    172                             /* an empty sequence can be of any type */
    173                             $1 = 1;
    174                         } else {
    175                             /* check the first element only */
    176                             T* obj;
    177                             tv = av_fetch(av, 0, 0);
    178                             if (SWIG_ConvertPtr(*tv, (void **)&obj,
    179                                                 $descriptor(T *),0) != -1)
    180                                 $1 = 1;
    181                             else
    182                                 $1 = 0;
    183                         }
    184                     }
    185                 } else {
    186                     $1 = 0;
    187                 }
    188             }
    189         }
    190       public:
    191         typedef size_t size_type;
    192         typedef T value_type;
    193         typedef const value_type& const_reference;
    194 
    195         list();
    196         list(const list<T> &);
    197 
    198         unsigned int size() const;
    199         bool empty() const;
    200         void clear();
    201         %rename(push) push_back;
    202         void push_back(const T& x);
    203     };
    204 
    205 
    206     // specializations for built-ins
    207 
    208     %define specialize_std_list(T,CHECK_T,TO_T,FROM_T)
    209     template<> class list<T> {
    210         %typemap(in) list<T> (std::list<T>* v) {
    211             if (SWIG_ConvertPtr($input,(void **) &v,
    212                                 $&1_descriptor,1) != -1){
    213                 $1 = *v;
    214             } else if (SvROK($input)) {
    215                 AV *av = (AV *)SvRV($input);
    216                 if (SvTYPE(av) != SVt_PVAV)
    217                     SWIG_croak("Type error in argument $argnum of $symname. "
    218                                "Expected an array of " #T);
    219                 SV **tv;
    220                 I32 len = av_len(av) + 1;
    221                 for (int i=0; i<len; i++) {
    222                     tv = av_fetch(av, i, 0);
    223                     if (CHECK_T(*tv)) {
    224                         $1.push_back(TO_T(*tv));
    225                     } else {
    226                         SWIG_croak("Type error in argument $argnum of "
    227                                    "$symname. "
    228                                    "Expected an array of " #T);
    229                     }
    230                 }
    231             } else {
    232                 SWIG_croak("Type error in argument $argnum of $symname. "
    233                            "Expected an array of " #T);
    234             }
    235         }
    236         %typemap(in) const list<T>& (std::list<T> temp,
    237                                        std::list<T>* v),
    238                      const list<T>* (std::list<T> temp,
    239                                        std::list<T>* v) {
    240             if (SWIG_ConvertPtr($input,(void **) &v,
    241                                 $1_descriptor,1) != -1) {
    242                 $1 = v;
    243             } else if (SvROK($input)) {
    244                 AV *av = (AV *)SvRV($input);
    245                 if (SvTYPE(av) != SVt_PVAV)
    246                     SWIG_croak("Type error in argument $argnum of $symname. "
    247                                "Expected an array of " #T);
    248                 SV **tv;
    249                 I32 len = av_len(av) + 1;
    250                 T* obj;
    251                 for (int i=0; i<len; i++) {
    252                     tv = av_fetch(av, i, 0);
    253                     if (CHECK_T(*tv)) {
    254                         temp.push_back(TO_T(*tv));
    255                     } else {
    256                         SWIG_croak("Type error in argument $argnum of "
    257                                    "$symname. "
    258                                    "Expected an array of " #T);
    259                     }
    260                 }
    261                 $1 = &temp;
    262             } else {
    263                 SWIG_croak("Type error in argument $argnum of $symname. "
    264                            "Expected an array of " #T);
    265             }
    266         }
    267         %typemap(out) list<T> {
    268 	    std::list<T>::const_iterator i;
    269             unsigned int j;
    270             int len = $1.size();
    271             SV **svs = new SV*[len];
    272             for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) {
    273                 svs[j] = sv_newmortal();
    274                 FROM_T(svs[j], *i);
    275             }
    276             AV *myav = av_make(len, svs);
    277             delete[] svs;
    278             $result = newRV_noinc((SV*) myav);
    279             sv_2mortal($result);
    280             argvi++;
    281         }
    282         %typecheck(SWIG_TYPECHECK_LIST) list<T> {
    283             {
    284                 /* wrapped list? */
    285                 std::list<T >* v;
    286                 if (SWIG_ConvertPtr($input,(void **) &v,
    287                                     $1_&descriptor,0) != -1) {
    288                     $1 = 1;
    289                 } else if (SvROK($input)) {
    290                     /* native sequence? */
    291                     AV *av = (AV *)SvRV($input);
    292                     if (SvTYPE(av) == SVt_PVAV) {
    293                         SV **tv;
    294                         I32 len = av_len(av) + 1;
    295                         if (len == 0) {
    296                             /* an empty sequence can be of any type */
    297                             $1 = 1;
    298                         } else {
    299                             /* check the first element only */
    300                             tv = av_fetch(av, 0, 0);
    301                             if (CHECK_T(*tv))
    302                                 $1 = 1;
    303                             else
    304                                 $1 = 0;
    305                         }
    306                     }
    307                 } else {
    308                     $1 = 0;
    309                 }
    310             }
    311         }
    312         %typecheck(SWIG_TYPECHECK_LIST) const list<T>&,
    313                                           const list<T>* {
    314             {
    315                 /* wrapped list? */
    316                 std::list<T >* v;
    317                 if (SWIG_ConvertPtr($input,(void **) &v,
    318                                     $1_descriptor,0) != -1) {
    319                     $1 = 1;
    320                 } else if (SvROK($input)) {
    321                     /* native sequence? */
    322                     AV *av = (AV *)SvRV($input);
    323                     if (SvTYPE(av) == SVt_PVAV) {
    324                         SV **tv;
    325                         I32 len = av_len(av) + 1;
    326                         if (len == 0) {
    327                             /* an empty sequence can be of any type */
    328                             $1 = 1;
    329                         } else {
    330                             /* check the first element only */
    331                             tv = av_fetch(av, 0, 0);
    332                             if (CHECK_T(*tv))
    333                                 $1 = 1;
    334                             else
    335                                 $1 = 0;
    336                         }
    337                     }
    338                 } else {
    339                     $1 = 0;
    340                 }
    341             }
    342         }
    343       public:
    344         typedef size_t size_type;
    345         typedef T value_type;
    346         typedef const value_type& const_reference;
    347 
    348         list();
    349         list(const list<T> &);
    350 
    351         unsigned int size() const;
    352         bool empty() const;
    353         void clear();
    354         %rename(push) push_back;
    355         void push_back(T x);
    356     };
    357     %enddef
    358 
    359     specialize_std_list(bool,SvIOK,SvIVX,sv_setiv);
    360     specialize_std_list(char,SvIOK,SvIVX,sv_setiv);
    361     specialize_std_list(int,SvIOK,SvIVX,sv_setiv);
    362     specialize_std_list(short,SvIOK,SvIVX,sv_setiv);
    363     specialize_std_list(long,SvIOK,SvIVX,sv_setiv);
    364     specialize_std_list(unsigned char,SvIOK,SvIVX,sv_setiv);
    365     specialize_std_list(unsigned int,SvIOK,SvIVX,sv_setiv);
    366     specialize_std_list(unsigned short,SvIOK,SvIVX,sv_setiv);
    367     specialize_std_list(unsigned long,SvIOK,SvIVX,sv_setiv);
    368     specialize_std_list(float,SvNIOK,SwigSvToNumber,sv_setnv);
    369     specialize_std_list(double,SvNIOK,SwigSvToNumber,sv_setnv);
    370     specialize_std_list(std::string,SvPOK,SvPVX,SwigSvFromString);
    371 
    372 }
    373 
    374