1/* ----------------------------------------------------------------------------- 2 * See the LICENSE file for information on copyright, usage and redistribution 3 * of SWIG, and the README file for authors - http://www.swig.org/release.html. 4 * 5 * octcontainer.swg 6 * 7 * Octave cell <-> C++ container wrapper 8 * 9 * This wrapper, and its iterator, allows a general use (and reuse) of 10 * the the mapping between C++ and Octave, thanks to the C++ 11 * templates. 12 * 13 * Of course, it needs the C++ compiler to support templates, but 14 * since we will use this wrapper with the STL containers, that should 15 * be the case. 16 * ----------------------------------------------------------------------------- */ 17 18%{ 19#include <iostream> 20%} 21 22 23#if !defined(SWIG_NO_EXPORT_ITERATOR_METHODS) 24# if !defined(SWIG_EXPORT_ITERATOR_METHODS) 25# define SWIG_EXPORT_ITERATOR_METHODS SWIG_EXPORT_ITERATOR_METHODS 26# endif 27#endif 28 29%include <octiterators.swg> 30 31// The Octave C++ Wrap 32 33%insert(header) %{ 34#include <stdexcept> 35%} 36 37%include <std_except.i> 38 39%fragment(SWIG_Traits_frag(octave_value),"header",fragment="StdTraits") { 40namespace swig { 41 template <> struct traits<octave_value > { 42 typedef value_category category; 43 static const char* type_name() { return "octave_value"; } 44 }; 45 46 template <> struct traits_from<octave_value> { 47 typedef octave_value value_type; 48 static octave_value from(const value_type& val) { 49 return val; 50 } 51 }; 52 53 template <> 54 struct traits_check<octave_value, value_category> { 55 static bool check(const octave_value&) { 56 return true; 57 } 58 }; 59 60 template <> struct traits_asval<octave_value > { 61 typedef octave_value value_type; 62 static int asval(const octave_value& obj, value_type *val) { 63 if (val) *val = obj; 64 return SWIG_OK; 65 } 66 }; 67} 68} 69 70%fragment("OctSequence_Base","header") 71{ 72%#include <functional> 73 74namespace std { 75 template <> 76 struct less <octave_value>: public binary_function<octave_value, octave_value, bool> 77 { 78 bool 79 operator()(const octave_value& v, const octave_value& w) const 80 { 81 octave_value res = do_binary_op(octave_value::op_le,v,w); 82 return res.is_true(); 83 } 84 }; 85} 86 87namespace swig { 88 inline size_t 89 check_index(ptrdiff_t i, size_t size, bool insert = false) { 90 if ( i < 0 ) { 91 if ((size_t) (-i) <= size) 92 return (size_t) (i + size); 93 } else if ( (size_t) i < size ) { 94 return (size_t) i; 95 } else if (insert && ((size_t) i == size)) { 96 return size; 97 } 98 99 throw std::out_of_range("index out of range"); 100 } 101 102 inline size_t 103 slice_index(ptrdiff_t i, size_t size) { 104 if ( i < 0 ) { 105 if ((size_t) (-i) <= size) { 106 return (size_t) (i + size); 107 } else { 108 throw std::out_of_range("index out of range"); 109 } 110 } else { 111 return ( (size_t) i < size ) ? ((size_t) i) : size; 112 } 113 } 114 115 template <class Sequence, class Difference> 116 inline typename Sequence::iterator 117 getpos(Sequence* self, Difference i) { 118 typename Sequence::iterator pos = self->begin(); 119 std::advance(pos, check_index(i,self->size())); 120 return pos; 121 } 122 123 template <class Sequence, class Difference> 124 inline typename Sequence::const_iterator 125 cgetpos(const Sequence* self, Difference i) { 126 typename Sequence::const_iterator pos = self->begin(); 127 std::advance(pos, check_index(i,self->size())); 128 return pos; 129 } 130 131 template <class Sequence, class Difference> 132 inline Sequence* 133 getslice(const Sequence* self, Difference i, Difference j) { 134 typename Sequence::size_type size = self->size(); 135 typename Sequence::size_type ii = swig::check_index(i, size); 136 typename Sequence::size_type jj = swig::slice_index(j, size); 137 138 if (jj > ii) { 139 typename Sequence::const_iterator vb = self->begin(); 140 typename Sequence::const_iterator ve = self->begin(); 141 std::advance(vb,ii); 142 std::advance(ve,jj); 143 return new Sequence(vb, ve); 144 } else { 145 return new Sequence(); 146 } 147 } 148 149 template <class Sequence, class Difference, class InputSeq> 150 inline void 151 setslice(Sequence* self, Difference i, Difference j, const InputSeq& v) { 152 typename Sequence::size_type size = self->size(); 153 typename Sequence::size_type ii = swig::check_index(i, size, true); 154 typename Sequence::size_type jj = swig::slice_index(j, size); 155 if (jj < ii) jj = ii; 156 size_t ssize = jj - ii; 157 if (ssize <= v.size()) { 158 typename Sequence::iterator sb = self->begin(); 159 typename InputSeq::const_iterator vmid = v.begin(); 160 std::advance(sb,ii); 161 std::advance(vmid, jj - ii); 162 self->insert(std::copy(v.begin(), vmid, sb), vmid, v.end()); 163 } else { 164 typename Sequence::iterator sb = self->begin(); 165 typename Sequence::iterator se = self->begin(); 166 std::advance(sb,ii); 167 std::advance(se,jj); 168 self->erase(sb,se); 169 self->insert(sb, v.begin(), v.end()); 170 } 171 } 172 173 template <class Sequence, class Difference> 174 inline void 175 delslice(Sequence* self, Difference i, Difference j) { 176 typename Sequence::size_type size = self->size(); 177 typename Sequence::size_type ii = swig::check_index(i, size, true); 178 typename Sequence::size_type jj = swig::slice_index(j, size); 179 if (jj > ii) { 180 typename Sequence::iterator sb = self->begin(); 181 typename Sequence::iterator se = self->begin(); 182 std::advance(sb,ii); 183 std::advance(se,jj); 184 self->erase(sb,se); 185 } 186 } 187} 188} 189 190%fragment("OctSequence_Cont","header", 191 fragment="StdTraits", 192 fragment="OctSequence_Base", 193 fragment="OctSwigIterator_T") 194{ 195namespace swig 196{ 197 template <class T> 198 struct OctSequence_Ref // * octave can't support these, because of how assignment works 199 { 200 OctSequence_Ref(const octave_value& seq, int index) 201 : _seq(seq), _index(index) 202 { 203 } 204 205 operator T () const 206 { 207 // swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, _index); 208 octave_value item; // * todo 209 try { 210 return swig::as<T>(item, true); 211 } catch (std::exception& e) { 212 char msg[1024]; 213 sprintf(msg, "in sequence element %d ", _index); 214 if (!Octave_Error_Occurred()) { 215 %type_error(swig::type_name<T>()); 216 } 217 SWIG_Octave_AddErrorMsg(msg); 218 SWIG_Octave_AddErrorMsg(e.what()); 219 throw; 220 } 221 } 222 223 OctSequence_Ref& operator=(const T& v) 224 { 225 // OctSequence_SetItem(_seq, _index, swig::from<T>(v)); 226 // * todo 227 return *this; 228 } 229 230 private: 231 octave_value _seq; 232 int _index; 233 }; 234 235 template <class T> 236 struct OctSequence_ArrowProxy 237 { 238 OctSequence_ArrowProxy(const T& x): m_value(x) {} 239 const T* operator->() const { return &m_value; } 240 operator const T*() const { return &m_value; } 241 T m_value; 242 }; 243 244 template <class T, class Reference > 245 struct OctSequence_InputIterator 246 { 247 typedef OctSequence_InputIterator<T, Reference > self; 248 249 typedef std::random_access_iterator_tag iterator_category; 250 typedef Reference reference; 251 typedef T value_type; 252 typedef T* pointer; 253 typedef int difference_type; 254 255 OctSequence_InputIterator() 256 { 257 } 258 259 OctSequence_InputIterator(const octave_value& seq, int index) 260 : _seq(seq), _index(index) 261 { 262 } 263 264 reference operator*() const 265 { 266 return reference(_seq, _index); 267 } 268 269 OctSequence_ArrowProxy<T> 270 operator->() const { 271 return OctSequence_ArrowProxy<T>(operator*()); 272 } 273 274 bool operator==(const self& ri) const 275 { 276 return (_index == ri._index); 277 } 278 279 bool operator!=(const self& ri) const 280 { 281 return !(operator==(ri)); 282 } 283 284 self& operator ++ () 285 { 286 ++_index; 287 return *this; 288 } 289 290 self& operator -- () 291 { 292 --_index; 293 return *this; 294 } 295 296 self& operator += (difference_type n) 297 { 298 _index += n; 299 return *this; 300 } 301 302 self operator +(difference_type n) const 303 { 304 return self(_seq, _index + n); 305 } 306 307 self& operator -= (difference_type n) 308 { 309 _index -= n; 310 return *this; 311 } 312 313 self operator -(difference_type n) const 314 { 315 return self(_seq, _index - n); 316 } 317 318 difference_type operator - (const self& ri) const 319 { 320 return _index - ri._index; 321 } 322 323 bool operator < (const self& ri) const 324 { 325 return _index < ri._index; 326 } 327 328 reference 329 operator[](difference_type n) const 330 { 331 return reference(_seq, _index + n); 332 } 333 334 private: 335 octave_value _seq; 336 difference_type _index; 337 }; 338 339 template <class T> 340 struct OctSequence_Cont 341 { 342 typedef OctSequence_Ref<T> reference; 343 typedef const OctSequence_Ref<T> const_reference; 344 typedef T value_type; 345 typedef T* pointer; 346 typedef int difference_type; 347 typedef int size_type; 348 typedef const pointer const_pointer; 349 typedef OctSequence_InputIterator<T, reference> iterator; 350 typedef OctSequence_InputIterator<T, const_reference> const_iterator; 351 352 OctSequence_Cont(const octave_value& seq) : _seq(seq) 353 { 354 // * assert that we have map type etc. 355 /* 356 if (!OctSequence_Check(seq)) { 357 throw std::invalid_argument("a sequence is expected"); 358 } 359 _seq = seq; 360 Py_INCREF(_seq); 361 */ 362 } 363 364 ~OctSequence_Cont() 365 { 366 } 367 368 size_type size() const 369 { 370 // return static_cast<size_type>(OctSequence_Size(_seq)); 371 return 0; // * todo 372 } 373 374 bool empty() const 375 { 376 return size() == 0; 377 } 378 379 iterator begin() 380 { 381 return iterator(_seq, 0); 382 } 383 384 const_iterator begin() const 385 { 386 return const_iterator(_seq, 0); 387 } 388 389 iterator end() 390 { 391 return iterator(_seq, size()); 392 } 393 394 const_iterator end() const 395 { 396 return const_iterator(_seq, size()); 397 } 398 399 reference operator[](difference_type n) 400 { 401 return reference(_seq, n); 402 } 403 404 const_reference operator[](difference_type n) const 405 { 406 return const_reference(_seq, n); 407 } 408 409 bool check(bool set_err = true) const 410 { 411 int s = size(); 412 for (int i = 0; i < s; ++i) { 413 // swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, i); 414 octave_value item; // * todo 415 if (!swig::check<value_type>(item)) { 416 if (set_err) { 417 char msg[1024]; 418 sprintf(msg, "in sequence element %d", i); 419 SWIG_Error(SWIG_RuntimeError, msg); 420 } 421 return false; 422 } 423 } 424 return true; 425 } 426 427 private: 428 octave_value _seq; 429 }; 430 431} 432} 433 434%define %swig_sequence_iterator(Sequence...) 435#if defined(SWIG_EXPORT_ITERATOR_METHODS) 436 class iterator; 437 class reverse_iterator; 438 class const_iterator; 439 class const_reverse_iterator; 440 441 %typemap(out,noblock=1,fragment="OctSequence_Cont") 442 iterator, reverse_iterator, const_iterator, const_reverse_iterator { 443 $result = SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &)), 444 swig::OctSwigIterator::descriptor(),SWIG_POINTER_OWN); 445 } 446 %typemap(out,fragment="OctSequence_Cont") 447 std::pair<iterator, iterator>, std::pair<const_iterator, const_iterator> { 448 octave_value_list tmpc; 449 tmpc.append(SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), 450 swig::OctSwigIterator::descriptor(),SWIG_POINTER_OWN)); 451 tmpc.append(SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).second), 452 swig::OctSwigIterator::descriptor(),SWIG_POINTER_OWN)); 453 $result = Cell(tmpc); 454 } 455 456 %fragment("SwigPyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="OctSequence_Cont") {} 457 458 %typemap(out,fragment="OctPairBoolOutputIterator") 459 std::pair<iterator, bool>, std::pair<const_iterator, bool> { 460 octave_value_list tmpc; 461 tmpc.append(SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), 462 swig::OctSwigIterator::descriptor(),SWIG_POINTER_OWN)); 463 tmpc.append(SWIG_From(bool)(%static_cast($1,const $type &).second)); 464 $result = Cell(tmpc); 465 } 466 467 %typemap(in,noblock=1,fragment="OctSequence_Cont") 468 iterator(swig::OctSwigIterator *iter = 0, int res), 469 reverse_iterator(swig::OctSwigIterator *iter = 0, int res), 470 const_iterator(swig::OctSwigIterator *iter = 0, int res), 471 const_reverse_iterator(swig::OctSwigIterator *iter = 0, int res) { 472 res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::OctSwigIterator::descriptor(), 0); 473 if (!SWIG_IsOK(res) || !iter) { 474 %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); 475 } else { 476 swig::OctSwigIterator_T<$type > *iter_t = dynamic_cast<swig::OctSwigIterator_T<$type > *>(iter); 477 if (iter_t) { 478 $1 = iter_t->get_current(); 479 } else { 480 %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); 481 } 482 } 483 } 484 485 %typecheck(%checkcode(ITERATOR),noblock=1,fragment="OctSequence_Cont") 486 iterator, reverse_iterator, const_iterator, const_reverse_iterator { 487 swig::OctSwigIterator *iter = 0; 488 int res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::OctSwigIterator::descriptor(), 0); 489 $1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::OctSwigIterator_T<$type > *>(iter) != 0)); 490 } 491 492 %fragment("OctSequence_Cont"); 493#endif //SWIG_EXPORT_ITERATOR_METHODS 494%enddef 495 496// The octave container methods 497 498%define %swig_container_methods(Container...) 499%enddef 500 501%define %swig_sequence_methods_common(Sequence...) 502 %swig_sequence_iterator(%arg(Sequence)) 503 %swig_container_methods(%arg(Sequence)) 504 505 %fragment("OctSequence_Base"); 506 507 %extend { 508 value_type pop() throw (std::out_of_range) { 509 if (self->size() == 0) 510 throw std::out_of_range("pop from empty container"); 511 Sequence::value_type x = self->back(); 512 self->pop_back(); 513 return x; 514 } 515 516 value_type __paren__(difference_type i) throw (std::out_of_range) { 517 return *(swig::cgetpos(self, i)); 518 } 519 520 void __paren_asgn__(difference_type i, value_type x) throw (std::out_of_range) { 521 *(swig::getpos(self,i)) = x; 522 } 523 524 void append(value_type x) { 525 self->push_back(x); 526 } 527 } 528 529%enddef 530 531%define %swig_sequence_methods(Sequence...) 532 %swig_sequence_methods_common(%arg(Sequence)) 533%enddef 534 535%define %swig_sequence_methods_val(Sequence...) 536 %swig_sequence_methods_common(%arg(Sequence)) 537%enddef 538 539// 540// Common fragments 541// 542 543%fragment("StdSequenceTraits","header", 544 fragment="StdTraits", 545 fragment="OctSequence_Cont") 546{ 547namespace swig { 548 template <class OctSeq, class Seq> 549 inline void 550 assign(const OctSeq& octseq, Seq* seq) { 551%#ifdef SWIG_STD_NOASSIGN_STL 552 typedef typename OctSeq::value_type value_type; 553 typename OctSeq::const_iterator it = octseq.begin(); 554 for (;it != octseq.end(); ++it) { 555 seq->insert(seq->end(),(value_type)(*it)); 556 } 557%#else 558 seq->assign(octseq.begin(), octseq.end()); 559%#endif 560 } 561 562 template <class Seq, class T = typename Seq::value_type > 563 struct traits_asptr_stdseq { 564 typedef Seq sequence; 565 typedef T value_type; 566 567 static int asptr(const octave_value& obj, sequence **seq) { 568 if (!obj.is_defined() || Swig::swig_value_deref(obj)) { 569 sequence *p; 570 if (SWIG_ConvertPtr(obj,(void**)&p, 571 swig::type_info<sequence>(),0) == SWIG_OK) { 572 if (seq) *seq = p; 573 return SWIG_OLDOBJ; 574 } 575 } else if (obj.is_cell()) { 576 try { 577 OctSequence_Cont<value_type> octseq(obj); 578 if (seq) { 579 sequence *pseq = new sequence(); 580 assign(octseq, pseq); 581 *seq = pseq; 582 return SWIG_NEWOBJ; 583 } else { 584 return octseq.check() ? SWIG_OK : SWIG_ERROR; 585 } 586 } catch (std::exception& e) { 587 if (seq&&!error_state) 588 error("swig type error: %s",e.what()); 589 return SWIG_ERROR; 590 } 591 } 592 return SWIG_ERROR; 593 } 594 }; 595 596 template <class Seq, class T = typename Seq::value_type > 597 struct traits_from_stdseq { 598 typedef Seq sequence; 599 typedef T value_type; 600 typedef typename Seq::size_type size_type; 601 typedef typename sequence::const_iterator const_iterator; 602 603 static octave_value from(const sequence& seq) { 604#ifdef SWIG_OCTAVE_EXTRA_NATIVE_CONTAINERS 605 swig_type_info *desc = swig::type_info<sequence>(); 606 if (desc && desc->clientdata) { 607 return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN); 608 } 609#endif 610 size_type size = seq.size(); 611 if (size <= (size_type)INT_MAX) { 612 Cell c(size,1); 613 int i = 0; 614 for (const_iterator it = seq.begin(); 615 it != seq.end(); ++it, ++i) { 616 c(i) = swig::from<value_type>(*it); 617 } 618 return c; 619 } else { 620 error("swig overflow error: sequence size not valid in octave"); 621 return octave_value(); 622 } 623 return octave_value(); 624 } 625 }; 626} 627} 628 629