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 %} 40 %fragment("<algorithm>"); 41 %fragment("<stdexcept>"); 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 ptrdiff_t difference_type; 193 typedef T value_type; 194 typedef value_type* pointer; 195 typedef const value_type* const_pointer; 196 typedef value_type& reference; 197 typedef const value_type& const_reference; 198 199 list(); 200 list(const list& other); 201 202 unsigned int size() const; 203 bool empty() const; 204 void clear(); 205 %rename(push) push_back; 206 void push_back(const T& x); 207 }; 208 209 210 // specializations for built-ins 211 212 %define specialize_std_list(T,CHECK_T,TO_T,FROM_T) 213 template<> class list<T> { 214 %typemap(in) list<T> (std::list<T>* v) { 215 if (SWIG_ConvertPtr($input,(void **) &v, 216 $&1_descriptor,1) != -1){ 217 $1 = *v; 218 } else if (SvROK($input)) { 219 AV *av = (AV *)SvRV($input); 220 if (SvTYPE(av) != SVt_PVAV) 221 SWIG_croak("Type error in argument $argnum of $symname. " 222 "Expected an array of " #T); 223 SV **tv; 224 I32 len = av_len(av) + 1; 225 for (int i=0; i<len; i++) { 226 tv = av_fetch(av, i, 0); 227 if (CHECK_T(*tv)) { 228 $1.push_back(TO_T(*tv)); 229 } else { 230 SWIG_croak("Type error in argument $argnum of " 231 "$symname. " 232 "Expected an array of " #T); 233 } 234 } 235 } else { 236 SWIG_croak("Type error in argument $argnum of $symname. " 237 "Expected an array of " #T); 238 } 239 } 240 %typemap(in) const list<T>& (std::list<T> temp, 241 std::list<T>* v), 242 const list<T>* (std::list<T> temp, 243 std::list<T>* v) { 244 if (SWIG_ConvertPtr($input,(void **) &v, 245 $1_descriptor,1) != -1) { 246 $1 = v; 247 } else if (SvROK($input)) { 248 AV *av = (AV *)SvRV($input); 249 if (SvTYPE(av) != SVt_PVAV) 250 SWIG_croak("Type error in argument $argnum of $symname. " 251 "Expected an array of " #T); 252 SV **tv; 253 I32 len = av_len(av) + 1; 254 T* obj; 255 for (int i=0; i<len; i++) { 256 tv = av_fetch(av, i, 0); 257 if (CHECK_T(*tv)) { 258 temp.push_back(TO_T(*tv)); 259 } else { 260 SWIG_croak("Type error in argument $argnum of " 261 "$symname. " 262 "Expected an array of " #T); 263 } 264 } 265 $1 = &temp; 266 } else { 267 SWIG_croak("Type error in argument $argnum of $symname. " 268 "Expected an array of " #T); 269 } 270 } 271 %typemap(out) list<T> { 272 std::list< T >::const_iterator i; 273 unsigned int j; 274 int len = $1.size(); 275 SV **svs = new SV*[len]; 276 for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) { 277 svs[j] = sv_newmortal(); 278 FROM_T(svs[j], *i); 279 } 280 AV *myav = av_make(len, svs); 281 delete[] svs; 282 $result = newRV_noinc((SV*) myav); 283 sv_2mortal($result); 284 argvi++; 285 } 286 %typecheck(SWIG_TYPECHECK_LIST) list<T> { 287 { 288 /* wrapped list? */ 289 std::list< T >* v; 290 if (SWIG_ConvertPtr($input,(void **) &v, 291 $1_&descriptor,0) != -1) { 292 $1 = 1; 293 } else if (SvROK($input)) { 294 /* native sequence? */ 295 AV *av = (AV *)SvRV($input); 296 if (SvTYPE(av) == SVt_PVAV) { 297 SV **tv; 298 I32 len = av_len(av) + 1; 299 if (len == 0) { 300 /* an empty sequence can be of any type */ 301 $1 = 1; 302 } else { 303 /* check the first element only */ 304 tv = av_fetch(av, 0, 0); 305 if (CHECK_T(*tv)) 306 $1 = 1; 307 else 308 $1 = 0; 309 } 310 } 311 } else { 312 $1 = 0; 313 } 314 } 315 } 316 %typecheck(SWIG_TYPECHECK_LIST) const list<T>&, 317 const list<T>* { 318 { 319 /* wrapped list? */ 320 std::list< T >* v; 321 if (SWIG_ConvertPtr($input,(void **) &v, 322 $1_descriptor,0) != -1) { 323 $1 = 1; 324 } else if (SvROK($input)) { 325 /* native sequence? */ 326 AV *av = (AV *)SvRV($input); 327 if (SvTYPE(av) == SVt_PVAV) { 328 SV **tv; 329 I32 len = av_len(av) + 1; 330 if (len == 0) { 331 /* an empty sequence can be of any type */ 332 $1 = 1; 333 } else { 334 /* check the first element only */ 335 tv = av_fetch(av, 0, 0); 336 if (CHECK_T(*tv)) 337 $1 = 1; 338 else 339 $1 = 0; 340 } 341 } 342 } else { 343 $1 = 0; 344 } 345 } 346 } 347 public: 348 typedef size_t size_type; 349 typedef T value_type; 350 typedef const value_type& const_reference; 351 352 list(); 353 list(const list& other); 354 355 unsigned int size() const; 356 bool empty() const; 357 void clear(); 358 %rename(push) push_back; 359 void push_back(T x); 360 }; 361 %enddef 362 363 specialize_std_list(bool,SvIOK,SvIVX,sv_setiv); 364 specialize_std_list(char,SvIOK,SvIVX,sv_setiv); 365 specialize_std_list(int,SvIOK,SvIVX,sv_setiv); 366 specialize_std_list(short,SvIOK,SvIVX,sv_setiv); 367 specialize_std_list(long,SvIOK,SvIVX,sv_setiv); 368 specialize_std_list(unsigned char,SvIOK,SvIVX,sv_setiv); 369 specialize_std_list(unsigned int,SvIOK,SvIVX,sv_setiv); 370 specialize_std_list(unsigned short,SvIOK,SvIVX,sv_setiv); 371 specialize_std_list(unsigned long,SvIOK,SvIVX,sv_setiv); 372 specialize_std_list(float,SvNIOK,SwigSvToNumber,sv_setnv); 373 specialize_std_list(double,SvNIOK,SwigSvToNumber,sv_setnv); 374 specialize_std_list(std::string,SvPOK,SvPVX,SwigSvFromString); 375 376 } 377 378