Home | History | Annotate | Download | only in ruby
      1 /* -----------------------------------------------------------------------------
      2  * rubyiterators.swg
      3  *
      4  * Implement a C++ 'output' iterator for Ruby.
      5  *
      6  * Users can derive form the Iterator to implemet their
      7  * own iterators. As an example (real one since we use it for STL/STD
      8  * containers), the template Iterator_T does the
      9  * implementation for generic C++ iterators.
     10  * ----------------------------------------------------------------------------- */
     11 
     12 %include <std_common.i>
     13 
     14 
     15 %fragment("ConstIterator","header",fragment="<stddef.h>",fragment="GC_VALUE_definition") {
     16 namespace swig {
     17   struct stop_iteration {
     18   };
     19 
     20   /**
     21    * Abstract base class used to represent all iterators of STL containers.
     22    */
     23   struct ConstIterator {
     24   public:
     25     typedef ConstIterator self_type;
     26 
     27   protected:
     28     GC_VALUE _seq;
     29 
     30   protected:
     31     ConstIterator(VALUE seq) : _seq(seq)
     32     {
     33     }
     34 
     35     // Random access iterator methods, but not required in Ruby
     36     virtual ptrdiff_t distance(const ConstIterator &x) const
     37     {
     38       throw std::invalid_argument("distance not supported");
     39     }
     40 
     41     virtual bool equal (const ConstIterator &x) const
     42     {
     43       throw std::invalid_argument("equal not supported");
     44     }
     45 
     46     virtual self_type* advance(ptrdiff_t n)
     47     {
     48       throw std::invalid_argument("advance not supported");
     49     }
     50 
     51   public:
     52     virtual ~ConstIterator() {}
     53 
     54     // Access iterator method, required by Ruby
     55     virtual VALUE value() const {
     56       throw std::invalid_argument("value not supported");
     57       return Qnil;
     58     };
     59 
     60     virtual VALUE setValue( const VALUE& v ) {
     61       throw std::invalid_argument("value= not supported");
     62       return Qnil;
     63     }
     64 
     65     virtual self_type* next( size_t n = 1 )
     66     {
     67       return this->advance( n );
     68     }
     69 
     70     virtual self_type* previous( size_t n = 1 )
     71     {
     72       ptrdiff_t nn = n;
     73       return this->advance( -nn );
     74     }
     75 
     76     virtual VALUE to_s() const {
     77       throw std::invalid_argument("to_s not supported");
     78       return Qnil;
     79     }
     80 
     81     virtual VALUE inspect() const {
     82       throw std::invalid_argument("inspect not supported");
     83       return Qnil;
     84     }
     85 
     86     virtual ConstIterator *dup() const
     87     {
     88       throw std::invalid_argument("dup not supported");
     89       return NULL;
     90     }
     91 
     92     //
     93     // C++ common/needed methods.  We emulate a bidirectional
     94     // operator, to be compatible with all the STL.
     95     // The iterator traits will then tell the STL what type of
     96     // iterator we really are.
     97     //
     98     ConstIterator() : _seq( Qnil )
     99     {
    100     }
    101 
    102     ConstIterator( const self_type& b ) : _seq( b._seq )
    103     {
    104     }
    105 
    106     self_type& operator=( const self_type& b )
    107     {
    108       _seq = b._seq;
    109       return *this;
    110     }
    111 
    112     bool operator == (const ConstIterator& x)  const
    113     {
    114       return equal(x);
    115     }
    116 
    117     bool operator != (const ConstIterator& x) const
    118     {
    119       return ! operator==(x);
    120     }
    121 
    122     // Pre-decrement operator
    123     self_type& operator--()
    124     {
    125       return *previous();
    126     }
    127 
    128     // Pre-increment operator
    129     self_type& operator++()
    130     {
    131       return *next();
    132     }
    133 
    134     // Post-decrement operator
    135     self_type operator--(int)
    136     {
    137       self_type r = *this;
    138       previous();
    139       return r;
    140     }
    141 
    142     // Post-increment operator
    143     self_type operator++(int)
    144     {
    145       self_type r = *this;
    146       next();
    147       return r;
    148     }
    149 
    150     ConstIterator& operator += (ptrdiff_t n)
    151     {
    152       return *advance(n);
    153     }
    154 
    155     ConstIterator& operator -= (ptrdiff_t n)
    156     {
    157       return *advance(-n);
    158     }
    159 
    160     ConstIterator* operator + (ptrdiff_t n) const
    161     {
    162       return dup()->advance(n);
    163     }
    164 
    165     ConstIterator* operator - (ptrdiff_t n) const
    166     {
    167       return dup()->advance(-n);
    168     }
    169 
    170     ptrdiff_t operator - (const ConstIterator& x) const
    171     {
    172       return x.distance(*this);
    173     }
    174 
    175     static swig_type_info* descriptor() {
    176       static int init = 0;
    177       static swig_type_info* desc = 0;
    178       if (!init) {
    179 	desc = SWIG_TypeQuery("swig::ConstIterator *");
    180 	init = 1;
    181       }
    182       return desc;
    183     }
    184   };
    185 
    186 
    187   /**
    188    * Abstract base class used to represent all non-const iterators of STL containers.
    189    *
    190    */
    191   struct Iterator : public ConstIterator {
    192   public:
    193     typedef Iterator self_type;
    194 
    195   protected:
    196     Iterator(VALUE seq) : ConstIterator(seq)
    197     {
    198     }
    199 
    200     virtual self_type* advance(ptrdiff_t n)
    201     {
    202       throw std::invalid_argument("operation not supported");
    203     }
    204 
    205   public:
    206     static swig_type_info* descriptor() {
    207       static int init = 0;
    208       static swig_type_info* desc = 0;
    209       if (!init) {
    210 	desc = SWIG_TypeQuery("swig::Iterator *");
    211 	init = 1;
    212       }
    213       return desc;
    214     }
    215 
    216     virtual Iterator *dup() const
    217     {
    218       throw std::invalid_argument("dup not supported");
    219       return NULL;
    220     }
    221 
    222     virtual self_type* next( size_t n = 1 )
    223     {
    224       return this->advance( n );
    225     }
    226 
    227     virtual self_type* previous( size_t n = 1 )
    228     {
    229       ptrdiff_t nn = n;
    230       return this->advance( -nn );
    231     }
    232 
    233     bool operator == (const ConstIterator& x)  const
    234     {
    235       return equal(x);
    236     }
    237 
    238     bool operator != (const Iterator& x) const
    239     {
    240       return ! operator==(x);
    241     }
    242 
    243     Iterator& operator += (ptrdiff_t n)
    244     {
    245       return *advance(n);
    246     }
    247 
    248     Iterator& operator -= (ptrdiff_t n)
    249     {
    250       return *advance(-n);
    251     }
    252 
    253     Iterator* operator + (ptrdiff_t n) const
    254     {
    255       return dup()->advance(n);
    256     }
    257 
    258     Iterator* operator - (ptrdiff_t n) const
    259     {
    260       return dup()->advance(-n);
    261     }
    262 
    263     ptrdiff_t operator - (const Iterator& x) const
    264     {
    265       return x.distance(*this);
    266     }
    267   };
    268 
    269 }
    270 }
    271 
    272 
    273 %fragment("ConstIterator_T","header",fragment="<stddef.h>",fragment="ConstIterator",fragment="StdTraits",fragment="StdIteratorTraits") {
    274 namespace swig {
    275 
    276   /**
    277    * Templated base classes for all custom const_iterators.
    278    *
    279    */
    280   template<typename OutConstIterator>
    281   class ConstIterator_T :  public ConstIterator
    282   {
    283   public:
    284     typedef OutConstIterator const_iter;
    285     typedef typename std::iterator_traits<const_iter>::value_type value_type;
    286     typedef ConstIterator_T<const_iter> self_type;
    287 
    288   protected:
    289 
    290 
    291     virtual bool equal (const ConstIterator &iter) const
    292     {
    293       const self_type *iters = dynamic_cast<const self_type *>(&iter);
    294       if (iters) {
    295 	return (current == iters->get_current());
    296       } else {
    297 	throw std::invalid_argument("bad iterator type");
    298       }
    299     }
    300 
    301     virtual ptrdiff_t distance(const ConstIterator &iter) const
    302     {
    303       const self_type *iters = dynamic_cast<const self_type *>(&iter);
    304       if (iters) {
    305 	return std::distance(current, iters->get_current());
    306       } else {
    307 	throw std::invalid_argument("bad iterator type");
    308       }
    309     }
    310 
    311     virtual ConstIterator* advance(ptrdiff_t n)
    312     {
    313       std::advance( current, n );
    314       return this;
    315     }
    316 
    317   public:
    318     ConstIterator_T() : ConstIterator(Qnil)
    319     {
    320     }
    321 
    322     ConstIterator_T(const_iter curr, VALUE seq = Qnil)
    323       : ConstIterator(seq), current(curr)
    324     {
    325     }
    326 
    327     const const_iter& get_current() const
    328     {
    329       return current;
    330     }
    331 
    332     const value_type& operator*() const
    333     {
    334       return *current;
    335     }
    336 
    337     virtual VALUE inspect() const
    338     {
    339       VALUE ret = rb_str_new2("#<");
    340       ret = rb_str_cat2( ret, rb_obj_classname(_seq) );
    341       ret = rb_str_cat2( ret, "::const_iterator " );
    342       VALUE cur = value();
    343       ret = rb_str_concat( ret, rb_inspect(cur) );
    344       ret = rb_str_cat2( ret, ">" );
    345       return ret;
    346     }
    347 
    348     virtual VALUE to_s()    const
    349     {
    350       VALUE ret = rb_str_new2( rb_obj_classname(_seq) );
    351       ret = rb_str_cat2( ret, "::const_iterator " );
    352       VALUE cur = value();
    353       ret = rb_str_concat( ret, rb_obj_as_string(cur) );
    354       return ret;
    355     }
    356 
    357   protected:
    358     const_iter current;
    359   };
    360 
    361 
    362   /**
    363    * Templated base classes for all custom non-const iterators.
    364    *
    365    */
    366   template<typename InOutIterator>
    367   class Iterator_T :  public Iterator
    368   {
    369   public:
    370     typedef InOutIterator nonconst_iter;
    371 
    372     // Make this class iterator STL compatible, by using iterator_traits
    373     typedef typename std::iterator_traits<nonconst_iter >::iterator_category iterator_category;
    374     typedef typename std::iterator_traits<nonconst_iter >::value_type        value_type;
    375     typedef typename std::iterator_traits<nonconst_iter >::difference_type   difference_type;
    376     typedef typename std::iterator_traits<nonconst_iter >::pointer           pointer;
    377     typedef typename std::iterator_traits<nonconst_iter >::reference         reference;
    378 
    379     typedef Iterator                         base;
    380     typedef Iterator_T< nonconst_iter > self_type;
    381 
    382   protected:
    383 
    384     virtual bool equal (const ConstIterator &iter) const
    385     {
    386       const self_type *iters = dynamic_cast<const self_type *>(&iter);
    387       if (iters) {
    388 	return (current == iters->get_current());
    389       } else {
    390 	throw std::invalid_argument("bad iterator type");
    391       }
    392     }
    393 
    394     virtual ptrdiff_t distance(const ConstIterator &iter) const
    395     {
    396       const self_type *iters = dynamic_cast<const self_type *>(&iter);
    397       if (iters) {
    398 	return std::distance(current, iters->get_current());
    399       } else {
    400 	throw std::invalid_argument("bad iterator type");
    401       }
    402     }
    403 
    404     virtual Iterator* advance(ptrdiff_t n)
    405     {
    406       std::advance( current, n );
    407       return this;
    408     }
    409 
    410   public:
    411 
    412     Iterator_T(nonconst_iter curr, VALUE seq = Qnil)
    413       : Iterator(seq), current(curr)
    414     {
    415     }
    416 
    417     const nonconst_iter& get_current() const
    418     {
    419       return current;
    420     }
    421 
    422     self_type& operator=( const self_type& b )
    423     {
    424       base::operator=( b );
    425       return *this;
    426     }
    427 
    428     self_type& operator=( const value_type& b )
    429     {
    430       *current = b;
    431       return *this;
    432     }
    433 
    434     const value_type& operator*() const
    435     {
    436       return *current;
    437     }
    438 
    439     value_type& operator*()
    440     {
    441       return *current;
    442     }
    443 
    444     virtual VALUE inspect() const
    445     {
    446       VALUE ret = rb_str_new2("#<");
    447       ret = rb_str_cat2( ret, rb_obj_classname(_seq) );
    448       ret = rb_str_cat2( ret, "::iterator " );
    449       VALUE cur = value();
    450       ret = rb_str_concat( ret, rb_inspect(cur) );
    451       ret = rb_str_cat2( ret, ">" );
    452       return ret;
    453     }
    454 
    455     virtual VALUE to_s()    const
    456     {
    457       VALUE ret = rb_str_new2( rb_obj_classname(_seq) );
    458       ret = rb_str_cat2( ret, "::iterator " );
    459       VALUE cur = value();
    460       ret = rb_str_concat( ret, rb_obj_as_string(cur) );
    461       return ret;
    462     }
    463 
    464   protected:
    465     nonconst_iter current;
    466   };
    467 
    468 
    469   /**
    470    * Auxiliary functor to store the value of a ruby object inside
    471    * a reference of a compatible C++ type.  ie: Ruby -> C++
    472    *
    473    */
    474   template <class ValueType>
    475   struct asval_oper
    476   {
    477     typedef ValueType    value_type;
    478     typedef bool        result_type;
    479     bool operator()(VALUE obj, value_type& v) const
    480     {
    481       return ( swig::asval< value_type >(obj, &v) == SWIG_OK );
    482     }
    483   };
    484 
    485   /**
    486    * Auxiliary functor to return a ruby object from a C++ type.
    487    * ie: C++ -> Ruby
    488    *
    489    */
    490   template <class ValueType>
    491   struct from_oper
    492   {
    493     typedef const ValueType& argument_type;
    494     typedef VALUE result_type;
    495     result_type operator()(argument_type v) const
    496     {
    497       return swig::from(v);
    498     }
    499   };
    500 
    501 
    502   /**
    503    * ConstIterator class for a const_iterator with no end() boundaries.
    504    *
    505    */
    506   template<typename OutConstIterator,
    507 	   typename ValueType = typename std::iterator_traits<OutConstIterator>::value_type,
    508 	   typename FromOper = from_oper<ValueType> >
    509   class ConstIteratorOpen_T :  public ConstIterator_T<OutConstIterator>
    510   {
    511   public:
    512     FromOper from;
    513     typedef OutConstIterator const_iter;
    514     typedef ValueType value_type;
    515     typedef ConstIterator_T<const_iter>  base;
    516     typedef ConstIteratorOpen_T<OutConstIterator, ValueType, FromOper> self_type;
    517 
    518     ConstIteratorOpen_T(const_iter curr, VALUE seq = Qnil)
    519       : ConstIterator_T<OutConstIterator>(curr, seq)
    520     {
    521     }
    522 
    523     virtual VALUE value() const {
    524       return from(static_cast<const value_type&>(*(base::current)));
    525     }
    526 
    527     ConstIterator *dup() const
    528     {
    529       return new self_type(*this);
    530     }
    531   };
    532 
    533   /**
    534    * Iterator class for an iterator with no end() boundaries.
    535    *
    536    */
    537   template<typename InOutIterator,
    538 	   typename ValueType = typename std::iterator_traits<InOutIterator>::value_type,
    539 	   typename FromOper = from_oper<ValueType>,
    540 	   typename AsvalOper = asval_oper<ValueType> >
    541   class IteratorOpen_T :  public Iterator_T<InOutIterator>
    542   {
    543   public:
    544     FromOper  from;
    545     AsvalOper asval;
    546     typedef InOutIterator nonconst_iter;
    547     typedef ValueType value_type;
    548     typedef Iterator_T<nonconst_iter>  base;
    549     typedef IteratorOpen_T<InOutIterator, ValueType, FromOper, AsvalOper> self_type;
    550 
    551   public:
    552     IteratorOpen_T(nonconst_iter curr, VALUE seq = Qnil)
    553       : Iterator_T<InOutIterator>(curr, seq)
    554     {
    555     }
    556 
    557     virtual VALUE value() const {
    558       return from(static_cast<const value_type&>(*(base::current)));
    559     }
    560 
    561     virtual VALUE setValue( const VALUE& v )
    562     {
    563       value_type& dst = *base::current;
    564       if ( asval(v, dst) ) return v;
    565       return Qnil;
    566     }
    567 
    568     Iterator *dup() const
    569     {
    570       return new self_type(*this);
    571     }
    572   };
    573 
    574   /**
    575    * ConstIterator class for a const_iterator where begin() and end() boundaries are known.
    576    *
    577    */
    578   template<typename OutConstIterator,
    579 	   typename ValueType = typename std::iterator_traits<OutConstIterator>::value_type,
    580 	   typename FromOper = from_oper<ValueType> >
    581   class ConstIteratorClosed_T :  public ConstIterator_T<OutConstIterator>
    582   {
    583   public:
    584     FromOper from;
    585     typedef OutConstIterator const_iter;
    586     typedef ValueType value_type;
    587     typedef ConstIterator_T<const_iter>  base;
    588     typedef ConstIteratorClosed_T<OutConstIterator, ValueType, FromOper> self_type;
    589 
    590   protected:
    591     virtual ConstIterator* advance(ptrdiff_t n)
    592     {
    593       std::advance( base::current, n );
    594       if ( base::current == end )
    595 	throw stop_iteration();
    596       return this;
    597     }
    598 
    599   public:
    600     ConstIteratorClosed_T(const_iter curr, const_iter first,
    601 			  const_iter last, VALUE seq = Qnil)
    602       : ConstIterator_T<OutConstIterator>(curr, seq), begin(first), end(last)
    603     {
    604     }
    605 
    606     virtual VALUE value() const {
    607       if (base::current == end) {
    608 	throw stop_iteration();
    609       } else {
    610 	return from(static_cast<const value_type&>(*(base::current)));
    611       }
    612     }
    613 
    614     ConstIterator *dup() const
    615     {
    616       return new self_type(*this);
    617     }
    618 
    619 
    620   private:
    621     const_iter begin;
    622     const_iter end;
    623   };
    624 
    625   /**
    626    * Iterator class for a iterator where begin() and end() boundaries are known.
    627    *
    628    */
    629   template<typename InOutIterator,
    630 	   typename ValueType = typename std::iterator_traits<InOutIterator>::value_type,
    631 	   typename FromOper = from_oper<ValueType>,
    632 	   typename AsvalOper = asval_oper<ValueType> >
    633   class IteratorClosed_T :  public Iterator_T<InOutIterator>
    634   {
    635   public:
    636     FromOper   from;
    637     AsvalOper asval;
    638     typedef InOutIterator nonconst_iter;
    639     typedef ValueType value_type;
    640     typedef Iterator_T<nonconst_iter>  base;
    641     typedef IteratorClosed_T<InOutIterator, ValueType, FromOper, AsvalOper> self_type;
    642 
    643   protected:
    644     virtual Iterator* advance(ptrdiff_t n)
    645     {
    646       std::advance( base::current, n );
    647       if ( base::current == end )
    648 	throw stop_iteration();
    649       return this;
    650     }
    651 
    652   public:
    653     IteratorClosed_T(nonconst_iter curr, nonconst_iter first,
    654 		     nonconst_iter last, VALUE seq = Qnil)
    655       : Iterator_T<InOutIterator>(curr, seq), begin(first), end(last)
    656     {
    657     }
    658 
    659     virtual VALUE value() const {
    660       if (base::current == end) {
    661 	throw stop_iteration();
    662       } else {
    663 	return from(static_cast<const value_type&>(*(base::current)));
    664       }
    665     }
    666 
    667     // Iterator setter method, required by Ruby
    668     virtual VALUE setValue( const VALUE& v )
    669     {
    670       if (base::current == end)
    671 	throw stop_iteration();
    672 
    673       value_type& dst = *base::current;
    674       if ( asval( v, dst ) ) return v;
    675       return Qnil;
    676     }
    677 
    678     Iterator *dup() const
    679     {
    680       return new self_type(*this);
    681     }
    682 
    683   private:
    684     nonconst_iter begin;
    685     nonconst_iter end;
    686   };
    687 
    688   /* Partial specialization for bools which don't allow de-referencing */
    689   template< typename InOutIterator, typename FromOper, typename AsvalOper >
    690   class IteratorOpen_T< InOutIterator, bool, FromOper, AsvalOper > :
    691     public Iterator_T<InOutIterator>
    692   {
    693   public:
    694     FromOper   from;
    695     AsvalOper asval;
    696     typedef InOutIterator nonconst_iter;
    697     typedef bool value_type;
    698     typedef Iterator_T<nonconst_iter>  base;
    699     typedef IteratorOpen_T<InOutIterator, bool, FromOper, AsvalOper> self_type;
    700 
    701     IteratorOpen_T(nonconst_iter curr, VALUE seq = Qnil)
    702       : Iterator_T<InOutIterator>(curr, seq)
    703     {
    704     }
    705 
    706     virtual VALUE value() const {
    707       return from(static_cast<const value_type&>(*(base::current)));
    708     }
    709 
    710     virtual VALUE setValue( const VALUE& v )
    711     {
    712       bool tmp = *base::current;
    713       if ( asval( v, tmp ) )
    714 	{
    715 	  *base::current = tmp;
    716 	  return v;
    717 	}
    718       return Qnil;
    719     }
    720 
    721     Iterator *dup() const
    722     {
    723       return new self_type(*this);
    724     }
    725 
    726   };
    727 
    728   /* Partial specialization for bools which don't allow de-referencing */
    729   template< typename InOutIterator, typename FromOper, typename AsvalOper >
    730   class IteratorClosed_T< InOutIterator, bool, FromOper, AsvalOper > :
    731     public Iterator_T<InOutIterator>
    732   {
    733   public:
    734     FromOper   from;
    735     AsvalOper asval;
    736     typedef InOutIterator nonconst_iter;
    737     typedef bool value_type;
    738     typedef Iterator_T<nonconst_iter>  base;
    739     typedef IteratorClosed_T<InOutIterator, bool, FromOper, AsvalOper> self_type;
    740 
    741   protected:
    742     virtual Iterator* advance(ptrdiff_t n)
    743     {
    744       std::advance( base::current, n );
    745       if ( base::current == end )
    746 	throw stop_iteration();
    747       return this;
    748     }
    749 
    750   public:
    751     IteratorClosed_T(nonconst_iter curr, nonconst_iter first,
    752 		     nonconst_iter last, VALUE seq = Qnil)
    753       : Iterator_T<InOutIterator>(curr, seq), begin(first), end(last)
    754     {
    755     }
    756 
    757     virtual VALUE value() const {
    758       if (base::current == end) {
    759 	throw stop_iteration();
    760       } else {
    761 	return from(static_cast<const value_type&>(*(base::current)));
    762       }
    763     }
    764 
    765     virtual VALUE setValue( const VALUE& v )
    766     {
    767       if (base::current == end)
    768 	throw stop_iteration();
    769 
    770       bool tmp = *base::current;
    771       if ( asval( v, tmp ) )
    772 	{
    773 	  *base::current = tmp;
    774 	  return v;
    775 	}
    776       return Qnil;
    777     }
    778 
    779     Iterator *dup() const
    780     {
    781       return new self_type(*this);
    782     }
    783 
    784   private:
    785     nonconst_iter begin;
    786     nonconst_iter end;
    787   };
    788 
    789 
    790   /**
    791    * Helper function used to wrap a bounded const_iterator.  This is to be used in
    792    * a %typemap(out), for example.
    793    *
    794    */
    795   template<typename InOutIter>
    796   inline Iterator*
    797   make_nonconst_iterator(const InOutIter& current, const InOutIter& begin,
    798 			 const InOutIter& end, VALUE seq = Qnil)
    799   {
    800     return new IteratorClosed_T<InOutIter>(current, begin, end, seq);
    801   }
    802 
    803   /**
    804    * Helper function used to wrap an unbounded const_iterator.  This is to be used in
    805    * a %typemap(out), for example.
    806    *
    807    */
    808   template<typename InOutIter>
    809   inline Iterator*
    810   make_nonconst_iterator(const InOutIter& current, VALUE seq = Qnil)
    811   {
    812     return new IteratorOpen_T<InOutIter>(current, seq);
    813   }
    814 
    815   /**
    816    * Helper function used to wrap a bounded const_iterator.  This is to be used in
    817    * a %typemap(out), for example.
    818    *
    819    */
    820   template<typename OutIter>
    821   inline ConstIterator*
    822   make_const_iterator(const OutIter& current, const OutIter& begin,
    823                        const OutIter& end, VALUE seq = Qnil)
    824   {
    825     return new ConstIteratorClosed_T<OutIter>(current, begin, end, seq);
    826   }
    827 
    828   /**
    829    * Helper function used to wrap an unbounded const_iterator.  This is to be used in
    830    * a %typemap(out), for example.
    831    *
    832    */
    833   template<typename OutIter>
    834   inline ConstIterator*
    835   make_const_iterator(const OutIter& current, VALUE seq = Qnil)
    836   {
    837     return new ConstIteratorOpen_T<OutIter>(current, seq);
    838   }
    839 }
    840 }
    841 
    842 
    843 %fragment("ConstIterator");
    844 
    845 
    846 //
    847 // This part is just so SWIG is aware of the base abstract iterator class.
    848 //
    849 namespace swig
    850 {
    851   /*
    852     Throw a StopIteration exception
    853   */
    854   %ignore stop_iteration;
    855   struct stop_iteration {};
    856 
    857   %typemap(throws) stop_iteration {
    858     (void)$1;
    859     SWIG_Ruby_ExceptionType(NULL, Qnil);
    860     SWIG_fail;
    861   }
    862 
    863   /*
    864      Mark methods that return new objects
    865   */
    866   %newobject ConstIterator::dup;
    867   %newobject ConstIterator::operator + (ptrdiff_t n) const;
    868   %newobject ConstIterator::operator - (ptrdiff_t n) const;
    869 
    870   %nodirector ConstIterator;
    871 
    872   %catches(swig::stop_iteration)  ConstIterator::value() const;
    873   %catches(swig::stop_iteration)  ConstIterator::incr(size_t n = 1);
    874   %catches(swig::stop_iteration)  ConstIterator::decr(size_t n = 1);
    875   %catches(std::invalid_argument) ConstIterator::distance(const ConstIterator &x) const;
    876   %catches(std::invalid_argument) ConstIterator::equal (const ConstIterator &x) const;
    877   %catches(swig::stop_iteration)  ConstIterator::next();
    878   %catches(swig::stop_iteration)  ConstIterator::previous();
    879   %catches(swig::stop_iteration)  ConstIterator::advance(ptrdiff_t n);
    880   %catches(swig::stop_iteration)  ConstIterator::operator += (ptrdiff_t n);
    881   %catches(swig::stop_iteration)  ConstIterator::operator -= (ptrdiff_t n);
    882   %catches(swig::stop_iteration)  ConstIterator::operator + (ptrdiff_t n) const;
    883   %catches(swig::stop_iteration)  ConstIterator::operator - (ptrdiff_t n) const;
    884 
    885 
    886   struct ConstIterator
    887   {
    888   protected:
    889     ConstIterator(VALUE seq);
    890 
    891   public:
    892     virtual ~ConstIterator();
    893 
    894     // Access iterator method, required by Ruby
    895     virtual VALUE value() const;
    896 
    897     // C++ common/needed methods
    898     virtual ConstIterator *dup() const;
    899 
    900     virtual VALUE inspect()    const;
    901     virtual VALUE to_s()    const;
    902 
    903     virtual ConstIterator* next(size_t n = 1);
    904     virtual ConstIterator* previous(size_t n = 1);
    905 
    906     bool operator == (const ConstIterator& x)  const;
    907     ConstIterator* operator + (ptrdiff_t n) const;
    908     ConstIterator* operator - (ptrdiff_t n) const;
    909     ptrdiff_t operator - (const ConstIterator& x) const;
    910   };
    911 
    912   struct Iterator : public ConstIterator
    913   {
    914     %rename("value=") setValue( const VALUE& v );
    915     virtual VALUE setValue( const VALUE& v );
    916 
    917     virtual Iterator *dup() const;
    918 
    919     virtual Iterator* next(size_t n = 1);
    920     virtual Iterator* previous(size_t n = 1);
    921 
    922     virtual VALUE inspect()    const;
    923     virtual VALUE to_s()    const;
    924 
    925     bool operator == (const Iterator& x)  const;
    926     Iterator* operator + (ptrdiff_t n) const;
    927     Iterator* operator - (ptrdiff_t n) const;
    928     ptrdiff_t operator - (const Iterator& x) const;
    929   };
    930 
    931 }
    932 
    933