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